You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2015/06/18 23:58:16 UTC
[38/50] [abbrv] qpid-proton git commit: PROTON-865: Stream like
Encoder/Decoder and AMQP Value type for C++ binding.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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/ea258831/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: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org