<commit_before>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include "core/reactor.hh"
#include "core/iostream.hh"
#include "core/distributed.hh"
#include "core/print.hh"
#include "core/sstring.hh"
#include "net/api.hh"
#include "util/serialization.hh"
#include "gms/inet_address.hh"
#include "rpc/rpc.hh"
#include <unordered_map>
#include "db/config.hh"
#include "frozen_mutation.hh"
#include "query-request.hh"
#include "db/serializer.hh"
#include "mutation_query.hh"

// forward declarations
namespace streaming { namespace messages {
    class stream_init_message;
}}

namespace net {

/* All verb handler identifiers */
enum class messaging_verb : int32_t {
    MUTATION,
    MUTATION_DONE,
    BINARY, // Deprecated
    READ_REPAIR,
    READ,
    READ_DATA,
    READ_MUTATION_DATA, // urchin-only
    READ_DIGEST,
    REQUEST_RESPONSE, // client-initiated reads and writes
    STREAM_INITIATE, // Deprecated
    STREAM_INITIATE_DONE, // Deprecated
    STREAM_REPLY, // Deprecated
    STREAM_REQUEST, // Deprecated
    RANGE_SLICE,
    BOOTSTRAP_TOKEN, // Deprecated
    TREE_REQUEST, // Deprecated
    TREE_RESPONSE, // Deprecated
    JOIN, // Deprecated
    GOSSIP_DIGEST_SYN,
    GOSSIP_DIGEST_ACK,
    GOSSIP_DIGEST_ACK2,
    DEFINITIONS_ANNOUNCE, // Deprecated
    DEFINITIONS_UPDATE,
    TRUNCATE,
    SCHEMA_CHECK,
    INDEX_SCAN, // Deprecated
    REPLICATION_FINISHED,
    INTERNAL_RESPONSE, // responses to internal calls
    COUNTER_MUTATION,
    STREAMING_REPAIR_REQUEST, // Deprecated
    STREAMING_REPAIR_RESPONSE, // Deprecated
    SNAPSHOT, // Similar to nt snapshot
    MIGRATION_REQUEST,
    GOSSIP_SHUTDOWN,
    _TRACE,
    ECHO,
    REPAIR_MESSAGE,
    PAXOS_PREPARE,
    PAXOS_PROPOSE,
    PAXOS_COMMIT,
    PAGED_RANGE,
    UNUSED_1,
    UNUSED_2,
    UNUSED_3,
    // Used by streaming
    STREAM_INIT_MESSAGE,
    PREPARE_MESSAGE,
    STREAM_MUTATION,
    INCOMING_FILE_MESSAGE,
    OUTGOING_FILE_MESSAGE,
    RECEIVED_MESSAGE,
    RETRY_MESSAGE,
    COMPLETE_MESSAGE,
    SESSION_FAILED_MESSAGE,
    LAST,
};

} // namespace net

namespace std {
template <>
class hash<net::messaging_verb> {
public:
    size_t operator()(const net::messaging_verb& x) const {
        return hash<int32_t>()(int32_t(x));
    }
};
} // namespace std

namespace net {

future<> ser_messaging_verb(output_stream<char>& out, messaging_verb& v);
future<> des_messaging_verb(input_stream<char>& in, messaging_verb& v);
future<> ser_sstring(output_stream<char>& out, sstring& v);
future<> des_sstring(input_stream<char>& in, sstring& v);

// NOTE: operator(input_stream<char>&, T&) takes a reference to uninitialized
//       T object and should use placement new in case T is non POD
struct serializer {
    template<typename T>
    inline future<T> read_integral(input_stream<char>& in) {
        static_assert(std::is_integral<T>::value, "T should be integral");

        return in.read_exactly(sizeof(T)).then([] (temporary_buffer<char> buf) {
            if (buf.size() != sizeof(T)) {
                throw rpc::closed_error();
            }
            return make_ready_future<T>(net::ntoh(*unaligned_cast<T*>(buf.get())));
        });
    }

    // Adaptor for writing objects having db::serializer<>
    template<typename Serializable>
    inline future<> write_serializable(output_stream<char>& out, const Serializable& v) {
        db::serializer<Serializable> ser(v);
        bytes b(bytes::initialized_later(), ser.size() + data_output::serialized_size<uint32_t>());
        data_output d_out(b);
        d_out.write<uint32_t>(ser.size());
        ser.write(d_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), b.size());
    }

    // Adaptor for reading objects having db::serializer<>
    template<typename Serializable>
    inline future<> read_serializable(input_stream<char>& in, Serializable& v) {
        return read_integral<uint32_t>(in).then([&in, &v] (auto sz) mutable {
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                data_input in(bv);
                db::serializer<Serializable>::read(v, in);
            });
        });
    }

    // For integer type
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<std::is_integral<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto v_ = net::hton(v);
        return out.write(reinterpret_cast<const char*>(&v_), sizeof(T));
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<std::is_integral<T>::value, void*> = nullptr) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            v = net::ntoh(*reinterpret_cast<const net::packed<T>*>(buf.get()));
        });
    }

    // For vectors
    template<typename T>
    inline auto operator()(output_stream<char>& out, std::vector<T>& v) {
        return operator()(out, v.size()).then([&out, &v, this] {
            return do_for_each(v.begin(), v.end(), [&out, this] (T& e) {
                return operator()(out, e);
            });
        });
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, std::vector<T>& v) {
        using size_type = typename  std::vector<T>::size_type;
        return read_integral<size_type>(in).then([&v, &in, this] (size_type c) {
            new (&v) std::vector<T>;
            v.reserve(c);
            union U {
                U(){}
                ~U(){}
                U(U&&) {}
                T v;
            };
            return do_with(U(), [c, &v, &in, this] (U& u) {
                return do_until([c = c] () mutable {return !c--;}, [&v, &in, &u, this] () mutable {
                    return operator()(in, u.v).then([&u, &v] {
                        v.emplace_back(std::move(u.v));
                    });
                });
            });
        });
    }

    // For messaging_verb
    inline auto operator()(output_stream<char>& out, messaging_verb& v) {
        return ser_messaging_verb(out, v);
    }
    inline auto operator()(input_stream<char>& in, messaging_verb& v) {
        return des_messaging_verb(in, v);
    }

    // For sstring
    inline auto operator()(output_stream<char>& out, sstring& v) {
        return ser_sstring(out, v);
    }
    inline auto operator()(input_stream<char>& in, sstring& v) {
        return des_sstring(in, v);
    }

    // For frozen_mutation
    inline auto operator()(output_stream<char>& out, const frozen_mutation& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(output_stream<char>& out, frozen_mutation& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(input_stream<char>& in, frozen_mutation& v) {
        return read_serializable(in, v);
    }

    // For reconcilable_result
    inline auto operator()(output_stream<char>& out, const reconcilable_result& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(output_stream<char>& out, reconcilable_result& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(input_stream<char>& in, reconcilable_result& v) {
        return read_serializable(in, v);
    }

    // For complex types which have serialize()/deserialize(),  e.g. gms::gossip_digest_syn, gms::gossip_digest_ack2
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<!std::is_integral<std::remove_reference_t<T>>::value &&
                                                                             !std::is_enum<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto sz = serialize_int32_size + v.serialized_size();
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int32(_out, int32_t(sz - serialize_int32_size));
        v.serialize(_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<!std::is_integral<T>::value &&
                                                                          !std::is_enum<T>::value, void*> = nullptr) {
        return in.read_exactly(serialize_int32_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int32_size) {
                throw rpc::closed_error();
            }
            size_t sz = net::ntoh(*reinterpret_cast<const net::packed<int32_t>*>(buf.get()));
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                new (&v) T(T::deserialize(bv));
                assert(bv.size() == 0);
                return make_ready_future<>();
            });
        });
    }
};

struct shard_id {
    gms::inet_address addr;
    uint32_t cpu_id;
    friend bool operator==(const shard_id& x, const shard_id& y);
    friend bool operator<(const shard_id& x, const shard_id& y);
    friend std::ostream& operator<<(std::ostream& os, const shard_id& x);
    struct hash {
        size_t operator()(const shard_id& id) const;
    };
};

class messaging_service {
public:
    using shard_id = net::shard_id;

    using rpc_protocol = rpc::protocol<serializer, messaging_verb>;
    struct rpc_protocol_wrapper : public rpc_protocol { using rpc_protocol::rpc_protocol; };
    struct rpc_protocol_client_wrapper : public rpc_protocol::client { using rpc_protocol::client::client; };
    struct rpc_protocol_server_wrapper : public rpc_protocol::server { using rpc_protocol::server::server; };

    // FIXME: messaging service versioning
    static constexpr int32_t current_version = 0;

    struct shard_info {
        shard_info(std::unique_ptr<rpc_protocol_client_wrapper>&& client);
        std::unique_ptr<rpc_protocol_client_wrapper> rpc_client;
    };

    void foreach_client(std::function<void(const shard_id& id, const shard_info& info)> f) const;

    void increment_dropped_messages(messaging_verb verb);

    uint64_t get_dropped_messages(messaging_verb verb) const;

    const uint64_t* get_dropped_messages() const;

    int32_t get_raw_version(const gms::inet_address& endpoint) const;

    bool knows_version(const gms::inet_address& endpoint) const;

private:
    static constexpr uint16_t _default_port = 7000;
    gms::inet_address _listen_address;
    uint16_t _port;
    std::unique_ptr<rpc_protocol_wrapper> _rpc;
    std::unique_ptr<rpc_protocol_server_wrapper> _server;
    std::unordered_map<shard_id, shard_info, shard_id::hash> _clients;
    uint64_t _dropped_messages[static_cast<int32_t>(messaging_verb::LAST)] = {};
public:
    messaging_service(gms::inet_address ip = gms::inet_address("0.0.0.0"));
public:
    uint16_t port();
    gms::inet_address listen_address();
    future<> stop();
    static rpc::no_wait_type no_wait();
public:
    // Register a handler (a callback lambda) for verb
    template <typename Func>
    void register_handler(messaging_verb verb, Func&& func) {
        _rpc->register_handler(verb, std::move(func));
    }

