http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/ContainerImpl.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/ContainerImpl.h b/proton-c/bindings/cpp/src/ContainerImpl.h index 65a6651..c0d2d12 100644 --- a/proton-c/bindings/cpp/src/ContainerImpl.h +++ b/proton-c/bindings/cpp/src/ContainerImpl.h @@ -41,20 +41,20 @@ class Acceptor; class ContainerImpl { public: - PROTON_CPP_EXTERN ContainerImpl(Handler &h); - PROTON_CPP_EXTERN ContainerImpl(); - PROTON_CPP_EXTERN ~ContainerImpl(); - PROTON_CPP_EXTERN Connection connect(std::string &host, Handler *h); - PROTON_CPP_EXTERN void run(); - PROTON_CPP_EXTERN pn_reactor_t *getReactor(); - PROTON_CPP_EXTERN Sender createSender(Connection &connection, std::string &addr, Handler *h); - PROTON_CPP_EXTERN Sender createSender(std::string &url); - PROTON_CPP_EXTERN Receiver createReceiver(Connection &connection, std::string &addr); - PROTON_CPP_EXTERN Receiver createReceiver(const std::string &url); - PROTON_CPP_EXTERN Acceptor listen(const std::string &url); - PROTON_CPP_EXTERN std::string getContainerId(); - PROTON_CPP_EXTERN Duration getTimeout(); - PROTON_CPP_EXTERN void setTimeout(Duration timeout); + PN_CPP_EXTERN ContainerImpl(Handler &h); + PN_CPP_EXTERN ContainerImpl(); + PN_CPP_EXTERN ~ContainerImpl(); + PN_CPP_EXTERN Connection connect(std::string &host, Handler *h); + PN_CPP_EXTERN void run(); + PN_CPP_EXTERN pn_reactor_t *getReactor(); + PN_CPP_EXTERN Sender createSender(Connection &connection, std::string &addr, Handler *h); + PN_CPP_EXTERN Sender createSender(std::string &url); + PN_CPP_EXTERN Receiver createReceiver(Connection &connection, std::string &addr); + PN_CPP_EXTERN Receiver createReceiver(const std::string &url); + PN_CPP_EXTERN Acceptor listen(const std::string &url); + PN_CPP_EXTERN std::string getContainerId(); + PN_CPP_EXTERN Duration getTimeout(); + PN_CPP_EXTERN void setTimeout(Duration timeout); void start(); bool process(); void stop();
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Data.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Data.cpp b/proton-c/bindings/cpp/src/Data.cpp new file mode 100644 index 0000000..6cfc09b --- /dev/null +++ b/proton-c/bindings/cpp/src/Data.cpp @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/Data.h" +#include <proton/codec.h> +#include "proton_bits.h" + +namespace proton { +namespace reactor { + +Data::Data(pn_data_t* p) : data(p ? p : pn_data(0)) {} + +Data::~Data() { if (data) pn_data_free(data); } + +Data& Data::operator=(const Data& x) { + if (this != &x) { + pn_data_free(data); + data = pn_data(pn_data_size(x.data)); + pn_data_copy(data, x.data); + } + return *this; +} + +void Data::clear() { pn_data_clear(data); } + +bool Data::empty() const { return pn_data_size(data) == 0; } + +std::ostream& operator<<(std::ostream& o, const Data& d) { + o << Object(d.data); +} + +}} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Decoder.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Decoder.cpp b/proton-c/bindings/cpp/src/Decoder.cpp new file mode 100644 index 0000000..4170378 --- /dev/null +++ b/proton-c/bindings/cpp/src/Decoder.cpp @@ -0,0 +1,265 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/Decoder.h" +#include <proton/codec.h> +#include "proton_bits.h" + +namespace proton { +namespace reactor { + + +/**@file + * + * Note the pn_data_t "current" node is always pointing *before* the next value + * to be returned by the Decoder. + * + */ +Decoder::Decoder() {} +Decoder::Decoder(const char* buffer, size_t size) { decode(buffer, size); } +Decoder::Decoder(const std::string& buffer) { decode(buffer); } +Decoder::~Decoder() {} + +namespace { +struct SaveState { + pn_data_t* data; + pn_handle_t handle; + SaveState(pn_data_t* d) : data(d), handle(pn_data_point(d)) {} + ~SaveState() { if (data) pn_data_restore(data, handle); } + void cancel() { data = 0; } +}; +} + +void Decoder::decode(const char* i, size_t size) { + SaveState ss(data); + const char* end = i + size; + while (i < end) { + int result = pn_data_decode(data, i, end - i); + if (result < 0) throw Decoder::Error("decode: " + errorStr(result)); + i += result; + } +} + +void Decoder::decode(const std::string& buffer) { + decode(buffer.data(), buffer.size()); +} + +bool Decoder::more() const { + SaveState ss(data); + return pn_data_next(data); +} + +namespace { + +void badType(TypeId want, TypeId got) { + if (want != got) + throw Decoder::Error("decode: expected "+typeName(want)+" found "+typeName(got)); +} + +TypeId preGet(pn_data_t* data) { + if (!pn_data_next(data)) throw Decoder::Error("decode: no more data"); + TypeId t = TypeId(pn_data_type(data)); + if (t < 0) throw Decoder::Error("decode: invalid data"); + return t; +} + +// Simple extract with no type conversion. +template <class T, class U> void extract(pn_data_t* data, T& value, U (*get)(pn_data_t*)) { + SaveState ss(data); + badType(TypeIdOf<T>::value, preGet(data)); + value = get(data); + ss.cancel(); // No error, no rewind +} + +} + +TypeId Decoder::type() const { + SaveState ss(data); + return preGet(data); +} + +Decoder& operator>>(Decoder& d, Bool& value) { + extract(d.data, value, pn_data_get_bool); + return d; +} + +Decoder& operator>>(Decoder& d, Ubyte& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case UBYTE: value = pn_data_get_ubyte(d.data); break; + default: badType(UBYTE, TypeId(TypeId(pn_data_type(d.data)))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Byte& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case BYTE: value = pn_data_get_ubyte(d.data); break; + default: badType(BYTE, TypeId(TypeId(pn_data_type(d.data)))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Ushort& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case UBYTE: value = pn_data_get_ubyte(d.data); break; + case USHORT: value = pn_data_get_ushort(d.data); break; + default: badType(USHORT, TypeId(TypeId(pn_data_type(d.data)))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Short& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case BYTE: value = pn_data_get_byte(d.data); break; + case SHORT: value = pn_data_get_short(d.data); break; + default: badType(SHORT, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Uint& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case UBYTE: value = pn_data_get_ubyte(d.data); break; + case USHORT: value = pn_data_get_ushort(d.data); break; + case UINT: value = pn_data_get_uint(d.data); break; + default: badType(UINT, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Int& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case BYTE: value = pn_data_get_byte(d.data); break; + case SHORT: value = pn_data_get_short(d.data); break; + case INT: value = pn_data_get_int(d.data); break; + default: badType(INT, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Ulong& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case UBYTE: value = pn_data_get_ubyte(d.data); break; + case USHORT: value = pn_data_get_ushort(d.data); break; + case UINT: value = pn_data_get_uint(d.data); break; + case ULONG: value = pn_data_get_ulong(d.data); break; + default: badType(ULONG, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Long& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case BYTE: value = pn_data_get_byte(d.data); break; + case SHORT: value = pn_data_get_short(d.data); break; + case INT: value = pn_data_get_int(d.data); break; + case LONG: value = pn_data_get_long(d.data); break; + default: badType(LONG, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Char& value) { + extract(d.data, value, pn_data_get_char); + return d; +} + +Decoder& operator>>(Decoder& d, Timestamp& value) { + extract(d.data, value, pn_data_get_timestamp); + return d; +} + +Decoder& operator>>(Decoder& d, Float& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case FLOAT: value = pn_data_get_float(d.data); break; + case DOUBLE: value = pn_data_get_double(d.data); break; + default: badType(FLOAT, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +Decoder& operator>>(Decoder& d, Double& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case FLOAT: value = pn_data_get_float(d.data); break; + case DOUBLE: value = pn_data_get_double(d.data); break; + default: badType(DOUBLE, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +// TODO aconway 2015-06-11: decimal conversions. +Decoder& operator>>(Decoder& d, Decimal32& value) { + extract(d.data, value, pn_data_get_decimal32); + return d; +} + +Decoder& operator>>(Decoder& d, Decimal64& value) { + extract(d.data, value, pn_data_get_decimal64); + return d; +} + +Decoder& operator>>(Decoder& d, Decimal128& value) { + extract(d.data, value, pn_data_get_decimal128); + return d; +} + +Decoder& operator>>(Decoder& d, Uuid& value) { + extract(d.data, value, pn_data_get_uuid); + return d; +} + +Decoder& operator>>(Decoder& d, std::string& value) { + SaveState ss(d.data); + switch (preGet(d.data)) { + case STRING: value = str(pn_data_get_string(d.data)); break; + case BINARY: value = str(pn_data_get_binary(d.data)); break; + case SYMBOL: value = str(pn_data_get_symbol(d.data)); break; + default: badType(STRING, TypeId(pn_data_type(d.data))); + } + ss.cancel(); + return d; +} + +void Decoder::checkType(TypeId want) { + TypeId got = type(); + if (want != got) badType(want, got); +} + + +}} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Encoder.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Encoder.cpp b/proton-c/bindings/cpp/src/Encoder.cpp new file mode 100644 index 0000000..81fa365 --- /dev/null +++ b/proton-c/bindings/cpp/src/Encoder.cpp @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/Encoder.h" +#include <proton/codec.h> +#include "proton_bits.h" + +namespace proton { +namespace reactor { + +Encoder::Encoder() {} +Encoder::~Encoder() {} + +namespace { +struct SaveState { + pn_data_t* data; + pn_handle_t handle; + SaveState(pn_data_t* d) : data(d), handle(pn_data_point(d)) {} + ~SaveState() { if (data) pn_data_restore(data, handle); } +}; + +template <class T> T check(T result) { + if (result < 0) + throw Encoder::Error("encode: " + errorStr(result)); + return result; +} +} + +bool Encoder::encode(char* buffer, size_t& size) { + SaveState ss(data); // In case of error + pn_data_rewind(data); + ssize_t result = pn_data_encode(data, buffer, size); + if (result == PN_OVERFLOW) { + size = pn_data_encoded_size(data); + return false; + } + check(result); + size = result; + ss.data = 0; // Don't restore state, all is well. + pn_data_clear(data); +} + +void Encoder::encode(std::string& s) { + size_t size = s.size(); + if (!encode(&s[0], size)) { + s.resize(size); + encode(&s[0], size); + } +} + +std::string Encoder::encode() { + std::string s; + encode(s); + return s; +} + +namespace { +template <class T, class U> +Encoder& insert(Encoder& e, pn_data_t* data, T& value, int (*put)(pn_data_t*, U)) { + SaveState ss(data); // Save state in case of error. + check(put(data, value)); + ss.data = 0; // Don't restore state, all is good. + return e; +} +} + +Encoder& operator<<(Encoder& e, Bool value) { return insert(e, e.data, value, pn_data_put_bool); } +Encoder& operator<<(Encoder& e, Ubyte value) { return insert(e, e.data, value, pn_data_put_ubyte); } +Encoder& operator<<(Encoder& e, Byte value) { return insert(e, e.data, value, pn_data_put_byte); } +Encoder& operator<<(Encoder& e, Ushort value) { return insert(e, e.data, value, pn_data_put_ushort); } +Encoder& operator<<(Encoder& e, Short value) { return insert(e, e.data, value, pn_data_put_short); } +Encoder& operator<<(Encoder& e, Uint value) { return insert(e, e.data, value, pn_data_put_uint); } +Encoder& operator<<(Encoder& e, Int value) { return insert(e, e.data, value, pn_data_put_int); } +Encoder& operator<<(Encoder& e, Char value) { return insert(e, e.data, value, pn_data_put_char); } +Encoder& operator<<(Encoder& e, Ulong value) { return insert(e, e.data, value, pn_data_put_ulong); } +Encoder& operator<<(Encoder& e, Long value) { return insert(e, e.data, value, pn_data_put_long); } +Encoder& operator<<(Encoder& e, Timestamp value) { return insert(e, e.data, value, pn_data_put_timestamp); } +Encoder& operator<<(Encoder& e, Float value) { return insert(e, e.data, value, pn_data_put_float); } +Encoder& operator<<(Encoder& e, Double value) { return insert(e, e.data, value, pn_data_put_double); } +Encoder& operator<<(Encoder& e, Decimal32 value) { return insert(e, e.data, value, pn_data_put_decimal32); } +Encoder& operator<<(Encoder& e, Decimal64 value) { return insert(e, e.data, value, pn_data_put_decimal64); } +Encoder& operator<<(Encoder& e, Decimal128 value) { return insert(e, e.data, value, pn_data_put_decimal128); } +Encoder& operator<<(Encoder& e, Uuid value) { return insert(e, e.data, value, pn_data_put_uuid); } +Encoder& operator<<(Encoder& e, String value) { return insert(e, e.data, value, pn_data_put_string); } +Encoder& operator<<(Encoder& e, Symbol value) { return insert(e, e.data, value, pn_data_put_symbol); } +Encoder& operator<<(Encoder& e, Binary value) { return insert(e, e.data, value, pn_data_put_binary); } + +}} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Msg.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Msg.h b/proton-c/bindings/cpp/src/Msg.h index 1168d35..cd8f9e8 100644 --- a/proton-c/bindings/cpp/src/Msg.h +++ b/proton-c/bindings/cpp/src/Msg.h @@ -72,7 +72,7 @@ inline std::ostream& operator<<(std::ostream& o, const Msg& m) { /** Construct a message using operator << and append (file:line) */ #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) -#define MSG(message) (::proton::reactor::Msg() << message << " (" __FILE__ ":" QUOTE(__LINE__) ")") +#define MSG(message) (::proton::reactor::Msg() << message) }} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Url.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Url.h b/proton-c/bindings/cpp/src/Url.h index 042ab45..d9651fc 100644 --- a/proton-c/bindings/cpp/src/Url.h +++ b/proton-c/bindings/cpp/src/Url.h @@ -32,13 +32,13 @@ namespace reactor { class Url : public ProtonHandle<pn_url_t> { public: - PROTON_CPP_EXTERN Url(const std::string &url); - PROTON_CPP_EXTERN ~Url(); - PROTON_CPP_EXTERN Url(const Url&); - PROTON_CPP_EXTERN Url& operator=(const Url&); - PROTON_CPP_EXTERN std::string getHost(); - PROTON_CPP_EXTERN std::string getPort(); - PROTON_CPP_EXTERN std::string getPath(); + PN_CPP_EXTERN Url(const std::string &url); + PN_CPP_EXTERN ~Url(); + PN_CPP_EXTERN Url(const Url&); + PN_CPP_EXTERN Url& operator=(const Url&); + PN_CPP_EXTERN std::string getHost(); + PN_CPP_EXTERN std::string getPort(); + PN_CPP_EXTERN std::string getPath(); private: friend class ProtonImplRef<Url>; }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/Value.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Value.cpp b/proton-c/bindings/cpp/src/Value.cpp new file mode 100644 index 0000000..8e1e38c --- /dev/null +++ b/proton-c/bindings/cpp/src/Value.cpp @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/Value.h" +#include "proton_bits.h" +#include <proton/codec.h> +#include <ostream> + +namespace proton { +namespace reactor { + +Values::Values() {} +Values::Values(const Values& v) { *this = v; } +Values::~Values() {} +Values& Values::operator=(const Values& v) { Data::operator=(v); } + +void Values::rewind() { pn_data_rewind(data); } + +Value::Value() {} +Value::Value(const Value& v) { *this = v; } +Value::~Value() {} +Value& Value::operator=(const Value& v) { values = v.values; } + +TypeId Value::type() const { + const_cast<Values&>(values).rewind(); + return values.type(); +} + +namespace { +template <class T> T check(T result) { + if (result < 0) + throw Encoder::Error("encode: " + errorStr(result)); + return result; +} +} + +Encoder& operator<<(Encoder& e, const Value& v) { + if (e.data == v.values.data) throw Encoder::Error("Values inserted into self"); + pn_data_narrow(e.data); + int result = pn_data_appendn(e.data, v.values.data, 1); + pn_data_widen(e.data); + check(result); + return e; +} + +Decoder& operator>>(Decoder& e, Value& v) { + if (e.data == v.values.data) throw Decoder::Error("Values extracted from self"); + pn_data_narrow(e.data); + int result = pn_data_appendn(e.data, v.values.data, 1); + pn_data_widen(e.data); + check(result); + return e; +} + +}} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h b/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h index 5f263ab..6adb65e 100644 --- a/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h +++ b/proton-c/bindings/cpp/src/blocking/BlockingConnectionImpl.h @@ -39,12 +39,12 @@ class SslDomain; class BlockingConnectionImpl : public MessagingHandler { public: - PROTON_CPP_EXTERN BlockingConnectionImpl(std::string &url, Duration d, SslDomain *ssld, Container *c); - PROTON_CPP_EXTERN ~BlockingConnectionImpl(); - PROTON_CPP_EXTERN void close(); - PROTON_CPP_EXTERN void wait(WaitCondition &condition); - PROTON_CPP_EXTERN void wait(WaitCondition &condition, std::string &msg, Duration timeout); - PROTON_CPP_EXTERN pn_connection_t *getPnBlockingConnection(); + PN_CPP_EXTERN BlockingConnectionImpl(std::string &url, Duration d, SslDomain *ssld, Container *c); + PN_CPP_EXTERN ~BlockingConnectionImpl(); + PN_CPP_EXTERN void close(); + PN_CPP_EXTERN void wait(WaitCondition &condition); + PN_CPP_EXTERN void wait(WaitCondition &condition, std::string &msg, Duration timeout); + PN_CPP_EXTERN pn_connection_t *getPnBlockingConnection(); Duration getTimeout() { return timeout; } static void incref(BlockingConnectionImpl *); static void decref(BlockingConnectionImpl *); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/grep ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/grep b/proton-c/bindings/cpp/src/grep new file mode 100644 index 0000000..a53cfb8 --- /dev/null +++ b/proton-c/bindings/cpp/src/grep @@ -0,0 +1,50 @@ + /home/aconway/proton/proton-c/bindings/cpp/src: + total used in directory 256 available 122608224 + drwxrwxr-x. 3 aconway aconway 4096 Jun 11 14:47 . + drwxrwxr-x. 4 aconway aconway 4096 Jun 11 14:48 .. + -rw-rw-r--. 1 aconway aconway 1478 Jun 10 08:40 Acceptor.cpp + -rw-rw-r--. 1 aconway aconway 1401 Jun 10 08:40 Acking.cpp + -rw-rw-r--. 1 aconway aconway 1295 Jun 11 14:45 proton_bits.cpp + -rw-rw-r--. 1 aconway aconway 915 Jun 11 14:44 proton_bits.h + drwxrwxr-x. 2 aconway aconway 4096 Jun 10 08:40 blocking + -rw-rw-r--. 1 aconway aconway 2390 Jun 10 08:40 Connection.cpp + -rw-rw-r--. 1 aconway aconway 4285 Jun 10 08:40 ConnectionImpl.cpp + -rw-rw-r--. 1 aconway aconway 2531 Jun 10 08:40 ConnectionImpl.h + -rw-rw-r--. 1 aconway aconway 2131 Jun 10 08:40 Connector.cpp + -rw-rw-r--. 1 aconway aconway 1624 Jun 10 08:40 Connector.h + -rw-rw-r--. 1 aconway aconway 3188 Jun 10 08:40 Container.cpp + -rw-rw-r--. 1 aconway aconway 12183 Jun 10 08:40 ContainerImpl.cpp + -rw-rw-r--. 1 aconway aconway 2689 Jun 10 08:40 ContainerImpl.h + -rw-rw-r--. 1 aconway aconway 2846 Jun 10 08:40 contexts.cpp + -rw-rw-r--. 1 aconway aconway 1764 Jun 10 08:40 contexts.h + -rw-rw-r--. 1 aconway aconway 4992 Jun 11 14:45 Data.cpp + -rw-rw-r--. 1 aconway aconway 4494 Jun 11 14:46 Decoder.cpp + -rw-rw-r--. 1 aconway aconway 1590 Jun 10 08:40 Delivery.cpp + -rw-rw-r--. 1 aconway aconway 1752 Jun 10 08:40 Duration.cpp + -rw-rw-r--. 1 aconway aconway 3933 Jun 11 14:47 Encoder.cpp + -rw-rw-r--. 1 aconway aconway 1125 Jun 10 08:40 Endpoint.cpp + -rw-rw-r--. 1 aconway aconway 1882 Jun 10 08:40 Event.cpp + -rw-rw-r--. 1 aconway aconway 1315 Jun 10 08:40 Handler.cpp + -rw-rw-r--. 1 aconway aconway 4220 Jun 11 11:13 interop_test.cpp + -rw-rw-r--. 1 aconway aconway 2821 Jun 10 08:40 Link.cpp + -rw-rw-r--. 1 aconway aconway 13358 Jun 10 08:40 Message.cpp + -rw-rw-r--. 1 aconway aconway 13424 Jun 10 08:40 MessagingAdapter.cpp + -rw-rw-r--. 1 aconway aconway 5864 Jun 10 08:40 MessagingEvent.cpp + -rw-rw-r--. 1 aconway aconway 5230 Jun 10 08:40 MessagingHandler.cpp + -rw-rw-r--. 1 aconway aconway 2587 Jun 10 08:40 Msg.h + -rw-rw-r--. 1 aconway aconway 2208 Jun 10 08:40 platform.cpp + -rw-rw-r--. 1 aconway aconway 1145 Jun 10 08:40 platform.h + -rw-rw-r--. 1 aconway aconway 1072 Jun 11 11:49 pn_data.h + -rw-rw-r--. 1 aconway aconway 3000 Jun 10 08:40 PrivateImplRef.h + -rw-rw-r--. 1 aconway aconway 6032 Jun 10 08:40 ProtonEvent.cpp + -rw-rw-r--. 1 aconway aconway 3818 Jun 10 08:40 ProtonHandler.cpp + -rw-rw-r--. 1 aconway aconway 2209 Jun 10 08:40 ProtonImplRef.h + -rw-rw-r--. 1 aconway aconway 1396 Jun 10 08:40 Receiver.cpp + -rw-rw-r--. 1 aconway aconway 2119 Jun 10 08:40 Sender.cpp + -rw-rw-r--. 1 aconway aconway 2031 Jun 10 08:40 Session.cpp + -rw-rw-r--. 1 aconway aconway 2850 Jun 10 08:40 Terminus.cpp + -rw-rw-r--. 1 aconway aconway 1234 Jun 10 08:40 Transport.cpp + -rw-rw-r--. 1 aconway aconway 6251 Jun 10 18:27 types.cpp + -rw-rw-r--. 1 aconway aconway 1942 Jun 10 08:40 Url.cpp + -rw-rw-r--. 1 aconway aconway 1469 Jun 10 08:40 Url.h + -rw-rw-r--. 1 aconway aconway 2211 Jun 11 14:47 Value.cpp http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/interop_test.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/interop_test.cpp b/proton-c/bindings/cpp/src/interop_test.cpp new file mode 100644 index 0000000..b344553 --- /dev/null +++ b/proton-c/bindings/cpp/src/interop_test.cpp @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/Decoder.h" +#include "proton/cpp/Encoder.h" +#include "proton/cpp/Value.h" +#include "./Msg.h" +#include <stdexcept> +#include <string> +#include <sstream> +#include <fstream> +#include <streambuf> +#include <iosfwd> +#include <unistd.h> + +using namespace std; +using namespace proton::reactor; + +std::string testsDir; + +struct Fail : public logic_error { Fail(const string& what) : logic_error(what) {} }; +#define FAIL(WHAT) throw Fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT)) +#define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false) +#define ASSERT_EQUAL(WANT, GOT) if ((WANT) != (GOT)) \ + FAIL(#WANT << " != " << #GOT << ": " << WANT << " != " << GOT) + + +string read(string filename) { + filename = testsDir+"/interop/"+filename+".amqp"; + ifstream ifs(filename.c_str()); + if (!ifs.good()) FAIL("Can't open " << filename); + return string(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>()); +} + +template <class T> T get(Decoder& d) { + T value; + d >> exact(value); + return value; +} + +template <class T> std::string str(const T& value) { + ostringstream oss; + oss << value; + return oss.str(); +} + +// Test Data ostream operator +void testDataOstream() { + Decoder d(read("primitives")); + ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(d)); +} + +// Test extracting to exact AMQP types works corectly, extrating to invalid types fails. +void testDecoderPrimitvesExact() { + Decoder d(read("primitives")); + ASSERT(d.more()); + try { get<int8_t>(d); FAIL("got bool as byte"); } catch(Decoder::Error){} + ASSERT_EQUAL(true, get<bool>(d)); + ASSERT_EQUAL(false, get<bool>(d)); + try { get<int8_t>(d); FAIL("got ubyte as byte"); } catch(Decoder::Error){} + ASSERT_EQUAL(42, get<uint8_t>(d)); + try { get<int32_t>(d); FAIL("got uint as ushort"); } catch(Decoder::Error){} + ASSERT_EQUAL(42, get<uint16_t>(d)); + try { get<uint16_t>(d); FAIL("got short as ushort"); } catch(Decoder::Error){} + ASSERT_EQUAL(-42, get<int16_t>(d)); + ASSERT_EQUAL(12345, get<uint32_t>(d)); + ASSERT_EQUAL(-12345, get<int32_t>(d)); + ASSERT_EQUAL(12345, get<uint64_t>(d)); + ASSERT_EQUAL(-12345, get<int64_t>(d)); + try { get<double>(d); FAIL("got float as double"); } catch(Decoder::Error){} + ASSERT_EQUAL(0.125, get<float>(d)); + try { get<float>(d); FAIL("got double as float"); } catch(Decoder::Error){} + ASSERT_EQUAL(0.125, get<double>(d)); + ASSERT(!d.more()); +} + +// Test inserting primitive sand encoding as AMQP. +void testEncoderPrimitives() { + Encoder e; + e << true << false; + e << uint8_t(42); + e << uint16_t(42) << int16_t(-42); + e << uint32_t(12345) << int32_t(-12345); + e << uint64_t(12345) << int64_t(-12345); + e << float(0.125) << double(0.125); + ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(e)); + std::string data = e.encode(); + ASSERT_EQUAL(read("primitives"), data); +} + +// Test type conversions. +void testValueConversions() { + Value v; + ASSERT_EQUAL(true, bool(v = true)); + ASSERT_EQUAL(2, int(v=Byte(2))); + ASSERT_EQUAL(3, long(v=Byte(3))); + ASSERT_EQUAL(3, long(v=Byte(3))); + ASSERT_EQUAL(1.0, double(v=Float(1.0))); + ASSERT_EQUAL(1.0, float(v=Double(1.0))); + try { bool(v = Byte(1)); FAIL("got byte as bool"); } catch (Decoder::Error) {} + try { float(v = true); FAIL("got bool as float"); } catch (Decoder::Error) {} +} + +int run_test(void (*testfn)(), const char* name) { + try { + testfn(); + return 0; + } catch(const Fail& e) { + cout << "FAIL " << name << endl << e.what(); + } catch(const std::exception& e) { + cout << "ERROR " << name << endl << e.what(); + } + return 1; +} + +// FIXME aconway 2015-06-11: not testing all types. + +#define RUN_TEST(T) run_test(&T, #T) + +int main(int argc, char** argv) { + int failed = 0; + char buf[1024]; + if (argc != 2) FAIL("Usage: " << argv[0] << " tests-dir" << " IN " << getcwd(buf, sizeof(buf))); + testsDir = argv[1]; + + failed += RUN_TEST(testDataOstream); + failed += RUN_TEST(testDecoderPrimitvesExact); + failed += RUN_TEST(testEncoderPrimitives); + failed += RUN_TEST(testValueConversions); + return failed; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/platform.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/platform.cpp b/proton-c/bindings/cpp/src/platform.cpp index 4eac408..80e3d51 100644 --- a/proton-c/bindings/cpp/src/platform.cpp +++ b/proton-c/bindings/cpp/src/platform.cpp @@ -22,6 +22,8 @@ #include "platform.h" #include <string> +// FIXME aconway 2015-06-09: probably don't need UUIDs in the binding. + // Copy neccesary platform neutral functionality from Proton-C // TODO: make this sensibly maintainable (even though it is mostly static) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/pn_data.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/pn_data.h b/proton-c/bindings/cpp/src/pn_data.h new file mode 100644 index 0000000..371d82c --- /dev/null +++ b/proton-c/bindings/cpp/src/pn_data.h @@ -0,0 +1,30 @@ +#ifndef PN_DATA_H +#define PN_DATA_H +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Some routines for handling pn_data_t + +std::ostream& operator<<(std::ostream& o, const Value& v) { + pn_string_t* str = pn_string(""); + pn_inspect(v.data, str); + return o << pn_string_get(str); +} + +#endif // PN_DATA_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/proton_bits.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/proton_bits.cpp b/proton-c/bindings/cpp/src/proton_bits.cpp new file mode 100644 index 0000000..2e96430 --- /dev/null +++ b/proton-c/bindings/cpp/src/proton_bits.cpp @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <string> +#include <ostream> +#include <proton/error.h> +#include <proton/object.h> +#include "proton_bits.h" + +std::string errorStr(int code) { + switch (code) + { + case 0: return "ok"; + case PN_EOS: return "end of data stream"; + case PN_ERR: return "error"; + case PN_OVERFLOW: return "overflow"; + case PN_UNDERFLOW: return "underflow"; + case PN_STATE_ERR: return "invalid state"; + case PN_ARG_ERR: return "invalud argument"; + case PN_TIMEOUT: return "timeout"; + case PN_INTR: return "interrupt"; + default: return "unknown error code"; + } +} + +std::ostream& operator<<(std::ostream& o, const Object& object) { + pn_string_t* str = pn_string(""); + pn_inspect(object.value, str); + o << pn_string_get(str); + pn_free(str); + return o; +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/proton_bits.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/proton_bits.h b/proton-c/bindings/cpp/src/proton_bits.h new file mode 100644 index 0000000..a905172 --- /dev/null +++ b/proton-c/bindings/cpp/src/proton_bits.h @@ -0,0 +1,39 @@ +#ifndef ERROR_H +#define ERROR_H +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <iosfwd> + +/**@file + * + * Assorted internal proton utilities. + */ +std::string errorStr(int code); + +/** Wrapper for a proton object pointer. */ +struct Object { void* value; Object(void* o) : value(o) {} }; + +/** Stream a proton object via pn_inspect. */ +std::ostream& operator<<(std::ostream& o, const Object& object); + + + + +#endif // ERROR_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/cpp/src/types.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp new file mode 100644 index 0000000..127ee7d --- /dev/null +++ b/proton-c/bindings/cpp/src/types.cpp @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "proton/cpp/types.h" +#include <proton/codec.h> + +namespace proton { +namespace reactor { + +const TypeId TypeIdOf<Null>::value = NULL_; +const TypeId TypeIdOf<Bool>::value = BOOL; +const TypeId TypeIdOf<Ubyte>::value = UBYTE; +const TypeId TypeIdOf<Byte>::value = BYTE; +const TypeId TypeIdOf<Ushort>::value = USHORT; +const TypeId TypeIdOf<Short>::value = SHORT; +const TypeId TypeIdOf<Uint>::value = UINT; +const TypeId TypeIdOf<Int>::value = INT; +const TypeId TypeIdOf<Char>::value = CHAR; +const TypeId TypeIdOf<Ulong>::value = ULONG; +const TypeId TypeIdOf<Long>::value = LONG; +const TypeId TypeIdOf<Timestamp>::value = TIMESTAMP; +const TypeId TypeIdOf<Float>::value = FLOAT; +const TypeId TypeIdOf<Double>::value = DOUBLE; +const TypeId TypeIdOf<Decimal32>::value = DECIMAL32; +const TypeId TypeIdOf<Decimal64>::value = DECIMAL64; +const TypeId TypeIdOf<Decimal128>::value = DECIMAL128; +const TypeId TypeIdOf<Uuid>::value = UUID; +const TypeId TypeIdOf<Binary>::value = BINARY; +const TypeId TypeIdOf<String>::value = STRING; +const TypeId TypeIdOf<Symbol>::value = SYMBOL; + +std::string typeName(TypeId t) { + switch (t) { + case NULL_: return "null"; + case BOOL: return "bool"; + case UBYTE: return "ubyte"; + case BYTE: return "byte"; + case USHORT: return "ushort"; + case SHORT: return "short"; + case UINT: return "uint"; + case INT: return "int"; + case CHAR: return "char"; + case ULONG: return "ulong"; + case LONG: return "long"; + case TIMESTAMP: return "timestamp"; + case FLOAT: return "float"; + case DOUBLE: return "double"; + case DECIMAL32: return "decimal32"; + case DECIMAL64: return "decimal64"; + case DECIMAL128: return "decimal128"; + case UUID: return "uuid"; + case BINARY: return "binary"; + case STRING: return "string"; + case SYMBOL: return "symbol"; + case DESCRIBED: return "described"; + case ARRAY: return "array"; + case LIST: return "list"; + case MAP: return "map"; + default: return "unknown"; + } +} + +std::string str(const pn_bytes_t& b) { return std::string(b.start, b.size); } +pn_bytes_t bytes(const std::string& s) { pn_bytes_t b; b.start = &s[0]; b.size = s.size(); return b; } + +}} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/052d4669/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go ---------------------------------------------------------------------- diff --git a/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go b/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go new file mode 100644 index 0000000..11049f7 --- /dev/null +++ b/proton-c/bindings/go/src/qpid.apache.org/proton/go/amqp/interop_test.go @@ -0,0 +1,308 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +// Test that conversion of Go type to/from AMQP is compatible with other +// bindings. +// +package amqp + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "reflect" + "strings" + "testing" +) + +func assertEqual(want interface{}, got interface{}) { + if !reflect.DeepEqual(want, got) { + panic(fmt.Errorf("%#v != %#v", want, got)) + } +} + +func assertNil(err interface{}) { + if err != nil { + panic(err) + } +} + +func getReader(name string) (r io.Reader) { + r, err := os.Open("interop/" + name + ".amqp") + if err != nil { + panic(fmt.Errorf("Can't open %#v: %v", name, err)) + } + return +} + +func remaining(d *Decoder) string { + remainder, _ := ioutil.ReadAll(io.MultiReader(d.Buffered(), d.reader)) + return string(remainder) +} + +// assertDecode: want is the expected value, gotPtr is a pointer to a +// instance of the same type for Decode. +func assertDecode(d *Decoder, want interface{}, gotPtr interface{}) { + + assertNil(d.Decode(gotPtr)) + + got := reflect.ValueOf(gotPtr).Elem().Interface() + assertEqual(want, got) + + // Try round trip encoding + bytes, err := Marshal(want, nil) + assertNil(err) + n, err := Unmarshal(bytes, gotPtr) + assertNil(err) + assertEqual(n, len(bytes)) + got = reflect.ValueOf(gotPtr).Elem().Interface() + assertEqual(want, got) +} + +func TestUnmarshal(t *testing.T) { + bytes, err := ioutil.ReadAll(getReader("strings")) + if err != nil { + t.Error(err) + } + for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} { + var got string + n, err := Unmarshal(bytes, &got) + if err != nil { + t.Error(err) + } + if want != got { + t.Errorf("%#v != %#v", want, got) + } + bytes = bytes[n:] + } +} + +func TestPrimitivesExact(t *testing.T) { + d := NewDecoder(getReader("primitives")) + // Decoding into exact types + var b bool + assertDecode(d, true, &b) + assertDecode(d, false, &b) + var u8 uint8 + assertDecode(d, uint8(42), &u8) + var u16 uint16 + assertDecode(d, uint16(42), &u16) + var i16 int16 + assertDecode(d, int16(-42), &i16) + var u32 uint32 + assertDecode(d, uint32(12345), &u32) + var i32 int32 + assertDecode(d, int32(-12345), &i32) + var u64 uint64 + assertDecode(d, uint64(12345), &u64) + var i64 int64 + assertDecode(d, int64(-12345), &i64) + var f32 float32 + assertDecode(d, float32(0.125), &f32) + var f64 float64 + assertDecode(d, float64(0.125), &f64) +} + +func TestPrimitivesCompatible(t *testing.T) { + d := NewDecoder(getReader("primitives")) + // Decoding into compatible types + var b bool + var i int + var u uint + var f float64 + assertDecode(d, true, &b) + assertDecode(d, false, &b) + assertDecode(d, uint(42), &u) + assertDecode(d, uint(42), &u) + assertDecode(d, -42, &i) + assertDecode(d, uint(12345), &u) + assertDecode(d, -12345, &i) + assertDecode(d, uint(12345), &u) + assertDecode(d, -12345, &i) + assertDecode(d, 0.125, &f) + assertDecode(d, 0.125, &f) +} + +// assertDecodeValue: want is the expected value, decode into a reflect.Value +func assertDecodeInterface(d *Decoder, want interface{}) { + + var got, got2 interface{} + assertNil(d.Decode(&got)) + + assertEqual(want, got) + + // Try round trip encoding + bytes, err := Marshal(got, nil) + assertNil(err) + n, err := Unmarshal(bytes, &got2) + assertNil(err) + assertEqual(n, len(bytes)) + assertEqual(want, got2) +} + +func TestPrimitivesInterface(t *testing.T) { + d := NewDecoder(getReader("primitives")) + assertDecodeInterface(d, true) + assertDecodeInterface(d, false) + assertDecodeInterface(d, uint8(42)) + assertDecodeInterface(d, uint16(42)) + assertDecodeInterface(d, int16(-42)) + assertDecodeInterface(d, uint32(12345)) + assertDecodeInterface(d, int32(-12345)) + assertDecodeInterface(d, uint64(12345)) + assertDecodeInterface(d, int64(-12345)) + assertDecodeInterface(d, float32(0.125)) + assertDecodeInterface(d, float64(0.125)) +} + +func TestStrings(t *testing.T) { + d := NewDecoder(getReader("strings")) + // Test decoding as plain Go strings + for _, want := range []string{"abc\000defg", "abcdefg", "abcdefg", "", "", ""} { + var got string + assertDecode(d, want, &got) + } + remains := remaining(d) + if remains != "" { + t.Errorf("leftover: %s", remains) + } + + // Test decoding as specific string types + d = NewDecoder(getReader("strings")) + var bytes []byte + var str, sym string + assertDecode(d, []byte("abc\000defg"), &bytes) + assertDecode(d, "abcdefg", &str) + assertDecode(d, "abcdefg", &sym) + assertDecode(d, make([]byte, 0), &bytes) + assertDecode(d, "", &str) + assertDecode(d, "", &sym) + remains = remaining(d) + if remains != "" { + t.Fatalf("leftover: %s", remains) + } + + // Test some error handling + d = NewDecoder(getReader("strings")) + var s string + err := d.Decode(s) + if err == nil { + t.Fatal("Expected error") + } + if !strings.Contains(err.Error(), "not a pointer") { + t.Error(err) + } + var i int + err = d.Decode(&i) + if !strings.Contains(err.Error(), "cannot unmarshal") { + t.Error(err) + } + _, err = Unmarshal([]byte{}, nil) + if !strings.Contains(err.Error(), "not enough data") { + t.Error(err) + } + _, err = Unmarshal([]byte("foobar"), nil) + if !strings.Contains(err.Error(), "invalid-argument") { + t.Error(err) + } +} + +func TestEncodeDecode(t *testing.T) { + type data struct { + s string + i int + u8 uint8 + b bool + f float32 + v interface{} + } + + in := data{"foo", 42, 9, true, 1.234, "thing"} + + buf := bytes.Buffer{} + e := NewEncoder(&buf) + assertNil(e.Encode(in.s)) + assertNil(e.Encode(in.i)) + assertNil(e.Encode(in.u8)) + assertNil(e.Encode(in.b)) + assertNil(e.Encode(in.f)) + assertNil(e.Encode(in.v)) + + var out data + d := NewDecoder(&buf) + assertNil(d.Decode(&out.s)) + assertNil(d.Decode(&out.i)) + assertNil(d.Decode(&out.u8)) + assertNil(d.Decode(&out.b)) + assertNil(d.Decode(&out.f)) + assertNil(d.Decode(&out.v)) + + assertEqual(in, out) +} + +func TestMap(t *testing.T) { + d := NewDecoder(getReader("maps")) + + // Generic map + var m Map + assertDecode(d, Map{"one": int32(1), "two": int32(2), "three": int32(3)}, &m) + + // Interface as map + var i interface{} + assertDecode(d, Map{int32(1): "one", int32(2): "two", int32(3): "three"}, &i) + + d = NewDecoder(getReader("maps")) + // Specific typed map + var m2 map[string]int + assertDecode(d, map[string]int{"one": 1, "two": 2, "three": 3}, &m2) + + // Round trip a nested map + m = Map{int64(1): "one", "two": int32(2), true: Map{uint8(1): true, uint8(2): false}} + bytes, err := Marshal(m, nil) + assertNil(err) + _, err = Unmarshal(bytes, &i) + assertNil(err) + assertEqual(m, i) +} + +func TestList(t *testing.T) { + d := NewDecoder(getReader("lists")) + var l List + assertDecode(d, List{int32(32), "foo", true}, &l) + assertDecode(d, List{}, &l) +} + +func FIXMETestMessage(t *testing.T) { + // FIXME aconway 2015-04-09: integrate Message encoding under marshal/unmarshal API. + bytes, err := ioutil.ReadAll(getReader("message")) + assertNil(err) + m, err := DecodeMessage(bytes) + assertNil(err) + fmt.Printf("%+v\n", m) + assertEqual(m.Body(), "hello") + + bytes2 := make([]byte, len(bytes)) + bytes2, err = m.Encode(bytes2) + assertNil(err) + assertEqual(bytes, bytes2) +} + +// FIXME aconway 2015-03-13: finish the full interop test --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
