You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2018/03/20 16:52:23 UTC

qpid-interop-test git commit: QPIDIT-46: Added encoding for AMQP list and map types, and which can contain other lists and maps. This has been completed on the ProtonCpp and ProtonPython{2, 3} shims, and RheaJs and AmqpNetLite have this test disabled for

Repository: qpid-interop-test
Updated Branches:
  refs/heads/master 90944238f -> b87dc72a3


QPIDIT-46: Added encoding for AMQP list and map types, and which can contain other lists and maps. This has been completed on the ProtonCpp and ProtonPython{2,3} shims, and RheaJs and AmqpNetLite have this test disabled for now.


Project: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/commit/b87dc72a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/tree/b87dc72a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/diff/b87dc72a

Branch: refs/heads/master
Commit: b87dc72a330724d6d888d87faa567d003a2e5c07
Parents: 9094423
Author: Kim van der Riet <kv...@localhost.localdomain>
Authored: Tue Mar 20 12:52:00 2018 -0400
Committer: Kim van der Riet <kv...@localhost.localdomain>
Committed: Tue Mar 20 12:52:00 2018 -0400

----------------------------------------------------------------------
 .../qpid-proton-cpp/src/qpidit/QpidItErrors.cpp |   4 +
 .../qpid-proton-cpp/src/qpidit/QpidItErrors.hpp |   1 +
 .../src/qpidit/amqp_types_test/Receiver.cpp     | 314 +++++++++++--------
 .../src/qpidit/amqp_types_test/Receiver.hpp     |   7 +-
 .../src/qpidit/amqp_types_test/Sender.cpp       | 231 ++++++++------
 .../src/qpidit/amqp_types_test/Sender.hpp       |  27 +-
 .../src/amqp_types_test/Receiver.py             | 220 ++++++++++---
 .../src/amqp_types_test/Sender.py               | 162 +++++++---
 src/python/qpid_interop_test/amqp_types_test.py |  77 ++---
 9 files changed, 648 insertions(+), 395 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.cpp b/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.cpp
index ed8bc09..71fb4e3 100644
--- a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.cpp
+++ b/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.cpp
@@ -133,6 +133,10 @@ namespace qpidit
 
     // --- InvalidTestValueError ---
 