    // Send a message for verb
    template <typename MsgIn, typename... MsgOut>
    auto send_message(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        auto& rpc_client = get_rpc_client(id);
        auto rpc_handler = _rpc->make_client<MsgIn(MsgOut...)>(verb);
        return rpc_handler(rpc_client, std::forward<MsgOut>(msg)...).then_wrapped([this, id, verb] (auto&& f) {
            try {
                if (f.failed()) {
                    this->increment_dropped_messages(verb);
                    f.get();
                    assert(false); // never reached
                }
                return std::move(f);
            } catch(...) {
                // FIXME: we need to distinguish between a transport error and
                // a server error.
                // remove_rpc_client(id);
                throw;
            }
        });
    }

    template <typename... MsgOut>
    auto send_message_oneway(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        return send_message<rpc::no_wait_type>(std::move(verb), std::move(id), std::forward<MsgOut>(msg)...);
    }

    // Wrapper fro STREAM_INIT_MESSAGE verb
    future<unsigned> send_stream_init_message(shard_id id, streaming::messages::stream_init_message&& msg, unsigned src_cpu_id);
    void register_stream_init_message(std::function<future<unsigned> (streaming::messages::stream_init_message msg, unsigned src_cpu_id)>&& func);

private:
    // Return rpc::protocol::client for a shard which is a ip + cpuid pair.
    rpc_protocol_client_wrapper& get_rpc_client(shard_id id);
    void remove_rpc_client(shard_id id);
};

extern distributed<messaging_service> _the_messaging_service;

inline distributed<messaging_service>& get_messaging_service() {
    return _the_messaging_service;
}

inline messaging_service& get_local_messaging_service() {
    return _the_messaging_service.local();
}

future<> init_messaging_service(sstring listen_address, db::config::seed_provider_type seed_provider);
} // namespace net
<commit_msg>messaging_service: Fix read_serializable()<commit_after>/*
 * Copyright (C) 2015 Cloudius Systems, Ltd.
 */

#pragma once

#include "core/reactor.hh"
#include "core/iostream.hh"
#include "core/distributed.hh"
#include "core/print.hh"
#include "core/sstring.hh"
#include "net/api.hh"
#include "util/serialization.hh"
#include "gms/inet_address.hh"
#include "rpc/rpc.hh"
#include <unordered_map>
#include "db/config.hh"
#include "frozen_mutation.hh"
#include "query-request.hh"
#include "db/serializer.hh"
#include "mutation_query.hh"

// forward declarations
namespace streaming { namespace messages {
    class stream_init_message;
}}

namespace net {

/* All verb handler identifiers */
enum class messaging_verb : int32_t {
    MUTATION,
    MUTATION_DONE,
    BINARY, // Deprecated
    READ_REPAIR,
    READ,
    READ_DATA,
    READ_MUTATION_DATA, // urchin-only
    READ_DIGEST,
    REQUEST_RESPONSE, // client-initiated reads and writes
    STREAM_INITIATE, // Deprecated
    STREAM_INITIATE_DONE, // Deprecated
    STREAM_REPLY, // Deprecated
    STREAM_REQUEST, // Deprecated
    RANGE_SLICE,
    BOOTSTRAP_TOKEN, // Deprecated
    TREE_REQUEST, // Deprecated
    TREE_RESPONSE, // Deprecated
    JOIN, // Deprecated
    GOSSIP_DIGEST_SYN,
    GOSSIP_DIGEST_ACK,
    GOSSIP_DIGEST_ACK2,
    DEFINITIONS_ANNOUNCE, // Deprecated
    DEFINITIONS_UPDATE,
    TRUNCATE,
    SCHEMA_CHECK,
    INDEX_SCAN, // Deprecated
    REPLICATION_FINISHED,
    INTERNAL_RESPONSE, // responses to internal calls
    COUNTER_MUTATION,
    STREAMING_REPAIR_REQUEST, // Deprecated
    STREAMING_REPAIR_RESPONSE, // Deprecated
    SNAPSHOT, // Similar to nt snapshot
    MIGRATION_REQUEST,
    GOSSIP_SHUTDOWN,
    _TRACE,
    ECHO,
    REPAIR_MESSAGE,
    PAXOS_PREPARE,
    PAXOS_PROPOSE,
    PAXOS_COMMIT,
    PAGED_RANGE,
    UNUSED_1,
    UNUSED_2,
    UNUSED_3,
    // Used by streaming
    STREAM_INIT_MESSAGE,
    PREPARE_MESSAGE,
    STREAM_MUTATION,
    INCOMING_FILE_MESSAGE,
    OUTGOING_FILE_MESSAGE,
    RECEIVED_MESSAGE,
    RETRY_MESSAGE,
    COMPLETE_MESSAGE,
    SESSION_FAILED_MESSAGE,
    LAST,
};

} // namespace net

namespace std {
template <>
class hash<net::messaging_verb> {
public:
    size_t operator()(const net::messaging_verb& x) const {
        return hash<int32_t>()(int32_t(x));
    }
};
} // namespace std

namespace net {

future<> ser_messaging_verb(output_stream<char>& out, messaging_verb& v);
future<> des_messaging_verb(input_stream<char>& in, messaging_verb& v);
future<> ser_sstring(output_stream<char>& out, sstring& v);
future<> des_sstring(input_stream<char>& in, sstring& v);

// NOTE: operator(input_stream<char>&, T&) takes a reference to uninitialized
//       T object and should use placement new in case T is non POD
struct serializer {
    template<typename T>
    inline future<T> read_integral(input_stream<char>& in) {
        static_assert(std::is_integral<T>::value, "T should be integral");

        return in.read_exactly(sizeof(T)).then([] (temporary_buffer<char> buf) {
            if (buf.size() != sizeof(T)) {
                throw rpc::closed_error();
            }
            return make_ready_future<T>(net::ntoh(*unaligned_cast<T*>(buf.get())));
        });
    }

    // Adaptor for writing objects having db::serializer<>
    template<typename Serializable>
    inline future<> write_serializable(output_stream<char>& out, const Serializable& v) {
        db::serializer<Serializable> ser(v);
        bytes b(bytes::initialized_later(), ser.size() + data_output::serialized_size<uint32_t>());
        data_output d_out(b);
        d_out.write<uint32_t>(ser.size());
        ser.write(d_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), b.size());
    }

