Repository: qpid-interop-test
Updated Branches:
  refs/heads/master c1fb41599 -> b4e6d0b56


QPIDIT-119: WIP: Data JSON files, generator (with Python and C++ generation 
complete) and Python 2/3 shims.


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/b4e6d0b5
Tree: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/tree/b4e6d0b5
Diff: http://git-wip-us.apache.org/repos/asf/qpid-interop-test/diff/b4e6d0b5

Branch: refs/heads/master
Commit: b4e6d0b56ef98c32eb4752032e512a46230e873e
Parents: c1fb415
Author: Kim van der Riet <kvdr@localhost.localdomain>
Authored: Fri Apr 13 12:45:58 2018 -0400
Committer: Kim van der Riet <kvdr@localhost.localdomain>
Committed: Fri Apr 13 12:45:58 2018 -0400

----------------------------------------------------------------------
 CMakeLists.txt                                  |  10 +
 setup.py                                        |   8 +
 .../src/amqp_complex_types_test/.gitignore      |   1 +
 .../qpidit/amqp_complex_types_test/.gitignore   |   1 +
 shims/qpid-proton-python/src/CMakeLists.txt     |   1 -
 shims/qpid-proton-python/src/_compat.py         |  20 +-
 .../src/amqp_complex_types_test/.gitignore      |   1 +
 .../src/amqp_complex_types_test/Common.py       | 185 +++++++++++++
 .../src/amqp_complex_types_test/Receiver.py     | 220 +++++++++++++--
 .../src/amqp_complex_types_test/Sender.py       |  65 +++--
 .../src/amqp_complex_types_test/__init__.py     |  16 ++
 .../src/amqp_types_test/Sender.py               |   4 +-
 .../src/jms_hdrs_props_test/Sender.py           |   8 +-
 .../src/jms_messages_test/Sender.py             |   6 +-
 .../rhea-js/amqp_complex_types_test/.gitignore  |   1 +
 .../amqp_complex_types_test.array.json          |   3 +-
 .../amqp_complex_types_test.list.json           |  48 +++-
 .../amqp_complex_types_test.map.json            |  37 ++-
 .../amqp_complex_types_test.py                  | 271 +++++++++++++++++++
 .../amqp_complex_types_test_generator.py        |  76 ++++--
 src/python/qpid_interop_test/qit_shim.py        |   6 +-
 21 files changed, 872 insertions(+), 116 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e209ea8..de50165 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -95,6 +95,16 @@ add_subdirectory(shims/amqpnetlite/src)
 add_subdirectory(shims/rhea-js)
 add_subdirectory(docs)
 
+# Generate data code files for amqp_complex_types_test
+install(CODE "execute_process(COMMAND python3 
src/python/qpid_interop_test/amqp_complex_types_test_generator.py --gen cpp 
--src-dir src/python/qpid_interop_test --gen-dir 
shims/qpid-proton-cpp/src/qpidit/amqp_complex_types_test
+                              WORKING_DIRECTORY ../)")
+install(CODE "execute_process(COMMAND python3 
src/python/qpid_interop_test/amqp_complex_types_test_generator.py --gen python 
--src-dir src/python/qpid_interop_test --gen-dir 
shims/qpid-proton-python/src/amqp_complex_types_test
+                              WORKING_DIRECTORY ../)")
+install(CODE "execute_process(COMMAND python3 
src/python/qpid_interop_test/amqp_complex_types_test_generator.py --gen 
javascript --src-dir src/python/qpid_interop_test --gen-dir 
shims/rhea-js/amqp_complex_types_test
+                              WORKING_DIRECTORY ../)")
+install(CODE "execute_process(COMMAND python3 
src/python/qpid_interop_test/amqp_complex_types_test_generator.py --gen dotnet 
--src-dir src/python/qpid_interop_test --gen-dir 
shims/amqpnetlite/src/amqp_complex_types_test
+                              WORKING_DIRECTORY ../)")
+
 # Install files using python setup.py
 install(CODE "MESSAGE(STATUS \"Python install dir: 
${CMAKE_INSTALL_PREFIX}/lib/${PYTHON_DIR_NAME}/site-packages/qpid_interop_test/\")")
 install(CODE "execute_process(COMMAND python setup.py install --prefix 
${CMAKE_INSTALL_PREFIX}

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/setup.py
----------------------------------------------------------------------
diff --git a/setup.py b/setup.py
index a4d0821..6310d34 100644
--- a/setup.py
+++ b/setup.py
@@ -41,6 +41,14 @@ setup(name='qpid-interop-test',
                       'shims/qpid-proton-python/src/amqp_types_test/Sender.py',
                      ]
                   ),