+    InvalidTestValueError::InvalidTestValueError(const std::string& valueStr) :
+                    std::runtime_error(MSG("Invalid element test value: \"" << valueStr << "\" is not in format \"amqp-type:value-as_str\""))
+    {}
+
     InvalidTestValueError::InvalidTestValueError(const std::string& type, const std::string& valueStr) :
                     std::runtime_error(MSG("Invalid test value: \"" << valueStr << "\" is not valid for type " << type))
     {}

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.hpp b/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.hpp
index 1779cce..7a1d2e2 100644
--- a/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.hpp
+++ b/shims/qpid-proton-cpp/src/qpidit/QpidItErrors.hpp
@@ -108,6 +108,7 @@ namespace qpidit
     class InvalidTestValueError: public std::runtime_error
     {
     public:
+        InvalidTestValueError(const std::string& valueStr);
         InvalidTestValueError(const std::string& type, const std::string& valueStr);
         virtual ~InvalidTestValueError() throw();
     };

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.cpp b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.cpp
index e5fe3d0..6b6f2ba 100644
--- a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.cpp
+++ b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.cpp
@@ -65,95 +65,7 @@ namespace qpidit
         void Receiver::on_message(proton::delivery &d, proton::message &m) {
             try {
                 if (_received < _expected) {
-                    if (_amqpType.compare("null") == 0) {
-                        checkMessageType(m, proton::NULL_TYPE);
-                        _receivedValueList.append("None");
-                    } else if (_amqpType.compare("boolean") == 0) {
-                        checkMessageType(m, proton::BOOLEAN);
-                        _receivedValueList.append(proton::get<bool>(m.body()) ? "True": "False");
-                    } else if (_amqpType.compare("ubyte") == 0) {
-                        checkMessageType(m, proton::UBYTE);
-                        _receivedValueList.append(toHexStr<uint8_t>(proton::get<uint8_t>(m.body())));
-                    } else if (_amqpType.compare("ushort") == 0) {
-                        checkMessageType(m, proton::USHORT);
-                        _receivedValueList.append(toHexStr<uint16_t>(proton::get<uint16_t>(m.body())));
-                    } else if (_amqpType.compare("uint") == 0) {
-                        checkMessageType(m, proton::UINT);
-                        _receivedValueList.append(toHexStr<uint32_t>(proton::get<uint32_t>(m.body())));
-                    } else if (_amqpType.compare("ulong") == 0) {
-                        checkMessageType(m, proton::ULONG);
-                        _receivedValueList.append(toHexStr<uint64_t>(proton::get<uint64_t>(m.body())));
-                    } else if (_amqpType.compare("byte") == 0) {
-                        checkMessageType(m, proton::BYTE);
-                        _receivedValueList.append(toHexStr<int8_t>(proton::get<int8_t>(m.body())));
-                    } else if (_amqpType.compare("short") == 0) {
-                        checkMessageType(m, proton::SHORT);
-                        _receivedValueList.append(toHexStr<int16_t>(proton::get<int16_t>(m.body())));
-                    } else if (_amqpType.compare("int") == 0) {
-                        checkMessageType(m, proton::INT);
-                        _receivedValueList.append(toHexStr<int32_t>(proton::get<int32_t>(m.body())));
-                    } else if (_amqpType.compare("long") == 0) {
-                        checkMessageType(m, proton::LONG);
-                        _receivedValueList.append(toHexStr<int64_t>(proton::get<int64_t>(m.body())));
-                    } else if (_amqpType.compare("float") == 0) {
-                        checkMessageType(m, proton::FLOAT);
-                        float f = proton::get<float>(m.body());
-                        _receivedValueList.append(toHexStr<uint32_t>(*((uint32_t*)&f), true));
-                    } else if (_amqpType.compare("double") == 0) {
-                        checkMessageType(m, proton::DOUBLE);
-                        double d = proton::get<double>(m.body());
-                        _receivedValueList.append(toHexStr<uint64_t>(*((uint64_t*)&d), true));
-                    } else if (_amqpType.compare("decimal32") == 0) {
-                        checkMessageType(m, proton::DECIMAL32);
-                        _receivedValueList.append(byteArrayToHexStr(proton::get<proton::decimal32>(m.body())));
-                    } else if (_amqpType.compare("decimal64") == 0) {
-                        checkMessageType(m, proton::DECIMAL64);
-                        _receivedValueList.append(byteArrayToHexStr(proton::get<proton::decimal64>(m.body())));
-                    } else if (_amqpType.compare("decimal128") == 0) {
-                        checkMessageType(m, proton::DECIMAL128);
-                        _receivedValueList.append(byteArrayToHexStr(proton::get<proton::decimal128>(m.body())));
-                    } else if (_amqpType.compare("char") == 0) {
-                        checkMessageType(m, proton::CHAR);
-                        wchar_t c = proton::get<wchar_t>(m.body());
-                        std::stringstream oss;
-                        if (c < 0x7f && std::iswprint(c)) {
-                            oss << (char)c;
-                        } else {
-                            oss << "0x" << std::hex << c;
-                        }
-                        _receivedValueList.append(oss.str());
-                    } else if (_amqpType.compare("timestamp") == 0) {
-                        checkMessageType(m, proton::TIMESTAMP);
-                        std::ostringstream oss;
-                        oss << "0x" << std::hex << proton::get<proton::timestamp>(m.body()).milliseconds();
-                        _receivedValueList.append(oss.str());
-                    } else if (_amqpType.compare("uuid") == 0) {
-                        checkMessageType(m, proton::UUID);
-                        std::ostringstream oss;
-                        oss << proton::get<proton::uuid>(m.body());
-                        _receivedValueList.append(oss.str());
-                    } else if (_amqpType.compare("binary") == 0) {
-                        checkMessageType(m, proton::BINARY);
-                        _receivedValueList.append(std::string(proton::get<proton::binary>(m.body())));
-                    } else if (_amqpType.compare("string") == 0) {
-                        checkMessageType(m, proton::STRING);
-                        _receivedValueList.append(proton::get<std::string>(m.body()));
-                    } else if (_amqpType.compare("symbol") == 0) {
-                        checkMessageType(m, proton::SYMBOL);
-                        _receivedValueList.append(proton::get<proton::symbol>(m.body()));
-                    } else if (_amqpType.compare("list") == 0) {
-                        checkMessageType(m, proton::LIST);
-                        Json::Value jsonList(Json::arrayValue);
-                        _receivedValueList.append(getSequence(jsonList, m.body()));
-                    } else if (_amqpType.compare("map") == 0) {
-                        checkMessageType(m, proton::MAP);
-                        Json::Value jsonMap(Json::objectValue);
-                        _receivedValueList.append(getMap(jsonMap, m.body()));
-                    } else if (_amqpType.compare("array") == 0) {
-                        throw qpidit::UnsupportedAmqpTypeError(_amqpType);
-                    } else {
-                        throw qpidit::UnknownAmqpTypeError(_amqpType);
-                    }
+                    _receivedValueList.append(getValue(_amqpType, m.body()));
                 }
                 _received++;
                 if (_received >= _expected) {
@@ -190,9 +102,40 @@ namespace qpidit
         // protected
 
         //static
-        void Receiver::checkMessageType(const proton::message& msg, proton::type_id amqpType) {
-            if (msg.body().type() != amqpType) {
-                throw qpidit::IncorrectMessageBodyTypeError(amqpType, msg.body().type());
+        void Receiver::checkMessageType(const proton::value& val, proton::type_id amqpType) {
+            if (val.type() != amqpType) {
+                throw qpidit::IncorrectMessageBodyTypeError(amqpType, val.type());
+            }
+        }
+
+        //static
+        std::string Receiver::getAmqpType(const proton::value& val) {
+            switch(val.type()) {
+            case proton::NULL_TYPE: return "null";
+            case proton::BOOLEAN: return "boolean";
+            case proton::UBYTE: return "ubyte";
+            case proton::USHORT: return "ushort";
+            case proton::UINT: return "uint";
+            case proton::ULONG: return "ulong";
+            case proton::BYTE: return "byte";
+            case proton::SHORT: return "short";
+            case proton::INT: return "int";
+            case proton::LONG: return "long";
+            case proton::FLOAT: return "float";
+            case proton::DOUBLE: return "double";
+            case proton::DECIMAL32: return "decimal32";
+            case proton::DECIMAL64: return "decimal64";
+            case proton::DECIMAL128: return "decimal128";
+            case proton::CHAR: return "char";
+            case proton::TIMESTAMP: return "timestamp";
+            case proton::UUID: return "uuid";
+            case proton::BINARY: return "binary";
+            case proton::STRING: return "string";
+            case proton::SYMBOL: return "symbol";
+            case proton::LIST: return "list";
+            case proton::MAP: return "map";
+            case proton::ARRAY: return "array";
+            //default: throw qpidit::UnknownAmqpTypeError(val);
             }
         }
 
@@ -201,27 +144,28 @@ namespace qpidit
             std::map<proton::value, proton::value> msgMap;
             proton::get(val, msgMap);
             for (std::map<proton::value, proton::value>::const_iterator i = msgMap.begin(); i != msgMap.end(); ++i) {
-                switch (i->second.type()) {
-                case proton::LIST:
-                {
-                    Json::Value jsonSubList(Json::arrayValue);
-                    jsonMap[proton::get<std::string>(i->first)] = getSequence(jsonSubList, i->second);
-                    break;
-                }
-                case proton::MAP:
-                {
-                    Json::Value jsonSubMap(Json::objectValue);
-                    jsonMap[proton::get<std::string>(i->first)] = getMap(jsonSubMap, i->second);
-                    break;
+
+                // Process key
+                Json::Value mapKey;
+                if (i->first.type() == proton::LIST || i->first.type() == proton::MAP || i->first.type() == proton::ARRAY) {
+                    mapKey = getValue(i->first);
+                } else {
+                    std::ostringstream oss;
+                    oss << getAmqpType(i->first) << ":" << getValue(i->first).asString();
+                    mapKey = oss.str();
                 }
-                case proton::ARRAY:
-                    break;
-                case proton::STRING:
-                    jsonMap[proton::get<std::string>(i->first)] = Json::Value(proton::get<std::string>(i->second));
-                    break;
-                default:
-                    throw qpidit::IncorrectValueTypeError(i->second);
+
+                // Process value
+                Json::Value mapValue;
+                if (i->second.type() == proton::LIST || i->second.type() == proton::MAP || i->second.type() == proton::ARRAY) {
+                    mapValue = getValue(i->second);
+                } else {
+                    std::ostringstream oss;
+                    oss << getAmqpType(i->second) << ":" << getValue(i->second).asString();
+                    mapValue = oss.str();
                 }
+
+                jsonMap[mapKey.asString()] = mapValue;
             }
             return jsonMap;
         }
@@ -231,39 +175,135 @@ namespace qpidit
             std::vector<proton::value> msgList;
             proton::get(val, msgList);
             for (std::vector<proton::value>::const_iterator i=msgList.begin(); i!=msgList.end(); ++i) {
-                switch ((*i).type()) {
-                case proton::LIST:
-                {
-                    Json::Value jsonSubList(Json::arrayValue);
-                    jsonList.append(getSequence(jsonSubList, *i));
-                    break;
-                }
-                case proton::MAP:
-                {
-                    Json::Value jsonSubMap(Json::objectValue);
-                    jsonList.append(getMap(jsonSubMap, *i));
-                    break;
-                }
-                case proton::ARRAY:
-                    break;
-                case proton::STRING:
-                    jsonList.append(Json::Value(proton::get<std::string>(*i)));
-                    break;
-                default:
-                    throw qpidit::IncorrectValueTypeError(*i);
+                if (i->type() == proton::LIST || i->type() == proton::MAP || i->type() == proton::ARRAY) {
+                    jsonList.append(getValue(*i));
+                } else {
+                    std::ostringstream oss;
+                    oss << getAmqpType(*i) << ":" << getValue(*i).asString();
+                    jsonList.append(oss.str());
                 }
             }
             return jsonList;
         }
 
         //static
-        std::string Receiver::stringToHexStr(const std::string& str) {
-            std::ostringstream oss;
-            oss << "0x" << std::hex;
-            for (std::string::const_iterator i=str.begin(); i!=str.end(); ++i) {
-                oss << std::setw(2) << std::setfill('0') << ((int)*i & 0xff);
+        Json::Value Receiver::getValue(const proton::value& val) {
+            return getValue(getAmqpType(val), val);
+        }
+
+        //static
+        Json::Value Receiver::getValue(const std::string& amqpType, const proton::value& val) {
+            if (amqpType.compare("null") == 0) {
+                checkMessageType(val, proton::NULL_TYPE);
+                return "None";
+            }
+            if (amqpType.compare("boolean") == 0) {
+                checkMessageType(val, proton::BOOLEAN);
+                return proton::get<bool>(val) ? "True" : "False";
+            }
+            if (amqpType.compare("ubyte") == 0) {
+                checkMessageType(val, proton::UBYTE);
+                return toHexStr<uint8_t>(proton::get<uint8_t>(val));
+            }
+            if (amqpType.compare("ushort") == 0) {
+                checkMessageType(val, proton::USHORT);
+                return toHexStr<uint16_t>(proton::get<uint16_t>(val));
+            }
+            if (amqpType.compare("uint") == 0) {
+                checkMessageType(val, proton::UINT);
+                return toHexStr<uint32_t>(proton::get<uint32_t>(val));
+            }
+            if (amqpType.compare("ulong") == 0) {
+                checkMessageType(val, proton::ULONG);
+                return toHexStr<uint64_t>(proton::get<uint64_t>(val));
+            }
+            if (amqpType.compare("byte") == 0) {
+                checkMessageType(val, proton::BYTE);
+                return toHexStr<int8_t>(proton::get<int8_t>(val));
+            }
+            if (amqpType.compare("short") == 0) {
+                checkMessageType(val, proton::SHORT);
+                return toHexStr<int16_t>(proton::get<int16_t>(val));
+            }
+            if (amqpType.compare("int") == 0) {
+                checkMessageType(val, proton::INT);
+                return toHexStr<int32_t>(proton::get<int32_t>(val));
+            }
+            if (amqpType.compare("long") == 0) {
+                checkMessageType(val, proton::LONG);
+                return toHexStr<int64_t>(proton::get<int64_t>(val));
+            }
+            if (amqpType.compare("float") == 0) {
+                checkMessageType(val, proton::FLOAT);
+                float f = proton::get<float>(val);
+                return toHexStr<uint32_t>(*((uint32_t*)&f), true);
+            }
+            if (amqpType.compare("double") == 0) {
+                checkMessageType(val, proton::DOUBLE);
+                double d = proton::get<double>(val);
+                return toHexStr<uint64_t>(*((uint64_t*)&d), true);
+            }
+            if (amqpType.compare("decimal32") == 0) {
+                checkMessageType(val, proton::DECIMAL32);
+                return byteArrayToHexStr(proton::get<proton::decimal32>(val));
+            }
+            if (amqpType.compare("decimal64") == 0) {
+                checkMessageType(val, proton::DECIMAL64);
+                return byteArrayToHexStr(proton::get<proton::decimal64>(val));
+            }
+            if (amqpType.compare("decimal128") == 0) {
+                checkMessageType(val, proton::DECIMAL128);
+                return byteArrayToHexStr(proton::get<proton::decimal128>(val));
+            }
+            if (amqpType.compare("char") == 0) {
+                checkMessageType(val, proton::CHAR);
+                wchar_t c = proton::get<wchar_t>(val);
+                std::stringstream oss;
+                if (c < 0x7f && std::iswprint(c)) {
+                    oss << (char)c;
+                } else {
+                    oss << "0x" << std::hex << c;
+                }
+                return oss.str();
+            }
+            if (amqpType.compare("timestamp") == 0) {
+                checkMessageType(val, proton::TIMESTAMP);
+                std::ostringstream oss;
+                oss << "0x" << std::hex << proton::get<proton::timestamp>(val).milliseconds();
+                return oss.str();
+            }
+            if (amqpType.compare("uuid") == 0) {
+                checkMessageType(val, proton::UUID);
+                std::ostringstream oss;
+                oss << proton::get<proton::uuid>(val);
+                return oss.str();
+            }
+            if (amqpType.compare("binary") == 0) {
+                checkMessageType(val, proton::BINARY);
+                return std::string(proton::get<proton::binary>(val));
+            }
+            if (amqpType.compare("string") == 0) {
+                checkMessageType(val, proton::STRING);
+                return proton::get<std::string>(val);
+            }
+            if (amqpType.compare("symbol") == 0) {
+                checkMessageType(val, proton::SYMBOL);
+                return proton::get<proton::symbol>(val);
+            }
+            if (amqpType.compare("list") == 0) {
+                checkMessageType(val, proton::LIST);
+                Json::Value jsonList(Json::arrayValue);
+                return getSequence(jsonList, val);
+            }
+            if (amqpType.compare("map") == 0) {
+                checkMessageType(val, proton::MAP);
+                Json::Value jsonMap(Json::objectValue);
+                return getMap(jsonMap, val);
+            }
+            if (amqpType.compare("array") == 0) {
+                throw qpidit::UnsupportedAmqpTypeError(amqpType);
             }
-            return oss.str();
+            throw qpidit::UnknownAmqpTypeError(amqpType);
         }
 
     } /* namespace amqp_types_test */

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.hpp b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.hpp
index 16c13c2..8b5b32d 100644
--- a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.hpp
+++ b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Receiver.hpp
@@ -55,10 +55,13 @@ namespace qpidit
             void on_transport_error(proton::transport &t);
             void on_error(const proton::error_condition &c);
         protected:
-            static void checkMessageType(const proton::message& msg, proton::type_id msgType);
+            //static void checkMessageType(const proton::message& msg, const proton::type_id amqpType);
+            static void checkMessageType(const proton::value& val, const proton::type_id amqpType);
+            static std::string getAmqpType(const proton::value& val);
             static Json::Value& getMap(Json::Value& jsonMap, const proton::value& val);
             static Json::Value& getSequence(Json::Value& jsonList, const proton::value& val);
-            static std::string stringToHexStr(const std::string& str);
+            static Json::Value getValue(const proton::value& val);
+            static Json::Value getValue(const std::string& amqpType, const proton::value& val);
 
             // Format signed numbers in negative hex format, ie -0xNNNN, positive numbers in 0xNNNN format
             template<typename T> static std::string toHexStr(T val, bool fillFlag = false) {

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.cpp b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.cpp
index 8cdb72c..d083791 100644
--- a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.cpp
+++ b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.cpp
@@ -21,6 +21,7 @@
 
 #include "qpidit/amqp_types_test/Sender.hpp"
 
+#include <cstdlib>
 #include <iomanip>
 #include <iostream>
 #include <json/json.h>
@@ -65,53 +66,94 @@ namespace qpidit
 
         proton::message& Sender::setMessage(proton::message& msg, const Json::Value& testValue) {
             msg.id(_msgsSent + 1);
-            if (_amqpType.compare("null") == 0) {
+            msg.body(convertAmqpValue(_amqpType, testValue));
+            return msg;
+        }
+
+        //static
+        std::string Sender::bytearrayToHexStr(const char* src, int len) {
+            std::ostringstream oss;
+            oss << "0x" << std::hex;
+            for (int i=0; i<len; ++i) {
+                oss <<  std::setw(2) << std::setfill('0') << ((int)src[i] & 0xff);
+            }
+            return oss.str();
+        }
+
+        //static
+        proton::value Sender::convertAmqpValue(const std::string& amqpType, const Json::Value& testValue) {
+            if (amqpType.compare("null") == 0) {
                 std::string testValueStr(testValue.asString());
-                if (testValueStr.compare("None") != 0) { throw qpidit::InvalidTestValueError(_amqpType, testValueStr); }
+                if (testValueStr.compare("None") != 0) {
+                    throw qpidit::InvalidTestValueError(amqpType, testValueStr);
+                }
                 proton::value v;
-                msg.body(v);
-            } else if (_amqpType.compare("boolean") == 0) {
+                return v;
+            }
+            if (amqpType.compare("boolean") == 0) {
                 std::string testValueStr(testValue.asString());
                 if (testValueStr.compare("True") == 0) {
-                    msg.body(true);
+                    return true;
                 } else if (testValueStr.compare("False") == 0) {
-                    msg.body(false);
+                    return false;
                 } else {
-                    throw qpidit::InvalidTestValueError(_amqpType, testValueStr);
+                    throw qpidit::InvalidTestValueError(amqpType, testValueStr);
                 }
-            } else if (_amqpType.compare("ubyte") == 0) {
-                setIntegralValue<uint8_t>(msg, testValue.asString(), true);
-            } else if (_amqpType.compare("ushort") == 0) {
-                setIntegralValue<uint16_t>(msg, testValue.asString(), true);
-            } else if (_amqpType.compare("uint") == 0) {
-                setIntegralValue<uint32_t>(msg, testValue.asString(), true);
-            } else if (_amqpType.compare("ulong") == 0) {
-                setIntegralValue<uint64_t>(msg, testValue.asString(), true);
-            } else if (_amqpType.compare("byte") == 0) {
-                setIntegralValue<int8_t>(msg, testValue.asString(), false);
-            } else if (_amqpType.compare("short") == 0) {
-                setIntegralValue<int16_t>(msg, testValue.asString(), false);
-            } else if (_amqpType.compare("int") == 0) {
-                setIntegralValue<int32_t>(msg, testValue.asString(), false);
-            } else if (_amqpType.compare("long") == 0) {
-                setIntegralValue<int64_t>(msg, testValue.asString(), false);
-            } else if (_amqpType.compare("float") == 0) {
-                setFloatValue<float, uint32_t>(msg, testValue.asString());
-            } else if (_amqpType.compare("double") == 0) {
-                setFloatValue<double, uint64_t>(msg, testValue.asString());
-            } else if (_amqpType.compare("decimal32") == 0) {
+            }
+            if (amqpType.compare("ubyte") == 0) {
+                return integralValue<uint8_t>(amqpType, testValue.asString(), true);
+            }
+            if (amqpType.compare("ushort") == 0) {
+                return integralValue<uint16_t>(amqpType, testValue.asString(), true);
+            }
+            if (amqpType.compare("uint") == 0) {
+                return integralValue<uint32_t>(amqpType, testValue.asString(), true);
+            }
+            if (amqpType.compare("ulong") == 0) {
+                return integralValue<uint64_t>(amqpType, testValue.asString(), true);
+            }
+            if (amqpType.compare("byte") == 0) {
+                return integralValue<int8_t>(amqpType, testValue.asString(), false);
+            }
+            if (amqpType.compare("short") == 0) {
+                return integralValue<int16_t>(amqpType, testValue.asString(), false);
+            }
+            if (amqpType.compare("int") == 0) {
+                return integralValue<int32_t>(amqpType, testValue.asString(), false);
+            }
+            if (amqpType.compare("long") == 0) {
+                return integralValue<int64_t>(amqpType, testValue.asString(), false);
+            }
+            if (amqpType.compare("float") == 0) {
+                const std::string testValueStr = testValue.asString();
+                if (testValueStr.find("0x") == std::string::npos) // regular decimal fraction
+                    return std::strtof(testValueStr.c_str(), nullptr);
+                // hex representation of float
+                return floatValue<float, uint32_t>(amqpType, testValue.asString());
+            }
+            if (amqpType.compare("double") == 0) {
+                const std::string testValueStr = testValue.asString();
+                if (testValueStr.find("0x") == std::string::npos) // regular decimal fraction
+                    return std::strtod(testValueStr.c_str(), nullptr);
+                // hex representation of float
+                return floatValue<double, uint64_t>(amqpType, testValue.asString());
+            }
+            if (amqpType.compare("decimal32") == 0) {
                 proton::decimal32 val;
                 hexStringToBytearray(val, testValue.asString().substr(2));
-                msg.body(val);
-            } else if (_amqpType.compare("decimal64") == 0) {
+                return val;
+            }
+            if (amqpType.compare("decimal64") == 0) {
                 proton::decimal64 val;
                 hexStringToBytearray(val, testValue.asString().substr(2));
-                msg.body(val);
-            } else if (_amqpType.compare("decimal128") == 0) {
+                return val;
+            }
+            if (amqpType.compare("decimal128") == 0) {
                 proton::decimal128 val;
                 hexStringToBytearray(val, testValue.asString().substr(2));
-                msg.body(val);
-            } else if (_amqpType.compare("char") == 0) {
+                return val;
+            }
+            if (amqpType.compare("char") == 0) {
                 std::string charStr = testValue.asString();
                 wchar_t val;
                 if (charStr.size() == 1) { // Single char "a"
@@ -121,11 +163,14 @@ namespace qpidit
                 } else {
                     //TODO throw format error
                 }
-                msg.body(val);
-            } else if (_amqpType.compare("timestamp") == 0) {
-                proton::timestamp val(std::strtoul(testValue.asString().data(), NULL, 16));
-                msg.body(val);
-            } else if (_amqpType.compare("uuid") == 0) {
+                return val;
+            }
+            if (amqpType.compare("timestamp") == 0) {
+                const std::string testValueStr(testValue.asString());
+                bool xhexFlag = testValueStr.find("0x") != std::string::npos;
+                return proton::timestamp(std::strtoul(testValue.asString().data(), NULL, xhexFlag ? 16 : 10));
+            }
+            if (amqpType.compare("uuid") == 0) {
                 proton::uuid val;
                 std::string uuidStr(testValue.asString());
                 // Expected format: "00000000-0000-0000-0000-000000000000"
@@ -136,70 +181,35 @@ namespace qpidit
                 hexStringToBytearray(val, uuidStr.substr(14, 4), 6, 2);
                 hexStringToBytearray(val, uuidStr.substr(19, 4), 8, 2);
                 hexStringToBytearray(val, uuidStr.substr(24, 12), 10, 6);
-                msg.body(val);
-            } else if (_amqpType.compare("binary") == 0) {
-                //setStringValue<proton::amqp_binary>(msg, testValue.asString());
-                proton::binary val(testValue.asString());
-                msg.body(val);
-            } else if (_amqpType.compare("string") == 0) {
-                //setStringValue<proton::amqp_string>(msg, testValue.asString());
-                std::string val(testValue.asString());
-                msg.body(val);
-            } else if (_amqpType.compare("symbol") == 0) {
-                //setStringValue<proton::amqp_symbol>(msg, testValue.asString());
-                proton::symbol val(testValue.asString());
-                msg.body(val);
-            } else if (_amqpType.compare("list") == 0) {
+                return val;
+            }
+            if (amqpType.compare("binary") == 0) {
+                return proton::binary(testValue.asString());
+            }
+            if (amqpType.compare("string") == 0) {
+                return std::string(testValue.asString());
+            }
+            if (amqpType.compare("symbol") == 0) {
+                return proton::symbol(testValue.asString());
+            }
+            if (amqpType.compare("list") == 0) {
                 std::vector<proton::value> list;
                 processList(list, testValue);
-                msg.body(list);
-            } else if (_amqpType.compare("map") == 0) {
-                std::map<std::string, proton::value> map;
+                return list;
+            } else if (amqpType.compare("map") == 0) {
+                std::map<proton::value, proton::value> map;
                 processMap(map, testValue);
-                msg.body(map);
-            } else if (_amqpType.compare("array") == 0) {
+                return map;
+            }
+            if (amqpType.compare("array") == 0) {
 /*
                 std::vector<proton::value> array;
                 processArray(array, testValue);
-                msg.body(proton::as<proton::ARRAY>(array));
+                return proton::as<proton::ARRAY>(array);
 */
-                throw qpidit::UnsupportedAmqpTypeError(_amqpType);
-            } else {
-                throw qpidit::UnknownAmqpTypeError(_amqpType);
-            }
-            return msg;
-        }
-
-        //static
-        std::string Sender::bytearrayToHexStr(const char* src, int len) {
-            std::ostringstream oss;
-            oss << "0x" << std::hex;
-            for (int i=0; i<len; ++i) {
-                oss <<  std::setw(2) << std::setfill('0') << ((int)src[i] & 0xff);
-            }
-            return oss.str();
-        }
-
-        //static
-        proton::value Sender::extractProtonValue(const Json::Value& val) {
-            switch (val.type()) {
-            case Json::nullValue:
-            {
-                proton::value v; //proton::null n;
-                return v; //proton::value(n);
-            }
-            case Json::intValue:
-                return proton::value(val.asInt());
-            case Json::uintValue:
-                return proton::value(val.asUInt());
-            case Json::realValue:
-                return proton::value(val.asDouble());
-            case Json::stringValue:
-                return proton::value(val.asString());
-            case Json::booleanValue:
-                return proton::value(val.asBool());
-            default:;
+                throw qpidit::UnsupportedAmqpTypeError(amqpType);
             }
+            throw qpidit::UnknownAmqpTypeError(amqpType);
         }
 
 //        //static
@@ -219,7 +229,7 @@ namespace qpidit
                     processArray(subArray, *i);
                     array.push_back(proton::value(subArray));
                 } else if ((*i).isObject()) {
-                    std::map<std::string, proton::value> subMap;
+                    std::map<proton::value, proton::value> subMap;
                     processMap(subMap, *i);
                     array.push_back(proton::value(subMap));
                 } else {
@@ -244,6 +254,19 @@ namespace qpidit
         }
 
         //static
+        proton::value Sender::processElement(const Json::Value& testValue) {
+            const std::string testValueStr(testValue.asString());
+            // testValue has the format amqp-type:amqp-str-value
+            const std::size_t splitIndex = testValueStr.find_first_of(':');
+            if (splitIndex == std::string::npos) {
+                throw qpidit::InvalidTestValueError(testValueStr);
+            }
+            const std::string amqpType = testValueStr.substr(0, splitIndex);
+            const std::string amqpValueAsStr = testValueStr.substr(splitIndex + 1);
+            return convertAmqpValue(amqpType, amqpValueAsStr);
+        }
+
+        //static
         void Sender::processList(std::vector<proton::value>& list, const Json::Value& testValues) {
             for (Json::Value::const_iterator i = testValues.begin(); i != testValues.end(); ++i) {
                 if ((*i).isArray()) {
@@ -251,31 +274,31 @@ namespace qpidit
                     processList(subList, *i);
                     list.push_back(proton::value(subList));
                 } else if ((*i).isObject()) {
-                    std::map<std::string, proton::value> subMap;
+                    std::map<proton::value, proton::value> subMap;
                     processMap(subMap, *i);
                     list.push_back(proton::value(subMap));
                 } else {
-                    list.push_back(extractProtonValue(*i));
+                    list.push_back(processElement(*i));
                 }
             }
-            //std::cout << std::endl;
         }
 
         //static
-        void Sender::processMap(std::map<std::string, proton::value>& map, const Json::Value& testValues) {
+        void Sender::processMap(std::map<proton::value, proton::value>& map, const Json::Value& testValues) {
             Json::Value::Members keys = testValues.getMemberNames();
             for (std::vector<std::string>::const_iterator i=keys.begin(); i!=keys.end(); ++i) {
+                proton::value key = processElement(*i);
                 Json::Value mapVal = testValues[*i];
                 if (mapVal.isArray()) {
                     std::vector<proton::value> subList;
                     processList(subList, mapVal);
-                    map[*i] = subList;
+                    map[key] = subList;
                 } else if (mapVal.isObject()) {
-                    std::map<std::string, proton::value> subMap;
+                    std::map<proton::value, proton::value> subMap;
                     processMap(subMap, mapVal);
-                    map[*i] = subMap;
+                    map[key] = subMap;
                 } else {
-                    map[*i] = extractProtonValue(mapVal);
+                    map[key] = processElement(mapVal);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.hpp b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.hpp
index 17879cd..88b81df 100644
--- a/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.hpp
+++ b/shims/qpid-proton-cpp/src/qpidit/amqp_types_test/Sender.hpp
@@ -51,11 +51,12 @@ namespace qpidit
             static void revMemcpy(char* dest, const char* src, int n);
             static void uint64ToChar16(char* dest, uint64_t upper, uint64_t lower);
 
-            static proton::value extractProtonValue(const Json::Value& val);
+            static proton::value convertAmqpValue(const std::string& amqpType, const Json::Value& testValue);
             //static Json::Value::ValueType getArrayType(const Json::Value& val);
             static void processArray(std::vector<proton::value>& array, const Json::Value& testValues);
+            static proton::value processElement(const Json::Value& testValue);
             static void processList(std::vector<proton::value>& list, const Json::Value& testValues);
-            static void processMap(std::map<std::string, proton::value>& map, const Json::Value& testValues);
+            static void processMap(std::map<proton::value, proton::value>& map, const Json::Value& testValues);
 
             template<size_t N> static void hexStringToBytearray(proton::byte_array<N>& ba, const std::string s, size_t fromArrayIndex = 0, size_t arrayLen = N) {
                 for (size_t i=0; i<arrayLen; ++i) {
@@ -65,25 +66,19 @@ namespace qpidit
 
             // Set message body to floating type T through integral type U
             // Used to convert a hex string representation of a float or double to a float or double
-            template<typename T, typename U> void setFloatValue(proton::message& msg, const std::string& testValueStr) {
+            template<typename T, typename U> static proton::value floatValue(const std::string& amqpType, const std::string& testValueStr) {
                 try {
                     U ival(std::strtoul(testValueStr.data(), NULL, 16));
-                    msg.body(T(*reinterpret_cast<T*>(&ival)));
-                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(_amqpType, testValueStr); }
+                    return proton::value(T(*reinterpret_cast<T*>(&ival)));
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(amqpType, testValueStr); }
             }
 
-            template<typename T> void setIntegralValue(proton::message& msg, const std::string& testValueStr, bool unsignedVal) {
+            template<typename T> static proton::value integralValue(const std::string& amqpType, const std::string& testValueStr, bool unsignedVal) {
+                const int base = (testValueStr.find("0x") != std::string::npos) ? 16 : 10;
                 try {
-                    T val(unsignedVal ? std::strtoul(testValueStr.data(), NULL, 16) : std::strtol(testValueStr.data(), NULL, 16));
-                    msg.body(val);
-                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(_amqpType, testValueStr); }
-            }
-
-            template<typename T> void setStringValue(proton::message& msg, const std::string& testValueStr) {
-                try {
-                    T val(testValueStr);
-                    msg.body(val);
-                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(_amqpType, testValueStr); }
+                    T val(unsignedVal ? std::strtoul(testValueStr.data(), NULL, base) : std::strtol(testValueStr.data(), NULL, base));
+                    return val;
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(amqpType, testValueStr); }
             }
         };
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py b/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
index 594d33a..5067de2 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
@@ -30,6 +30,7 @@ import string
 import struct
 import sys
 import traceback
+import uuid
 
 import proton
 import proton.handlers
@@ -66,61 +67,178 @@ class AmqpTypesTestReceiver(proton.handlers.MessagingHandler):
         """Event callback when a message is received by the client"""
         if event.message.id and event.message.id < self.received:
             return # ignore duplicate message
-        if self.received < self.expected:
-            if self.amqp_type == 'null' or \
-               self.amqp_type == 'boolean' or \
-               self.amqp_type == 'uuid':
-                self.received_value_list.append(str(event.message.body))
-            elif self.amqp_type == 'ubyte' or \
-               self.amqp_type == 'ushort' or \
-               self.amqp_type == 'byte' or \
-               self.amqp_type == 'short' or \
-               self.amqp_type == 'int':
-                self.received_value_list.append(hex(event.message.body))
-            elif self.amqp_type == 'uint' or \
-               self.amqp_type == 'ulong' or \
-               self.amqp_type == 'long' or \
-               self.amqp_type == 'timestamp':
-                hex_str = hex(int(event.message.body))
-                if len(hex_str) == 19 and hex_str[-1] == 'L':
-                    self.received_value_list.append(hex_str[:-1]) # strip trailing 'L' if present on some ulongs
-                else:
-                    self.received_value_list.append(hex_str)
-            elif self.amqp_type == 'float':
-                self.received_value_list.append('0x%08x' % struct.unpack('!L',
-                                                                         struct.pack('!f', event.message.body))[0])
-            elif self.amqp_type == 'double':
-                self.received_value_list.append('0x%016x' % struct.unpack('!Q',
-                                                                          struct.pack('!d', event.message.body))[0])
-            elif self.amqp_type == 'decimal32':
-                self.received_value_list.append('0x%08x' % event.message.body)
-            elif self.amqp_type == 'decimal64':
-                self.received_value_list.append('0x%016x' % event.message.body)
-            elif self.amqp_type == 'decimal128':
-                self.received_value_list.append('0x' + ''.join(['%02x' % _compat.byte_char_ord(c) \
-                                                                for c in event.message.body]).strip())
-            elif self.amqp_type == 'char':
-                if ord(event.message.body) < 0x80 and event.message.body in \
-                   string.digits + _compat.letters() + string.punctuation + ' ':
-                    self.received_value_list.append(event.message.body)
-                else:
-                    self.received_value_list.append(hex(ord(event.message.body)))
-            elif self.amqp_type == 'binary':
-                self.received_value_list.append(event.message.body.decode('utf-8'))
-            elif self.amqp_type == 'string' or \
-                 self.amqp_type == 'symbol':
-                self.received_value_list.append(event.message.body)
-            elif self.amqp_type == 'list' or \
-                 self.amqp_type == 'map':
-                self.received_value_list.append(event.message.body)
-            else:
-                print('receive: Unsupported AMQP type "%s"' % self.amqp_type)
-                return
-            self.received += 1
+        test_value = AmqpTypesTestReceiver.decode_amqp_type(self.amqp_type, event.message.body)
+        if test_value is None:
+            return
+        self.received_value_list.append(test_value)
+        self.received += 1
         if self.received >= self.expected:
             event.receiver.close()
             event.connection.close()
 
+    @staticmethod
+    def longhex(amqp_value):
+        """Create a long hex string"""
+        hex_str = hex(int(amqp_value))
+        if len(hex_str) == 19 and hex_str[-1] == 'L':
+            return hex_str[:-1] # strip trailing 'L' if present on some ulongs
+        return hex_str
+
+    @staticmethod
+    def decode_amqp_type(amqp_type, amqp_value):
+        """Decode amqp type"""
+        if amqp_type == 'null':
+            return str(amqp_value)
+        if amqp_type == 'boolean':
+            return str(amqp_value)
+        if amqp_type == 'ubyte':
+            return hex(amqp_value)
+        if amqp_type == 'ushort':
+            return hex(amqp_value)
+        if amqp_type == 'uint':
+            return AmqpTypesTestReceiver.longhex(amqp_value)
+        if amqp_type == 'ulong':
+            return AmqpTypesTestReceiver.longhex(amqp_value)
+        if amqp_type == 'byte':
+            return hex(amqp_value)
+        if amqp_type == 'short':
+            return hex(amqp_value)
+        if amqp_type == 'int':
+            return hex(amqp_value)
+        if amqp_type == 'long':
+            return AmqpTypesTestReceiver.longhex(amqp_value)
+        if amqp_type == 'float':
+            return '0x%08x' % struct.unpack('!L', struct.pack('!f', amqp_value))[0]
+        if amqp_type == 'double':
+            return '0x%016x' % struct.unpack('!Q', struct.pack('!d', amqp_value))[0]
+        if amqp_type == 'decimal32':
+            return '0x%08x' % amqp_value
+        if amqp_type == 'decimal64':
+            return '0x%016x' % amqp_value
+        if amqp_type == 'decimal128':
+            return '0x' + ''.join(['%02x' % _compat.byte_char_ord(c) for c in amqp_value]).strip()
+        if amqp_type == 'char':
+            if ord(amqp_value) < 0x80 and amqp_value in string.digits + _compat.letters() + string.punctuation + ' ':
+                return amqp_value
+            return hex(ord(amqp_value))
+        if amqp_type == 'timestamp':
+            return AmqpTypesTestReceiver.longhex(amqp_value)
+        if amqp_type == 'uuid':
+            return str(amqp_value)
+        if amqp_type == 'binary':
+            return amqp_value.decode('utf-8')
+        if amqp_type == 'string':
+            return amqp_value
+        if amqp_type == 'symbol':
+            return amqp_value
+        if amqp_type == 'list':
+            return AmqpTypesTestReceiver.decode_amqp_list(amqp_value)
+        if amqp_type == 'map':
+            return AmqpTypesTestReceiver.decode_amqp_map(amqp_value)
+        if amqp_type == 'array':
+            #return AmqpTypesTestReceiver.decode_amqp_array(amqp_value)
+            print('receive: Unsupported AMQP type "%s"' % amqp_type)
+            return None
+        print('receive: Unknown AMQP type "%s"' % amqp_type)
+        return None
+
+    @staticmethod
+    def get_amqp_type(amqp_value):
+        """Get the AMQP type from the Python type"""
+        if amqp_value is None:
+            return "null"
+        if isinstance(amqp_value, bool):
+            return "boolean"
+        if isinstance(amqp_value, proton.ubyte):
+            return "ubyte"
+        if isinstance(amqp_value, proton.ushort):
+            return "ushort"
+        if isinstance(amqp_value, proton.uint):
+            return "uint"
+        if isinstance(amqp_value, proton.ulong):
+            return "ulong"
+        if isinstance(amqp_value, proton.byte):
+            return "byte"
+        if isinstance(amqp_value, proton.short):
+            return "short"
+        if isinstance(amqp_value, proton.int32):
+            return "int"
+        if isinstance(amqp_value, proton.float32):
+            return "float"
+        if isinstance(amqp_value, proton.decimal32):
+            return "decimal32"
+        if isinstance(amqp_value, proton.decimal64):
+            return "decimal64"
+        if isinstance(amqp_value, proton.decimal128):
+            return "decimal128"
+        if isinstance(amqp_value, proton.char):
+            return "char"
+        if isinstance(amqp_value, proton.timestamp):
+            return "timestamp"
+        if isinstance(amqp_value, uuid.UUID):
+            return "uuid"
+        if isinstance(amqp_value, proton.symbol):
+            return "symbol"
+        if isinstance(amqp_value, proton.Array):
+            return "array"
+        # Native types come last so that parent classes will not be found instead (issue using isinstance()
+        if _compat.IS_PY3:
+            if isinstance(amqp_value, int):
+                return "long"
+            if isinstance(amqp_value, bytes):
+                return "binary"
+            if isinstance(amqp_value, str):
+                return "string"
+        else:
+            import __builtin__
+            if isinstance(amqp_value, __builtin__.long):
+                return "long"
+            if isinstance(amqp_value, str):
+                return "binary"
+            if isinstance(amqp_value, unicode):
+                return "string"
+        if isinstance(amqp_value, float):
+            return "double"
+        if isinstance(amqp_value, list):
+            return "list"
+        if isinstance(amqp_value, dict):
+            return "map"
+
+        print('receive: Unmapped AMQP type: %s:%s' % (type(amqp_value), amqp_value))
+
+    @staticmethod
+    def decode_complex_amqp_element(amqp_value):
+        """Decode an element from a complex AMQP type from its Python value"""
+        amqp_type = AmqpTypesTestReceiver.get_amqp_type(amqp_value)
+        if amqp_type == "list":
+            return AmqpTypesTestReceiver.decode_amqp_list(amqp_value)
+        if amqp_type == "map":
+            return AmqpTypesTestReceiver.decode_amqp_map(amqp_value)
+        return "%s:%s" % (amqp_type, AmqpTypesTestReceiver.decode_amqp_type(amqp_type, amqp_value))
+
+    @staticmethod
+    def decode_amqp_list(amqp_value):
+        """Decode amqp list type"""
+#        print('LIST:%s' % amqp_value)
+        amqp_list = []
+        for list_item in amqp_value:
+            amqp_list.append(AmqpTypesTestReceiver.decode_complex_amqp_element(list_item))
+        return amqp_list
+
+    @staticmethod
+    def decode_amqp_map(amqp_value):
+        """Decode amqp map type"""
+        amqp_map = {}
+        for key, value in amqp_value.items():
+            amqp_map[AmqpTypesTestReceiver.decode_complex_amqp_element(key)] = \
+                    AmqpTypesTestReceiver.decode_complex_amqp_element(value)
+        return amqp_map
+
+    @staticmethod
+    def decode_amqp_array(amqp_value):
+        """Decode amqp array type"""
+        return amqp_value
+
     def on_transport_error(self, event):
         print('Receiver: Broker not found at %s' % self.broker_url)
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/shims/qpid-proton-python/src/amqp_types_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_types_test/Sender.py b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
index a4664b7..cd0384e 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
@@ -77,60 +77,122 @@ class AmqpTypesTestSender(proton.handlers.MessagingHandler):
         Creates a single message with the test value translated from its string representation to the appropriate
         AMQP value (set in self.amqp_type).
         """
-        if self.amqp_type == 'null':
-            return proton.Message(id=(self.sent+1), body=None)
-        if self.amqp_type == 'boolean':
-            return proton.Message(id=(self.sent+1), body=True if test_value == 'True' else False)
-        if self.amqp_type == 'ubyte':
-            return proton.Message(id=(self.sent+1), body=proton.ubyte(int(test_value, 16)))
-        if self.amqp_type == 'ushort':
-            return proton.Message(id=(self.sent+1), body=proton.ushort(int(test_value, 16)))
-        if self.amqp_type == 'uint':
-            return proton.Message(id=(self.sent+1), body=proton.uint(int(test_value, 16)))
-        if self.amqp_type == 'ulong':
-            return proton.Message(id=(self.sent+1), body=proton.ulong(int(test_value, 16)))
-        if self.amqp_type == 'byte':
-            return proton.Message(id=(self.sent+1), body=proton.byte(int(test_value, 16)))
-        if self.amqp_type == 'short':
-            return proton.Message(id=(self.sent+1), body=proton.short(int(test_value, 16)))
-        if self.amqp_type == 'int':
-            return proton.Message(id=(self.sent+1), body=proton.int32(int(test_value, 16)))
-        if self.amqp_type == 'long':
-            return proton.Message(id=(self.sent+1), body=_compat.long(test_value, 16))
-        if self.amqp_type == 'float':
-            return proton.Message(id=(self.sent+1),
-                                  body=proton.float32(struct.unpack('!f', _compat.decode_hex(test_value[2:]))[0]))
-        if self.amqp_type == 'double':
-            return proton.Message(id=(self.sent+1), body=struct.unpack('!d', _compat.decode_hex(test_value[2:]))[0])
-        if self.amqp_type == 'decimal32':
-            return proton.Message(id=(self.sent+1), body=proton.decimal32(int(test_value[2:], 16)))
-        if self.amqp_type == 'decimal64':
-            l64 = _compat.long(test_value[2:], 16)
-            return proton.Message(id=(self.sent+1), body=proton.decimal64(l64))
-        if self.amqp_type == 'decimal128':
-            return proton.Message(id=(self.sent+1), body=proton.decimal128(_compat.decode_hex(test_value[2:])))
-        if self.amqp_type == 'char':
+        return proton.Message(id=(self.sent+1), body=self.encode_amqp_type(self.amqp_type, test_value))
+
+    @staticmethod
+    def encode_amqp_type(amqp_type, test_value):
+        """Encode an AMQP type from a stringified test_value"""
+        if amqp_type == 'null':
+            return None
+        if amqp_type == 'boolean':
+            return True if test_value == 'True' else False
+        if amqp_type == 'ubyte':
+            return proton.ubyte(int(test_value, 16))
+        if amqp_type == 'ushort':
+            return proton.ushort(int(test_value, 16))
+        if amqp_type == 'uint':
+            return proton.uint(int(test_value, 16))
+        if amqp_type == 'ulong':
+            return proton.ulong(int(test_value, 16))
+        if amqp_type == 'byte':
+            return proton.byte(int(test_value, 16))
+        if amqp_type == 'short':
+            return proton.short(int(test_value, 16))
+        if amqp_type == 'int':
+            return proton.int32(int(test_value, 16))
+        if amqp_type == 'long':
+            return _compat.long(test_value, 16)
+        if amqp_type == 'float':
+            return proton.float32(struct.unpack('!f', _compat.decode_hex(test_value[2:]))[0])
+        if amqp_type == 'double':
+            return struct.unpack('!d', _compat.decode_hex(test_value[2:]))[0]
+        if amqp_type == 'decimal32':
+            return proton.decimal32(int(test_value[2:], 16))
+        if amqp_type == 'decimal64':
+            return proton.decimal64(_compat.long(test_value[2:], 16))
+        if amqp_type == 'decimal128':
+            return proton.decimal128(_compat.decode_hex(test_value[2:]))
+        if amqp_type == 'char':
             if len(test_value) == 1: # Format 'a'
-                return proton.Message(id=(self.sent+1), body=proton.char(test_value))
+                return proton.char(test_value)
             val = int(test_value, 16)
-            return proton.Message(id=(self.sent+1), body=proton.char(_compat.unichr(val)))
-        if self.amqp_type == 'timestamp':
-            return proton.Message(id=(self.sent+1), body=proton.timestamp(int(test_value, 16)))
-        if self.amqp_type == 'uuid':
-            return proton.Message(id=(self.sent+1), body=uuid.UUID(test_value))
-        if self.amqp_type == 'binary':
-            return proton.Message(id=(self.sent+1), body=test_value.encode('utf-8'))
-        if self.amqp_type == 'string':
-            return proton.Message(id=(self.sent+1), body=_compat.unicode(test_value))
-        if self.amqp_type == 'symbol':
-            return proton.Message(id=(self.sent+1), body=proton.symbol(test_value))
-        if self.amqp_type == 'list':
-            return proton.Message(id=(self.sent+1), body=test_value)
-        if self.amqp_type == 'map':
-            return proton.Message(id=(self.sent+1), body=test_value)
-        print('send: Unsupported AMQP type "%s"' % self.amqp_type)
+            return proton.char(_compat.unichr(val))
+        if amqp_type == 'timestamp':
+            return proton.timestamp(int(test_value, 16))
+        if amqp_type == 'uuid':
+            return uuid.UUID(test_value)
+        if amqp_type == 'binary':
+            return test_value.encode('utf-8')
+        if amqp_type == 'string':
+            return _compat.unicode(test_value)
+        if amqp_type == 'symbol':
+            return proton.symbol(test_value)
+        if amqp_type == 'list':
+            return AmqpTypesTestSender.encode_amqp_list(test_value)
+        if amqp_type == 'map':
+            return AmqpTypesTestSender.encode_amqp_map(test_value)
+        if amqp_type == 'array':
+            #return AmqpTypesTestSender.encode_amqp_array(test_value)
+            print('send: Unsupported AMQP type "%s"' % amqp_type)
+            return None
+        print('send: Unknown AMQP type "%s"' % amqp_type)
         return None
 
+    @staticmethod
+    def encode_complex_amqp_element(test_element, make_hashable=False):
+        """
+        Encode a single complex AMQP element (ie list or array member, map key or value)
+        A complex element may be one of:
+        str/unicode: 'amqp_type:amqp_value'
+        list: [...]
+        dict: {...}
+        """
+        if _compat.IS_PY3:
+            is_string = isinstance(test_element, str)
+        else:
+            is_string = isinstance(test_element, unicode)
+        if is_string:
+            split_list = test_element.split(':', 1)
+            return AmqpTypesTestSender.encode_amqp_type(split_list[0], split_list[1])
+        if isinstance(test_element, list):
+            enc_list = AmqpTypesTestSender.encode_amqp_list(test_element)
+            if make_hashable:
+                return tuple(enc_list) # Convert list to tuple
+            return enc_list
+        if isinstance(test_element, dict):
+            enc_dict = AmqpTypesTestSender.encode_amqp_map(test_element)
+            if make_hashable:
+                return tuple(enc_dict.items()) # Convert to tuple of k,v pairs
+            return enc_dict
+        else:
+            print('Unexpected complex amqp element type: %s, value=%s' % (type(test_element), str(test_element)))
+
+    @staticmethod
+    def encode_amqp_list(test_value):
+        """
+        Encode an AMQP list from the format [val1, val2, ...]
+        Each val is in the string format amqp_type:amqp_val_as_str
+        """
+        val_list = []
+        for val in test_value:
+            val_list.append(AmqpTypesTestSender.encode_complex_amqp_element(val))
+        return val_list
+
+    @staticmethod
+    def encode_amqp_map(test_value):
+        """Encode an AMQP map from the format {key1:val1, key2:val2, ...}"""
+        val_map = {}
+        for key, val in test_value.items():
+            encoded_key = AmqpTypesTestSender.encode_complex_amqp_element(key, True) # make keys hashable
+            encoded_val = AmqpTypesTestSender.encode_complex_amqp_element(val)
+            val_map[encoded_key] = encoded_val
+        return val_map
+
+    @staticmethod
+    def encode_amqp_array(test_value):
+        """Encode an AMQP array"""
+        return test_value
+
     def on_accepted(self, event):
         """Event callback for when a sent message is accepted by the broker"""
         self.confirmed += 1

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b87dc72a/src/python/qpid_interop_test/amqp_types_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_types_test.py b/src/python/qpid_interop_test/amqp_types_test.py
index 3bf5987..23a1880 100755
--- a/src/python/qpid_interop_test/amqp_types_test.py
+++ b/src/python/qpid_interop_test/amqp_types_test.py
@@ -175,52 +175,55 @@ class AmqpPrimitiveTypes(qpid_interop_test.qit_common.QitTestTypeMap):
                    'domain.0123456789.' * 100,
                   ],
         'list': [[],
-                 ['ubyte:1', 'int:-2', 'float:3.14'],
-                 ['string:a', 'string:b', 'string:c'],
-                 ['ulong:12345',
-                  'timestamp:%d' % (time()*1000),
-                  'short:-2500',
-                  'uuid:%s' % uuid4(),
+                 ['ubyte:0x1', 'int:-0x2', 'float:0x40490fdb'],
+                 ['string:a', 'string:hello', 'string:world!', 'binary:\x01\x02\x03\x04\x05abcde'],
+                 ['long:0x102030405',
+                  'timestamp:0x%x' % int(time()*1000),
+                  'short:-0x8000',
+                  'uuid:%s' % str(uuid4()),
                   'symbol:a.b.c',
-                  'none:',
-                  'decimal64:0x400921fb54442eea'
+                  'null:None',
+                  'ulong:0x400921fb54442eea',
+                  #'decimal64:0x400921fb54442eea' # Decimal byte reversal issue: PROTON-1160
                  ],
                  [[],
-                  'none',
-                  ['ubyte:1', 'ubyte:2', 'ubyte:3'],
+                  'null:None',
+                  ['ubyte:0x1', 'ubyte:0x2', 'ubyte:0x3'],
                   'boolean:True',
                   'boolean:False',
-                  {'string:hello': 'long:1234', 'string:goodbye': 'boolean:True'}
+                  {},
+                  {'string:hello': 'long:-0x1234', 'string:goodbye': 'boolean:True'}
                  ],
                  [[], [[], [[], [], []], []], []],
-                 ['short:0',
-                  'short:1',
-                  'short:2',
-                  'short:3',
-                  'short:4',
-                  'short:5',
-                  'short:6',
-                  'short:7',
-                  'short:8',
-                  'short:9'] * 10
+                 ['short:0x0',
+                  'short:0x1',
+                  'short:0x2',
+                  'short:0x3',
+                  'short:0x4',
+                  'short:0x5',
+                  'short:0x6',
+                  'short:0x7',
+                  'short:0x8',
+                  'short:0x9'] * 10
                 ],
         'map': [{}, # Enpty map
                 # Map with string keys
-                {'string:one': 'ubyte:1',
-                 'string:two': 'ushort:2'},
+                {'string:one': 'ubyte:0x1',
+                 'string:two': 'ushort:0x2'},
                 # Map with other AMQP simple types as keys
-                {'none:': 'string:None',
-                 'string:None': 'none:',
-                 'string:One': 'long:-1234567890',
-                 'short:2': 'int:2',
+                {'null:None': 'string:None',
+                 'string:None': 'null:None',
+                 'string:One': 'long:-0x102030405',
+                 'short:0x2': 'int:0x2',
                  'boolean:True': 'string:True',
                  'string:False': 'boolean:False',
-                 #['string:AAA', 'ushort:5951']: 'string:list value',
+                 #['string:AAA', 'ushort:0x5951']: 'string:list value',
                  #{'byte:-55': 'ubyte:200',
                  # 'boolean:True': 'string:Hello, world'}: 'symbol:map.value',
-                 #'string:list': [],
-                 'string:map': {'char:A': 'int:1',
-                                'char:B': 'int:2'}},
+                 'string:list': ['byte:0x12', 'ushort:0x234', 'uuid:%s' % str(uuid4()), ],
+                 'string:map': {'char:A': 'int:0x1',
+                                'char:B': 'int:0x2'}
+                },
                ],
         # array: Each array is constructed from the test values in this map. This list contains
         # the keys to the array value types to be included in the test. See function create_test_arrays()
@@ -268,10 +271,14 @@ class AmqpPrimitiveTypes(qpid_interop_test.qit_common.QitTestTypeMap):
         }
 
     client_skip = {
-        'char': {'AmqpNetLite': 'Char types not supported: https://github.com/Azure/amqpnetlite/issues/259', },
-        'decimal32': {'AmqpNetLite': 'Decimal types not supported: https://github.com/Azure/amqpnetlite/issues/223', },
-        'decimal64': {'AmqpNetLite': 'Decimal types not supported: https://github.com/Azure/amqpnetlite/issues/223', },
-        'decimal128': {'AmqpNetLite': 'Decimal types not supported: https://github.com/Azure/amqpnetlite/issues/223', },
+        'char': {'AmqpNetLite': 'Char type and decimal types to be added to shim: QPIDIT-118', },
+        'decimal32': {'AmqpNetLite': 'Char type and decimal types to be added to shim: QPIDIT-118', },
+        'decimal64': {'AmqpNetLite': 'Char type and decimal types to be added to shim: QPIDIT-118', },
+        'decimal128': {'AmqpNetLite': 'Char type and decimal types to be added to shim: QPIDIT-118', },
+        'list': {'AmqpNetLite': 'Encoding/decoding of complex types not yet complete: QPIDIT-46',
+                 'RheaJs': 'Encoding/decoding of complex types not yet complete: QPIDIT-46'},
+        'map': {'AmqpNetLite': 'Encoding/decoding of complex types not yet complete: QPIDIT-46',
+                'RheaJs': 'Encoding/decoding of complex types not yet complete: QPIDIT-46'},
     }
 
     def create_array(self, array_amqp_type, repeat):


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org