    // Adaptor for reading objects having db::serializer<>
    template<typename Serializable>
    inline future<> read_serializable(input_stream<char>& in, Serializable& v) {
        return read_integral<uint32_t>(in).then([&in, &v] (auto sz) mutable {
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                data_input in(bv);
                new (&v) Serializable(db::serializer<Serializable>::read(in));
            });
        });
    }

    // For integer type
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<std::is_integral<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto v_ = net::hton(v);
        return out.write(reinterpret_cast<const char*>(&v_), sizeof(T));
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<std::is_integral<T>::value, void*> = nullptr) {
        return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != sizeof(v)) {
                throw rpc::closed_error();
            }
            v = net::ntoh(*reinterpret_cast<const net::packed<T>*>(buf.get()));
        });
    }

    // For vectors
    template<typename T>
    inline auto operator()(output_stream<char>& out, std::vector<T>& v) {
        return operator()(out, v.size()).then([&out, &v, this] {
            return do_for_each(v.begin(), v.end(), [&out, this] (T& e) {
                return operator()(out, e);
            });
        });
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, std::vector<T>& v) {
        using size_type = typename  std::vector<T>::size_type;
        return read_integral<size_type>(in).then([&v, &in, this] (size_type c) {
            new (&v) std::vector<T>;
            v.reserve(c);
            union U {
                U(){}
                ~U(){}
                U(U&&) {}
                T v;
            };
            return do_with(U(), [c, &v, &in, this] (U& u) {
                return do_until([c = c] () mutable {return !c--;}, [&v, &in, &u, this] () mutable {
                    return operator()(in, u.v).then([&u, &v] {
                        v.emplace_back(std::move(u.v));
                    });
                });
            });
        });
    }

    // For messaging_verb
    inline auto operator()(output_stream<char>& out, messaging_verb& v) {
        return ser_messaging_verb(out, v);
    }
    inline auto operator()(input_stream<char>& in, messaging_verb& v) {
        return des_messaging_verb(in, v);
    }

    // For sstring
    inline auto operator()(output_stream<char>& out, sstring& v) {
        return ser_sstring(out, v);
    }
    inline auto operator()(input_stream<char>& in, sstring& v) {
        return des_sstring(in, v);
    }

    // For frozen_mutation
    inline auto operator()(output_stream<char>& out, const frozen_mutation& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(output_stream<char>& out, frozen_mutation& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(input_stream<char>& in, frozen_mutation& v) {
        return read_serializable(in, v);
    }

    // For reconcilable_result
    inline auto operator()(output_stream<char>& out, const reconcilable_result& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(output_stream<char>& out, reconcilable_result& v) {
        return write_serializable(out, v);
    }
    inline auto operator()(input_stream<char>& in, reconcilable_result& v) {
        return read_serializable(in, v);
    }

    // For complex types which have serialize()/deserialize(),  e.g. gms::gossip_digest_syn, gms::gossip_digest_ack2
    template<typename T>
    inline auto operator()(output_stream<char>& out, T&& v, std::enable_if_t<!std::is_integral<std::remove_reference_t<T>>::value &&
                                                                             !std::is_enum<std::remove_reference_t<T>>::value, void*> = nullptr) {
        auto sz = serialize_int32_size + v.serialized_size();
        bytes b(bytes::initialized_later(), sz);
        auto _out = b.begin();
        serialize_int32(_out, int32_t(sz - serialize_int32_size));
        v.serialize(_out);
        return out.write(reinterpret_cast<const char*>(b.c_str()), sz);
    }
    template<typename T>
    inline auto operator()(input_stream<char>& in, T& v, std::enable_if_t<!std::is_integral<T>::value &&
                                                                          !std::is_enum<T>::value, void*> = nullptr) {
        return in.read_exactly(serialize_int32_size).then([&in, &v] (temporary_buffer<char> buf) mutable {
            if (buf.size() != serialize_int32_size) {
                throw rpc::closed_error();
            }
            size_t sz = net::ntoh(*reinterpret_cast<const net::packed<int32_t>*>(buf.get()));
            return in.read_exactly(sz).then([sz, &v] (temporary_buffer<char> buf) mutable {
                if (buf.size() != sz) {
                    throw rpc::closed_error();
                }
                bytes_view bv(reinterpret_cast<const int8_t*>(buf.get()), sz);
                new (&v) T(T::deserialize(bv));
                assert(bv.size() == 0);
                return make_ready_future<>();
            });
        });
    }
};

struct shard_id {
    gms::inet_address addr;
    uint32_t cpu_id;
    friend bool operator==(const shard_id& x, const shard_id& y);
    friend bool operator<(const shard_id& x, const shard_id& y);
    friend std::ostream& operator<<(std::ostream& os, const shard_id& x);
    struct hash {
        size_t operator()(const shard_id& id) const;
    };
};

class messaging_service {
public:
    using shard_id = net::shard_id;

    using rpc_protocol = rpc::protocol<serializer, messaging_verb>;
    struct rpc_protocol_wrapper : public rpc_protocol { using rpc_protocol::rpc_protocol; };
    struct rpc_protocol_client_wrapper : public rpc_protocol::client { using rpc_protocol::client::client; };
    struct rpc_protocol_server_wrapper : public rpc_protocol::server { using rpc_protocol::server::server; };

    // FIXME: messaging service versioning
    static constexpr int32_t current_version = 0;

    struct shard_info {
        shard_info(std::unique_ptr<rpc_protocol_client_wrapper>&& client);
        std::unique_ptr<rpc_protocol_client_wrapper> rpc_client;
    };

    void foreach_client(std::function<void(const shard_id& id, const shard_info& info)> f) const;

    void increment_dropped_messages(messaging_verb verb);

    uint64_t get_dropped_messages(messaging_verb verb) const;

    const uint64_t* get_dropped_messages() const;

    int32_t get_raw_version(const gms::inet_address& endpoint) const;

    bool knows_version(const gms::inet_address& endpoint) const;

private:
    static constexpr uint16_t _default_port = 7000;
    gms::inet_address _listen_address;
    uint16_t _port;
    std::unique_ptr<rpc_protocol_wrapper> _rpc;
    std::unique_ptr<rpc_protocol_server_wrapper> _server;
    std::unordered_map<shard_id, shard_info, shard_id::hash> _clients;
    uint64_t _dropped_messages[static_cast<int32_t>(messaging_verb::LAST)] = {};
public:
    messaging_service(gms::inet_address ip = gms::inet_address("0.0.0.0"));
public:
    uint16_t port();
    gms::inet_address listen_address();
    future<> stop();
    static rpc::no_wait_type no_wait();
public:
    // Register a handler (a callback lambda) for verb
    template <typename Func>
    void register_handler(messaging_verb verb, Func&& func) {
        _rpc->register_handler(verb, std::move(func));
    }

    // Send a message for verb
    template <typename MsgIn, typename... MsgOut>
    auto send_message(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        auto& rpc_client = get_rpc_client(id);
        auto rpc_handler = _rpc->make_client<MsgIn(MsgOut...)>(verb);
        return rpc_handler(rpc_client, std::forward<MsgOut>(msg)...).then_wrapped([this, id, verb] (auto&& f) {
            try {
                if (f.failed()) {
                    this->increment_dropped_messages(verb);
                    f.get();
                    assert(false); // never reached
                }
                return std::move(f);
            } catch(...) {
                // FIXME: we need to distinguish between a transport error and
                // a server error.
                // remove_rpc_client(id);
                throw;
            }
        });
    }

    template <typename... MsgOut>
    auto send_message_oneway(messaging_verb verb, shard_id id, MsgOut&&... msg) {
        return send_message<rpc::no_wait_type>(std::move(verb), std::move(id), std::forward<MsgOut>(msg)...);
    }

    // Wrapper fro STREAM_INIT_MESSAGE verb
    future<unsigned> send_stream_init_message(shard_id id, streaming::messages::stream_init_message&& msg, unsigned src_cpu_id);
    void register_stream_init_message(std::function<future<unsigned> (streaming::messages::stream_init_message msg, unsigned src_cpu_id)>&& func);

private:
    // Return rpc::protocol::client for a shard which is a ip + cpuid pair.
    rpc_protocol_client_wrapper& get_rpc_client(shard_id id);
    void remove_rpc_client(shard_id id);
};

extern distributed<messaging_service> _the_messaging_service;

inline distributed<messaging_service>& get_messaging_service() {
    return _the_messaging_service;
}

inline messaging_service& get_local_messaging_service() {
    return _the_messaging_service.local();
}

future<> init_messaging_service(sstring listen_address, db::config::seed_provider_type seed_provider);
} // namespace net
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for T0 calibration                       TM--AM_6-02-2006         //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliT0CalibData.h"
#include "AliT0LookUpValue.h"
#include "AliT0LookUpKey.h"
#include "AliLog.h"

#include <Riostream.h>

//#include <string>

using std::ifstream;
ClassImp(AliT0CalibData)

//________________________________________________________________
  AliT0CalibData::AliT0CalibData():   TNamed(),
				      fLookup(0),
				      fNumberOfTRMs(0)

{
  //
}

//________________________________________________________________
AliT0CalibData::AliT0CalibData(const char* name):TNamed(),
				      fLookup(0),
				      fNumberOfTRMs(0)
{
  TString namst = "Calib_";
  namst += name;
  SetName(namst.Data());
  SetTitle(namst.Data());

}

//________________________________________________________________
AliT0CalibData::AliT0CalibData(const AliT0CalibData& calibda) :
  TNamed(calibda),
  fLookup(0),
  fNumberOfTRMs(0)

{
// copy constructor
  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

}

//________________________________________________________________
AliT0CalibData &AliT0CalibData::operator =(const AliT0CalibData& calibda)
{
// assignment operator
  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  return *this;
}

//________________________________________________________________
AliT0CalibData::~AliT0CalibData()
{
  //
}
//________________________________________________________________
void  AliT0CalibData::PrintLookup(Option_t*, Int_t iTRM, Int_t iTDC, Int_t iChannel) const
{
  // print lookup table

  AliT0LookUpKey* lookkey; //= new AliT0LookUpKey();
  AliT0LookUpValue*  lookvalue= new AliT0LookUpValue();
  printf("Number Of TRMs in setup %i\n",GetNumberOfTRMs());

  iTRM=0; iTDC=0; Int_t chain=0; iChannel=0;

  for (Int_t ik=0; ik<105; ik++){
    lookvalue->SetTRM(iTRM);
    lookvalue->SetTDC(iTDC);
    lookvalue->SetChain(chain);
    lookvalue->SetChannel(iChannel);

    if (iChannel<6) iChannel +=2;
    else {iChannel = 0; iTDC++;}
    if(ik==57) { iTDC=0; iChannel=0; iTRM=1;}

  printf(" AliT0CalibData::PrintLookup ::start GetValue %i %i %i %i\n",iTRM, iTDC,chain, iChannel);
    lookkey = (AliT0LookUpKey*) fLookup.GetValue((TObject*)lookvalue);
    //    TString name= lookkey->GetChannelName();
    // cout<<name.Data()<<endl;
    if (lookkey)
      {
	TString name= lookkey->GetChannelName();
	/*	cout<<" lookup KEY!!! "<<name.Data()<<" "<<lookkey->GetKey()<<" VALUE "<<lookvalue->GetTRM()<<" "
	    <<lookvalue->GetTDC()<<" "
	    << lookvalue->GetChain()<<" "
	    <<lookvalue->GetChannel()<<endl;*/
      }
  }

}
//________________________________________________________________

void AliT0CalibData::ReadAsciiLookup(const Char_t *filename)
{
  // read lookup table from ascii file

  Int_t key, trm, tdc, chain, channel;

  if(filename == 0){
    AliError(Form("Please, specify file with database")) ;
    return ;
  }
  cout<<" read file "<<filename<<endl;

  ifstream lookup;
  lookup.open(filename);
  if(!lookup)
    {
     AliError(Form("!!!!!!!!!!!!!!No look up table in CDB!" ));

    }
  Char_t varname[11];
  Int_t ntrms;
  if(lookup)
    {
      lookup>>ntrms;
      //      fNumberOfTRMs=ntrms;
      SetNumberOfTRMs(ntrms);
      cout<<" N TRMS "<<ntrms<<endl;
       while(!lookup.eof())
	{
	  AliT0LookUpKey * lookkey= new AliT0LookUpKey();
	  AliT0LookUpValue * lookvalue= new AliT0LookUpValue();

	  lookup>>varname>>key>>trm>>chain>>tdc>>channel;
	  lookvalue->SetTRM(trm);
	  lookvalue->SetTDC(tdc);
	  lookvalue->SetChain(chain);
	  lookvalue->SetChannel(channel);
	  lookkey->SetKey(key);
	  lookkey->SetChannelName(varname);
	  cout<<trm<<" "<<chain<<" "<<tdc<<" "<<channel<<" "<<key<<" "<<varname<<endl;
	  fLookup.Add((TObject*)lookvalue,(TObject*)lookkey);

	}

      lookup.close();

    }
}
//________________________________________________________________

Int_t AliT0CalibData::GetChannel(Int_t trm,  Int_t tdc, Int_t chain, Int_t channel)
{
  // read number of channel according physical addres

  AliT0LookUpKey * lookkey;//= new AliT0LookUpKey();
  AliT0LookUpValue * lookvalue= new AliT0LookUpValue(trm,tdc,chain,channel);

  lookkey = (AliT0LookUpKey*) fLookup.GetValue((TObject*)lookvalue);

  return lookkey->GetKey();

}

<commit_msg>some c++11 fixes<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for T0 calibration                       TM--AM_6-02-2006         //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliT0CalibData.h"
#include "AliT0LookUpValue.h"
#include "AliT0LookUpKey.h"
#include "AliLog.h"

#include <Riostream.h>

//#include <string>

using std::ifstream;
using std::cout;
using std::endl;

ClassImp(AliT0CalibData)

//________________________________________________________________
  AliT0CalibData::AliT0CalibData():   TNamed(),
				      fLookup(0),
				      fNumberOfTRMs(0)

{
  //
}

//________________________________________________________________
AliT0CalibData::AliT0CalibData(const char* name):TNamed(),
				      fLookup(0),
				      fNumberOfTRMs(0)
{
  TString namst = "Calib_";
  namst += name;
  SetName(namst.Data());
  SetTitle(namst.Data());

}

//________________________________________________________________
AliT0CalibData::AliT0CalibData(const AliT0CalibData& calibda) :
  TNamed(calibda),
  fLookup(0),
  fNumberOfTRMs(0)

{
// copy constructor
  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

}

//________________________________________________________________
AliT0CalibData &AliT0CalibData::operator =(const AliT0CalibData& calibda)
{
// assignment operator
  SetName(calibda.GetName());
  SetTitle(calibda.GetName());

  return *this;
}

//________________________________________________________________
AliT0CalibData::~AliT0CalibData()
{
  //
}
//________________________________________________________________
void  AliT0CalibData::PrintLookup(Option_t*, Int_t iTRM, Int_t iTDC, Int_t iChannel) const
{
  // print lookup table

  AliT0LookUpKey* lookkey; //= new AliT0LookUpKey();
  AliT0LookUpValue*  lookvalue= new AliT0LookUpValue();
  printf("Number Of TRMs in setup %i\n",GetNumberOfTRMs());

  iTRM=0; iTDC=0; Int_t chain=0; iChannel=0;

  for (Int_t ik=0; ik<105; ik++){
    lookvalue->SetTRM(iTRM);
    lookvalue->SetTDC(iTDC);
    lookvalue->SetChain(chain);
    lookvalue->SetChannel(iChannel);

    if (iChannel<6) iChannel +=2;
    else {iChannel = 0; iTDC++;}
    if(ik==57) { iTDC=0; iChannel=0; iTRM=1;}

  printf(" AliT0CalibData::PrintLookup ::start GetValue %i %i %i %i\n",iTRM, iTDC,chain, iChannel);
    lookkey = (AliT0LookUpKey*) fLookup.GetValue((TObject*)lookvalue);
    //    TString name= lookkey->GetChannelName();
    // cout<<name.Data()<<endl;
    if (lookkey)
      {
	TString name= lookkey->GetChannelName();
	/*	cout<<" lookup KEY!!! "<<name.Data()<<" "<<lookkey->GetKey()<<" VALUE "<<lookvalue->GetTRM()<<" "
	    <<lookvalue->GetTDC()<<" "
	    << lookvalue->GetChain()<<" "
	    <<lookvalue->GetChannel()<<endl;*/
      }
  }

}
//________________________________________________________________

void AliT0CalibData::ReadAsciiLookup(const Char_t *filename)
{
  // read lookup table from ascii file

  Int_t key, trm, tdc, chain, channel;

  if(filename == 0){
    AliError(Form("Please, specify file with database")) ;
    return ;
  }
  cout<<" read file "<<filename<<endl;

  ifstream lookup;
  lookup.open(filename);
  if(!lookup)
    {
     AliError(Form("!!!!!!!!!!!!!!No look up table in CDB!" ));

    }
  Char_t varname[11];
  Int_t ntrms;
  if(lookup)
    {
      lookup>>ntrms;
      //      fNumberOfTRMs=ntrms;
      SetNumberOfTRMs(ntrms);
      cout<<" N TRMS "<<ntrms<<endl;
       while(!lookup.eof())
	{
	  AliT0LookUpKey * lookkey= new AliT0LookUpKey();
	  AliT0LookUpValue * lookvalue= new AliT0LookUpValue();

	  lookup>>varname>>key>>trm>>chain>>tdc>>channel;
	  lookvalue->SetTRM(trm);
	  lookvalue->SetTDC(tdc);
	  lookvalue->SetChain(chain);
	  lookvalue->SetChannel(channel);
	  lookkey->SetKey(key);
	  lookkey->SetChannelName(varname);
	  cout<<trm<<" "<<chain<<" "<<tdc<<" "<<channel<<" "<<key<<" "<<varname<<endl;
	  fLookup.Add((TObject*)lookvalue,(TObject*)lookkey);

	}

      lookup.close();

    }
}
//________________________________________________________________

Int_t AliT0CalibData::GetChannel(Int_t trm,  Int_t tdc, Int_t chain, Int_t channel)
{
  // read number of channel according physical addres

  AliT0LookUpKey * lookkey;//= new AliT0LookUpKey();
  AliT0LookUpValue * lookvalue= new AliT0LookUpValue(trm,tdc,chain,channel);

  lookkey = (AliT0LookUpKey*) fLookup.GetValue((TObject*)lookvalue);

  return lookkey->GetKey();

}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rtl_old_teststrbuf.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 15:58:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// LLA:
// this file is converted to use with testshl2
// original was placed in sal/test/textenc.cxx

// -----------------------------------------------------------------------------

#include <string.h>
#include <stdio.h>

// #ifndef _OSL_DIAGNOSE_H_
// #include <osl/diagnose.h>
// #endif

#ifndef _RTL_STRBUF_HXX
#include <rtl/strbuf.hxx>
#endif

#ifndef _RTL_WSTRBUF_HXX
#include <rtl/ustrbuf.hxx>
#endif

#include <cppunit/simpleheader.hxx>

using namespace rtl;

#define TEST_ENSURE(c, m) CPPUNIT_ASSERT_MESSAGE((m), (c))

// #if OSL_DEBUG_LEVEL > 0
// #define TEST_ENSHURE(c, m)   OSL_ENSURE(c, m)
// #else
// #define TEST_ENSHURE(c, m)   OSL_VERIFY(c)
// #endif

// -----------------------------------------------------------------------------
namespace rtl_OStringBuffer
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OStringBuffer();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OStringBuffer );
        CPPUNIT_TEST_SUITE_END( );
    };