+                  ('%s/qpid-proton-python/amqp_complex_types_test' % SHIM_DIR,
+                     
['shims/qpid-proton-python/src/amqp_complex_types_test/__init__.py',
+                      
'shims/qpid-proton-python/src/amqp_complex_types_test/amqp_complex_types_test_data.py',
+                      
'shims/qpid-proton-python/src/amqp_complex_types_test/Common.py',
+                      
'shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py',
+                      
'shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py',
+                     ]
+                  ),
                   ('%s/qpid-proton-python/amqp_large_content_test' % SHIM_DIR,
                      
['shims/qpid-proton-python/src/amqp_large_content_test/Receiver.py',
                       
'shims/qpid-proton-python/src/amqp_large_content_test/Sender.py',

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/amqpnetlite/src/amqp_complex_types_test/.gitignore
----------------------------------------------------------------------
diff --git a/shims/amqpnetlite/src/amqp_complex_types_test/.gitignore 
b/shims/amqpnetlite/src/amqp_complex_types_test/.gitignore
new file mode 100644
index 0000000..918f79c
--- /dev/null
+++ b/shims/amqpnetlite/src/amqp_complex_types_test/.gitignore
@@ -0,0 +1 @@
+/amqp_complex_types_test_data.cs

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-cpp/src/qpidit/amqp_complex_types_test/.gitignore
----------------------------------------------------------------------
diff --git 
a/shims/qpid-proton-cpp/src/qpidit/amqp_complex_types_test/.gitignore 
b/shims/qpid-proton-cpp/src/qpidit/amqp_complex_types_test/.gitignore
new file mode 100644
index 0000000..ce0dc65
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/amqp_complex_types_test/.gitignore
@@ -0,0 +1 @@
+/amqp_complex_types_test_data.cpp

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/CMakeLists.txt 
b/shims/qpid-proton-python/src/CMakeLists.txt
index 0b26d2e..4c5fef2 100644
--- a/shims/qpid-proton-python/src/CMakeLists.txt
+++ b/shims/qpid-proton-python/src/CMakeLists.txt
@@ -20,4 +20,3 @@
 project (qpid-interop-test-python-shim)
 
 cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)
-

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/_compat.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/_compat.py 
b/shims/qpid-proton-python/src/_compat.py
index 3e772c8..a0680c9 100644
--- a/shims/qpid-proton-python/src/_compat.py
+++ b/shims/qpid-proton-python/src/_compat.py
@@ -29,11 +29,17 @@ import types
 IS_PY3 = sys.version_info[0] == 3
 
 if IS_PY3:
+    def bytes_type():
+        return bytes
     def decode_hex(s):
         return bytes.fromhex(s)
     def letters():
         return string.ascii_letters
-    def long(i, r):
+    def long(i):
+        return int(i)
+    def long_type():
+        return int
+    def str2long(i, r):
         return int(i, r)
     def byte_char_ord(c):
         return c
@@ -41,15 +47,23 @@ if IS_PY3:
         return chr(i)
     def unicode(i):
         return str(i)
+    def unicode_type():
+        return str
 
 else:
     import __builtin__
 
+    def bytes_type():
+        return str
     def decode_hex(s):
         return s.decode('hex')
     def letters():
         return string.letters
-    def long(i, r):
+    def long(i):
+        return __builtin__.long(i)
+    def long_type():
+        return __builtin__.long
+    def str2long(i, r):
         return __builtin__.long(i, r)
     def byte_char_ord(c):
         return __builtin__.ord(c)
@@ -57,3 +71,5 @@ else:
         return __builtin__.unichr(i)
     def unicode(i):
         return __builtin__.unicode(i)
+    def unicode_type():
+        return __builtin__.unicode

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/amqp_complex_types_test/.gitignore
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_complex_types_test/.gitignore 
b/shims/qpid-proton-python/src/amqp_complex_types_test/.gitignore
new file mode 100644
index 0000000..3917f7f
--- /dev/null
+++ b/shims/qpid-proton-python/src/amqp_complex_types_test/.gitignore
@@ -0,0 +1 @@
+/amqp_complex_types_test_data.py

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/amqp_complex_types_test/Common.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_complex_types_test/Common.py 
b/shims/qpid-proton-python/src/amqp_complex_types_test/Common.py
new file mode 100644
index 0000000..6b8103a
--- /dev/null
+++ b/shims/qpid-proton-python/src/amqp_complex_types_test/Common.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+
+"""
+AMQP complex type test common classes
+"""
+
+#
+# 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.
+#
+
+from __future__ import print_function
+
+import signal
+import sys
+import uuid
+
+import proton
+import _compat
+
+class AmqpComplexTypesTestShim(proton.handlers.MessagingHandler):
+    """
+    Common methods for both send and receive shims for AMQP complex types test
+    """
+    def __init__(self, broker_url, queue_name, amqp_type, amqp_subtype, role):
+        super(AmqpComplexTypesTestShim, self).__init__()
+        self.broker_url = broker_url
+        self.queue_name = queue_name
+        self.amqp_type = amqp_type
+        self.amqp_subtype = amqp_subtype
+        self.role = role
+        self.result = None
+        signal.signal(signal.SIGINT, self.signal_handler)
+        signal.signal(signal.SIGTERM, self.signal_handler)
+
+    def get_array(self, array_data):
+        """Get AMQP array from array_data"""
+        for array in array_data:
+            if array.type == self.proton_type(self.amqp_subtype):
+                return array
+        print('%s: get_array(): Unable to find array subtype "%s" in array 
test data' %
+              (self.role, self.amqp_subtype), file=sys.stderr)
+        sys.exit(1)
+
+    def get_list(self, list_data):
+        """Get AMQP list from list_data"""
+        for this_list in list_data:
+            if self.amqp_subtype == 'None': # empty list
+                if not this_list: # list is empty
+                    return this_list
+                else:
+                    print('%s: get_list(): Non-empty list %s found for empty 
list type' %
+                          (self.role, this_list), file=sys.stderr)
+                    sys.exit(1)
+            if this_list: # list is not empty
+                if self.amqp_subtype == 'null':
+                    if isinstance(this_list[0], type(None)):
+                        return this_list
+                elif self.amqp_subtype == '*':
+                    if isinstance(this_list[0], _compat.unicode_type()) and 
this_list[0] == u'*':
+                        return this_list
+                else:
+                    if self.amqp_subtype != '*':
+                        #pylint: disable=unidiomatic-typecheck
+                        if type(this_list[0]) == 
self.get_class(self.amqp_subtype):
+                            return this_list
+        print('%s: get_list(): Subtype "%s" not found in list test data' %
+              (self.role, self.get_class(self.amqp_subtype) if 
self.amqp_subtype != '*' else '*'), file=sys.stderr)
+        sys.exit(1)
+
+    def get_map(self, map_data):
+        """Get AMQP map from map_data"""
+        for this_map in map_data:
+            if self.amqp_subtype == 'None': # empty map
+                if not this_map: # map is empty
+                    return this_map
+                else:
+                    print('%s: get_map(): Non-empty map %s found for empty map 
type' %
+                          (self.role, this_map), file=sys.stderr)
+                    sys.exit(1)
+            if this_map: # map is not empty
+                if self.amqp_subtype == 'null':
+                    if isinstance(list(this_map.keys())[0], type(None)):
+                        return this_map
+                elif self.amqp_subtype == '*':
+                    for this_key in list(this_map.keys()): # can't use if u'*' 
in list(this_map.keys()) - unicode errors
+                        if isinstance(this_key, _compat.unicode_type()) and 
this_key == u'*':
+                            return this_map
+                else:
+                    key0 = list(this_map.keys())[0]
+                    #pylint: disable=unidiomatic-typecheck
+                    if type(this_map[key0]) == 
self.get_class(self.amqp_subtype):
+                        return this_map
+        print('%s: et_map(): Subtype "%s" not found in map test data' %
+              (self.role, self.get_class(self.amqp_subtype) if 
self.amqp_subtype != '*' else '*'), file=sys.stderr)
+        sys.exit(1)
+
+    PROTON_CLASS_MAP = {'boolean': bool,
+                        'ubyte': proton.ubyte,
+                        'byte': proton.byte,
+                        'ushort': proton.ushort,
+                        'short': proton.short,
+                        'uint': proton.uint,
+                        'int': proton.int32,
+                        'char': proton.char,
+                        'ulong': proton.ulong,
+                        'long': _compat.long_type(),
+                        'timestamp': proton.timestamp,
+                        'float': proton.float32,
+                        'double': float,
+                        'decimal32': proton.decimal32,
+                        'decimal64': proton.decimal64,
+                        'decimal128': proton.decimal128,
+                        'uuid': uuid.UUID,
+                        'binary': _compat.bytes_type(),
+                        'string': _compat.unicode_type(),
+                        'symbol': proton.symbol,
+                        'array': proton.Array,
+                        'list': list,
+                        'map': dict,
+                       }
+
+    def get_class(self, amqp_subtype):
+        """Return underlying Python class from named AMQP type"""
+        try:
+            return AmqpComplexTypesTestShim.PROTON_CLASS_MAP[amqp_subtype]
+        except KeyError:
+            print('%s: get_class(): Unknown subtype "%s"' % (self.role, 
amqp_subtype), file=sys.stderr)
+            sys.exit(1)
+
+    PROTON_TYPE_MAP = {'None': None,
+                       'null': proton.Data.NULL,
+                       'boolean': proton.Data.BOOL,
+                       'ubyte': proton.Data.UBYTE,
+                       'byte': proton.Data.BYTE,
+                       'ushort': proton.Data.USHORT,
+                       'short': proton.Data.SHORT,
+                       'uint': proton.Data.UINT,
+                       'int': proton.Data.INT,
+                       'char': proton.Data.CHAR,
+                       'ulong': proton.Data.ULONG,
+                       'long': proton.Data.LONG,
+                       'timestamp': proton.Data.TIMESTAMP,
+                       'float': proton.Data.FLOAT,
+                       'double': proton.Data.DOUBLE,
+                       'decimal32': proton.Data.DECIMAL32,
+                       'decimal64': proton.Data.DECIMAL64,
+                       'decimal128': proton.Data.DECIMAL128,
+                       'uuid': proton.Data.UUID,
+                       'binary': proton.Data.BINARY,
+                       'string': proton.Data.STRING,
+                       'symbol': proton.Data.SYMBOL,
+                       'array': proton.Data.ARRAY,
+                       'list': proton.Data.LIST,
+                       'map': proton.Data.MAP,
+                      }
+
+    def proton_type(self, amqp_subtype):
+        """Return underlying Proton type code (a byte) from named AMQP type. 
Needed for proton.Array"""
+        try:
+            return AmqpComplexTypesTestShim.PROTON_TYPE_MAP[amqp_subtype]
+        except KeyError:
+            print('%s: proton_type(): Unknown subtype "%s"' % (self.role, 
amqp_subtype), file=sys.stderr)
+            sys.exit(1)
+
+    @staticmethod
+    def signal_handler(signal_number, _):
+        """Signal handler"""
+        if signal_number in [signal.SIGTERM, signal.SIGINT]:
+            print('Received signal %d, terminating' % signal_number, 
file=sys.stderr)
+            sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py 
b/shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py
index c252239..6d2e13b 100644
--- a/shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py
+++ b/shims/qpid-proton-python/src/amqp_complex_types_test/Receiver.py
@@ -23,9 +23,8 @@ AMQP complex type test receiver shim for qpid-interop-test
 # under the License.
 #
 
-import json
-import os.path
-import signal
+from __future__ import print_function
+
 import sys
 import traceback
 
@@ -33,26 +32,25 @@ import proton
 import proton.handlers
 import proton.reactor
 
-class AmqpComplexTypesTestReceiver(proton.handlers.MessagingHandler):
+from qpid_interop_test.qit_errors import InteropTestError
+
+from amqp_complex_types_test.amqp_complex_types_test_data import TEST_DATA
+import amqp_complex_types_test.Common
+
+class 
AmqpComplexTypesTestReceiver(amqp_complex_types_test.Common.AmqpComplexTypesTestShim):
     """
     Reciver shim for AMQP complex types test
     This shim receives the number of messages supplied on the command-line and 
checks that they contain message
     bodies of the exptected AMQP type. The values are then aggregated and 
returned.
     """
-    def __init__(self, broker_url, queue_name, amqp_type, 
num_expected_messages_str):
-        super(AmqpComplexTypesTestReceiver, self).__init__()
-        self.broker_url = broker_url
-        self.queue_name = queue_name
-        self.received_value_list = []
-        self.amqp_type = amqp_type
-        self.expected = int(num_expected_messages_str)
+    def __init__(self, broker_url, queue_name, amqp_type, amqp_subtype):
+        super(AmqpComplexTypesTestReceiver, self).__init__(broker_url, 
queue_name, amqp_type, amqp_subtype, 'Receiver')
+        self.expected = 0
         self.received = 0
-        signal.signal(signal.SIGINT, self.signal_handler)
-        signal.signal(signal.SIGTERM, self.signal_handler)
 
-    def get_received_value_list(self):
+    def get_result(self):
         """Return the received list of AMQP values"""
-        return self.received_value_list
+        return self.result
 
     def on_start(self, event):
         """Event callback for when the client starts"""
@@ -63,35 +61,205 @@ class 
AmqpComplexTypesTestReceiver(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.amqp_type == 'array':
+            test_value = self.get_array(TEST_DATA['array'])
+        elif self.amqp_type == 'list':
+            test_value = self.get_list(TEST_DATA['list'])
+        elif self.amqp_type == 'map':
+            test_value = self.get_map(TEST_DATA['map'])
+        else:
+            print('Receiver: on_message(): unknown amqp complex type: "%s"' % 
self.amqp_type, file=sys.stderr)
+            sys.exit(1)
+
+        # Compare received with expected
+        if self.check_received_value_equal(event.message.body, test_value):
+            self.result = '["pass"]'
+        else:
+            self.result = '["FAIL:\nreceived: %s\nexpected: %s"]' % 
(event.message.body, test_value)
         self.received += 1
         if self.received >= self.expected:
             event.receiver.close()
             event.connection.close()
 
+    def check_received_value_equal(self, received_value, expected_value):
+        """Check received and expected test values are equal"""
+        if self.amqp_type == 'array':
+            return 
AmqpComplexTypesTestReceiver.check_arrays_equal(received_value, expected_value)
+        if self.amqp_type == 'list':
+            return 
AmqpComplexTypesTestReceiver.check_lists_equal(received_value, expected_value)
+        if self.amqp_type == 'map':
+            return 
AmqpComplexTypesTestReceiver.check_maps_equal(received_value, expected_value)
+        return False
+
     def on_transport_error(self, event):
-        print('Receiver: Broker not found at %s' % self.broker_url)
+        print('Receiver: Broker not found at %s' % self.broker_url, 
file=sys.stderr)
 
     @staticmethod
-    def signal_handler(signal_number, _):
-        """Signal handler"""
-        if signal_number in [signal.SIGTERM, signal.SIGINT]:
-            print('Receiver: received signal %d, terminating' % signal_number)
-            sys.exit(1)
+    def check_arrays_equal(arr1, arr2):
+        """Check two Proton arrays are equal"""
+        # Check params are proton.Array
+        if not isinstance(arr1, proton.Array) or not isinstance(arr2, 
proton.Array):
+            return False
+        # Check array types are same
+        if arr1.type != arr2.type:
+            return False
+        # Check array sizes are equal
+        if len(arr1.elements) != len(arr2.elements):
+            return False
+        # Check each element is the same value
+        for elt1, elt2 in zip(arr1.elements, arr2.elements):
+            if arr1.type == proton.Data.ARRAY and isinstance(elt1, 
proton.Array):
+                if not AmqpComplexTypesTestReceiver.check_arrays_equal(elt1, 
elt2):
+                    return False
+            elif arr1.type == proton.Data.LIST and isinstance(elt1, list):
+                if not AmqpComplexTypesTestReceiver.check_lists_equal(elt1, 
elt2):
+                    return False
+            elif arr1.type == proton.Data.MAP and isinstance(elt1, dict):
+                if not AmqpComplexTypesTestReceiver.check_maps_equal(elt1, 
elt2):
+                    return False
+            else:
+                if not 
AmqpComplexTypesTestReceiver.check_simple_values_equal(elt1, elt2):
+                    return False
+        return True
+
+    @staticmethod
+    def check_lists_equal(list1, list2):
+        """Check two Proton lists are equal"""
+        # Check params are lists
+        if not isinstance(list1, list) or not isinstance(list2, list):
+            return False
+        # Check list sizes equal
+        if len(list1) != len(list2):
+            return False
+        # Check each element is the same type and value
+        for elt1, elt2 in zip(list1, list2):
+            #pylint: disable=unidiomatic-typecheck
+            if type(elt1) != type(elt2):
+                return False
+            elif isinstance(elt1, proton.Array):
+                if not AmqpComplexTypesTestReceiver.check_arrays_equal(elt1, 
elt2):
+                    return False
+            elif isinstance(elt1, list):
+                if not AmqpComplexTypesTestReceiver.check_lists_equal(elt1, 
elt2):
+                    return False
+            elif isinstance(elt1, dict):
+                if not AmqpComplexTypesTestReceiver.check_maps_equal(elt1, 
elt2):
+                    return False
+            else:
+                if not 
AmqpComplexTypesTestReceiver.check_simple_values_equal(elt1, elt2):
+                    return False
+        return True
+
+    @staticmethod
+    def check_maps_equal(map1, map2):
+        """
+        Check two Proton maps are equal. Equality ignores map element 
ordering, and must make allowances
+        for floating point indexes that may have small rounding error 
differences.
+
+        eg {1.23: 'a', 25: 'b'} and {25: 'b', 1.230000001234: 'a'} are equal.
+
+        NOTE: At this point, map indexes may only be AMQP simple types, as the 
current Proton Python implementation
+        does not support them.
+        """
+        # Check params are maps
+        if not isinstance(map1, dict) or not isinstance(map2, dict):
+            return False
+        # Check list sizes equal
+        if len(map1) != len(map2):
+            return False
+        # Compare key sets of maps
+        key_list_1 = list(map1.keys())
+        key_list_2 = list(map2.keys())
+        try:
+            map1_to_map2_index = 
AmqpComplexTypesTestReceiver.check_map_keys_equal(key_list_1, key_list_2)
+        except InteropTestError as err:
+            print('Receiver: %s' % err, file=sys.stderr)
+            return False
+        # Compare values of maps
+        # We need to use the actual keys from each map otherwise KeyError 
failures will occur for float keys
+        # which have small rounding differences between them. 
map1_to_map2_index provides a mapping for the
+        # keys in map2 relative to the keys in map1 (as the map element 
ordering may not be the same).
+        for key1_index, key1 in enumerate(key_list_1):
+            val1 = map1[key1]
+            val2 = map2[key_list_2[map1_to_map2_index[key1_index]]]
+            if isinstance(val1, proton.Array):
+                if not AmqpComplexTypesTestReceiver.check_arrays_equal(val1, 
val2):
+                    return False
+            elif isinstance(val1, list):
+                if not AmqpComplexTypesTestReceiver.check_lists_equal(val1, 
val2):
+                    return False
+            elif isinstance(val1, dict):
+                if not AmqpComplexTypesTestReceiver.check_maps_equal(val1, 
val2):
+                    return False
+            else:
+                if not 
AmqpComplexTypesTestReceiver.check_simple_values_equal(val1, val2):
+                    return False
+        return True
+
+    @staticmethod
+    def check_map_keys_equal(key_list_1, key_list_2):
+        """
+        Check map keys are equal. The map keys:
+        * Are not ordered, so cannot rely on position in list
+        * May contain floating point values which may contain small rounding 
errors
+        * May contain differing types, so cannot be sorted
+        * May contain complex types (but not at this point, as the Python 
binding won't support it)
+        Return a list containing the indexes of map2 keys corresponding to the 
values in map1 keys
+        """
+        map12_index = []
+        # Check length of key lists are same
+        if len(key_list_1) != len(key_list_2):
+            raise InteropTestError('check_map_keys_equal(): Key list not equal 
length, len(key_list_1)=%d ' \
+                                   'len(key_list_2)=%d' % (len(key_list_1), 
len(key_list_2)))
+        for key1 in key_list_1:
+            
map12_index.append(AmqpComplexTypesTestReceiver.find_simple_value_in_list(key1, 
key_list_2))
+        if len(map12_index) != len(key_list_1):
+            raise InteropTestError('check_map_keys_equal(): Key mapping list 
size mismatch: keylist size %d, ' \
+                                   'mapping list size: %d' % (len(key_list_1), 
len(map12_index)))
+        return map12_index
+
+    @staticmethod
+    def find_simple_value_in_list(val, list_):
+        """Find the index of val in list_. Raise InteropTestError if not 
found"""
+        list_index = 0
+        for list_val in list_:
+            if AmqpComplexTypesTestReceiver.check_simple_values_equal(val, 
list_val):
+                return list_index
+            list_index += 1
+        raise InteropTestError('find_simple_value_in_list(): map1 key "%s" not 
found in map2 keys %s' % (val, list_))
+
+    @staticmethod
+    def check_simple_values_equal(val1, val2):
+        """Check two simple values are equal, use rounding when floats or 
proton.float32 are compared."""
+        #pylint: disable=unidiomatic-typecheck
+        if type(val1) != type(val2):
+            return False
+        if isinstance(val1, proton.float32):
+            return AmqpComplexTypesTestReceiver.compare_float_numbers(val1, 
val2, 6)
+        if isinstance(val1, float):
+            return AmqpComplexTypesTestReceiver.compare_float_numbers(val1, 
val2, 14)
+        return val1 == val2
+
+    @staticmethod
+    def compare_float_numbers(f_1, f_2, precision):
+        """Compare two float numbers to precision digits after the decimal"""
+        format_string = '%%.%de' % precision
+        return format_string % f_1 == format_string % f_2
+
 
 # --- main ---
 # Args: 1: Broker address (ip-addr:port)
 #       2: Queue name
 #       3: AMQP complex type
-#       4: Test data reference list
+#       4: AMQP subtype
 try:
     RECEIVER = AmqpComplexTypesTestReceiver(sys.argv[1], sys.argv[2], 
sys.argv[3], sys.argv[4])
     proton.reactor.Container(RECEIVER).run()
     print(sys.argv[3])
-    print(json.dumps(RECEIVER.get_received_value_list()))
+    print(RECEIVER.get_result())
 except KeyboardInterrupt:
     pass
 except Exception as exc:
-    print(os.path.basename(sys.argv[0]), 'EXCEPTION', exc)
-    print(traceback.format_exc())
+    print('Receiver: EXCEPTION: %s' % exc, file=sys.stderr)
+    print(traceback.format_exc(), file=sys.stderr)
     sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py 
b/shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py
index fa2c49b..7640eac 100644
--- a/shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_complex_types_test/Sender.py
@@ -23,9 +23,8 @@ AMQP complex type test sender shim for qpid-interop-test
 # under the License.
 #
 
-import json
-import os.path
-import signal
+from __future__ import print_function
+
 import sys
 import traceback
 
@@ -33,23 +32,20 @@ import proton
 import proton.handlers
 import proton.reactor
 
-class AmqpComplexTypesTestSender(proton.handlers.MessagingHandler):
+from amqp_complex_types_test.amqp_complex_types_test_data import TEST_DATA
+import amqp_complex_types_test.Common
+
+class 
AmqpComplexTypesTestSender(amqp_complex_types_test.Common.AmqpComplexTypesTestShim):
     """
     Sender shim for AMQP complex types test
     This shim receives the AMQP type and a list of test values. Each value is 
sent in a message body of the appropriate
     AMQP type. There is no returned value.
     """
-    def __init__(self, broker_url, queue_name, amqp_type, test_value_list):
-        super(AmqpComplexTypesTestSender, self).__init__()
-        self.broker_url = broker_url
-        self.queue_name = queue_name
-        self.amqp_type = amqp_type
-        self.test_value_list = test_value_list
+    def __init__(self, broker_url, queue_name, amqp_type, amqp_subtype):
+        super(AmqpComplexTypesTestSender, self).__init__(broker_url, 
queue_name, amqp_type, amqp_subtype, 'Sender')
         self.sent = 0
         self.confirmed = 0
-        self.total = len(test_value_list)
-        signal.signal(signal.SIGINT, self.signal_handler)
-        signal.signal(signal.SIGTERM, self.signal_handler)
+        self.total = 1
 
     def on_start(self, event):
         """Event callback for when the client starts"""
@@ -59,15 +55,24 @@ class 
AmqpComplexTypesTestSender(proton.handlers.MessagingHandler):
     def on_sendable(self, event):
         """Event callback for when send credit is received, allowing the 
sending of messages"""
         if self.sent == 0:
-            for test_value in self.test_value_list:
-                if event.sender.credit:
-                    message = self.create_message(test_value)
-                    if message is not None:
-                        event.sender.send(message)
-                        self.sent += 1
-                    else:
-                        event.connection.close()
-                        return
+            if self.amqp_type == 'array':
+                test_value = self.get_array(TEST_DATA['array'])
+            elif self.amqp_type == 'list':
+                test_value = self.get_list(TEST_DATA['list'])
+            elif self.amqp_type == 'map':
+                test_value = self.get_map(TEST_DATA['map'])
+            else:
+                print('Sender: on_sendable(): unknown amqp complex type: "%s"' 
% self.amqp_type, file=sys.stderr)
+                sys.exit(1)
+
+            if event.sender.credit:
+                message = self.create_message(test_value)
+                if message is not None:
+                    event.sender.send(message)
+                    self.sent += 1
+                else:
+                    event.connection.close()
+                    return
 
     def create_message(self, test_value):
         """
@@ -87,27 +92,21 @@ class 
AmqpComplexTypesTestSender(proton.handlers.MessagingHandler):
         self.sent = self.confirmed
 
     def on_transport_error(self, event):
-        print('Sender: Broker not found at %s' % self.broker_url)
+        print('Sender: Broker not found at %s' % self.broker_url, 
file=sys.stderr)
 
-    @staticmethod
-    def signal_handler(signal_number, _):
-        """Signal handler"""
-        if signal_number in [signal.SIGTERM, signal.SIGINT]:
-            print('Sender: received signal %d, terminating' % signal_number)
-            sys.exit(1)
 
 
 # --- main ---
 # Args: 1: Broker address (ip-addr:port)
 #       2: Queue name
 #       3: AMQP type
-#       4: JSON list of test value references to use in test
+#       4: AMQP subtype
 try:
-    SENDER = AmqpComplexTypesTestSender(sys.argv[1], sys.argv[2], sys.argv[3], 
json.loads(sys.argv[4]))
+    SENDER = AmqpComplexTypesTestSender(sys.argv[1], sys.argv[2], sys.argv[3], 
sys.argv[4])
     proton.reactor.Container(SENDER).run()
 except KeyboardInterrupt:
     pass
 except Exception as exc:
-    print(os.path.basename(sys.argv[0]), 'EXCEPTION:', exc)
-    print(traceback.format_exc())
+    print('Sender: EXCEPTION: %s' % exc, file=sys.stderr)
+    print(traceback.format_exc(), file=sys.stderr)
     sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/amqp_complex_types_test/__init__.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/amqp_complex_types_test/__init__.py 
b/shims/qpid-proton-python/src/amqp_complex_types_test/__init__.py
new file mode 100644
index 0000000..978b68a
--- /dev/null
+++ b/shims/qpid-proton-python/src/amqp_complex_types_test/__init__.py
@@ -0,0 +1,16 @@
+# 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.

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/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 cd0384e..0ad200a 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
@@ -101,7 +101,7 @@ class AmqpTypesTestSender(proton.handlers.MessagingHandler):
         if amqp_type == 'int':
             return proton.int32(int(test_value, 16))
         if amqp_type == 'long':
-            return _compat.long(test_value, 16)
+            return _compat.str2long(test_value, 16)
         if amqp_type == 'float':
             return proton.float32(struct.unpack('!f', 
_compat.decode_hex(test_value[2:]))[0])
         if amqp_type == 'double':
@@ -109,7 +109,7 @@ class AmqpTypesTestSender(proton.handlers.MessagingHandler):
         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))
+            return proton.decimal64(_compat.str2long(test_value[2:], 16))
         if amqp_type == 'decimal128':
             return proton.decimal128(_compat.decode_hex(test_value[2:]))
         if amqp_type == 'char':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py 
b/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
index b3d5d7e..08a8e98 100755
--- a/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
+++ b/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
@@ -176,7 +176,7 @@ class 
JmsHdrsPropsTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             body_bytes = struct.pack('!i', int(test_value, 16))
         elif test_value_type == 'long':
-            body_bytes = struct.pack('!q', _compat.long(test_value, 16))
+            body_bytes = struct.pack('!q', _compat.str2long(test_value, 16))
         elif test_value_type == 'short':
             body_bytes = struct.pack('!h', proton.short(test_value, 16))
         elif test_value_type == 'string':
@@ -211,7 +211,7 @@ class 
JmsHdrsPropsTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             value = proton.int32(int(test_value, 16))
         elif test_value_type == 'long':
-            value = _compat.long(test_value, 16)
+            value = _compat.str2long(test_value, 16)
         elif test_value_type == 'short':
             value = proton.short(int(test_value, 16))
         elif test_value_type == 'string':
@@ -268,7 +268,7 @@ class 
JmsHdrsPropsTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             body_list = [proton.int32(int(test_value, 16))]
         elif test_value_type == 'long':
-            body_list = [_compat.long(test_value, 16)]
+            body_list = [_compat.str2long(test_value, 16)]
         elif test_value_type == 'short':
             body_list = [proton.short(int(test_value, 16))]
         elif test_value_type == 'string':
@@ -354,7 +354,7 @@ class 
JmsHdrsPropsTestSender(proton.handlers.MessagingHandler):
             elif value_type == 'int':
                 message.properties[property_name] = proton.int32(int(value, 
16))
             elif value_type == 'long':
-                message.properties[property_name] = _compat.long(value, 16)
+                message.properties[property_name] = _compat.str2long(value, 16)
             elif value_type == 'short':
                 message.properties[property_name] = proton.short(int(value, 
16))
             elif value_type == 'string':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/qpid-proton-python/src/jms_messages_test/Sender.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_messages_test/Sender.py 
b/shims/qpid-proton-python/src/jms_messages_test/Sender.py
index 734ded2..931da10 100755
--- a/shims/qpid-proton-python/src/jms_messages_test/Sender.py
+++ b/shims/qpid-proton-python/src/jms_messages_test/Sender.py
@@ -165,7 +165,7 @@ class 
JmsMessagesTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             body_bytes = struct.pack('!i', int(test_value, 16))
         elif test_value_type == 'long':
-            body_bytes = struct.pack('!q', _compat.long(test_value, 16))
+            body_bytes = struct.pack('!q', _compat.str2long(test_value, 16))
         elif test_value_type == 'short':
             body_bytes = struct.pack('!h', proton.short(test_value, 16))
         elif test_value_type == 'string':
@@ -199,7 +199,7 @@ class 
JmsMessagesTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             value = proton.int32(int(test_value, 16))
         elif test_value_type == 'long':
-            value = _compat.long(test_value, 16)
+            value = _compat.str2long(test_value, 16)
         elif test_value_type == 'short':
             value = proton.short(int(test_value, 16))
         elif test_value_type == 'string':
@@ -252,7 +252,7 @@ class 
JmsMessagesTestSender(proton.handlers.MessagingHandler):
         elif test_value_type == 'int':
             body_list = [proton.int32(int(test_value, 16))]
         elif test_value_type == 'long':
-            body_list = [_compat.long(test_value, 16)]
+            body_list = [_compat.str2long(test_value, 16)]
         elif test_value_type == 'short':
             body_list = [proton.short(int(test_value, 16))]
         elif test_value_type == 'string':

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/shims/rhea-js/amqp_complex_types_test/.gitignore
----------------------------------------------------------------------
diff --git a/shims/rhea-js/amqp_complex_types_test/.gitignore 
b/shims/rhea-js/amqp_complex_types_test/.gitignore
new file mode 100644
index 0000000..1ddf6e7
--- /dev/null
+++ b/shims/rhea-js/amqp_complex_types_test/.gitignore
@@ -0,0 +1 @@
+/amqp_complex_types_test_data.js

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/amqp_complex_types_test.array.json
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_complex_types_test.array.json 
b/src/python/qpid_interop_test/amqp_complex_types_test.array.json
index c43356e..6145bf8 100644
--- a/src/python/qpid_interop_test/amqp_complex_types_test.array.json
+++ b/src/python/qpid_interop_test/amqp_complex_types_test.array.json
@@ -81,8 +81,7 @@
             ["char", "0xff"],
             ["char", "0x16b5"],
             ["char", "0x010203"],
-            ["char", "0x10ffff"],
-            ["char", "0xffffffff"]]],
+            ["char", "0x10ffff"]]],
  ["array", [["timestamp", 0],
             ["timestamp", "0xdc6be25480"],
             ["timestamp", "0x1624e900fa5"]]],

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/amqp_complex_types_test.list.json
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_complex_types_test.list.json 
b/src/python/qpid_interop_test/amqp_complex_types_test.list.json
index 86de15f..6059e0d 100644
--- a/src/python/qpid_interop_test/amqp_complex_types_test.list.json
+++ b/src/python/qpid_interop_test/amqp_complex_types_test.list.json
@@ -28,7 +28,7 @@
  ["list", [["byte", -128],
            ["byte", -1],
            ["byte", 0],
-           ["byte", 255]]],
+           ["byte", 127]]],
  ["list", [["short", "-0x8000"],
            ["short", -1],
            ["short", 0],
@@ -81,8 +81,7 @@
            ["char", "0xff"],
            ["char", "0x16b5"],
            ["char", "0x010203"],
-           ["char", "0x10ffff"],
-           ["char", "0xffffffff"]]],
+           ["char", "0x10ffff"]]],
  ["list", [["timestamp", 0],
            ["timestamp", "0xdc6be25480"],
            ["timestamp", "0x1624e900fa5"]]],
@@ -132,9 +131,6 @@
            ["list", [["binary", "Hello, world"],
                      ["string", "Hello, world"],
                      ["symbol", "Hello, world"]]],
-           ["list", [["array", []],
-                     ["array", [["byte", 1],
-                                ["byte", 2]]]]],
            ["list", [["list", []],
                      ["list", [["byte", 3],
                                ["string", "hello"]]]]],
@@ -153,5 +149,43 @@
                     ["double", 0.12345678], ["binary", "world"]]],
            ["map", [["string", "hello"], ["int", -25],
                     ["symbol", "world"], ["long", -12345678],
-                    ["binary", "today\\x01\\x02"], ["byte", -7]]]]]
+                    ["binary", "today\\x01\\x02"], ["byte", -7]]]]],
+ ["list", [["string", "*"],
+           ["null", null],
+           ["boolean", true],
+           ["ubyte", 1],
+           ["ushort", 2],
+           ["uint", 3],
+           ["ulong", 4],
+           ["byte", -1],
+           ["short", -2],
+           ["int", -3],
+           ["long", -4],
+           ["float", 3.14159],
+           ["double", -2.71828182845905],
+           ["decimal32", "0x03020100"],
+           ["decimal64", "0x0706050403020100"],
+           ["decimal128", "0x0f0e0d0c0b0a09080706050403020100"],
+           ["char", "A"],
+           ["timestamp", "0xdc6be25480"],
+           ["uuid", "00010203-0405-0607-0809-0a0b0c0d0e0f"],
+           ["binary", "0x0f0e0d0c0b0a09080706050403020100"],
+           ["string", "The quick brown fox jumped over the lazy dog 
0123456789."],
+           ["symbol", "myDomain.123"],
+           ["list", [["ubyte", 16],
+                     ["ushort", 17],
+                     ["uint", 18],
+                     ["ulong", 19],
+                     ["byte", 20],
+                     ["short", 21],
+                     ["int", 22],
+                     ["long", 23]]],
+           ["map", [["ubyte", 16], ["string", "sixteen"],
+                    ["ushort", 17], ["string", "seventeen"],
+                    ["uint", 18], ["string", "eighteen"],
+                    ["ulong", 19], ["string", "nineteen"],
+                    ["byte", 20], ["string", "twenty"],
+                    ["short", 21], ["string", "twenty-one"],
+                    ["int", 22], ["string", "twenty-two"],
+                    ["long", 23], ["string", "twenty-three"]]]]]
 ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/amqp_complex_types_test.map.json
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_complex_types_test.map.json 
b/src/python/qpid_interop_test/amqp_complex_types_test.map.json
index 9a6cbb2..8dbfbc7 100644
--- a/src/python/qpid_interop_test/amqp_complex_types_test.map.json
+++ b/src/python/qpid_interop_test/amqp_complex_types_test.map.json
@@ -27,7 +27,7 @@
  ["map", [["byte", -128], ["byte", -128],
           ["byte", -1], ["byte", -1],
           ["byte", 0], ["byte", 0],
-          ["byte", 255], ["byte", 255]]],
+          ["byte", 127], ["byte", 127]]],
  ["map", [["short", "-0x8000"], ["short", "-0x8000"],
           ["short", -1], ["short", -1],
           ["short", 0], ["short", 0],
@@ -80,8 +80,7 @@
           ["char", "0xff"], ["char", "0xff"],
           ["char", "0x16b5"], ["char", "0x16b5"],
           ["char", "0x010203"], ["char", "0x010203"],
-          ["char", "0x10ffff"], ["char", "0x10ffff"],
-          ["char", "0xffffffff"], ["char", "0xffffffff"]]],
+          ["char", "0x10ffff"], ["char", "0x10ffff"]]],
  ["map", [["timestamp", 0], ["timestamp", 0],
           ["timestamp", "0xdc6be25480"], ["timestamp", "0xdc6be25480"],
           ["timestamp", "0x1624e900fa5"], ["timestamp", "0x1624e900fa5"]]],
@@ -112,5 +111,35 @@
                                           ["ubyte", 128],
                                           ["ubyte", 255]]]]],
  ["map", [["string", "map01"], ["map", [["boolean", false], ["boolean", false],
-                                        ["boolean", true], ["boolean", 
true]]]]]
+                                        ["boolean", true], ["boolean", 
true]]]]],
+ ["map", [["string", "*"], ["string", "*"],
+          ["null", null], ["null", null],
+          ["boolean", false], ["boolean", true],
+          ["ubyte", 1], ["ubyte", 2],
+          ["ushort", 3], ["ushort", 4],
+          ["uint", 5], ["uint", 6],
+          ["ulong", 7], ["ulong", 8],
+          ["byte", -1], ["byte", -2],
+          ["short", -3], ["short", -4],
+          ["int", -5], ["int", -6],
+          ["long", -7], ["long", -8],
+          ["float", 3.14159], ["float", 3.14159],
+          ["double", -2.71828182845905], ["double", -2.71828182845905],
+          ["decimal32", "0x03020100"], ["decimal32", "0x01020304"],
+          ["decimal64", "0x0706050403020100"], ["decimal64", 
"0x0102030405060708"],
+          ["decimal128", "0x0f0e0d0c0b0a09080706050403020100"], ["decimal128", 
"0x0102030405060708090a0b0c0d0e0f00"],
+          ["char", "A"], ["char", "z"],
+          ["timestamp", "0xdc6be25480"], ["timestamp", "0x1624e900fa5"],
+          ["uuid", "0x0f0e0d0c0b0a09080706050403020100"], ["uuid", 
"68907a08-2a1b-4154-9733-2c0b9f4c5597"],
+          ["binary", "0x0f0e0d0c0b0a09080706050403020100"], ["binary", 543210],
+          ["string", "Hello, world"], ["string", "Goodbye, universe"],
+          ["symbol", "myDomain.123"], ["symbol", 
"yourDomain.321.hello.goodbye"],
+          ["float", 987.654], ["list", [["boolean", false],
+                                        ["boolean", true],
+                                        ["ubyte", 0],
+                                        ["ubyte", 127],
+                                        ["ubyte", 128],
+                                        ["ubyte", 255]]],
+          ["binary", 2560], ["map", [["boolean", false], ["boolean", false],
+                                     ["boolean", true], ["boolean", true]]]]]
 ]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/amqp_complex_types_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_complex_types_test.py 
b/src/python/qpid_interop_test/amqp_complex_types_test.py
new file mode 100755
index 0000000..865f27c
--- /dev/null
+++ b/src/python/qpid_interop_test/amqp_complex_types_test.py
@@ -0,0 +1,271 @@
+#!/usr/bin/env python
+
+"""
+Module to test AMQP complex types across different clients
+"""
+
+#
+# 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.
+#
+
+import copy
+import signal
+import sys
+import unittest
+
+import itertools
+
+import qpid_interop_test.qit_common
+from qpid_interop_test.qit_errors import InteropTestError, InteropTestTimeout
+
+DEFAULT_TEST_TIMEOUT = 10 # seconds
+
+class AmqpComplexTypes(qpid_interop_test.qit_common.QitTestTypeMap):
+    """
+    Class which contains all the described AMQP complex types and the test 
values to be used in testing.
+    """
+
+    default_type_list = ['array',
+                         'list',
+                         'map',
+                        ]
+    _type_list = []
+    default_subtype_list = ['None',
+                            'null',
+                            'boolean',
+                            'ubyte',
+                            'ushort',
+                            'uint',
+                            'ulong',
+                            'byte',
+                            'short',
+                            'int',
+                            'long',
+                            'float',
+                            'double',
+                            'decimal32',
+                            'decimal64',
+                            'decimal128',
+                            'char',
+                            'timestamp',
+                            'uuid',
+                            'binary',
+                            'string',
+                            'symbol',
+                            'array',
+                            'list',
+                            'map',
+                            '*', # Reserved type string used for mixed subtypes
+                           ]
+    _subtype_list = []
+
+    # This section contains tests that should be skipped because of known 
issues that would cause the test to fail.
+    # As the issues are resolved, these should be removed.
+    broker_skip = {}
+
+    client_skip = {}
+
+    def get_types(self, args):
+        """Return the list of types"""
+        if "include_type" in args and args.include_type is not None:
+            for this_type in args.include_type:
+                if this_type in self.default_type_list:
+                    self._type_list.append(this_type)
+                else:
+                    print('No such type: "%s". Use --help for valid types' % 
this_type)
+                    sys.exit(1) # Errors or failures present
+        elif "exclude_type" in args and args.exclude_type is not None:
+            self._type_list = copy.deepcopy(self.default_type_list)
+            for this_type in args.exclude_type:
+                try:
+                    self._type_list.remove(this_type)
+                except KeyError:
+                    print('No such type: "%s". Use --help for valid types' % 
this_type)
+                    sys.exit(1) # Errors or failures present
+        else:
+            self._type_list = self.default_type_list
+        if "include_subtype" in args and args.include_subtype is not None:
+            for this_subtype in args.include_subtype:
+                if this_subtype in self.default_subtype_list:
+                    self._subtype_list.append(this_subtype)
+                else:
+                    print('No such subtype: "%s". Use --help for valid types' 
% this_subtype)
+                    sys.exit(1) # Errors or failures present
+        elif "exclude_subtype" in args and args.exclude_subtype is not None:
+            self._subtype_list = copy.deepcopy(self.default_subtype_list)
+            for this_subtype in args.exclude_subtype:
+                try:
+                    self._subtype_list.remove(this_subtype)
+                except KeyError:
+                    print('No such subtype "%s". Use --help for valid 
subtypes' % this_subtype)
+                    sys.exit(1)
+        else:
+            self._subtype_list = self.default_subtype_list
+        return self
+
+    def get_type_list(self):
+        """Return a list of types"""
+        return self._type_list
+
+    def get_subtype_list(self):
+        """Return a list of subtypes which this test suite supports"""
+        return self._subtype_list
+
+
+class AmqpComplexTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
+    """Abstract base class for AMQP Complex Type test cases"""
+
+    def run_test(self, sender_addr, receiver_addr, amqp_type, amqp_subtype, 
send_shim, receive_shim, timeout):
+        """
+        Runs this test by invoking the shim send method to send the test 
values, followed by the shim receive method
+        to receive the values. Finally, compare the sent values with the 
received values.
+        """
+        test_name = 'amqp_complex_types_test.%s.%s.%s.%s' % (amqp_type, 
amqp_subtype, send_shim.NAME, receive_shim.NAME)
+        queue_name = 'qit.%s' % test_name
+
+        # Start the receive shim first (for queueless brokers/dispatch)
+        receiver = receive_shim.create_receiver(receiver_addr, queue_name, 
amqp_type, amqp_subtype)
+
+        # Start the send shim
+        sender = send_shim.create_sender(sender_addr, queue_name, amqp_type, 
amqp_subtype)
+
+        # Wait for sender, process return string
+        try:
+            send_obj = sender.wait_for_completion(timeout)
+        except (KeyboardInterrupt, InteropTestTimeout):
+            receiver.send_signal(signal.SIGINT)
+            raise
+        if send_obj is not None:
+            if isinstance(send_obj, str):
+                if send_obj: # len > 0
+                    receiver.send_signal(signal.SIGINT)
+                    raise InteropTestError('Send shim \'%s\':\n%s' % 
(send_shim.NAME, send_obj))
+            else:
+                receiver.send_signal(signal.SIGINT)
+                raise InteropTestError('Send shim \'%s\':\n%s' % 
(send_shim.NAME, send_obj))
+
+        # Wait for receiver, process return string
+        receive_obj = receiver.wait_for_completion(timeout)
+        if isinstance(receive_obj, tuple):
+            if len(receive_obj) == 2:
+                return_amqp_type, pass_text = receive_obj
+                self.assertEqual(return_amqp_type, amqp_type,
+                                 msg='AMQP type error:\n\n    sent:%s\n\n    
received:%s' % \
+                                 (amqp_type, return_amqp_type))
+                self.assertEqual(pass_text, ['pass'], msg='\n    %s' % 
pass_text)
+            else:
+                raise InteropTestError('Receive shim \'%s\':\n%s' % 
(receive_shim.NAME, receive_obj))
+        else:
+            raise InteropTestError('Receive shim \'%s\':\n%s' % 
(receive_shim.NAME, receive_obj))
+
+class TestOptions(qpid_interop_test.qit_common.QitCommonTestOptions):
+    """Command-line arguments used to control the test"""
+
+    def __init__(self, shim_map, default_timeout=DEFAULT_TEST_TIMEOUT,
+                 
default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
+        super(TestOptions, self).__init__('Qpid-interop AMQP client 
interoparability test suite for AMQP complex types',
+                                          shim_map, default_timeout, 
default_xunit_dir)
+        type_group = self._parser.add_mutually_exclusive_group()
+        type_group.add_argument('--include-type', action='append', 
metavar='AMQP-TYPE',
+                                help='Name of AMQP type to include. Supported 
types:\n%s' %
+                                sorted(AmqpComplexTypes.default_type_list))
+        type_group.add_argument('--exclude-type', action='append', 
metavar='AMQP-TYPE',
+                                help='Name of AMQP type to exclude. Supported 
types: see "include-type" above')
+        subtype_group = self._parser.add_mutually_exclusive_group()
+        subtype_group.add_argument('--include-subtype', action='append', 
metavar='AMQP-SUBTYPE',
+                                   help='Name of AMQP subtype to include. 
Supported types:\n%s' %
+                                   
sorted(AmqpComplexTypes.default_subtype_list))
+        subtype_group.add_argument('--exclude-subtype', action='append', 
metavar='AMQP-SUBTYPE',
+                                   help='Name of AMQP subtype to exclude. 
Supported types: see "include-subtype" above')
+
+
+class AmqpComplexTypesTest(qpid_interop_test.qit_common.QitTest):
+    """Top-level test for AMQP complex types"""
+
+    TEST_NAME = 'amqp_complex_types_test'
+
+    def __init__(self):
+        super(AmqpComplexTypesTest, self).__init__(TestOptions, 
AmqpComplexTypes)
+
+    def _generate_tests(self):
+        """Generate tests dynamically"""
+        self.test_suite = unittest.TestSuite()
+        # Create test classes dynamically
+        for amqp_type in self.types.get_type_list():
+            if self.args.exclude_type is None or amqp_type not in 
self.args.exclude_type:
+                for amqp_subtype in self.types.get_subtype_list():
+                    test_case_class = self.create_testcase_class(amqp_type, 
amqp_subtype,
+                                                                 
itertools.product(self.shim_map.values(), repeat=2),
+                                                                 
int(self.args.timeout))
+                    
self.test_suite.addTest(unittest.makeSuite(test_case_class))
+
+    def create_testcase_class(self, amqp_type, amqp_subtype, shim_product, 
timeout):
+        """Class factory function which creates new subclasses to 
AmqpTypeTestCase"""
+
+        def __repr__(self):
+            """Print the class name"""
+            return self.__class__.__name__
+
+        def add_test_method(cls, send_shim, receive_shim, timeout):
+            """Function which creates a new test method in class cls"""
+
+            @unittest.skipIf(self.types.skip_test(amqp_type, self.broker),
+                             self.types.skip_test_message(amqp_type, 
self.broker))
+            @unittest.skipIf(self.types.skip_client_test(amqp_type, 
send_shim.NAME),
+                             self.types.skip_client_test_message(amqp_type, 
send_shim.NAME, u'SENDER'))
+            @unittest.skipIf(self.types.skip_client_test(amqp_type, 
receive_shim.NAME),
+                             self.types.skip_client_test_message(amqp_type, 
receive_shim.NAME, u'RECEIVER'))
+            def inner_test_method(self):
+                self.run_test(self.sender_addr,
+                              self.receiver_addr,
+                              self.amqp_type,
+                              amqp_subtype,
+                              send_shim,
+                              receive_shim,
+                              timeout)
+
+            inner_test_method.__name__ = 'test_%s_%s_%s->%s' % (amqp_type, 
amqp_subtype, send_shim.NAME,
+                                                                
receive_shim.NAME)
+            setattr(cls, inner_test_method.__name__, inner_test_method)
+
+        class_name = amqp_type.title() + 'TestCase'
+        class_dict = {'__name__': class_name,
+                      '__repr__': __repr__,
+                      '__doc__': 'Test case for AMQP 1.0 simple type \'%s\'' % 
amqp_type,
+                      'amqp_type': amqp_type,
+                      'sender_addr': self.args.sender,
+                      'receiver_addr': self.args.receiver,
+                      'test_value_list': self.types.get_test_values(amqp_type)}
+        new_class = type(class_name, (AmqpComplexTypeTestCase,), class_dict)
+        for send_shim, receive_shim in shim_product:
+            add_test_method(new_class, send_shim, receive_shim, timeout)
+        return new_class
+
+
+#--- Main program start ---
+
+if __name__ == '__main__':
+    try:
+        AMQP_COMPLEX_TYPES_TEST = AmqpComplexTypesTest()
+        AMQP_COMPLEX_TYPES_TEST.run_test()
+        AMQP_COMPLEX_TYPES_TEST.write_logs()
+        if not AMQP_COMPLEX_TYPES_TEST.get_result():
+            sys.exit(1) # Errors or failures present
+    except InteropTestError as err:
+        print(err)
+        sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/amqp_complex_types_test_generator.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_complex_types_test_generator.py 
b/src/python/qpid_interop_test/amqp_complex_types_test_generator.py
old mode 100644
new mode 100755
index 5fdaec6..72d2753
--- a/src/python/qpid_interop_test/amqp_complex_types_test_generator.py
+++ b/src/python/qpid_interop_test/amqp_complex_types_test_generator.py
@@ -26,6 +26,7 @@ Module to generate test data files for the AMQP complex types 
test
 import argparse
 import json
 import os.path
+import sys
 import time
 from abc import abstractmethod
 
@@ -67,19 +68,19 @@ class JsonReader(object):
         for target in gen_targets:
             target_file_name = None
             if target == GENERATOR_TARGETS[0]: # Python
-                target_file_name = os.path.join(gen_path, u'%s.data.py' % 
self.args.json_base_name)
+                target_file_name = os.path.join(gen_path, u'%s_data.py' % 
self.args.json_base_name)
                 with PythonGenerator(target_file_name) as generator:
                     self._generate_target(target, generator)
             elif target == GENERATOR_TARGETS[1]: # C++
-                target_file_name = os.path.join(gen_path, u'%s.data.cpp' % 
self.args.json_base_name)
+                target_file_name = os.path.join(gen_path, u'%s_data.cpp' % 
self.args.json_base_name)
                 with CppGenerator(target_file_name) as generator:
                     self._generate_target(target, generator)
             elif target == GENERATOR_TARGETS[2]: # JavaScript
-                target_file_name = os.path.join(gen_path, u'%s.data.js' % 
self.args.json_base_name)
+                target_file_name = os.path.join(gen_path, u'%s_data.js' % 
self.args.json_base_name)
                 with JavaScriptGenerator(target_file_name) as generator:
                     self._generate_target(target, generator)
             elif target == GENERATOR_TARGETS[3]: # DotNet
-                target_file_name = os.path.join(gen_path, u'%s.data.cs' % 
self.args.json_base_name)
+                target_file_name = os.path.join(gen_path, u'%s_data.cs' % 
self.args.json_base_name)
                 with DotNetGenerator(target_file_name) as generator:
                     self._generate_target(target, generator)
             else:
@@ -87,7 +88,7 @@ class JsonReader(object):
 
     def _generate_target(self, target, generator):
         """Generate the output file for target type"""
-        print(u'_generate_target(t=%s g=%s)' % (target, 
generator.__class__.__name__))
+        print(u'amqp_complex_types_test_generator: target=%s generator=%s' % 
(target, generator.__class__.__name__))
         generator.write_prefix()
         if self.args.type == u'ALL':
             amqp_test_types = AMQP_COMPEX_TYPES[:-1]
@@ -97,18 +98,22 @@ class JsonReader(object):
         for amqp_test_type in amqp_test_types:
             json_file_name = os.path.join(os.path.abspath(self.args.src_dir), 
u'%s.%s.json' %
                                           (self.args.json_base_name, 
amqp_test_type))
-            print(u' * _generate_type(t=%s f=%s)' % (amqp_test_type, 
os.path.basename(json_file_name)))
+            #print(u' * _generate_type(t=%s f=%s)' % (amqp_test_type, 
os.path.basename(json_file_name)))
             generator.write_code(amqp_test_type, 
JsonReader._read_file(json_file_name))
         generator.write_postfix()
 
     @staticmethod
     def _read_file(json_file_name):
         """Read the file into a Python data structure"""
-        print(u'reading file %s' % os.path.basename(json_file_name))
-        json_file = open(json_file_name, u'r')
-        json_file_data = json_file.read()
-        json_file.close()
-        return json.loads(json_file_data)
+        #print(u'reading file %s' % os.path.basename(json_file_name))
+        try:
+            json_file = open(json_file_name, u'r')
+            json_file_data = json_file.read()
+            json_file.close()
+            return json.loads(json_file_data)
+        except IOError:
+            print(u'ERROR: Unable to read JSON source file "%s"' % 
json_file_name)
+            sys.exit(1)
 
     @staticmethod
     def _target_file_extension(target):
@@ -159,7 +164,7 @@ class PythonGenerator(Generator):
         self.target_file.write(u'\n# *** THIS IS A GENERATED FILE, DO NOT EDIT 
DIRECTLY ***\n')
         self.target_file.write(u'# Generated by building qpid_interop_test\n')
         self.target_file.write(u'# Generated: %s\n\n' % 
time.strftime(u'%Y-%m-%d %H:%M:%S', time.gmtime()))
-        self.target_file.write(u'import uuid\nimport proton\n\n')
+        self.target_file.write(u'import uuid\nimport proton\nimport 
_compat\n\n')
         self.target_file.write(u'TEST_DATA = {\n')
 
     def write_code(self, amqp_test_type, json_data):
@@ -173,9 +178,10 @@ class PythonGenerator(Generator):
             self._write_data_pair(2, data_pair)
         self.target_file.write(u'    ], # end: AMQP type %s\n' % 
amqp_test_type)
 
-    def _write_data_pair(self, indent_level, data_pair, separator=u',', 
eol=True):
+    def _write_data_pair(self, indent_level, data_pair, separator=u',', 
eol=True, indent=True):
         """Write a JOSN pair ['amqp_type', value]"""
-        indent_str = u' ' * (indent_level * INDENT_LEVEL_SIZE)
+        indent_str = u' ' * (indent_level * INDENT_LEVEL_SIZE) if indent else 
u''
+        post_indent_str = u' ' * (indent_level * INDENT_LEVEL_SIZE)
         eol_char = u'\n' if eol else u''
         amqp_type, value = data_pair
         if amqp_type == u'null':
@@ -197,15 +203,23 @@ class PythonGenerator(Generator):
         elif amqp_type == u'ulong':
             self.target_file.write(u'%sproton.ulong(%s)%s%s' % (indent_str, 
value, separator, eol_char))
         elif amqp_type == u'long':
-            self.target_file.write(u'%sint(%s)%s%s' % (indent_str, value, 
separator, eol_char))
+            if isinstance(value, str):
+                if (len(value) > 2 and value[:2] == u'0x') or (len(value) > 3 
and value[:3] == u'-0x'):
+                    self.target_file.write(u'%s_compat.str2long(u\'%s\', 
16)%s%s' %
+                                           (indent_str, value, separator, 
eol_char))
+                else:
+                    self.target_file.write(u'%s_compat.str2long(u\'%s\', 
10)%s%s' %
+                                           (indent_str, value, separator, 
eol_char))
+            else:
+                self.target_file.write(u'%s_compat.long(%s)%s%s' % 
(indent_str, value, separator, eol_char))
         elif amqp_type == u'float':
             if isinstance(value, str) and (value[-3:] == u'inf' or value[-3:] 
== u'NaN'):
-                self.target_file.write(u'%sproton.float32(\'%s\')%s%s' % 
(indent_str, value, separator, eol_char))
+                self.target_file.write(u'%sproton.float32(u\'%s\')%s%s' % 
(indent_str, value, separator, eol_char))
             else:
                 self.target_file.write(u'%sproton.float32(%s)%s%s' % 
(indent_str, value, separator, eol_char))
         elif amqp_type == u'double':
             if isinstance(value, str) and (value[-3:] == u'inf' or value[-3:] 
== u'NaN'):
-                self.target_file.write(u'%sfloat(\'%s\')%s%s' % (indent_str, 
value, separator, eol_char))
+                self.target_file.write(u'%sfloat(u\'%s\')%s%s' % (indent_str, 
value, separator, eol_char))
             else:
                 self.target_file.write(u'%sfloat(%s)%s%s' % (indent_str, 
value, separator, eol_char))
         elif amqp_type == u'decimal32':
@@ -219,14 +233,12 @@ class PythonGenerator(Generator):
                 self.target_file.write(u'\\x%c%c' % (char_, next(byte_itr)))
             self.target_file.write(u'\')%s%s' % (separator, eol_char))
         elif amqp_type == u'char':
-            self.target_file.write(u'%sproton.char(u\'' % indent_str)
+            self.target_file.write(u'%sproton.char(' % indent_str)
             if len(value) == 1: # single char
-                self.target_file.write(value)
+                self.target_file.write(u'u\'%s\'' % value)
             else:
-                byte_itr = iter(value[2:])
-                for char_ in byte_itr:
-                    self.target_file.write(u'\\x%c%c' % (char_, 
next(byte_itr)))
-            self.target_file.write(u'\')%s%s' % (separator, eol_char))
+                self.target_file.write(u'_compat.unichr(int(u\'%s\', 16))' % 
value)
+            self.target_file.write(u')%s%s' % (separator, eol_char))
         elif amqp_type == u'timestamp':
             self.target_file.write(u'%sproton.timestamp(%s)%s%s' % 
(indent_str, value, separator, eol_char))
         elif amqp_type == u'uuid':
@@ -234,13 +246,18 @@ class PythonGenerator(Generator):
             if value[:2] == u'0x':
                 self.target_file.write(u'int=%s' % value)
             else:
-                self.target_file.write(u'\'{%s}\'' % value)
+                self.target_file.write(u'u\'{%s}\'' % value)
             self.target_file.write(u')%s%s' % (separator, eol_char))
         elif amqp_type == u'binary':
+            if isinstance(value, int):
+                value = hex(value)
             if isinstance(value, str):
                 self.target_file.write(u'%sb\'' % indent_str)
                 if value[:2] == u'0x':
-                    byte_itr = iter(value[2:])
+                    value = value[2:]
+                    if len(value) % 2 > 0:
+                        value = '0' + value
+                    byte_itr = iter(value)
                     for char_ in byte_itr:
                         self.target_file.write(u'\\x%c%c' % (char_, 
next(byte_itr)))
                 else:
@@ -278,14 +295,14 @@ class PythonGenerator(Generator):
                     raise RuntimeError(u'AMQP array of type %s has element of 
type %s' %
                                        (amqp_type, value_data_pair[0]))
                 self._write_data_pair(indent_level+1, value_data_pair)
-            self.target_file.write(u'%s]),%s' % (indent_str, eol_char))
+            self.target_file.write(u'%s]),%s' % (post_indent_str, eol_char))
         elif amqp_type == u'list':
             if not isinstance(value, list):
                 raise RuntimeError(u'AMQP list value not a list, found %s' % 
type(value))
             self.target_file.write(u'%s[\n' % indent_str)
             for value_data_pair in value:
                 self._write_data_pair(indent_level+1, value_data_pair)
-            self.target_file.write(u'%s],%s' % (indent_str, eol_char))
+            self.target_file.write(u'%s],%s' % (post_indent_str, eol_char))
         elif amqp_type == u'map':
             if not isinstance(value, list):
                 raise RuntimeError(u'AMQP map value not a list, found %s' % 
type(value))
@@ -297,8 +314,8 @@ class PythonGenerator(Generator):
             for value_data_pair in value_iter:
                 self._write_data_pair(indent_level+1, value_data_pair, 
separator=u': ', eol=False)
                 value_data_pair = next(value_iter)
-                self._write_data_pair(0, value_data_pair)
-            self.target_file.write(u'%s},%s' % (indent_str, eol_char))
+                self._write_data_pair(indent_level+1, value_data_pair, 
indent=False)
+            self.target_file.write(u'%s},%s' % (post_indent_str, eol_char))
         else:
             raise RuntimeError(u'Unknown AMQP type \'%s\'' % amqp_type)
 
@@ -696,7 +713,6 @@ class JavaScriptGenerator(Generator):
 
     def write_postfix(self):
         """Write postfix at bottom of JavaScript source file"""
-        self.target_file.write()
         self.target_file.write(u'// <eof>\n')
 
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/b4e6d0b5/src/python/qpid_interop_test/qit_shim.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/qit_shim.py 
b/src/python/qpid_interop_test/qit_shim.py
index 938976b..49cc0e9 100644
--- a/src/python/qpid_interop_test/qit_shim.py
+++ b/src/python/qpid_interop_test/qit_shim.py
@@ -32,13 +32,13 @@ from qpid_interop_test.qit_errors import InteropTestTimeout
 
 class ShimProcess(subprocess.Popen):
     """Abstract parent class for Sender and Receiver shim process"""
-    def __init__(self, args, python3_flag, proc_name):
+    def __init__(self, params, python3_flag, proc_name):
         self.proc_name = proc_name
         self.killed_flag = False
         self.env = copy.deepcopy(os.environ)
         if python3_flag:
             self.env['PYTHONPATH'] = self.env['PYTHON3PATH']
-        super(ShimProcess, self).__init__(args, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, preexec_fn=os.setsid,
+        super(ShimProcess, self).__init__(params, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE, preexec_fn=os.setsid,
                                           env=self.env)
 
     def wait_for_completion(self, timeout):
@@ -49,6 +49,8 @@ class ShimProcess(subprocess.Popen):
             (stdoutdata, stderrdata) = self.communicate()
             if self.killed_flag:
                 raise InteropTestTimeout('%s: Timeout after %d seconds' % 
(self.proc_name, timeout))
+            if self.returncode != 0:
+                return 'Return code %d\nstderr=%s\nstdout=%s' % 
(self.returncode, stderrdata, stdoutdata)
             if stderrdata: # length > 0
                 # Workaround for Amqp.NetLite which on some OSs produces a 
spurious error message on stderr
                 # which should be ignored:


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

Reply via email to