void oldtests::test_OStringBuffer()
{
    //         "Mein erster RTL OString\n"
    //          |    |    |    |    |
    //  Index   0    5    10   15   20
    OString s1("Mein erster RTL OString\n");

    OStringBuffer b1(s1);

    TEST_ENSURE( b1.getCapacity() == 16 + s1.getLength(), "test_OStringBuffer error 1");

    b1.insert(b1.getLength() - 1, "Buffer");
    s1 = "Mein erster RTL OStringBuffer\n";
    TEST_ENSURE( s1 == b1.getStr(), "test_OStringBuffer error 2");

    b1.insert(b1.getLength() - 1, " ist viel zu gross fuer den alten Buffer");
    TEST_ENSURE( b1.getCapacity() == b1.getLength(), "test_OStringBuffer error 3");

    OStringBuffer b2(30);

    s1 = "false";
    sal_Bool b = sal_False;
    b2.append(b);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 4");

    sal_Int32 n = 123456789L;
    s1 += " 123456789";
    b2.append(" ");
    b2.append(n);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 5");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s1 += " -3223372036854775807";
    b2.append(" ");
    b2.append(m);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 6");
#endif

    OString s2(b2.makeStringAndClear());
    TEST_ENSURE( s1 == s2, "test_OStringBuffer error 7");

    b2.ensureCapacity(50);
    TEST_ENSURE( b2.getCapacity() == 50, "test_OStringBuffer error 8");

    b2.append("Hier fuege ich jetzt ein > <\n");
    b2.insert(26, " Hallo");
    s2 = "Hier fuege ich jetzt ein > Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 9");

    b2.insert(26, b);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 10");

    b2.insert(26, n);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > 123456789 false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 11");

#ifndef SAL_OS2
    b2.insert(26, m);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > -3223372036854775807 123456789 false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 12");
#endif

    printf("test_OStringBuffer OK !!!\n");
    return;
}
} // namespace rtl_OStringBuffer

// -----------------------------------------------------------------------------

namespace rtl_OUStringBuffer
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OUStringBuffer();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OUStringBuffer );
        CPPUNIT_TEST_SUITE_END( );
    };

void oldtests::test_OUStringBuffer()
{
    //          "Mein erster RTL OUString\n"
    //           |    |    |    |    |
    //  Index    0    5    10   15   20
    OUString s1(OUString::createFromAscii("Mein erster RTL OUString\n"));

    OUStringBuffer b1(s1);

    TEST_ENSURE( b1.getCapacity() == 16 + s1.getLength(), "test_OWStringBuffer error 1");

    b1.insert(b1.getLength() - 1, OUString::createFromAscii("Buffer"));
    s1 = OUString::createFromAscii("Mein erster RTL OUStringBuffer\n");
    TEST_ENSURE( s1 == b1.getStr(), "test_OWStringBuffer error 2");

    b1.insert(b1.getLength() - 1, OUString::createFromAscii(" ist viel zu gross fuer den alten Buffer"));
    //TEST_ENSURE( b1.getCapacity() == b1.getLength(), "test_OWStringBuffer error 3");

    OUStringBuffer b2(30);

    s1 = OUString::createFromAscii("false");
    sal_Bool b = sal_False;
    b2.append(b);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 4");

    sal_Int32 n = 123456789L;
    s1 += OUString::createFromAscii(" 123456789");
    b2.append(OUString::createFromAscii(" "));
    b2.append(n);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 5");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s1 += OUString::createFromAscii(" -3223372036854775807");
    b2.append(OUString::createFromAscii(" "));
    b2.append(m);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 6");
#endif

    OUString s2(b2.makeStringAndClear());
    TEST_ENSURE( s1 == s2, "test_OWStringBuffer error 7");

    b2.ensureCapacity(50);
    TEST_ENSURE( b2.getCapacity() == 50, "test_OWStringBuffer error 8");

    b2.append(OUString::createFromAscii("Hier fuege ich jetzt ein > <\n"));
    b2.insert(26, OUString::createFromAscii(" Hallo"));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 9");

    b2.insert(26, b);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 10");

    b2.insert(26, n);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > 123456789 false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 11");

#ifndef SAL_OS2
    b2.insert(26, m);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > -3223372036854775807 123456789 false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 12");
#endif

    // ASCII-Schnittstelle, AB 15.10.1999
    OUString s3(OUString::createFromAscii("Noch'n RTL OUString"));
    OUStringBuffer b3(s3);
    sal_Char aAsciiStr[] = " mit appendetem ASCII\n";
    b3.appendAscii( aAsciiStr );
    s3 = OUString::createFromAscii("Noch'n RTL OUString mit appendetem ASCII\n");
    TEST_ENSURE( b3.getStr() == s3 , "test_OWStringBuffer error 13");

    printf("test_OWStringBuffer OK !!!\n");
    return;
}

} // namespace rtl_OUStringBuffer

// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OUStringBuffer::oldtests, "rtl_OUStringBuffer" );
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OStringBuffer::oldtests, "rtl_OStringBuffer" );

// -----------------------------------------------------------------------------
NOADDITIONAL;
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.140); FILE MERGED 2006/09/01 17:34:16 kaib 1.4.140.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rtl_old_teststrbuf.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 09:03:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"

// LLA:
// this file is converted to use with testshl2
// original was placed in sal/test/textenc.cxx

// -----------------------------------------------------------------------------

#include <string.h>
#include <stdio.h>

// #ifndef _OSL_DIAGNOSE_H_
// #include <osl/diagnose.h>
// #endif

#ifndef _RTL_STRBUF_HXX
#include <rtl/strbuf.hxx>
#endif

#ifndef _RTL_WSTRBUF_HXX
#include <rtl/ustrbuf.hxx>
#endif

#include <cppunit/simpleheader.hxx>

using namespace rtl;

#define TEST_ENSURE(c, m) CPPUNIT_ASSERT_MESSAGE((m), (c))

// #if OSL_DEBUG_LEVEL > 0
// #define TEST_ENSHURE(c, m)   OSL_ENSURE(c, m)
// #else
// #define TEST_ENSHURE(c, m)   OSL_VERIFY(c)
// #endif

// -----------------------------------------------------------------------------
namespace rtl_OStringBuffer
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OStringBuffer();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OStringBuffer );
        CPPUNIT_TEST_SUITE_END( );
    };

void oldtests::test_OStringBuffer()
{
    //         "Mein erster RTL OString\n"
    //          |    |    |    |    |
    //  Index   0    5    10   15   20
    OString s1("Mein erster RTL OString\n");

    OStringBuffer b1(s1);

    TEST_ENSURE( b1.getCapacity() == 16 + s1.getLength(), "test_OStringBuffer error 1");

    b1.insert(b1.getLength() - 1, "Buffer");
    s1 = "Mein erster RTL OStringBuffer\n";
    TEST_ENSURE( s1 == b1.getStr(), "test_OStringBuffer error 2");

    b1.insert(b1.getLength() - 1, " ist viel zu gross fuer den alten Buffer");
    TEST_ENSURE( b1.getCapacity() == b1.getLength(), "test_OStringBuffer error 3");

    OStringBuffer b2(30);

    s1 = "false";
    sal_Bool b = sal_False;
    b2.append(b);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 4");

    sal_Int32 n = 123456789L;
    s1 += " 123456789";
    b2.append(" ");
    b2.append(n);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 5");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s1 += " -3223372036854775807";
    b2.append(" ");
    b2.append(m);
    TEST_ENSURE( s1 == b2.getStr(), "test_OStringBuffer error 6");
#endif

    OString s2(b2.makeStringAndClear());
    TEST_ENSURE( s1 == s2, "test_OStringBuffer error 7");

    b2.ensureCapacity(50);
    TEST_ENSURE( b2.getCapacity() == 50, "test_OStringBuffer error 8");

    b2.append("Hier fuege ich jetzt ein > <\n");
    b2.insert(26, " Hallo");
    s2 = "Hier fuege ich jetzt ein > Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 9");

    b2.insert(26, b);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 10");

    b2.insert(26, n);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > 123456789 false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 11");

#ifndef SAL_OS2
    b2.insert(26, m);
    b2.insert(26, " ");
    s2 = "Hier fuege ich jetzt ein > -3223372036854775807 123456789 false Hallo <\n";
    TEST_ENSURE( s2 == b2.getStr(), "test_OStringBuffer error 12");
#endif

    printf("test_OStringBuffer OK !!!\n");
    return;
}
} // namespace rtl_OStringBuffer

// -----------------------------------------------------------------------------

namespace rtl_OUStringBuffer
{
    class oldtests : public CppUnit::TestFixture
    {
    public:
        void test_OUStringBuffer();

        CPPUNIT_TEST_SUITE( oldtests );
        CPPUNIT_TEST( test_OUStringBuffer );
        CPPUNIT_TEST_SUITE_END( );
    };

void oldtests::test_OUStringBuffer()
{
    //          "Mein erster RTL OUString\n"
    //           |    |    |    |    |
    //  Index    0    5    10   15   20
    OUString s1(OUString::createFromAscii("Mein erster RTL OUString\n"));

    OUStringBuffer b1(s1);

    TEST_ENSURE( b1.getCapacity() == 16 + s1.getLength(), "test_OWStringBuffer error 1");

    b1.insert(b1.getLength() - 1, OUString::createFromAscii("Buffer"));
    s1 = OUString::createFromAscii("Mein erster RTL OUStringBuffer\n");
    TEST_ENSURE( s1 == b1.getStr(), "test_OWStringBuffer error 2");

    b1.insert(b1.getLength() - 1, OUString::createFromAscii(" ist viel zu gross fuer den alten Buffer"));
    //TEST_ENSURE( b1.getCapacity() == b1.getLength(), "test_OWStringBuffer error 3");

    OUStringBuffer b2(30);

    s1 = OUString::createFromAscii("false");
    sal_Bool b = sal_False;
    b2.append(b);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 4");

    sal_Int32 n = 123456789L;
    s1 += OUString::createFromAscii(" 123456789");
    b2.append(OUString::createFromAscii(" "));
    b2.append(n);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 5");

#ifndef SAL_OS2
#ifdef SAL_UNX
    sal_Int64 m = -3223372036854775807LL;
#elif defined(SAL_OS2)
    sal_Int64 m;
    sal_setInt64(&m, 3965190145L, -750499787L);
#else
    sal_Int64 m = -3223372036854775807;
#endif
    s1 += OUString::createFromAscii(" -3223372036854775807");
    b2.append(OUString::createFromAscii(" "));
    b2.append(m);
    TEST_ENSURE( s1 == b2.getStr(), "test_OWStringBuffer error 6");
#endif

    OUString s2(b2.makeStringAndClear());
    TEST_ENSURE( s1 == s2, "test_OWStringBuffer error 7");

    b2.ensureCapacity(50);
    TEST_ENSURE( b2.getCapacity() == 50, "test_OWStringBuffer error 8");

    b2.append(OUString::createFromAscii("Hier fuege ich jetzt ein > <\n"));
    b2.insert(26, OUString::createFromAscii(" Hallo"));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 9");

    b2.insert(26, b);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 10");

    b2.insert(26, n);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > 123456789 false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 11");

#ifndef SAL_OS2
    b2.insert(26, m);
    b2.insert(26, OUString::createFromAscii(" "));
    s2 = OUString::createFromAscii("Hier fuege ich jetzt ein > -3223372036854775807 123456789 false Hallo <\n");
    TEST_ENSURE( s2 == b2.getStr(), "test_OWStringBuffer error 12");
#endif

    // ASCII-Schnittstelle, AB 15.10.1999
    OUString s3(OUString::createFromAscii("Noch'n RTL OUString"));
    OUStringBuffer b3(s3);
    sal_Char aAsciiStr[] = " mit appendetem ASCII\n";
    b3.appendAscii( aAsciiStr );
    s3 = OUString::createFromAscii("Noch'n RTL OUString mit appendetem ASCII\n");
    TEST_ENSURE( b3.getStr() == s3 , "test_OWStringBuffer error 13");

    printf("test_OWStringBuffer OK !!!\n");
    return;
}

} // namespace rtl_OUStringBuffer

// -----------------------------------------------------------------------------
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OUStringBuffer::oldtests, "rtl_OUStringBuffer" );
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rtl_OStringBuffer::oldtests, "rtl_OStringBuffer" );

// -----------------------------------------------------------------------------
NOADDITIONAL;
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "XDisplay.h"
#include "XWindow.h"
#include "BzfEvent.h"
#include <string.h>
#include <X11/keysym.h>

//
// XDisplay::Rep
//

XDisplay::Rep::Rep(const char* displayName) :
				refCount(1),
				display(NULL),
				screen(0)
{
  // open display
  display = XOpenDisplay(displayName);
  if (!display) return;

  // other initialization
  screen = DefaultScreen(display);
}

XDisplay::Rep::~Rep()
{
  if (display) XCloseDisplay(display);
}

void			XDisplay::Rep::ref()
{
  refCount++;
}

void			XDisplay::Rep::unref()
{
  if (--refCount <= 0) delete this;
}

Window			XDisplay::Rep::getRootWindow() const
{
  return display ? RootWindow(display, screen) : None;
}

//
// XDisplay
//

XDisplay::XDisplay(const char* displayName, XDisplayMode* _mode) :
				rep(NULL),
				mode(_mode)
{
  // open display
  rep = new Rep(displayName);

  // make default mode changer if one wasn't supplied
  if (!mode)
    mode = new XDisplayMode;

  if (rep->getDisplay()) {
    // get resolutions
    int numModes, currentMode;
    ResInfo** resInfo = mode->init(this, numModes, currentMode);

    // if no modes then make default
    if (!resInfo) {
      resInfo = new ResInfo*[1];
      resInfo[0] = new ResInfo("default",
			DisplayWidth(rep->getDisplay(), rep->getScreen()),
			DisplayHeight(rep->getDisplay(), rep->getScreen()), 0);
      numModes = 1;
      currentMode = 0;
    }

    // register modes
    initResolutions(resInfo, numModes, currentMode);
  }
}

XDisplay::~XDisplay()
{
  setDefaultResolution();
  delete mode;
  rep->unref();
}

bool			XDisplay::isValid() const
{
  return rep->getDisplay() != NULL;
}

bool			XDisplay::isEventPending() const
{
  return (XPending(rep->getDisplay()) != 0);
}

bool			XDisplay::peekEvent(BzfEvent& event) const
{
  return false;
}

bool			XDisplay::getEvent(BzfEvent& event) const
{
  XEvent xevent;
  XNextEvent(rep->getDisplay(), &xevent);

  switch (xevent.type) {
    case Expose:
    case ConfigureNotify:
    case MotionNotify:
    case MapNotify:
    case UnmapNotify:
    case ButtonPress:
    case ButtonRelease:
    case KeyPress:
    case KeyRelease:
    case ClientMessage:
      event.window = XWindow::lookupWindow(xevent.xexpose.window);
      if (!event.window) return false;
      break;

    default:
      return false;
  }

  switch (xevent.type) {
    case Expose:
      if (xevent.xexpose.count != 0) return false;
      event.type = BzfEvent::Redraw;
      break;

    case ConfigureNotify: {
/* attempt to filter out non-size changes, but getSize() returns the
 * current size so it always matches the size in the event.
      int width, height;
      event.window->getSize(width, height);
      if (width == xevent.xconfigure.width &&
	  height == xevent.xconfigure.height)
	return false;
*/
      event.type = BzfEvent::Resize;
      event.resize.width = xevent.xconfigure.width;
      event.resize.height = xevent.xconfigure.height;
      break;
    }

    case MotionNotify:
      event.type = BzfEvent::MouseMove;
      event.mouseMove.x = xevent.xmotion.x;
      event.mouseMove.y = xevent.xmotion.y;
      break;

    case MapNotify:
      event.type = BzfEvent::Map;
      break;

    case UnmapNotify:
      event.type = BzfEvent::Unmap;
      break;

    case ButtonPress:
      event.type = BzfEvent::KeyDown;
      event.keyDown.ascii = 0;
      event.keyDown.shift = 0;
      switch (xevent.xbutton.button) {
	case Button1: event.keyDown.button = BzfKeyEvent::LeftMouse; break;
	case Button2: event.keyDown.button = BzfKeyEvent::MiddleMouse; break;
	case Button3: event.keyDown.button = BzfKeyEvent::RightMouse; break;
	default:      return false;
      }
      break;

    case ButtonRelease:
      event.type = BzfEvent::KeyUp;
      event.keyUp.ascii = 0;
      event.keyUp.shift = 0;
      switch (xevent.xbutton.button) {
	case Button1: event.keyUp.button = BzfKeyEvent::LeftMouse; break;
	case Button2: event.keyUp.button = BzfKeyEvent::MiddleMouse; break;
	case Button3: event.keyUp.button = BzfKeyEvent::RightMouse; break;
	default:      return false;
      }
      break;

    case KeyPress:
      event.type = BzfEvent::KeyDown;
      if (!getKey(xevent, event.keyDown)) return false;
      break;

    case KeyRelease:
      event.type = BzfEvent::KeyUp;
      if (!getKey(xevent, event.keyUp)) return false;
      break;

    case ClientMessage: {
      XClientMessageEvent* cme = (XClientMessageEvent*)&xevent;
      if (cme->format == 32) {
	if ((Atom)cme->data.l[0] == XInternAtom(rep->getDisplay(),
					"WM_DELETE_WINDOW", true)) {
	  event.type = BzfEvent::Quit;
	  break;
	}
      }
      return false;
    }
  }

  return true;
}

bool			XDisplay::getKey(const XEvent& xevent,
						BzfKeyEvent& key) const
{
  char buf[3];
  KeySym keysym;
  if (XLookupString((XKeyEvent*)&xevent.xkey, buf, 1, &keysym, NULL) == 1) {
    key.ascii = buf[0];
    key.button = BzfKeyEvent::NoButton;

    if (keysym == XK_Delete) {
      key.ascii = 0;
      key.button = BzfKeyEvent::Delete;
    }
  }
  else {
    key.ascii = 0;
    switch (keysym) {
      case XK_Pause:	key.button = BzfKeyEvent::Pause; break;
      case XK_Home:	key.button = BzfKeyEvent::Home; break;
      case XK_End:	key.button = BzfKeyEvent::End; break;
      case XK_Left:	key.button = BzfKeyEvent::Left; break;
      case XK_Right:	key.button = BzfKeyEvent::Right; break;
      case XK_Up:	key.button = BzfKeyEvent::Up; break;
      case XK_Down:	key.button = BzfKeyEvent::Down; break;
      case XK_Page_Up:	key.button = BzfKeyEvent::PageUp; break;
      case XK_Page_Down: key.button = BzfKeyEvent::PageDown; break;
      case XK_Insert:	key.button = BzfKeyEvent::Insert; break;
      case XK_Delete:	key.button = BzfKeyEvent::Delete; break;
      case XK_F1:	key.button = BzfKeyEvent::F1; break;
      case XK_F2:	key.button = BzfKeyEvent::F2; break;
      case XK_F3:	key.button = BzfKeyEvent::F3; break;
      case XK_F4:	key.button = BzfKeyEvent::F4; break;
      case XK_F5:	key.button = BzfKeyEvent::F5; break;
      case XK_F6:	key.button = BzfKeyEvent::F6; break;
      case XK_F7:	key.button = BzfKeyEvent::F7; break;
      case XK_F8:	key.button = BzfKeyEvent::F8; break;
      case XK_F9:	key.button = BzfKeyEvent::F9; break;
      case XK_F10:	key.button = BzfKeyEvent::F10; break;
      case XK_F11:	key.button = BzfKeyEvent::F11; break;
      case XK_F12:	key.button = BzfKeyEvent::F12; break;
      default:		return false;
    }
  }

  key.shift = 0;
  if (xevent.xkey.state & ShiftMask) key.shift |= BzfKeyEvent::ShiftKey;
  if (xevent.xkey.state & ControlMask) key.shift |= BzfKeyEvent::ControlKey;
  if (xevent.xkey.state & Mod1Mask) key.shift |= BzfKeyEvent::AltKey;
  return true;
}

bool			XDisplay::doSetResolution(int modeIndex)
{
  return mode->set(modeIndex);
}

bool			XDisplay::doSetDefaultResolution()
{
  return mode->setDefault(getDefaultResolution());
}

//
// XDisplayMode
//

XDisplayMode::XDisplayMode()
{
  // do nothing
}

XDisplayMode::~XDisplayMode()
{
  // do nothing
}

XDisplayMode::ResInfo**	XDisplayMode::init(XDisplay*, int&, int&)
{
  // no switching
  return NULL;
}

bool			XDisplayMode::set(int)
{
  // no switching
  return false;
}

bool			XDisplayMode::setDefault(int mode)
{
  return set(mode);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<commit_msg>warning<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "XDisplay.h"
#include "XWindow.h"
#include "BzfEvent.h"
#include <string.h>
#include <X11/keysym.h>

//
// XDisplay::Rep
//

XDisplay::Rep::Rep(const char* displayName) :
				refCount(1),
				display(NULL),
				screen(0)
{
  // open display
  display = XOpenDisplay(displayName);
  if (!display) return;

  // other initialization
  screen = DefaultScreen(display);
}

XDisplay::Rep::~Rep()
{
  if (display) XCloseDisplay(display);
}

void			XDisplay::Rep::ref()
{
  refCount++;
}

void			XDisplay::Rep::unref()
{
  if (--refCount <= 0) delete this;
}

Window			XDisplay::Rep::getRootWindow() const
{
  return display ? RootWindow(display, screen) : None;
}

//
// XDisplay
//

XDisplay::XDisplay(const char* displayName, XDisplayMode* _mode) :
				rep(NULL),
				mode(_mode)
{
  // open display
  rep = new Rep(displayName);

  // make default mode changer if one wasn't supplied
  if (!mode)
    mode = new XDisplayMode;

  if (rep->getDisplay()) {
    // get resolutions
    int numModes, currentMode;
    ResInfo** resInfo = mode->init(this, numModes, currentMode);

    // if no modes then make default
    if (!resInfo) {
      resInfo = new ResInfo*[1];
      resInfo[0] = new ResInfo("default",
			DisplayWidth(rep->getDisplay(), rep->getScreen()),
			DisplayHeight(rep->getDisplay(), rep->getScreen()), 0);
      numModes = 1;
      currentMode = 0;
    }

    // register modes
    initResolutions(resInfo, numModes, currentMode);
  }
}

XDisplay::~XDisplay()
{
  setDefaultResolution();
  delete mode;
  rep->unref();
}

bool			XDisplay::isValid() const
{
  return rep->getDisplay() != NULL;
}

bool			XDisplay::isEventPending() const
{
  return (XPending(rep->getDisplay()) != 0);
}

bool			XDisplay::peekEvent(BzfEvent& /* event */) const
{
  return false;
}

bool			XDisplay::getEvent(BzfEvent& event) const
{
  XEvent xevent;
  XNextEvent(rep->getDisplay(), &xevent);

  switch (xevent.type) {
    case Expose:
    case ConfigureNotify:
    case MotionNotify:
    case MapNotify:
    case UnmapNotify:
    case ButtonPress:
    case ButtonRelease:
    case KeyPress:
    case KeyRelease:
    case ClientMessage:
      event.window = XWindow::lookupWindow(xevent.xexpose.window);
      if (!event.window) return false;
      break;

    default:
      return false;
  }

  switch (xevent.type) {
    case Expose:
      if (xevent.xexpose.count != 0) return false;
      event.type = BzfEvent::Redraw;
      break;

    case ConfigureNotify: {
/* attempt to filter out non-size changes, but getSize() returns the
 * current size so it always matches the size in the event.
      int width, height;
      event.window->getSize(width, height);
      if (width == xevent.xconfigure.width &&
	  height == xevent.xconfigure.height)
	return false;
*/
      event.type = BzfEvent::Resize;
      event.resize.width = xevent.xconfigure.width;
      event.resize.height = xevent.xconfigure.height;
      break;
    }

    case MotionNotify:
      event.type = BzfEvent::MouseMove;
      event.mouseMove.x = xevent.xmotion.x;
      event.mouseMove.y = xevent.xmotion.y;
      break;

    case MapNotify:
      event.type = BzfEvent::Map;
      break;

    case UnmapNotify:
      event.type = BzfEvent::Unmap;
      break;

    case ButtonPress:
      event.type = BzfEvent::KeyDown;
      event.keyDown.ascii = 0;
      event.keyDown.shift = 0;
      switch (xevent.xbutton.button) {
	case Button1: event.keyDown.button = BzfKeyEvent::LeftMouse; break;
	case Button2: event.keyDown.button = BzfKeyEvent::MiddleMouse; break;
	case Button3: event.keyDown.button = BzfKeyEvent::RightMouse; break;
	default:      return false;
      }
      break;

    case ButtonRelease:
      event.type = BzfEvent::KeyUp;
      event.keyUp.ascii = 0;
      event.keyUp.shift = 0;
      switch (xevent.xbutton.button) {
	case Button1: event.keyUp.button = BzfKeyEvent::LeftMouse; break;
	case Button2: event.keyUp.button = BzfKeyEvent::MiddleMouse; break;
	case Button3: event.keyUp.button = BzfKeyEvent::RightMouse; break;
	default:      return false;
      }
      break;

    case KeyPress:
      event.type = BzfEvent::KeyDown;
      if (!getKey(xevent, event.keyDown)) return false;
      break;

    case KeyRelease:
      event.type = BzfEvent::KeyUp;
      if (!getKey(xevent, event.keyUp)) return false;
      break;

    case ClientMessage: {
      XClientMessageEvent* cme = (XClientMessageEvent*)&xevent;
      if (cme->format == 32) {
	if ((Atom)cme->data.l[0] == XInternAtom(rep->getDisplay(),
					"WM_DELETE_WINDOW", true)) {
	  event.type = BzfEvent::Quit;
	  break;
	}
      }
      return false;
    }
  }

  return true;
}

bool			XDisplay::getKey(const XEvent& xevent,
						BzfKeyEvent& key) const
{
  char buf[3];
  KeySym keysym;
  if (XLookupString((XKeyEvent*)&xevent.xkey, buf, 1, &keysym, NULL) == 1) {
    key.ascii = buf[0];
    key.button = BzfKeyEvent::NoButton;

    if (keysym == XK_Delete) {
      key.ascii = 0;
      key.button = BzfKeyEvent::Delete;
    }
  }
  else {
    key.ascii = 0;
    switch (keysym) {
      case XK_Pause:	key.button = BzfKeyEvent::Pause; break;
      case XK_Home:	key.button = BzfKeyEvent::Home; break;
      case XK_End:	key.button = BzfKeyEvent::End; break;
      case XK_Left:	key.button = BzfKeyEvent::Left; break;
      case XK_Right:	key.button = BzfKeyEvent::Right; break;
      case XK_Up:	key.button = BzfKeyEvent::Up; break;
      case XK_Down:	key.button = BzfKeyEvent::Down; break;
      case XK_Page_Up:	key.button = BzfKeyEvent::PageUp; break;
      case XK_Page_Down: key.button = BzfKeyEvent::PageDown; break;
      case XK_Insert:	key.button = BzfKeyEvent::Insert; break;
      case XK_Delete:	key.button = BzfKeyEvent::Delete; break;
      case XK_F1:	key.button = BzfKeyEvent::F1; break;
      case XK_F2:	key.button = BzfKeyEvent::F2; break;
      case XK_F3:	key.button = BzfKeyEvent::F3; break;
      case XK_F4:	key.button = BzfKeyEvent::F4; break;
      case XK_F5:	key.button = BzfKeyEvent::F5; break;
      case XK_F6:	key.button = BzfKeyEvent::F6; break;
      case XK_F7:	key.button = BzfKeyEvent::F7; break;
      case XK_F8:	key.button = BzfKeyEvent::F8; break;
      case XK_F9:	key.button = BzfKeyEvent::F9; break;
      case XK_F10:	key.button = BzfKeyEvent::F10; break;
      case XK_F11:	key.button = BzfKeyEvent::F11; break;
      case XK_F12:	key.button = BzfKeyEvent::F12; break;
      default:		return false;
    }
  }

  key.shift = 0;
  if (xevent.xkey.state & ShiftMask) key.shift |= BzfKeyEvent::ShiftKey;
  if (xevent.xkey.state & ControlMask) key.shift |= BzfKeyEvent::ControlKey;
  if (xevent.xkey.state & Mod1Mask) key.shift |= BzfKeyEvent::AltKey;
  return true;
}

bool			XDisplay::doSetResolution(int modeIndex)
{
  return mode->set(modeIndex);
}

bool			XDisplay::doSetDefaultResolution()
{
  return mode->setDefault(getDefaultResolution());
}

//
// XDisplayMode
//

XDisplayMode::XDisplayMode()
{
  // do nothing
}

XDisplayMode::~XDisplayMode()
{
  // do nothing
}

XDisplayMode::ResInfo**	XDisplayMode::init(XDisplay*, int&, int&)
{
  // no switching
  return NULL;
}

bool			XDisplayMode::set(int)
{
  // no switching
  return false;
}

bool			XDisplayMode::setDefault(int mode)
{
  return set(mode);
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8

<|endoftext|>


<commit_before>//===- JITEmitter.cpp - Unit tests for the JIT code emitter ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Function.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Type.h"

using namespace llvm;

namespace {

Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
  std::vector<const Type*> params;
  const FunctionType *FTy = FunctionType::get(Type::VoidTy, params, false);
  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
  BasicBlock *Entry = BasicBlock::Create("entry", F);
  IRBuilder<> builder(Entry);
  Value *Load = builder.CreateLoad(G);
  const Type *GTy = G->getType()->getElementType();
  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
  builder.CreateStore(Add, G);
  builder.CreateRet(Add);
  return F;
}

// Regression test for a bug.  The JIT used to allocate globals inside the same
// memory block used for the function, and when the function code was freed,
// the global was left in the same place.  This test allocates a function
// that uses and global, deallocates it, and then makes sure that the global
// stays alive after that.
TEST(JIT, GlobalInFunction) {
  LLVMContext context;
  Module *M = new Module("<main>", context);
  ExistingModuleProvider *MP = new ExistingModuleProvider(M);

  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
  // Tell the memory manager to poison freed memory so that accessing freed
  // memory is more easily tested.
  MemMgr->setPoisonMemory(true);
  std::string Error;
  OwningPtr<ExecutionEngine> JIT(ExecutionEngine::createJIT(
      MP,
      &Error,
      MemMgr,
      CodeGenOpt::Default,
      false));  // This last argument enables the fix.
  ASSERT_EQ(Error, "");

  // Create a global variable.
  const Type *GTy = Type::Int32Ty;
  GlobalVariable *G = new GlobalVariable(
      *M,
      GTy,
      false,  // Not constant.
      GlobalValue::InternalLinkage,
      Constant::getNullValue(GTy),
      "myglobal");

  // Make a function that points to a global.
  Function *F1 = makeReturnGlobal("F1", G, M);

  // Get the pointer to the native code to force it to JIT the function and
  // allocate space for the global.
  void (*F1Ptr)();
  // Hack to avoid ISO C++ warning about casting function pointers.
  *(void**)(void*)&F1Ptr = JIT->getPointerToFunction(F1);

  // Since F1 was codegen'd, a pointer to G should be available.
  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
  ASSERT_NE((int32_t*)NULL, GPtr);
  EXPECT_EQ(0, *GPtr);

  // F1() should increment G.
  F1Ptr();
  EXPECT_EQ(1, *GPtr);

  // Make a second function identical to the first, referring to the same
  // global.
  Function *F2 = makeReturnGlobal("F2", G, M);
  // Hack to avoid ISO C++ warning about casting function pointers.
  void (*F2Ptr)();
  *(void**)(void*)&F2Ptr = JIT->getPointerToFunction(F2);

  // F2() should increment G.
  F2Ptr();
  EXPECT_EQ(2, *GPtr);

  // Deallocate F1.
  JIT->freeMachineCodeForFunction(F1);

  // F2() should *still* increment G.
  F2Ptr();
  EXPECT_EQ(3, *GPtr);
}

// TODO(rnk): This seems to only run once for both tests, which is unexpected.
// That works just fine, but we shouldn't duplicate the code.
class JITEnvironment : public testing::Environment {
  virtual void SetUp() {
    // Required for ExecutionEngine::createJIT to create a JIT.
    InitializeNativeTarget();
  }
};
testing::Environment* const jit_env =
  testing::AddGlobalTestEnvironment(new JITEnvironment);

}
<commit_msg>Don't use a void return type with a function that returns a value.<commit_after>//===- JITEmitter.cpp - Unit tests for the JIT code emitter ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Function.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Type.h"

using namespace llvm;

namespace {

Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
  std::vector<const Type*> params;
  const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
                                              params, false);
  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
  BasicBlock *Entry = BasicBlock::Create("entry", F);
  IRBuilder<> builder(Entry);
  Value *Load = builder.CreateLoad(G);
  const Type *GTy = G->getType()->getElementType();
  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
  builder.CreateStore(Add, G);
  builder.CreateRet(Add);
  return F;
}

// Regression test for a bug.  The JIT used to allocate globals inside the same
// memory block used for the function, and when the function code was freed,
// the global was left in the same place.  This test allocates a function
// that uses and global, deallocates it, and then makes sure that the global
// stays alive after that.
TEST(JIT, GlobalInFunction) {
  LLVMContext context;
  Module *M = new Module("<main>", context);
  ExistingModuleProvider *MP = new ExistingModuleProvider(M);

  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
  // Tell the memory manager to poison freed memory so that accessing freed
  // memory is more easily tested.
  MemMgr->setPoisonMemory(true);
  std::string Error;
  OwningPtr<ExecutionEngine> JIT(ExecutionEngine::createJIT(
      MP,
      &Error,
      MemMgr,
      CodeGenOpt::Default,
      false));  // This last argument enables the fix.
  ASSERT_EQ(Error, "");

  // Create a global variable.
  const Type *GTy = Type::Int32Ty;
  GlobalVariable *G = new GlobalVariable(
      *M,
      GTy,
      false,  // Not constant.
      GlobalValue::InternalLinkage,
      Constant::getNullValue(GTy),
      "myglobal");

  // Make a function that points to a global.
  Function *F1 = makeReturnGlobal("F1", G, M);

  // Get the pointer to the native code to force it to JIT the function and
  // allocate space for the global.
  void (*F1Ptr)();
  // Hack to avoid ISO C++ warning about casting function pointers.
  *(void**)(void*)&F1Ptr = JIT->getPointerToFunction(F1);

  // Since F1 was codegen'd, a pointer to G should be available.
  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
  ASSERT_NE((int32_t*)NULL, GPtr);
  EXPECT_EQ(0, *GPtr);

  // F1() should increment G.
  F1Ptr();
  EXPECT_EQ(1, *GPtr);

  // Make a second function identical to the first, referring to the same
  // global.
  Function *F2 = makeReturnGlobal("F2", G, M);
  // Hack to avoid ISO C++ warning about casting function pointers.
  void (*F2Ptr)();
  *(void**)(void*)&F2Ptr = JIT->getPointerToFunction(F2);

  // F2() should increment G.
  F2Ptr();
  EXPECT_EQ(2, *GPtr);

  // Deallocate F1.
  JIT->freeMachineCodeForFunction(F1);

  // F2() should *still* increment G.
  F2Ptr();
  EXPECT_EQ(3, *GPtr);
}

// TODO(rnk): This seems to only run once for both tests, which is unexpected.
// That works just fine, but we shouldn't duplicate the code.
class JITEnvironment : public testing::Environment {
  virtual void SetUp() {
    // Required for ExecutionEngine::createJIT to create a JIT.
    InitializeNativeTarget();
  }
};
testing::Environment* const jit_env =
  testing::AddGlobalTestEnvironment(new JITEnvironment);

}
<|endoftext|>


<commit_before>//===---- QueryParserTest.cpp - clang-query test --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "QueryParser.h"
#include "Query.h"
#include "QuerySession.h"
#include "llvm/LineEditor/LineEditor.h"
#include "gtest/gtest.h"

using namespace clang;
using namespace clang::query;

class QueryParserTest : public ::testing::Test {
protected:
  QueryParserTest() : QS(llvm::ArrayRef<std::unique_ptr<ASTUnit>>()) {}
  QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); }

  QuerySession QS;
};

TEST_F(QueryParserTest, NoOp) {
  QueryRef Q = parse("");
  EXPECT_TRUE(isa<NoOpQuery>(Q));

  Q = parse("\n");
  EXPECT_TRUE(isa<NoOpQuery>(Q));
}

TEST_F(QueryParserTest, Invalid) {
  QueryRef Q = parse("foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Help) {
  QueryRef Q = parse("help");
  ASSERT_TRUE(isa<HelpQuery>(Q));

  Q = parse("help me");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Set) {
  QueryRef Q = parse("set");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set foo bar");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'diag', 'print' or 'dump', got ''",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set bind-root true foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'diag', 'print' or 'dump', got 'foo'",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output dump");
  ASSERT_TRUE(isa<SetQuery<OutputKind> >(Q));
  EXPECT_EQ(&QuerySession::OutKind, cast<SetQuery<OutputKind> >(Q)->Var);
  EXPECT_EQ(OK_Dump, cast<SetQuery<OutputKind> >(Q)->Value);

  Q = parse("set bind-root foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'true' or 'false', got 'foo'",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set bind-root true");
  ASSERT_TRUE(isa<SetQuery<bool> >(Q));
  EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var);
  EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value);
}

TEST_F(QueryParserTest, Match) {
  QueryRef Q = parse("match decl()");
  ASSERT_TRUE(isa<MatchQuery>(Q));
  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>());

  Q = parse("m stmt()");
  ASSERT_TRUE(isa<MatchQuery>(Q));
  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>());
}

TEST_F(QueryParserTest, LetUnlet) {
  QueryRef Q = parse("let foo decl()");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("foo", cast<LetQuery>(Q)->Name);
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher());
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>());

  Q = parse("let bar \"str\"");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("bar", cast<LetQuery>(Q)->Name);
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString());
  EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString());

  Q = parse("let");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("unlet x");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("x", cast<LetQuery>(Q)->Name);
  EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue());

  Q = parse("unlet");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("unlet x bad_data");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' bad_data'",
            cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Complete) {
  std::vector<llvm::LineEditor::Completion> Comps =
      QueryParser::complete("", 0, QS);
  ASSERT_EQ(5u, Comps.size());
  EXPECT_EQ("help ", Comps[0].TypedText);
  EXPECT_EQ("help", Comps[0].DisplayText);
  EXPECT_EQ("let ", Comps[1].TypedText);
  EXPECT_EQ("let", Comps[1].DisplayText);
  EXPECT_EQ("match ", Comps[2].TypedText);
  EXPECT_EQ("match", Comps[2].DisplayText);
  EXPECT_EQ("set ", Comps[3].TypedText);
  EXPECT_EQ("set", Comps[3].DisplayText);
  EXPECT_EQ("unlet ", Comps[4].TypedText);
  EXPECT_EQ("unlet", Comps[4].DisplayText);

  Comps = QueryParser::complete("set o", 5, QS);
  ASSERT_EQ(1u, Comps.size());
  EXPECT_EQ("utput ", Comps[0].TypedText);
  EXPECT_EQ("output", Comps[0].DisplayText);

  Comps = QueryParser::complete("match while", 11, QS);
  ASSERT_EQ(1u, Comps.size());
  EXPECT_EQ("Stmt(", Comps[0].TypedText);
  EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)",
            Comps[0].DisplayText);
}
<commit_msg>Correcting and adding tests for r244206.<commit_after>//===---- QueryParserTest.cpp - clang-query test --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "QueryParser.h"
#include "Query.h"
#include "QuerySession.h"
#include "llvm/LineEditor/LineEditor.h"
#include "gtest/gtest.h"

using namespace clang;
using namespace clang::query;

class QueryParserTest : public ::testing::Test {
protected:
  QueryParserTest() : QS(llvm::ArrayRef<std::unique_ptr<ASTUnit>>()) {}
  QueryRef parse(StringRef Code) { return QueryParser::parse(Code, QS); }

  QuerySession QS;
};

TEST_F(QueryParserTest, NoOp) {
  QueryRef Q = parse("");
  EXPECT_TRUE(isa<NoOpQuery>(Q));

  Q = parse("\n");
  EXPECT_TRUE(isa<NoOpQuery>(Q));
}

TEST_F(QueryParserTest, Invalid) {
  QueryRef Q = parse("foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unknown command: foo", cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Help) {
  QueryRef Q = parse("help");
  ASSERT_TRUE(isa<HelpQuery>(Q));

  Q = parse("help me");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' me'", cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Set) {
  QueryRef Q = parse("set");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set foo bar");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unknown variable: 'foo'", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'diag', 'print' or 'dump', got ''",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set bind-root true foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' foo'", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'diag', 'print' or 'dump', got 'foo'",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set output dump");
  ASSERT_TRUE(isa<SetQuery<OutputKind> >(Q));
  EXPECT_EQ(&QuerySession::OutKind, cast<SetQuery<OutputKind> >(Q)->Var);
  EXPECT_EQ(OK_Dump, cast<SetQuery<OutputKind> >(Q)->Value);

  Q = parse("set bind-root foo");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected 'true' or 'false', got 'foo'",
            cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("set bind-root true");
  ASSERT_TRUE(isa<SetQuery<bool> >(Q));
  EXPECT_EQ(&QuerySession::BindRoot, cast<SetQuery<bool> >(Q)->Var);
  EXPECT_EQ(true, cast<SetQuery<bool> >(Q)->Value);
}

TEST_F(QueryParserTest, Match) {
  QueryRef Q = parse("match decl()");
  ASSERT_TRUE(isa<MatchQuery>(Q));
  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Decl>());

  Q = parse("m stmt()");
  ASSERT_TRUE(isa<MatchQuery>(Q));
  EXPECT_TRUE(cast<MatchQuery>(Q)->Matcher.canConvertTo<Stmt>());
}

TEST_F(QueryParserTest, LetUnlet) {
  QueryRef Q = parse("let foo decl()");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("foo", cast<LetQuery>(Q)->Name);
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isMatcher());
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.getMatcher().hasTypedMatcher<Decl>());

  Q = parse("let bar \"str\"");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("bar", cast<LetQuery>(Q)->Name);
  EXPECT_TRUE(cast<LetQuery>(Q)->Value.isString());
  EXPECT_EQ("str", cast<LetQuery>(Q)->Value.getString());

  Q = parse("let");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("unlet x");
  ASSERT_TRUE(isa<LetQuery>(Q));
  EXPECT_EQ("x", cast<LetQuery>(Q)->Name);
  EXPECT_FALSE(cast<LetQuery>(Q)->Value.hasValue());

  Q = parse("unlet");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("expected variable name", cast<InvalidQuery>(Q)->ErrStr);

  Q = parse("unlet x bad_data");
  ASSERT_TRUE(isa<InvalidQuery>(Q));
  EXPECT_EQ("unexpected extra input: ' bad_data'",
            cast<InvalidQuery>(Q)->ErrStr);
}

TEST_F(QueryParserTest, Complete) {
  std::vector<llvm::LineEditor::Completion> Comps =
      QueryParser::complete("", 0, QS);
  ASSERT_EQ(6u, Comps.size());
  EXPECT_EQ("help ", Comps[0].TypedText);
  EXPECT_EQ("help", Comps[0].DisplayText);
  EXPECT_EQ("let ", Comps[1].TypedText);
  EXPECT_EQ("let", Comps[1].DisplayText);
  EXPECT_EQ("match ", Comps[2].TypedText);
  EXPECT_EQ("match", Comps[2].DisplayText);
  EXPECT_EQ("set ", Comps[3].TypedText);
  EXPECT_EQ("set", Comps[3].DisplayText);
  EXPECT_EQ("unlet ", Comps[4].TypedText);
  EXPECT_EQ("unlet", Comps[4].DisplayText);
  EXPECT_EQ("quit", Comps[5].DisplayText);
  EXPECT_EQ("quit ", Comps[5].TypedText);

  Comps = QueryParser::complete("set o", 5, QS);
  ASSERT_EQ(1u, Comps.size());
  EXPECT_EQ("utput ", Comps[0].TypedText);
  EXPECT_EQ("output", Comps[0].DisplayText);

  Comps = QueryParser::complete("match while", 11, QS);
  ASSERT_EQ(1u, Comps.size());
  EXPECT_EQ("Stmt(", Comps[0].TypedText);
  EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)",
            Comps[0].DisplayText);
}
<|endoftext|>