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 2016/10/07 16:50:40 UTC

[1/5] qpid-interop-test git commit: QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parame

Repository: qpid-interop-test
Updated Branches:
  refs/heads/master 83b89fe40 -> 514bac751


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/jms_hdrs_props_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/jms_hdrs_props_test.py b/src/python/qpid_interop_test/jms_hdrs_props_test.py
new file mode 100755
index 0000000..134f465
--- /dev/null
+++ b/src/python/qpid_interop_test/jms_hdrs_props_test.py
@@ -0,0 +1,520 @@
+#!/usr/bin/env python
+
+"""
+Module to test JMS headers and properties
+"""
+
+#
+# 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 argparse
+import sys
+import unittest
+
+from itertools import product
+from json import dumps
+from os import getenv, path
+
+from proton import symbol
+import qpid_interop_test.broker_properties
+import qpid_interop_test.shims
+from qpid_interop_test.test_type_map import TestTypeMap
+
+
+# TODO: propose a sensible default when installation details are worked out
+QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
+if QPID_INTEROP_TEST_HOME is None:
+    print 'ERROR: Environment variable QPID_INTEROP_TEST_HOME is not set'
+    sys.exit(1)
+MAVEN_REPO_PATH = getenv('MAVEN_REPO_PATH', path.join(getenv('HOME'), '.m2', 'repository'))
+
+class JmsMessageTypes(TestTypeMap):
+    """
+    Class which contains all the described JMS message types and the test values to be used in testing.
+    """
+
+    COMMON_SUBMAP = {
+        'boolean': ['True',
+                    'False'],
+        'byte': ['-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f'],
+        'double': ['0x0000000000000000', # 0.0
+                   '0x8000000000000000', # -0.0
+                   '0x400921fb54442eea', # pi (3.14159265359) positive decimal
+                   '0xc005bf0a8b145fcf', # -e (-2.71828182846) negative decimal
+                   '0x0000000000000001', # Smallest positive denormalized number
+                   '0x8000000000000001', # Smallest negative denormalized number
+                   '0x000fffffffffffff', # Largest positive denormalized number
+                   '0x8010000000000000', # Largest negative denormalized number
+                   '0x7fefffffffffffff', # Largest positive normalized number
+                   '0xffefffffffffffff', # Largest negative normalized number
+                   '0x7ff0000000000000', # +Infinity
+                   '0xfff0000000000000', # -Infinity
+                   '0x7ff8000000000000'], # +NaN
+        'float': ['0x00000000', # 0.0
+                  '0x80000000', # -0.0
+                  '0x40490fdb', # pi (3.14159265359) positive decimal
+                  '0xc02df854', # -e (-2.71828182846) negative decimal
+                  '0x00000001', # Smallest positive denormalized number
+                  '0x80000001', # Smallest negative denormalized number
+                  '0x007fffff', # Largest positive denormalized number
+                  '0x807fffff', # Largest negative denormalized number
+                  '0x00800000', # Smallest positive normalized number
+                  '0x80800000', # Smallest negative normalized number
+                  '0x7f7fffff', # Largest positive normalized number
+                  '0xff7fffff', # Largest negative normalized number
+                  #'0x7f800000', # +Infinity  # PROTON-1149 - fails on RHEL7
+                  #'0xff800000', # -Infinity # PROTON-1149 - fails on RHEL7
+                  '0x7fc00000'], # +NaN
+        'int': ['-0x80000000',
+                '-0x81',
+                '-0x80',
+                '-0x1',
+                '0x0',
+                '0x7f',
+                '0x80',
+                '0x7fffffff'],
+        'long': ['-0x8000000000000000',
+                 '-0x81',
+                 '-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f',
+                 '0x80',
+                 '0x7fffffffffffffff'],
+        'short': ['-0x8000',
+                  '-0x1',
+                  '0x0',
+                  '0x7fff'],
+        'string': ['',
+                   'Hello, world',
+                   '"Hello, world"',
+                   "Charlie's \"peach\"",
+                   'Charlie\'s "peach"',
+                   'The quick brown fox jumped over the lazy dog 0123456789.'# * 100]
+                  ]
+        }
+
+    TYPE_ADDITIONAL_SUBMAP = {
+        'bytes': [b'',
+                  b'12345',
+                  b'Hello, world',
+                  b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
+                  b'The quick brown fox jumped over the lazy dog 0123456789.' #* 100],
+                 ],
+        'char': ['a',
+                 'Z',
+                 '\x01',
+                 '\x7f'],
+        }
+
+    # The TYPE_SUBMAP defines test values for JMS message types that allow typed message content. Note that the
+    # types defined here are understood to be *Java* types and the stringified values are to be interpreted
+    # as the appropriate Java type by the send shim.
+    TYPE_SUBMAP = TestTypeMap.merge_dicts(COMMON_SUBMAP, TYPE_ADDITIONAL_SUBMAP)
+
+    # Defines JMS headers that should be set by the send or publish API call of the client
+    HEADERS_PUBLISH_LIST = [
+        'JMS_DESTINATION',
+        'JMS_DELIVERY_MODE',
+        'JMS_EXPIRATION',
+        'JMS_PRIORITY',
+        'JMS_MESSAGEID',
+        'JMS_TIMESTAMP',
+        ]
+
+    # Defines JMS headers that are modified by the broker when he message is consumed
+    HEADERS_BROKER_LIST = [
+        'JMS_REDELIVERED',
+        ]
+
+    # JMS headers that can be set by the client prior to send / publish, and that should be preserved byt he broker
+    HEADERS_MAP = {
+        'JMS_CORRELATIONID_HEADER': {'string': ['Hello, world',
+                                                '"Hello, world"',
+                                                "Charlie's \"peach\"",
+                                                'Charlie\'s "peach"',
+                                                'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
+                                                #'', # TODO: Re-enable when PROTON-1288 is fixed
+                                               ],
+                                     'bytes': [b'12345\\x006789',
+                                               b'Hello, world',
+                                               b'"Hello, world"',
+                                               b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
+                                               b'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
+                                               #b'', # TODO: Re-enable when PROTON-1288 is fixed
+                                              ],
+                                    },
+        'JMS_REPLYTO_HEADER': {'queue': ['q_aaa', 'q_bbb'],
+                               'topic': ['t_aaa', 't_bbb'],
+                              },
+        'JMS_TYPE_HEADER': {'string': ['Hello, world',
+                                       '"Hello, world"',
+                                       "Charlie's \"peach\"",
+                                       'Charlie\'s "peach"',
+                                       'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
+                                       #'', # TODO: Re-enable when PROTON-1288 is fixed
+                                      ],
+                           },
+        }
+
+    PROPERTIES_MAP = COMMON_SUBMAP # disabled until PROTON-1284 is fixed
+
+    TYPE_MAP = {
+        'JMS_MESSAGE_TYPE': {'none': [None]},
+        'JMS_BYTESMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_MAPMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_STREAMMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_TEXTMESSAGE_TYPE': {'text': ['',
+                                          'Hello, world',
+                                          '"Hello, world"',
+                                          "Charlie's \"peach\"",
+                                          'Charlie\'s "peach"',
+                                          'The quick brown fox jumped over the lazy dog 0123456789.' * 10
+                                         ]
+                                },
+        # TODO: Add Object messages when other (non-JMS clients) can generate Java class strings used in this message
+        # type
+        #'JMS_OBJECTMESSAGE_TYPE': {
+        #    'java.lang.Boolean': ['true',
+        #                          'false'],
+        #    'java.lang.Byte': ['-128',
+        #                       '0',
+        #                       '127'],
+        #    'java.lang.Character': [u'a',
+        #                            u'Z'],
+        #    'java.lang.Double': ['0.0',
+        #                         '3.141592654',
+        #                         '-2.71828182846'],
+        #    'java.lang.Float': ['0.0',
+        #                        '3.14159',
+        #                        '-2.71828'],
+        #    'java.lang.Integer': ['-2147483648',
+        #                          '-129',
+        #                          '-128',
+        #                          '-1',
+        #                          '0',
+        #                          '127',
+        #                          '128',
+        #                          '2147483647'],
+        #    'java.lang.Long' : ['-9223372036854775808',
+        #                        '-129',
+        #                        '-128',
+        #                        '-1',
+        #                        '0',
+        #                        '127',
+        #                        '128',
+        #                        '9223372036854775807'],
+        #    'java.lang.Short': ['-32768',
+        #                        '-129',
+        #                        '-128',
+        #                        '-1',
+        #                        '0',
+        #                        '127',
+        #                        '128',
+        #                        '32767'],
+        #    'java.lang.String': [u'',
+        #                         u'Hello, world',
+        #                         u'"Hello, world"',
+        #                         u"Charlie's \"peach\"",
+        #                         u'Charlie\'s "peach"']
+        #    },
+        }
+
+    BROKER_SKIP = {}
+
+
+class JmsMessageTypeTestCase(unittest.TestCase):
+    """
+    Abstract base class for JMS message type test cases
+    """
+
+    def run_test(self, broker_addr, jms_message_type, test_values, msg_hdrs, msg_props, send_shim, receive_shim):
+        """
+        Run 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.
+        """
+        queue_name = 'jms.queue.qpid-interop.jms_message_type_tests.%s.%s.%s' % (jms_message_type, send_shim.NAME,
+                                                                                 receive_shim.NAME)
+
+        # First create a map containing the numbers of expected mesasges for each JMS message type
+        num_test_values_map = {}
+        if len(test_values) > 0:
+            for index in test_values.keys():
+                num_test_values_map[index] = len(test_values[index])
+        # Create a map of flags which indicate to the receiver the details of some of the messages so that it can
+        # be correctly handled (as these require some prior knowledge)
+        flags_map = {}
+        if 'JMS_CORRELATIONID_HEADER' in msg_hdrs and 'bytes' in msg_hdrs['JMS_CORRELATIONID_HEADER']:
+            flags_map['JMS_CORRELATIONID_AS_BYTES'] = True
+        if 'JMS_REPLYTO_HEADER' in msg_hdrs and 'topic' in msg_hdrs['JMS_REPLYTO_HEADER']:
+            flags_map['JMS_REPLYTO_AS_TOPIC'] = True
+        # Start the receiver shim
+        receiver = receive_shim.create_receiver(broker_addr, queue_name, jms_message_type,
+                                                dumps([num_test_values_map, flags_map]))
+        receiver.start()
+
+        # Start the send shim
+        sender = send_shim.create_sender(broker_addr, queue_name, jms_message_type,
+                                         dumps([test_values, msg_hdrs, msg_props]))
+        sender.start()
+
+        # Wait for both shims to finish
+        sender.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+        receiver.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+
+        # Process return string from sender
+        send_obj = sender.get_return_object()
+        if send_obj is not None:
+            if isinstance(send_obj, str) and len(send_obj) > 0:
+                self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
+            else:
+                self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, str(send_obj)))
+
+        # Process return string from receiver
+        receive_obj = receiver.get_return_object()
+        if receive_obj is None:
+            self.fail('JmsReceiver shim returned None')
+        else:
+            if isinstance(receive_obj, tuple):
+                if len(receive_obj) == 2:
+                    return_jms_message_type, return_list = receive_obj
+                    if (len(return_list) == 3):
+                        return_test_values = return_list[0]
+                        return_msg_hdrs = return_list[1]
+                        return_msg_props = return_list[2]
+                        self.assertEqual(return_jms_message_type, jms_message_type,
+                                         msg='JMS message type error:\n\n    sent:%s\n\n    received:%s' % \
+                                         (jms_message_type, return_jms_message_type))
+                        self.assertEqual(return_test_values, test_values,
+                                         msg='JMS message body error:\n\n    sent:%s\n\n    received:%s' % \
+                                         (test_values, return_test_values))
+                        self.assertEqual(return_msg_hdrs, msg_hdrs,
+                                         msg='JMS message headers error:\n\n    sent:%s\n\n    received:%s' % \
+                                         (msg_hdrs, return_msg_hdrs))
+                        self.assertEqual(return_msg_props, msg_props,
+                                         msg='JMS message properties error:\n\n    sent:%s\n\n    received:%s' % \
+                                         (msg_props, return_msg_props))
+                    else:
+                        self.fail('Return value list needs 3 items, found %d items: %s' % (len(return_list),
+                                                                                           str(return_list)))
+            else:
+                self.fail(str(receive_obj))
+
+
+def create_testcase_class(broker_name, types, broker_addr, jms_message_type, shim_product):
+    """
+    Class factory function which creates new subclasses to JmsMessageTypeTestCase. Each call creates a single new
+    test case named and based on the parameters supplied to the method
+    """
+
+    def __repr__(self):
+        """Print the class name"""
+        return self.__class__.__name__
+
+    def add_test_method(cls, hdrs, props, send_shim, receive_shim):
+        """Function which creates a new test method in class cls"""
+
+        @unittest.skipIf(types.skip_test(jms_message_type, broker_name),
+                         types.skip_test_message(jms_message_type, broker_name))
+        def inner_test_method(self):
+            self.run_test(self.broker_addr,
+                          self.jms_message_type,
+                          self.test_values,
+                          hdrs[1],
+                          props[1],
+                          send_shim,
+                          receive_shim)
+
+        inner_test_method.__name__ = 'test_%s%s%s_%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0], send_shim.NAME,
+                                                             receive_shim.NAME)
+        setattr(cls, inner_test_method.__name__, inner_test_method)
+
+    class_name = jms_message_type[4:-5].title() + 'TestCase'
+    class_dict = {'__name__': class_name,
+                  '__repr__': __repr__,
+                  '__doc__': 'Test case for JMS message type \'%s\'' % jms_message_type,
+                  'jms_message_type': jms_message_type,
+                  'broker_addr': broker_addr,
+                  'test_values': types.get_test_values(jms_message_type)} # tuple (tot_size, {...}
+    new_class = type(class_name, (JmsMessageTypeTestCase,), class_dict)
+    for send_shim, receive_shim in shim_product:
+        # Message without any headers or properties
+        add_test_method(new_class, ('', {}), ('', {}), send_shim, receive_shim)
+
+        # Iterate through message headers, add one test per header value, no combinations
+        # Structure: {HEADER_NAME_1; {header_type_1: [val_1_1, val_1_2, val_1_3, ...],
+        #                             header_type_2: [val_2_1, val_2_2, val_2_3, ...],
+        #                             ...
+        #                            },
+        #             ...
+        #            }
+        for msg_header, header_type_dict in types.HEADERS_MAP.iteritems():
+            for header_type, header_val_list in header_type_dict.iteritems():
+                hdr_val_cnt = 0
+                for header_val in header_val_list:
+                    hdr_val_cnt += 1
+                    test_name = '_hdr.%s.%s.%02d' % (msg_header[4:-7], header_type, hdr_val_cnt)
+                    add_test_method(new_class,
+                                    (test_name, {msg_header: {header_type: header_val}}),
+                                    ('', {}),
+                                    send_shim,
+                                    receive_shim)
+
+        # One message with all the headers together using type[0] and val[0]
+        all_hdrs = {}
+        for msg_header in types.HEADERS_MAP.iterkeys():
+            header_type_dict = types.HEADERS_MAP[msg_header]
+            header_type, header_val_list = header_type_dict.iteritems().next()
+            header_val = header_val_list[0]
+            all_hdrs[msg_header] = {header_type: header_val}
+        add_test_method(new_class, ('_hdrs', all_hdrs), ('', {}), send_shim, receive_shim)
+
+        # Properties tests disabled until PROTON-1284 fixed
+        ## Iterate through properties
+        ## Structure: {prop_type_1: [val_1_1, val_1_2, ...],
+        ##             prop_type_2: [val_2_1, val_2_2, ...],
+        ##             ...
+        ##            }
+        #all_props = {}
+        #for prop_type, prop_val_list in types.PROPERTIES_MAP.iteritems():
+        #    prop_val_cnt = 0
+        #    for prop_val in prop_val_list:
+        #        prop_val_cnt += 1
+        #        all_props['%s_%02d' % (prop_type, prop_val_cnt)] = {prop_type: prop_val}
+
+        ## One message with all properties together
+        #add_test_method(new_class, ('', {}), ('_props', all_props), send_shim, receive_shim)
+
+        ## One message with all headers and all properties together
+        #add_test_method(new_class, ('_hdrs', all_hdrs), ('_props', all_props), send_shim, receive_shim)
+
+    return new_class
+
+
+PROTON_CPP_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_hdrs_props_test',
+                                     'Receiver')
+PROTON_CPP_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_hdrs_props_test',
+                                   'Sender')
+PROTON_PYTHON_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src',
+                                        'jms_hdrs_props_test', 'Receiver.py')
+PROTON_PYTHON_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src',
+                                      'jms_hdrs_props_test', 'Sender.py')
+QIT_JMS_CLASSPATH_FILE = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'cp.txt')
+with open(QIT_JMS_CLASSPATH_FILE, 'r') as classpath_file:
+    QIT_JMS_CLASSPATH = classpath_file.read()
+QPID_JMS_RECEIVER_SHIM = 'org.apache.qpid.interop_test.jms_hdrs_props_test.Receiver'
+QPID_JMS_SENDER_SHIM = 'org.apache.qpid.interop_test.jms_hdrs_props_test.Sender'
+
+# SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
+# every shim in this list, a test is dynamically constructed which tests it against itself as well as every
+# other shim in the list.
+#
+# As new shims are added, add them into this map to have them included in the test cases.
+SHIM_MAP = {qpid_interop_test.shims.ProtonCppShim.NAME: \
+                qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
+            qpid_interop_test.shims.ProtonPythonShim.NAME: \
+                qpid_interop_test.shims.ProtonPythonShim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+            qpid_interop_test.shims.QpidJmsShim.NAME: \
+                qpid_interop_test.shims.QpidJmsShim(QIT_JMS_CLASSPATH, QPID_JMS_SENDER_SHIM, QPID_JMS_RECEIVER_SHIM),
+           }
+
+# TODO: Complete the test options to give fine control over running tests
+class TestOptions(object):
+    """
+    Class controlling command-line arguments used to control the test.
+    """
+    def __init__(self,):
+        parser = argparse.ArgumentParser(description='Qpid-interop AMQP client interoparability test suite '
+                                         'for JMS message types')
+        parser.add_argument('--broker', action='store', default='localhost:5672', metavar='BROKER:PORT',
+                            help='Broker against which to run test suite.')
+#        test_group = parser.add_mutually_exclusive_group()
+#        test_group.add_argument('--include-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to include')
+#        test_group.add_argument('--exclude-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to exclude')
+#        type_group = test_group.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(JmsMessageTypes.TYPE_MAP.keys()))
+        parser.add_argument('--exclude-type', action='append', metavar='JMS-MESSAGE-TYPE',
+                            help='Name of JMS message type to exclude. Supported types:\n%s' %
+                            sorted(JmsMessageTypes.TYPE_MAP.keys()))
+#        shim_group = test_group.add_mutually_exclusive_group()
+#        shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',
+#                                help='Name of shim to include. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        parser.add_argument('--exclude-shim', action='append', metavar='SHIM-NAME',
+                            help='Name of shim to exclude. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        self.args = parser.parse_args()
+
+
+#--- Main program start ---
+
+if __name__ == '__main__':
+    ARGS = TestOptions().args
+    #print 'ARGS:', ARGS # debug
+
+    # Connect to broker to find broker type
+    CONNECTION_PROPS = qpid_interop_test.broker_properties.get_broker_properties(ARGS.broker)
+    if CONNECTION_PROPS is None:
+        print 'WARNING: Unable to get connection properties - unknown broker'
+        BROKER = 'unknown'
+    else:
+        BROKER = CONNECTION_PROPS[symbol(u'product')] if symbol(u'product') in CONNECTION_PROPS \
+                 else '<product not found>'
+        BROKER_VERSION = CONNECTION_PROPS[symbol(u'version')] if symbol(u'version') in CONNECTION_PROPS \
+                         else '<version not found>'
+        BROKER_PLATFORM = CONNECTION_PROPS[symbol(u'platform')] if symbol(u'platform') in CONNECTION_PROPS \
+                          else '<platform not found>'
+        print 'Test Broker: %s v.%s on %s' % (BROKER, BROKER_VERSION, BROKER_PLATFORM)
+        print
+        sys.stdout.flush()
+
+    TYPES = JmsMessageTypes()
+
+    # TEST_CASE_CLASSES is a list that collects all the test classes that are constructed. One class is constructed
+    # per AMQP type used as the key in map JmsMessageTypes.TYPE_MAP.
+    TEST_CASE_CLASSES = []
+
+    # TEST_SUITE is the final suite of tests that will be run and which contains all the dynamically created
+    # type classes, each of which contains a test for the combinations of client shims
+    TEST_SUITE = unittest.TestSuite()
+
+    # Remove shims excluded from the command-line
+    if ARGS.exclude_shim is not None:
+        for shim in ARGS.exclude_shim:
+            SHIM_MAP.pop(shim)
+    # Create test classes dynamically
+    for jmt in sorted(TYPES.get_type_list()):
+        if ARGS.exclude_type is None or jmt not in ARGS.exclude_type:
+            test_case_class = create_testcase_class(BROKER,
+                                                    TYPES,
+                                                    ARGS.broker,
+                                                    jmt,
+                                                    product(SHIM_MAP.values(), repeat=2))
+            TEST_CASE_CLASSES.append(test_case_class)
+            TEST_SUITE.addTest(unittest.makeSuite(test_case_class))
+
+    # Finally, run all the dynamically created tests
+    RES = unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
+    if not RES.wasSuccessful():
+        sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/jms_messages_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/jms_messages_test.py b/src/python/qpid_interop_test/jms_messages_test.py
new file mode 100755
index 0000000..8de22b2
--- /dev/null
+++ b/src/python/qpid_interop_test/jms_messages_test.py
@@ -0,0 +1,402 @@
+#!/usr/bin/env python
+
+"""
+Module to test JMS message types across different APIs
+"""
+
+#
+# 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 argparse
+import sys
+import unittest
+
+from itertools import product
+from json import dumps
+from os import getenv, path
+
+from proton import symbol
+import qpid_interop_test.broker_properties
+import qpid_interop_test.shims
+from qpid_interop_test.test_type_map import TestTypeMap
+
+
+# TODO: propose a sensible default when installation details are worked out
+QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
+if QPID_INTEROP_TEST_HOME is None:
+    print 'ERROR: Environment variable QPID_INTEROP_TEST_HOME is not set'
+    sys.exit(1)
+MAVEN_REPO_PATH = getenv('MAVEN_REPO_PATH', path.join(getenv('HOME'), '.m2', 'repository'))
+
+class JmsMessageTypes(TestTypeMap):
+    """
+    Class which contains all the described JMS message types and the test values to be used in testing.
+    """
+
+    COMMON_SUBMAP = {
+        'boolean': ['True',
+                    'False'],
+        'byte': ['-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f'],
+        'double': ['0x0000000000000000', # 0.0
+                   '0x8000000000000000', # -0.0
+                   '0x400921fb54442eea', # pi (3.14159265359) positive decimal
+                   '0xc005bf0a8b145fcf', # -e (-2.71828182846) negative decimal
+                   '0x0000000000000001', # Smallest positive denormalized number
+                   '0x8000000000000001', # Smallest negative denormalized number
+                   '0x000fffffffffffff', # Largest positive denormalized number
+                   '0x8010000000000000', # Largest negative denormalized number
+                   '0x7fefffffffffffff', # Largest positive normalized number
+                   '0xffefffffffffffff', # Largest negative normalized number
+                   '0x7ff0000000000000', # +Infinity
+                   '0xfff0000000000000', # -Infinity
+                   '0x7ff8000000000000'], # +NaN
+        'float': ['0x00000000', # 0.0
+                  '0x80000000', # -0.0
+                  '0x40490fdb', # pi (3.14159265359) positive decimal
+                  '0xc02df854', # -e (-2.71828182846) negative decimal
+                  '0x00000001', # Smallest positive denormalized number
+                  '0x80000001', # Smallest negative denormalized number
+                  '0x007fffff', # Largest positive denormalized number
+                  '0x807fffff', # Largest negative denormalized number
+                  '0x00800000', # Smallest positive normalized number
+                  '0x80800000', # Smallest negative normalized number
+                  '0x7f7fffff', # Largest positive normalized number
+                  '0xff7fffff', # Largest negative normalized number
+                  #'0x7f800000', # +Infinity  # PROTON-1149 - fails on RHEL7
+                  #'0xff800000', # -Infinity # PROTON-1149 - fails on RHEL7
+                  '0x7fc00000'], # +NaN
+        'int': ['-0x80000000',
+                '-0x81',
+                '-0x80',
+                '-0x1',
+                '0x0',
+                '0x7f',
+                '0x80',
+                '0x7fffffff'],
+        'long': ['-0x8000000000000000',
+                 '-0x81',
+                 '-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f',
+                 '0x80',
+                 '0x7fffffffffffffff'],
+        'short': ['-0x8000',
+                  '-0x1',
+                  '0x0',
+                  '0x7fff'],
+        'string': ['',
+                   'Hello, world',
+                   '"Hello, world"',
+                   "Charlie's \"peach\"",
+                   'Charlie\'s "peach"',
+                   'The quick brown fox jumped over the lazy dog 0123456789.'# * 100]
+                  ]
+        }
+
+    TYPE_ADDITIONAL_SUBMAP = {
+        'bytes': [b'',
+                  b'12345',
+                  b'Hello, world',
+                  b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
+                  b'The quick brown fox jumped over the lazy dog 0123456789.' #* 100],
+                 ],
+        'char': ['a',
+                 'Z',
+                 '\x01',
+                 '\x7f'],
+        }
+
+    # The TYPE_SUBMAP defines test values for JMS message types that allow typed message content. Note that the
+    # types defined here are understood to be *Java* types and the stringified values are to be interpreted
+    # as the appropriate Java type by the send shim.
+    TYPE_SUBMAP = TestTypeMap.merge_dicts(COMMON_SUBMAP, TYPE_ADDITIONAL_SUBMAP)
+
+    TYPE_MAP = {
+        'JMS_MESSAGE_TYPE': {'none': [None]},
+        'JMS_BYTESMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_MAPMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_STREAMMESSAGE_TYPE': TYPE_SUBMAP,
+        'JMS_TEXTMESSAGE_TYPE': {'text': ['',
+                                          'Hello, world',
+                                          '"Hello, world"',
+                                          "Charlie's \"peach\"",
+                                          'Charlie\'s "peach"',
+                                          'The quick brown fox jumped over the lazy dog 0123456789.' * 10
+                                         ]
+                                },
+        # TODO: Add Object messages when other (non-JMS clients) can generate Java class strings used in this message
+        # type
+        #'JMS_OBJECTMESSAGE_TYPE': {
+        #    'java.lang.Boolean': ['true',
+        #                          'false'],
+        #    'java.lang.Byte': ['-128',
+        #                       '0',
+        #                       '127'],
+        #    'java.lang.Character': [u'a',
+        #                            u'Z'],
+        #    'java.lang.Double': ['0.0',
+        #                         '3.141592654',
+        #                         '-2.71828182846'],
+        #    'java.lang.Float': ['0.0',
+        #                        '3.14159',
+        #                        '-2.71828'],
+        #    'java.lang.Integer': ['-2147483648',
+        #                          '-129',
+        #                          '-128',
+        #                          '-1',
+        #                          '0',
+        #                          '127',
+        #                          '128',
+        #                          '2147483647'],
+        #    'java.lang.Long' : ['-9223372036854775808',
+        #                        '-129',
+        #                        '-128',
+        #                        '-1',
+        #                        '0',
+        #                        '127',
+        #                        '128',
+        #                        '9223372036854775807'],
+        #    'java.lang.Short': ['-32768',
+        #                        '-129',
+        #                        '-128',
+        #                        '-1',
+        #                        '0',
+        #                        '127',
+        #                        '128',
+        #                        '32767'],
+        #    'java.lang.String': [u'',
+        #                         u'Hello, world',
+        #                         u'"Hello, world"',
+        #                         u"Charlie's \"peach\"",
+        #                         u'Charlie\'s "peach"']
+        #    },
+        }
+
+    BROKER_SKIP = {}
+
+
+class JmsMessageTypeTestCase(unittest.TestCase):
+    """
+    Abstract base class for JMS message type test cases
+    """
+
+    def run_test(self, broker_addr, jms_message_type, test_values, send_shim, receive_shim):
+        """
+        Run 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.
+        """
+        queue_name = 'jms.queue.qpid-interop.jms_message_type_tests.%s.%s.%s' % (jms_message_type, send_shim.NAME,
+                                                                                 receive_shim.NAME)
+
+        # First create a map containing the numbers of expected mesasges for each JMS message type
+        num_test_values_map = {}
+        if len(test_values) > 0:
+            for index in test_values.keys():
+                num_test_values_map[index] = len(test_values[index])
+        # Start the receiver shim
+        receiver = receive_shim.create_receiver(broker_addr, queue_name, jms_message_type, dumps(num_test_values_map))
+        receiver.start()
+
+        # Start the send shim
+        sender = send_shim.create_sender(broker_addr, queue_name, jms_message_type, dumps(test_values))
+        sender.start()
+
+        # Wait for both shims to finish
+        sender.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+        receiver.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+
+        # Process return string from sender
+        send_obj = sender.get_return_object()
+        if send_obj is not None:
+            if isinstance(send_obj, str) and len(send_obj) > 0:
+                self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
+            else:
+                self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, str(send_obj)))
+
+        # Process return string from receiver
+        receive_obj = receiver.get_return_object()
+        if receive_obj is None:
+            self.fail('JmsReceiver shim returned None')
+        else:
+            if isinstance(receive_obj, tuple):
+                if len(receive_obj) == 2:
+                    return_jms_message_type, return_test_values = receive_obj
+                    self.assertEqual(return_jms_message_type, jms_message_type,
+                                     msg='JMS message type error:\n\n    sent:%s\n\n    received:%s' % \
+                                     (jms_message_type, return_jms_message_type))
+                    self.assertEqual(return_test_values, test_values,
+                                     msg='JMS message body error:\n\n    sent:%s\n\n    received:%s' % \
+                                     (test_values, return_test_values))
+                else:
+                    self.fail('Received incorrect tuple format: %s' % str(receive_obj))
+            else:
+                self.fail('Received non-tuple: %s' % str(receive_obj))
+
+
+def create_testcase_class(broker_name, types, broker_addr, jms_message_type, shim_product):
+    """
+    Class factory function which creates new subclasses to JmsMessageTypeTestCase. Each call creates a single new
+    test case named and based on the parameters supplied to the method
+    """
+
+    def __repr__(self):
+        """Print the class name"""
+        return self.__class__.__name__
+
+    def add_test_method(cls, send_shim, receive_shim):
+        """Function which creates a new test method in class cls"""
+
+        @unittest.skipIf(types.skip_test(jms_message_type, broker_name),
+                         types.skip_test_message(jms_message_type, broker_name))
+        def inner_test_method(self):
+            self.run_test(self.broker_addr,
+                          self.jms_message_type,
+                          self.test_values,
+                          send_shim,
+                          receive_shim)
+
+        inner_test_method.__name__ = 'test_%s_%s->%s' % (jms_message_type[4:-5], send_shim.NAME, receive_shim.NAME)
+        setattr(cls, inner_test_method.__name__, inner_test_method)
+
+    class_name = jms_message_type[4:-5].title() + 'TestCase'
+    class_dict = {'__name__': class_name,
+                  '__repr__': __repr__,
+                  '__doc__': 'Test case for JMS message type \'%s\'' % jms_message_type,
+                  'jms_message_type': jms_message_type,
+                  'broker_addr': broker_addr,
+                  'test_values': types.get_test_values(jms_message_type)} # tuple (tot_size, {...}
+    new_class = type(class_name, (JmsMessageTypeTestCase,), class_dict)
+    for send_shim, receive_shim in shim_product:
+        add_test_method(new_class, send_shim, receive_shim)
+
+    return new_class
+
+
+PROTON_CPP_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_messages_test',
+                                     'Receiver')
+PROTON_CPP_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_messages_test',
+                                   'Sender')
+PROTON_PYTHON_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src',
+                                        'jms_messages_test', 'Receiver.py')
+PROTON_PYTHON_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src',
+                                      'jms_messages_test', 'Sender.py')
+QIT_JMS_CLASSPATH_FILE = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'cp.txt')
+with open(QIT_JMS_CLASSPATH_FILE, 'r') as classpath_file:
+    QIT_JMS_CLASSPATH = classpath_file.read()
+QPID_JMS_RECEIVER_SHIM = 'org.apache.qpid.interop_test.jms_messages_test.Receiver'
+QPID_JMS_SENDER_SHIM = 'org.apache.qpid.interop_test.jms_messages_test.Sender'
+
+# SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
+# every shim in this list, a test is dynamically constructed which tests it against itself as well as every
+# other shim in the list.
+#
+# As new shims are added, add them into this map to have them included in the test cases.
+SHIM_MAP = {qpid_interop_test.shims.ProtonCppShim.NAME: \
+                qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
+            qpid_interop_test.shims.ProtonPythonShim.NAME: \
+                qpid_interop_test.shims.ProtonPythonShim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+            qpid_interop_test.shims.QpidJmsShim.NAME: \
+                qpid_interop_test.shims.QpidJmsShim(QIT_JMS_CLASSPATH, QPID_JMS_SENDER_SHIM, QPID_JMS_RECEIVER_SHIM),
+           }
+
+# TODO: Complete the test options to give fine control over running tests
+class TestOptions(object):
+    """
+    Class controlling command-line arguments used to control the test.
+    """
+    def __init__(self,):
+        parser = argparse.ArgumentParser(description='Qpid-interop AMQP client interoparability test suite '
+                                         'for JMS message types')
+        parser.add_argument('--broker', action='store', default='localhost:5672', metavar='BROKER:PORT',
+                            help='Broker against which to run test suite.')
+#        test_group = parser.add_mutually_exclusive_group()
+#        test_group.add_argument('--include-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to include')
+#        test_group.add_argument('--exclude-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to exclude')
+#        type_group = test_group.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(JmsMessageTypes.TYPE_MAP.keys()))
+        parser.add_argument('--exclude-type', action='append', metavar='JMS-MESSAGE-TYPE',
+                            help='Name of JMS message type to exclude. Supported types:\n%s' %
+                            sorted(JmsMessageTypes.TYPE_MAP.keys()))
+#        shim_group = test_group.add_mutually_exclusive_group()
+#        shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',
+#                                help='Name of shim to include. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        parser.add_argument('--exclude-shim', action='append', metavar='SHIM-NAME',
+                            help='Name of shim to exclude. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        self.args = parser.parse_args()
+
+
+#--- Main program start ---
+
+if __name__ == '__main__':
+    ARGS = TestOptions().args
+    #print 'ARGS:', ARGS # debug
+
+    # Connect to broker to find broker type
+    CONNECTION_PROPS = qpid_interop_test.broker_properties.get_broker_properties(ARGS.broker)
+    if CONNECTION_PROPS is None:
+        print 'WARNING: Unable to get connection properties - unknown broker'
+        BROKER = 'unknown'
+    else:
+        BROKER = CONNECTION_PROPS[symbol(u'product')] if symbol(u'product') in CONNECTION_PROPS \
+                 else '<product not found>'
+        BROKER_VERSION = CONNECTION_PROPS[symbol(u'version')] if symbol(u'version') in CONNECTION_PROPS \
+                         else '<version not found>'
+        BROKER_PLATFORM = CONNECTION_PROPS[symbol(u'platform')] if symbol(u'platform') in CONNECTION_PROPS \
+                          else '<platform not found>'
+        print 'Test Broker: %s v.%s on %s' % (BROKER, BROKER_VERSION, BROKER_PLATFORM)
+        print
+        sys.stdout.flush()
+
+    TYPES = JmsMessageTypes()
+
+    # TEST_CASE_CLASSES is a list that collects all the test classes that are constructed. One class is constructed
+    # per AMQP type used as the key in map JmsMessageTypes.TYPE_MAP.
+    TEST_CASE_CLASSES = []
+
+    # TEST_SUITE is the final suite of tests that will be run and which contains all the dynamically created
+    # type classes, each of which contains a test for the combinations of client shims
+    TEST_SUITE = unittest.TestSuite()
+
+    # Remove shims excluded from the command-line
+    if ARGS.exclude_shim is not None:
+        for shim in ARGS.exclude_shim:
+            SHIM_MAP.pop(shim)
+    # Create test classes dynamically
+    for jmt in sorted(TYPES.get_type_list()):
+        if ARGS.exclude_type is None or jmt not in ARGS.exclude_type:
+            test_case_class = create_testcase_class(BROKER,
+                                                    TYPES,
+                                                    ARGS.broker,
+                                                    jmt,
+                                                    product(SHIM_MAP.values(), repeat=2))
+            TEST_CASE_CLASSES.append(test_case_class)
+            TEST_SUITE.addTest(unittest.makeSuite(test_case_class))
+
+    # Finally, run all the dynamically created tests
+    RES = unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
+    if not RES.wasSuccessful():
+        sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/shims.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/shims.py b/src/python/qpid_interop_test/shims.py
new file mode 100644
index 0000000..f6d019e
--- /dev/null
+++ b/src/python/qpid_interop_test/shims.py
@@ -0,0 +1,227 @@
+"""
+Module containing worker thread classes and shims
+"""
+#
+# 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 json import loads
+from os import getenv, getpgid, killpg, path, setsid
+from signal import SIGKILL, SIGTERM
+from subprocess import Popen, PIPE, CalledProcessError
+from sys import stdout
+from threading import Thread
+from time import sleep
+
+
+THREAD_TIMEOUT = 10.0 # seconds to complete before join is forced
+
+
+class ShimWorkerThread(Thread):
+    """Parent class for shim worker threads and return a string once the thread has ended"""
+    def __init__(self, thread_name):
+        super(ShimWorkerThread, self).__init__(name=thread_name)
+        self.arg_list = []
+        self.return_obj = None
+        self.proc = None
+
+    def get_return_object(self):
+        """Get the return object from the completed thread"""
+        return self.return_obj
+
+    def join_or_kill(self, timeout):
+        """
+        Wait for thread to join after timeout (seconds). If still alive, it is then terminated, then if still alive,
+        killed
+        """
+        self.join(timeout)
+        if self.is_alive():
+            if self.proc is not None:
+                if self._terminate_pg_loop():
+                    if self._kill_pg_loop():
+                        print '\n  ERROR: Thread %s (pid=%d) alive after kill' % (self.name, self.proc.pid)
+                    else:
+                        print 'Killed'
+                        stdout.flush()
+                else:
+                    print 'Terminated'
+                    stdout.flush()
+            else:
+                print 'ERROR: shims.join_or_kill(): Process joined and is alive, yet proc is None.'
+
+    def _terminate_pg_loop(self, num_attempts=2, wait_time=2):
+        cnt = 0
+        while cnt < num_attempts and self.is_alive():
+            cnt += 1
+            print '\n  Thread %s (pid=%d) alive after timeout, terminating (try #%d)...' % (self.name, self.proc.pid,
+                                                                                            cnt),
+            stdout.flush()
+            killpg(getpgid(self.proc.pid), SIGTERM)
+            sleep(wait_time)
+        return self.is_alive()
+
+    def _kill_pg_loop(self, num_attempts=2, wait_time=5):
+        cnt = 0
+        while cnt < num_attempts and self.is_alive():
+            cnt += 1
+            print '\n  Thread %s (pid=%d) alive after terminate, killing (try #%d)...' % (self.name, self.proc.pid,
+                                                                                          cnt),
+            stdout.flush()
+            killpg(getpgid(self.proc.pid), SIGKILL)
+            sleep(wait_time)
+        return self.is_alive()
+
+
+class Sender(ShimWorkerThread):
+    """Sender class for multi-threaded send"""
+    def __init__(self, use_shell_flag, send_shim_args, broker_addr, queue_name, msg_type, json_test_str):
+        super(Sender, self).__init__('sender_thread_%s' % queue_name)
+        if send_shim_args is None:
+            print 'ERROR: Sender: send_shim_args == None'
+        self.use_shell_flag = use_shell_flag
+        self.arg_list.extend(send_shim_args)
+        self.arg_list.extend([broker_addr, queue_name, msg_type, json_test_str])
+
+    def run(self):
+        """Thread starts here"""
+        try:
+            #print '\n>>>', self.arg_list # DEBUG - useful to see command-line sent to shim
+            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, shell=self.use_shell_flag, preexec_fn=setsid)
+            (stdoutdata, stderrdata) = self.proc.communicate()
+            if len(stdoutdata) > 0 or len(stderrdata) > 0:
+                self.return_obj = (stdoutdata, stderrdata)
+        except CalledProcessError as exc:
+            self.return_obj = str(exc) + '\n\nOutput:\n' + exc.output
+
+
+class Receiver(ShimWorkerThread):
+    """Receiver class for multi-threaded receive"""
+    def __init__(self, receive_shim_args, broker_addr, queue_name, msg_type, json_test_str):
+        super(Receiver, self).__init__('receiver_thread_%s' % queue_name)
+        if receive_shim_args is None:
+            print 'ERROR: Receiver: receive_shim_args == None'
+        self.arg_list.extend(receive_shim_args)
+        self.arg_list.extend([broker_addr, queue_name, msg_type, json_test_str])
+
+    def run(self):
+        """Thread starts here"""
+        try:
+            #print '\n>>>', self.arg_list # DEBUG - useful to see command-line sent to shim
+            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, preexec_fn=setsid)
+            (stdoutdata, stderrdata) = self.proc.communicate()
+            if len(stderrdata) > 0:
+                self.return_obj = (stdoutdata, stderrdata)
+            else:
+                #print '<<<', stdoutdata # DEBUG - useful to see text received from shim
+                str_tvl = stdoutdata.split('\n')[0:-1] # remove trailing \n
+                #if len(str_tvl) == 1:
+                #    self.return_obj = output
+                if len(str_tvl) == 2:
+                    self.return_obj = (str_tvl[0], loads(str_tvl[1]))
+                else: # Make a single line of all the bits and return that
+                    #self.return_obj = loads("".join(str_tvl[1:]))
+                    self.return_obj = stdoutdata
+        except CalledProcessError as exc:
+            self.return_obj = str(exc) + '\n\n' + exc.output
+
+class Shim(object):
+    """Abstract shim class, parent of all shims."""
+    NAME = None
+    def __init__(self, sender_shim, receiver_shim):
+        self.sender_shim = sender_shim
+        self.receiver_shim = receiver_shim
+        self.send_params = None
+        self.receive_params = None
+        self.use_shell_flag = False
+
+    def create_sender(self, broker_addr, queue_name, msg_type, json_test_str):
+        """Create a new sender instance"""
+        return Sender(self.use_shell_flag, self.send_params, broker_addr, queue_name, msg_type, json_test_str)
+
+    def create_receiver(self, broker_addr, queue_name, msg_type, json_test_str):
+        """Create a new receiver instance"""
+        return Receiver(self.receive_params, broker_addr, queue_name, msg_type, json_test_str)
+
+class ProtonPythonShim(Shim):
+    """Shim for qpid-proton Python client"""
+    NAME = 'ProtonPython'
+    def __init__(self, sender_shim, receiver_shim):
+        super(ProtonPythonShim, self).__init__(sender_shim, receiver_shim)
+        self.send_params = [self.sender_shim]
+        self.receive_params = [self.receiver_shim]
+
+
+class ProtonCppShim(Shim):
+    """Shim for qpid-proton C++ client"""
+    NAME = 'ProtonCpp'
+    def __init__(self, sender_shim, receiver_shim):
+        super(ProtonCppShim, self).__init__(sender_shim, receiver_shim)
+        self.send_params = [self.sender_shim]
+        self.receive_params = [self.receiver_shim]
+
+
+class QpidJmsShim(Shim):
+    """Shim for qpid-jms JMS client"""
+    NAME = 'QpidJms'
+
+    # Installed versions
+    # TODO: Automate this - it gets out of date quickly
+    # Maven works out all the deps, should use that
+    QPID_JMS_SHIM_VER = '0.1.0-SNAPSHOT'
+    QPID_JMS_VER = '0.20.0-SNAPSHOT'
+    QPID_PROTON_J_VER = '0.15.0-SNAPSHOT'
+    JMS_API_VER = '1.1.1'
+    LOGGER_API_VER = '1.7.21'
+    LOGGER_IMPL_VER = '1.7.21'
+    NETTY_VER = '4.0.40.Final'
+
+    # Classpath components
+    #QPID_INTEROP_TEST_SHIM_JAR = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'target', 'qpid-jms-shim.jar')
+    MAVEN_REPO_PATH = path.join(getenv('HOME'), '.m2', 'repository')
+    JMS_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'geronimo', 'specs', 'geronimo-jms_1.1_spec', JMS_API_VER,
+                            'geronimo-jms_1.1_spec-%s.jar' % JMS_API_VER)
+    JMS_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-jms-client', QPID_JMS_VER,
+                             'qpid-jms-client-%s.jar' % QPID_JMS_VER)
+    LOGGER_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-api', LOGGER_API_VER,
+                               'slf4j-api-%s.jar' % LOGGER_API_VER)
+    LOGGER_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-nop', LOGGER_IMPL_VER,
+                                'slf4j-nop-%s.jar' % LOGGER_IMPL_VER)
+    PROTON_J_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'proton-j', QPID_PROTON_J_VER,
+                             'proton-j-%s.jar' % QPID_PROTON_J_VER)
+    NETTY_JAR = path.join(MAVEN_REPO_PATH, 'io', 'netty', 'netty-all', NETTY_VER, 'netty-all-%s.jar' % NETTY_VER)
+    QPID_JMS_SHIM_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-interop-test-jms-shim',
+                                  QPID_JMS_SHIM_VER, 'qpid-interop-test-jms-shim-%s.jar' % QPID_JMS_SHIM_VER)
+
+    JAVA_HOME = getenv('JAVA_HOME', '/usr/bin') # Default only works in Linux
+    JAVA_EXEC = path.join(JAVA_HOME, 'java')
+
+    def __init__(self, dependency_class_path, sender_shim, receiver_shim):
+        super(QpidJmsShim, self).__init__(sender_shim, receiver_shim)
+        self.dependency_class_path = dependency_class_path
+        self.send_params = [self.JAVA_EXEC, '-cp', self.get_java_class_path(), self.sender_shim]
+        self.receive_params = [self.JAVA_EXEC, '-cp', self.get_java_class_path(), self.receiver_shim]
+
+    def get_java_class_path(self):
+        """Method to construct and return the Java class path necessary to run the shim"""
+        return ':'.join([self.QPID_JMS_SHIM_JAR, self.dependency_class_path])
+    #                     self.JMS_API_JAR,
+    #                     self.JMS_IMPL_JAR,
+    #                     self.LOGGER_API_JAR,
+    #                     self.LOGGER_IMPL_JAR,
+    #                     self.PROTON_J_JAR,
+    #                     self.NETTY_JAR])

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/test_type_map.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/test_type_map.py b/src/python/qpid_interop_test/test_type_map.py
new file mode 100644
index 0000000..0fd4552
--- /dev/null
+++ b/src/python/qpid_interop_test/test_type_map.py
@@ -0,0 +1,86 @@
+"""
+Module containing Error classes for interop testing
+"""
+#
+# 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.
+#
+
+class TestTypeMap(object):
+    """
+    Class which contains all the described types and the test values to be used in testing against those types.
+    """
+
+    # TYPE_MAP: Map containing all described types as the indecies, and a list of values to be used in testing
+    # that type as a list of values.
+    #
+    # Format: {'type_1' : [val_1_1, val_1_2, ...],
+    #          'type_2' : [val_2_1, val_2_2, ...],
+    #          ...
+    #         }
+    TYPE_MAP = {}
+
+    # BROKER_SKIP: For know broker issues where a type would cause a test to fail or hang,
+    # entries in BROKER_SKIP will cause the test to be skipped with a message.
+    # This is a map containing AMQP types as a key, and a list of brokers for which this
+    # type should be skipped.
+    # Format: {'jms_msg_type_1' : {'broker_1' : 'skip msg for broker_1',
+    #                              'broker_2' : 'skip msg for broker_2',
+    #                               ...
+    #                             },
+    #          'jms_msg_type_2' : {'broker_1' : 'skip msg for broker_1',
+    #                              'broker_2' : 'skip msg for broker_2',
+    #                              ...
+    #                             },
+    #          ...
+    #         }
+    # where broker_1, broker_2, ... are broker product names as defined by the
+    # connection property string it returns.
+    BROKER_SKIP = {}
+
+    def __init__(self):
+        pass
+
+    def get_type_list(self):
+        """Return a list of types which this test suite supports"""
+        return self.TYPE_MAP.keys()
+
+    def get_test_values(self, test_type):
+        """Return test values to use when testing the supplied type."""
+        if test_type not in self.TYPE_MAP.keys():
+            return None
+        return self.TYPE_MAP[test_type]
+
+    def skip_test_message(self, test_type, broker_name):
+        """Return the message to use if a test is skipped"""
+        if test_type in self.BROKER_SKIP.keys():
+            if broker_name in self.BROKER_SKIP[test_type]:
+                return str(self.BROKER_SKIP[test_type][broker_name])
+        return None
+
+    def skip_test(self, test_type, broker_name):
+        """Return boolean True if test should be skipped"""
+        return test_type in self.BROKER_SKIP.keys() and \
+            broker_name in self.BROKER_SKIP[test_type]
+
+    @staticmethod
+    def merge_dicts(*dict_args):
+        """Static method to merge two or more dictionaries"""
+        res = {}
+        for this_dict in dict_args:
+            res.update(this_dict)
+        return res


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


[4/5] qpid-interop-test git commit: QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parame

Posted by kp...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.cpp b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.cpp
new file mode 100644
index 0000000..19a40ed
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.cpp
@@ -0,0 +1,396 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpidit/jms_hdrs_props_test/Receiver.hpp"
+
+#include <iostream>
+#include <json/json.h>
+#include "proton/connection.hpp"
+#include "proton/default_container.hpp"
+#include "proton/delivery.hpp"
+#include "proton/transport.hpp"
+#include "qpidit/QpidItErrors.hpp"
+
+namespace qpidit
+{
+    namespace jms_hdrs_props_test
+    {
+        Receiver::Receiver(const std::string& brokerUrl,
+                           const std::string& jmsMessageType,
+                           const Json::Value& testNumberMap,
+                           const Json::Value& flagMap):
+                            _brokerUrl(brokerUrl),
+                            _jmsMessageType(jmsMessageType),
+                            _testNumberMap(testNumberMap),
+                            _flagMap(flagMap),
+                            _subTypeList(testNumberMap.getMemberNames()),
+                            _subTypeIndex(0),
+                            _expected(getTotalNumExpectedMsgs(testNumberMap)),
+                            _received(0UL),
+                            _receivedSubTypeList(Json::arrayValue),
+                            _receivedValueMap(Json::objectValue),
+                            _receivedHeadersMap(Json::objectValue),
+                            _receivedPropertiesMap(Json::objectValue)
+        {}
+
+        Receiver::~Receiver() {}
+
+        Json::Value& Receiver::getReceivedValueMap() {
+            return _receivedValueMap;
+        }
+
+        Json::Value& Receiver::getReceivedHeadersMap() {
+            return _receivedHeadersMap;
+        }
+
+        Json::Value& Receiver::getReceivedPropertiesMap() {
+            return _receivedPropertiesMap;
+        }
+
+        void Receiver::on_container_start(proton::container &c) {
+            c.open_receiver(_brokerUrl);
+        }
+
+        void Receiver::on_message(proton::delivery &d, proton::message &m) {
+            try {
+                if (_received < _expected) {
+                    int8_t t = qpidit::JMS_MESSAGE_TYPE;
+                    try {t = m.message_annotations().get(proton::symbol("x-opt-jms-msg-type")).get<int8_t>();}
+                    catch (const std::exception& e) {
+                        std::cout << "JmsReceiver::on_message(): Missing annotation \"x-opt-jms-msg-type\"" << std::endl;
+                        throw;
+                    }
+                    switch (t) {
+                    case qpidit::JMS_MESSAGE_TYPE:
+                        receiveJmsMessage(m);
+                        break;
+                    case qpidit::JMS_OBJECTMESSAGE_TYPE:
+                        receiveJmsObjectMessage(m);
+                        break;
+                    case qpidit::JMS_MAPMESSAGE_TYPE:
+                        receiveJmsMapMessage(m);
+                        break;
+                    case qpidit::JMS_BYTESMESSAGE_TYPE:
+                        receiveJmsBytesMessage(m);
+                        break;
+                    case qpidit::JMS_STREAMMESSAGE_TYPE:
+                        receiveJmsStreamMessage(m);
+                        break;
+                    case qpidit::JMS_TEXTMESSAGE_TYPE:
+                        receiveJmsTextMessage(m);
+                        break;
+                    default:;
+                        // TODO: handle error - unknown JMS message type
+                    }
+
+                    processMessageHeaders(m);
+                    processMessageProperties(m);
+
+                    std::string subType(_subTypeList[_subTypeIndex]);
+                    // Increment the subtype if the required number of messages have been received
+                    if (_receivedSubTypeList.size() >= _testNumberMap[subType].asInt() &&
+                                    _subTypeIndex < _testNumberMap.size()) {
+                        _receivedValueMap[subType] = _receivedSubTypeList;
+                        _receivedSubTypeList.clear();
+                        ++_subTypeIndex;
+                    }
+                    _received++;
+                    if (_received >= _expected) {
+                        d.receiver().close();
+                        d.connection().close();
+                    }
+                }
+            } catch (const std::exception&) {
+                d.receiver().close();
+                d.connection().close();
+                throw;
+            }
+        }
+
+       //static
+        uint32_t Receiver::getTotalNumExpectedMsgs(const Json::Value testNumberMap) {
+            uint32_t total(0UL);
+            for (Json::Value::const_iterator i=testNumberMap.begin(); i!=testNumberMap.end(); ++i) {
+                total += (*i).asUInt();
+            }
+            return total;
+
+        }
+
+        // protected
+
+        void Receiver::receiveJmsMessage(const proton::message& msg) {
+            _receivedSubTypeList.append(Json::Value());
+        }
+
+        void Receiver::receiveJmsObjectMessage(const proton::message& msg) {
+            // TODO
+        }
+
+        void Receiver::receiveJmsMapMessage(const proton::message& msg) {
+            if(_jmsMessageType.compare("JMS_MAPMESSAGE_TYPE") != 0) {
+                throw qpidit::IncorrectMessageBodyTypeError(_jmsMessageType, "JMS_MAPMESSAGE_TYPE");
+            }
+            std::string subType(_subTypeList[_subTypeIndex]);
+            std::map<std::string, proton::value> m;
+            msg.body().get(m);
+            for (std::map<std::string, proton::value>::const_iterator i=m.begin(); i!=m.end(); ++i) {
+                std::string key = i->first;
+                if (subType.compare(key.substr(0, key.size()-3)) != 0) {
+                    throw qpidit::IncorrectJmsMapKeyPrefixError(subType, key);
+                }
+                proton::value val = i->second;
+                if (subType.compare("boolean") == 0) {
+                    _receivedSubTypeList.append(val.get<bool>() ? Json::Value("True") : Json::Value("False"));
+                } else if (subType.compare("byte") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int8_t>(val.get<int8_t>())));
+                } else if (subType.compare("bytes") == 0) {
+                    _receivedSubTypeList.append(Json::Value(std::string(val.get<proton::binary>())));
+                } else if (subType.compare("char") == 0) {
+                    std::ostringstream oss;
+                    oss << (char)val.get<wchar_t>();
+                    _receivedSubTypeList.append(Json::Value(oss.str()));
+                } else if (subType.compare("double") == 0) {
+                    double d = val.get<double>();
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(*((int64_t*)&d), true, false)));
+                } else if (subType.compare("float") == 0) {
+                    float f = val.get<float>();
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(*((int32_t*)&f), true, false)));
+                } else if (subType.compare("int") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(val.get<int32_t>())));
+                } else if (subType.compare("long") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(val.get<int64_t>())));
+                } else if (subType.compare("short") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int16_t>(val.get<int16_t>())));
+                } else if (subType.compare("string") == 0) {
+                    _receivedSubTypeList.append(Json::Value(val.get<std::string>()));
+                } else {
+                    throw qpidit::UnknownJmsMessageSubTypeError(subType);
+                }
+            }
+        }
+
+        void Receiver::receiveJmsBytesMessage(const proton::message& msg) {
+            if(_jmsMessageType.compare("JMS_BYTESMESSAGE_TYPE") != 0) {
+                throw qpidit::IncorrectMessageBodyTypeError(_jmsMessageType, "JMS_BYTESMESSAGE_TYPE");
+            }
+            std::string subType(_subTypeList[_subTypeIndex]);
+            proton::binary body = msg.body().get<proton::binary>();
+            if (subType.compare("boolean") == 0) {
+                if (body.size() != 1) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=boolean", 1, body.size());
+                _receivedSubTypeList.append(body[0] ? Json::Value("True") : Json::Value("False"));
+            } else if (subType.compare("byte") == 0) {
+                if (body.size() != sizeof(int8_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=byte", sizeof(int8_t), body.size());
+                int8_t val = *((int8_t*)body.data());
+                _receivedSubTypeList.append(Json::Value(toHexStr<int8_t>(val)));
+            } else if (subType.compare("bytes") == 0) {
+                _receivedSubTypeList.append(Json::Value(std::string(body)));
+            } else if (subType.compare("char") == 0) {
+                if (body.size() != sizeof(uint16_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=char", sizeof(uint16_t), body.size());
+                // TODO: This is ugly: ignoring first byte - handle UTF-16 correctly
+                char c = body[1];
+                std::ostringstream oss;
+                oss << c;
+                _receivedSubTypeList.append(Json::Value(oss.str()));
+            } else if (subType.compare("double") == 0) {
+                if (body.size() != sizeof(int64_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=double", sizeof(int64_t), body.size());
+                int64_t val = be64toh(*((int64_t*)body.data()));
+                _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(val, true, false)));
+            } else if (subType.compare("float") == 0) {
+                if (body.size() != sizeof(int32_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=float", sizeof(int32_t), body.size());
+                int32_t val = be32toh(*((int32_t*)body.data()));
+                _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(val, true, false)));
+            } else if (subType.compare("long") == 0) {
+                if (body.size() != sizeof(int64_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=long", sizeof(int64_t), body.size());
+                int64_t val = be64toh(*((int64_t*)body.data()));
+                _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(val)));
+            } else if (subType.compare("int") == 0) {
+                if (body.size() != sizeof(int32_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=int", sizeof(int32_t), body.size());
+                int32_t val = be32toh(*((int32_t*)body.data()));
+                _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(val)));
+            } else if (subType.compare("short") == 0) {
+                if (body.size() != sizeof(int16_t)) throw IncorrectMessageBodyLengthError("JmsReceiver::receiveJmsBytesMessage, subType=short", sizeof(int16_t), body.size());
+                int16_t val = be16toh(*((int16_t*)body.data()));
+                _receivedSubTypeList.append(Json::Value(toHexStr<int16_t>(val)));
+            } else if (subType.compare("string") == 0) {
+                // TODO: decode string size in first two bytes and check string size
+                _receivedSubTypeList.append(Json::Value(std::string(body).substr(2)));
+            } else {
+                throw qpidit::UnknownJmsMessageSubTypeError(subType);
+            }
+        }
+
+        void Receiver::receiveJmsStreamMessage(const proton::message& msg) {
+            if(_jmsMessageType.compare("JMS_STREAMMESSAGE_TYPE") != 0) {
+                throw qpidit::IncorrectMessageBodyTypeError(_jmsMessageType, "JMS_STREAMMESSAGE_TYPE");
+            }
+            std::string subType(_subTypeList[_subTypeIndex]);
+            std::vector<proton::value> l;
+            msg.body().get(l);
+            for (std::vector<proton::value>::const_iterator i=l.begin(); i!=l.end(); ++i) {
+                if (subType.compare("boolean") == 0) {
+                    _receivedSubTypeList.append(i->get<bool>() ? Json::Value("True") : Json::Value("False"));
+                } else if (subType.compare("byte") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int8_t>(i->get<int8_t>())));
+                } else if (subType.compare("bytes") == 0) {
+                    _receivedSubTypeList.append(Json::Value(std::string(i->get<proton::binary>())));
+                } else if (subType.compare("char") == 0) {
+                    std::ostringstream oss;
+                    oss << (char)i->get<wchar_t>();
+                    _receivedSubTypeList.append(Json::Value(oss.str()));
+                } else if (subType.compare("double") == 0) {
+                    double d = i->get<double>();
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(*((int64_t*)&d), true, false)));
+                } else if (subType.compare("float") == 0) {
+                    float f = i->get<float>();
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(*((int32_t*)&f), true, false)));
+                } else if (subType.compare("int") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int32_t>(i->get<int32_t>())));
+                } else if (subType.compare("long") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int64_t>(i->get<int64_t>())));
+                } else if (subType.compare("short") == 0) {
+                    _receivedSubTypeList.append(Json::Value(toHexStr<int16_t>(i->get<int16_t>())));
+                } else if (subType.compare("string") == 0) {
+                    _receivedSubTypeList.append(Json::Value(i->get<std::string>()));
+                } else {
+                    throw qpidit::UnknownJmsMessageSubTypeError(subType);
+                }
+            }
+
+        }
+
+        void Receiver::receiveJmsTextMessage(const proton::message& msg) {
+            if(_jmsMessageType.compare("JMS_TEXTMESSAGE_TYPE") != 0) {
+                throw qpidit::IncorrectMessageBodyTypeError(_jmsMessageType, "JMS_TEXTMESSAGE_TYPE");
+            }
+            _receivedSubTypeList.append(Json::Value(msg.body().get<std::string>()));
+        }
+
+        void Receiver::processMessageHeaders(const proton::message& msg) {
+            addMessageHeaderString("JMS_TYPE_HEADER", msg.subject());
+            if (_flagMap.isMember("JMS_CORRELATIONID_AS_BYTES") && _flagMap["JMS_CORRELATIONID_AS_BYTES"].asBool()) {
+                addMessageHeaderByteArray("JMS_CORRELATIONID_HEADER", proton::get<proton::binary>(msg.correlation_id()));
+            } else {
+                try {
+                    addMessageHeaderString("JMS_CORRELATIONID_HEADER", proton::get<std::string>(msg.correlation_id()));
+                } catch (const std::exception& e) {} // TODO: UGLY, how do you check if there _is_ a correlation id?
+            }
+
+            std::string reply_to = msg.reply_to();
+            // Some brokers prepend 'queue://' and 'topic://' to reply_to addresses, strip these when present
+            if (_flagMap.isMember("JMS_REPLYTO_AS_TOPIC") && _flagMap["JMS_REPLYTO_AS_TOPIC"].asBool()) {
+                if (reply_to.find("topic://") == 0) {
+                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", qpidit::JMS_TOPIC, reply_to.substr(8));
+                } else {
+                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", qpidit::JMS_TOPIC, reply_to);
+                }
+            } else {
+                if (reply_to.find("queue://") == 0) {
+                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", qpidit::JMS_QUEUE, reply_to.substr(8));
+                } else {
+                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", qpidit::JMS_QUEUE, reply_to);
+                }
+            }
+        }
+
+        void Receiver::addMessageHeaderString(const char* headerName, const std::string& value) {
+            if (!value.empty()) { // TODO: Remove this test when PROTON-1288 is fixed as empty strings are allowed in headers
+                Json::Value valueMap(Json::objectValue);
+                valueMap["string"] = value;
+                _receivedHeadersMap[headerName] = valueMap;
+            }
+        }
+
+        void Receiver::addMessageHeaderByteArray(const std::string& headerName, const proton::binary ba) {
+            if (!ba.empty()) { // TODO: Remove this test when PROTON-1288 is fixed as empty binaries are allowed in headers
+                Json::Value valueMap(Json::objectValue);
+                valueMap["bytes"] = std::string(ba);
+                _receivedHeadersMap[headerName] = valueMap;
+            }
+        }
+
+        void Receiver::addMessageHeaderDestination(const std::string& headerName, qpidit::jmsDestinationType_t dt, const std::string& d) {
+            if (!d.empty()) {
+                Json::Value valueMap(Json::objectValue);
+                switch (dt) {
+                case qpidit::JMS_QUEUE:
+                    valueMap["queue"] = d;
+                    break;
+                case qpidit::JMS_TOPIC:
+                    valueMap["topic"] = d;
+                    break;
+                default:
+                    ; // TODO: Handle error: remaining JMS destinations not handled.
+                }
+                _receivedHeadersMap[headerName] = valueMap;
+            }
+        }
+
+        void Receiver::processMessageProperties(const proton::message& msg) {
+            // TODO: Add this function when PROTON-1284 is fixed
+//            std::map<proton::value, proton::value> props;
+//            msg.properties().value() >> props;
+        }
+
+    } /* namespace jms_hdrs_props_test */
+} /* namespace qpidit */
+
+/* --- main ---
+ * Args: 1: Broker address (ip-addr:port)
+ *       2: Queue name
+ *       3: JMS message type
+ *       4: JSON Test parameters containing 2 maps: [testValuesMap, flagMap]
+ */
+int main(int argc, char** argv) {
+    /*
+        for (int i=0; i<argc; ++i) {
+            std::cout << "*** argv[" << i << "] : " << argv[i] << std::endl;
+        }
+    */
+    // TODO: improve arg management a little...
+    if (argc != 5) {
+        throw qpidit::ArgumentError("Incorrect number of arguments");
+    }
+
+    std::ostringstream oss;
+    oss << argv[1] << "/" << argv[2];
+
+    try {
+        Json::Value testParams;
+        Json::Reader jsonReader;
+        if (not jsonReader.parse(argv[4], testParams, false)) {
+            throw qpidit::JsonParserError(jsonReader);
+        }
+
+        qpidit::jms_hdrs_props_test::Receiver receiver(oss.str(), argv[3], testParams[0], testParams[1]);
+        proton::default_container(receiver).run();
+
+        Json::FastWriter fw;
+        std::cout << argv[3] << std::endl;
+        Json::Value returnList(Json::arrayValue);
+        returnList.append(receiver.getReceivedValueMap());
+        returnList.append(receiver.getReceivedHeadersMap());
+        returnList.append(receiver.getReceivedPropertiesMap());
+        std::cout << fw.write(returnList);
+    } catch (const std::exception& e) {
+        std::cout << "JmsReceiver error: " << e.what() << std::endl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.hpp b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.hpp
new file mode 100644
index 0000000..36db58d
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Receiver.hpp
@@ -0,0 +1,100 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_RECEIVER_HPP_
+#define SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_RECEIVER_HPP_
+
+#include <iomanip>
+#include <json/value.h>
+#include "proton/messaging_handler.hpp"
+#include "proton/types.hpp"
+#include "qpidit/JmsTestBase.hpp"
+#include <sstream>
+
+namespace qpidit
+{
+    namespace jms_hdrs_props_test
+    {
+
+        class Receiver : public qpidit::JmsTestBase
+        {
+        protected:
+            const std::string _brokerUrl;
+            const std::string _jmsMessageType;
+            const Json::Value _testNumberMap;
+            const Json::Value _flagMap;
+            Json::Value::Members _subTypeList;
+            int _subTypeIndex;
+            uint32_t _expected;
+            uint32_t _received;
+            Json::Value _receivedSubTypeList;
+            Json::Value _receivedValueMap;
+            Json::Value _receivedHeadersMap;
+            Json::Value _receivedPropertiesMap;
+        public:
+            Receiver(const std::string& brokerUrl,
+                     const std::string& jmsMessageType,
+                     const Json::Value& testNumberMap,
+                     const Json::Value& flagMap);
+            virtual ~Receiver();
+            Json::Value& getReceivedValueMap();
+            Json::Value& getReceivedHeadersMap();
+            Json::Value& getReceivedPropertiesMap();
+            void on_container_start(proton::container &c);
+            void on_message(proton::delivery &d, proton::message &m);
+
+            static uint32_t getTotalNumExpectedMsgs(const Json::Value testNumberMap);
+
+        protected:
+            void receiveJmsMessage(const proton::message& msg);
+            void receiveJmsObjectMessage(const proton::message& msg);
+            void receiveJmsMapMessage(const proton::message& msg);
+            void receiveJmsBytesMessage(const proton::message& msg);
+            void receiveJmsStreamMessage(const proton::message& msg);
+            void receiveJmsTextMessage(const proton::message& msg);
+
+            void processMessageHeaders(const proton::message& msg);
+            void addMessageHeaderString(const char* headerName, const std::string& value);
+            void addMessageHeaderByteArray(const std::string& headerName, const proton::binary ba);
+            void addMessageHeaderDestination(const std::string& headerName, qpidit::jmsDestinationType_t dt, const std::string& d);
+            void processMessageProperties(const proton::message& msg);
+
+            // Format signed numbers in negative hex format if signedFlag is true, ie -0xNNNN, positive numbers in 0xNNNN format
+            template<typename T> static std::string toHexStr(T val, bool fillFlag = false, bool signedFlag = true) {
+                std::ostringstream oss;
+                bool neg = false;
+                if (signedFlag) {
+                    neg = val < 0;
+                    if (neg) val = -val;
+                }
+                oss << (neg ? "-" : "") << "0x" << std::hex;
+                if (fillFlag) {
+                    oss << std::setw(sizeof(T)*2) << std::setfill('0');
+                }
+                oss << (sizeof(T) == 1 ? (int)val & 0xff : sizeof(T) == 2 ? val & 0xffff : sizeof(T) == 4 ? val & 0xffffffff : val);
+                return oss.str();
+            }
+        };
+
+    } /* namespace jms_hdrs_props_test */
+} /* namespace qpidit */
+
+#endif /* SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_RECEIVER_HPP_ */

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.cpp b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.cpp
new file mode 100644
index 0000000..e3ff0e6
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.cpp
@@ -0,0 +1,451 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "qpidit/jms_hdrs_props_test/Sender.hpp"
+
+#include <cerrno>
+#include <iomanip>
+#include <iostream>
+#include <json/json.h>
+#include "proton/connection.hpp"
+#include "proton/default_container.hpp"
+#include "proton/tracker.hpp"
+#include "proton/transport.hpp"
+#include <stdio.h>
+
+namespace qpidit
+{
+    namespace jms_hdrs_props_test
+    {
+        Sender::Sender(const std::string& brokerUrl,
+                       const std::string& jmsMessageType,
+                       const Json::Value& testParams) :
+                _brokerUrl(brokerUrl),
+                _jmsMessageType(jmsMessageType),
+                _testValueMap(testParams[0]),
+                _testHeadersMap(testParams[1]),
+                _testPropertiesMap(testParams[2]),
+                _msgsSent(0),
+                _msgsConfirmed(0),
+                _totalMsgs(getTotalNumMessages(_testValueMap))
+        {
+            if (_testValueMap.type() != Json::objectValue) {
+                throw qpidit::InvalidJsonRootNodeError(Json::objectValue, _testValueMap.type());
+            }
+        }
+
+        Sender::~Sender() {}
+
+        void Sender::on_container_start(proton::container &c) {
+            c.open_sender(_brokerUrl);
+        }
+
+        void Sender::on_sendable(proton::sender &s) {
+            if (_totalMsgs == 0) {
+                s.connection().close();
+            } else if (_msgsSent == 0) {
+                Json::Value::Members subTypes = _testValueMap.getMemberNames();
+                std::sort(subTypes.begin(), subTypes.end());
+                for (std::vector<std::string>::const_iterator i=subTypes.begin(); i!=subTypes.end(); ++i) {
+                    sendMessages(s, *i, _testValueMap[*i]);
+                }
+            }
+        }
+
+        void Sender::on_tracker_accept(proton::tracker &t) {
+            _msgsConfirmed++;
+            if (_msgsConfirmed == _totalMsgs) {
+                t.connection().close();
+            }
+        }
+
+        void Sender::on_transport_close(proton::transport &t) {
+            _msgsSent = _msgsConfirmed;
+        }
+
+        // protected
+
+        void Sender::sendMessages(proton::sender &s, const std::string& subType, const Json::Value& testValues) {
+            uint32_t valueNumber = 0;
+            for (Json::Value::const_iterator i=testValues.begin(); i!=testValues.end(); ++i) {
+                if (s.credit()) {
+                    proton::message msg;
+                    if (_jmsMessageType.compare("JMS_MESSAGE_TYPE") == 0) {
+                        setMessage(msg, subType, (*i).asString());
+                    } else if (_jmsMessageType.compare("JMS_BYTESMESSAGE_TYPE") == 0) {
+                        setBytesMessage(msg, subType, (*i).asString());
+                    } else if (_jmsMessageType.compare("JMS_MAPMESSAGE_TYPE") == 0) {
+                        setMapMessage(msg, subType, (*i).asString(), valueNumber);
+                    } else if (_jmsMessageType.compare("JMS_OBJECTMESSAGE_TYPE") == 0) {
+                        setObjectMessage(msg, subType, *i);
+                    } else if (_jmsMessageType.compare("JMS_STREAMMESSAGE_TYPE") == 0) {
+                        setStreamMessage(msg, subType, (*i).asString());
+                    } else if (_jmsMessageType.compare("JMS_TEXTMESSAGE_TYPE") == 0) {
+                        setTextMessage(msg, *i);
+                    } else {
+                        throw qpidit::UnknownJmsMessageTypeError(_jmsMessageType);
+                    }
+                    addMessageHeaders(msg);
+                    addMessageProperties(msg);
+                    s.send(msg);
+                    _msgsSent += 1;
+                    valueNumber += 1;
+                }
+            }
+
+        }
+
+        proton::message& Sender::setMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr) {
+            if (subType.compare("none") != 0) {
+                throw qpidit::UnknownJmsMessageSubTypeError(subType);
+            }
+            if (testValueStr.size() != 0) {
+                throw InvalidTestValueError(subType, testValueStr);
+            }
+            msg.content_type(proton::symbol("application/octet-stream"));
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_MESSAGE_TYPE"]);
+            return msg;
+        }
+
+        proton::message& Sender::setBytesMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr) {
+            proton::binary bin;
+            if (subType.compare("boolean") == 0) {
+                if (testValueStr.compare("False") == 0) bin.push_back(char(0));
+                else if (testValueStr.compare("True") == 0) bin.push_back(char(1));
+                else throw InvalidTestValueError(subType, testValueStr);
+            } else if (subType.compare("byte") == 0) {
+                uint8_t val = getIntegralValue<int8_t>(testValueStr);
+                bin.push_back(char(val));
+            } else if (subType.compare("bytes") == 0) {
+                bin.assign(testValueStr.begin(), testValueStr.end());
+            } else if (subType.compare("char") == 0) {
+                bin.push_back(char(0));
+                if (testValueStr[0] == '\\') { // Format: '\xNN'
+                    bin.push_back(getIntegralValue<char>(testValueStr.substr(2)));
+                } else { // Format: 'c'
+                    bin.push_back(testValueStr[0]);
+                }
+            } else if (subType.compare("double") == 0) {
+                uint64_t val;
+                try {
+                    val = htobe64(std::strtoul(testValueStr.data(), NULL, 16));
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError("double", testValueStr); }
+                numToBinary(val, bin);
+               //for (int i=0; i<sizeof(val); ++i) {
+               //     bin.push_back(* ((char*)&val + i));
+               // }
+            } else if (subType.compare("float") == 0) {
+                uint32_t val;
+                try {
+                    val = htobe32((uint32_t)std::strtoul(testValueStr.data(), NULL, 16));
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError("float", testValueStr); }
+                numToBinary(val, bin);
+                //for (int i=0; i<sizeof(val); ++i) {
+                //    bin.push_back(* ((char*)&val + i));
+                //}
+            } else if (subType.compare("long") == 0) {
+                uint64_t val = htobe64(getIntegralValue<uint64_t>(testValueStr));
+                numToBinary(val, bin);
+                //bin.assign(sizeof(val), val);
+            } else if (subType.compare("int") == 0) {
+                uint32_t val = htobe32(getIntegralValue<uint32_t>(testValueStr));
+                numToBinary(val, bin);
+                //bin.assign(sizeof(val), val);
+            } else if (subType.compare("short") == 0) {
+                uint16_t val = htobe16(getIntegralValue<int16_t>(testValueStr));
+                numToBinary(val, bin);
+                //bin.assign(sizeof(val), val);
+            } else if (subType.compare("string") == 0) {
+                std::ostringstream oss;
+                uint16_t strlen = htobe16((uint16_t)testValueStr.size());
+                oss.write((char*)&strlen, sizeof(strlen));
+                oss << testValueStr;
+                std::string os = oss.str();
+                bin.assign(os.begin(), os.end());
+            } else {
+                throw qpidit::UnknownJmsMessageSubTypeError(subType);
+            }
+            msg.body(bin);
+            msg.inferred(true);
+            msg.content_type(proton::symbol("application/octet-stream"));
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_BYTESMESSAGE_TYPE"]);
+            return msg;
+        }
+
+        proton::message& Sender::setMapMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr, uint32_t valueNumber) {
+            std::ostringstream oss;
+            oss << subType << std::setw(3) << std::setfill('0') << valueNumber;
+            std::string mapKey(oss.str());
+            std::map<std::string, proton::value> m;
+            if (subType.compare("boolean") == 0) {
+                if (testValueStr.compare("False") == 0) m[mapKey] = false;
+                else if (testValueStr.compare("True") == 0) m[mapKey] = true;
+                else throw InvalidTestValueError(subType, testValueStr);
+            } else if (subType.compare("byte") == 0) {
+                m[mapKey] = int8_t(getIntegralValue<int8_t>(testValueStr));
+            } else if (subType.compare("bytes") == 0) {
+                m[mapKey] = proton::binary(testValueStr);
+            } else if (subType.compare("char") == 0) {
+                wchar_t val;
+                if (testValueStr[0] == '\\') { // Format: '\xNN'
+                    val = (wchar_t)getIntegralValue<wchar_t>(testValueStr.substr(2));
+                } else { // Format: 'c'
+                    val = testValueStr[0];
+                }
+                m[mapKey] = val;
+            } else if (subType.compare("double") == 0) {
+                m[mapKey] = getFloatValue<double, uint64_t>(testValueStr);
+            } else if (subType.compare("float") == 0) {
+                m[mapKey] = getFloatValue<float, uint32_t>(testValueStr);
+            } else if (subType.compare("int") == 0) {
+                m[mapKey] = getIntegralValue<int32_t>(testValueStr);
+            } else if (subType.compare("long") == 0) {
+                m[mapKey] = getIntegralValue<int64_t>(testValueStr);
+            } else if (subType.compare("short") == 0) {
+                m[mapKey] = getIntegralValue<int16_t>(testValueStr);
+            } else if (subType.compare("string") == 0) {
+                m[mapKey] = testValueStr;
+            } else {
+                throw qpidit::UnknownJmsMessageSubTypeError(subType);
+            }
+            msg.inferred(false);
+            msg.body(m);
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_MAPMESSAGE_TYPE"]);
+            return msg;
+        }
+
+        proton::message& Sender::setObjectMessage(proton::message& msg, const std::string& subType, const Json::Value& testValue) {
+            msg.body(getJavaObjectBinary(subType, testValue.asString()));
+            msg.inferred(true);
+            msg.content_type(proton::symbol("application/x-java-serialized-object"));
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_OBJECTMESSAGE_TYPE"]);
+            return msg;
+        }
+
+        proton::message& Sender::setStreamMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr) {
+            std::vector<proton::value> l;
+            if (subType.compare("boolean") == 0) {
+                if (testValueStr.compare("False") == 0) l.push_back(false);
+                else if (testValueStr.compare("True") == 0) l.push_back(true);
+                else throw InvalidTestValueError(subType, testValueStr);
+            } else if (subType.compare("byte") == 0) {
+                l.push_back(int8_t(getIntegralValue<int8_t>(testValueStr)));
+            } else if (subType.compare("bytes") == 0) {
+                l.push_back(proton::binary(testValueStr));
+            } else if (subType.compare("char") == 0) {
+                wchar_t val;
+                if (testValueStr[0] == '\\') { // Format: '\xNN'
+                    val = (wchar_t)getIntegralValue<wchar_t>(testValueStr.substr(2));
+                } else { // Format: 'c'
+                    val = testValueStr[0];
+                }
+                l.push_back(val);
+            } else if (subType.compare("double") == 0) {
+                l.push_back(getFloatValue<double, uint64_t>(testValueStr));
+            } else if (subType.compare("float") == 0) {
+                l.push_back(getFloatValue<float, uint32_t>(testValueStr));
+            } else if (subType.compare("int") == 0) {
+                l.push_back(getIntegralValue<int32_t>(testValueStr));
+            } else if (subType.compare("long") == 0) {
+                l.push_back(getIntegralValue<int64_t>(testValueStr));
+            } else if (subType.compare("short") == 0) {
+                l.push_back(getIntegralValue<int16_t>(testValueStr));
+            } else if (subType.compare("string") == 0) {
+                l.push_back(testValueStr);
+            } else {
+                throw qpidit::UnknownJmsMessageSubTypeError(subType);
+            }
+            msg.body(l);
+            msg.inferred(true);
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_STREAMMESSAGE_TYPE"]);
+            return msg;
+       }
+
+        proton::message& Sender::setTextMessage(proton::message& msg, const Json::Value& testValue) {
+            msg.body(testValue.asString());
+            msg.inferred(false);
+            msg.message_annotations().put(proton::symbol("x-opt-jms-msg-type"), s_jmsMessageTypeAnnotationValues["JMS_TEXTMESSAGE_TYPE"]);
+            return msg;
+        }
+
+        proton::message& Sender::addMessageHeaders(proton::message& msg) {
+            Json::Value::Members headerNames = _testHeadersMap.getMemberNames();
+            for (std::vector<std::string>::const_iterator i=headerNames.begin(); i!=headerNames.end(); ++i) {
+                const Json::Value _subMap = _testHeadersMap[*i];
+                const std::string headerValueType = _subMap.getMemberNames()[0]; // There is always only one entry in map
+                std::string val = _subMap[headerValueType].asString();
+                if (i->compare("JMS_TYPE_HEADER") == 0) {
+                    setJmsTypeHeader(msg, val);
+                } else if (i->compare("JMS_CORRELATIONID_HEADER") == 0) {
+                    if (headerValueType.compare("bytes") == 0) {
+                        setJmsCorrelationId(msg, proton::binary(val));
+                    } else {
+                        setJmsCorrelationId(msg, val);
+                    }
+                } else if (i->compare("JMS_REPLYTO_HEADER") == 0) {
+                    setJmsReplyTo(msg, headerValueType, val);
+                } else {
+                    throw qpidit::UnknownJmsHeaderTypeError(*i);
+                }
+            }
+            return msg;
+        }
+
+        //static
+        proton::message& Sender::setJmsTypeHeader(proton::message& msg, const std::string& t) {
+            msg.subject(t);
+            return msg;
+        }
+
+        //static
+        proton::message& Sender::setJmsCorrelationId(proton::message& msg, const std::string& cid) {
+            proton::message_id mid(cid);
+            msg.correlation_id(mid);
+            msg.message_annotations().put(proton::symbol("x-opt-app-correlation-id"), true);
+            return msg;
+        }
+
+        //static
+        proton::message& Sender::setJmsCorrelationId(proton::message& msg, const proton::binary cid) {
+            proton::message_id mid(cid);
+            msg.correlation_id(cid);
+            msg.message_annotations().put(proton::symbol("x-opt-app-correlation-id"), true);
+            return msg;
+        }
+
+        //static
+        proton::message& Sender::setJmsReplyTo(proton::message& msg, const std::string& dts, const std::string& d) {
+            if (dts.compare("queue") == 0) {
+                msg.reply_to(/*std::string("queue://") + */d);
+                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(qpidit::JMS_QUEUE));
+            } else if (dts.compare("temp_queue") == 0) {
+                msg.reply_to(/*std::string("queue://") + */d);
+                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(qpidit::JMS_TMEP_QUEUE));
+            } else if (dts.compare("topic") == 0) {
+                msg.reply_to(/*std::string("topic://") + */d);
+                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(qpidit::JMS_TOPIC));
+            } else if (dts.compare("temp_topic") == 0) {
+                msg.reply_to(/*std::string("topic://") + */d);
+                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(qpidit::JMS_TEMP_TOPIC));
+            } else {
+                throw qpidit::UnknownJmsDestinationTypeError(dts);
+            }
+            return msg;
+        }
+
+        proton::message& Sender::addMessageProperties(proton::message& msg) {
+            Json::Value::Members propertyNames = _testPropertiesMap.getMemberNames();
+            for (std::vector<std::string>::const_iterator i=propertyNames.begin(); i!=propertyNames.end(); ++i) {
+                const Json::Value _subMap = _testPropertiesMap[*i];
+                const std::string propertyValueType = _subMap.getMemberNames()[0]; // There is always only one entry in map
+                std::string val = _subMap[propertyValueType].asString();
+                if (propertyValueType.compare("boolean") == 0) {
+                    if (val.compare("False") == 0) setMessageProperty(msg, *i, false);
+                    else if (val.compare("True") == 0) setMessageProperty(msg, *i, true);
+                    else throw InvalidTestValueError(propertyValueType, val);
+                } else if (propertyValueType.compare("byte") == 0) {
+                    setMessageProperty(msg, *i, getIntegralValue<int8_t>(val));
+                } else if (propertyValueType.compare("double") == 0) {
+                    setMessageProperty(msg, *i, getFloatValue<double, uint64_t>(val));
+                } else if (propertyValueType.compare("float") == 0) {
+                    setMessageProperty(msg, *i, getFloatValue<float, uint64_t>(val));
+                } else if (propertyValueType.compare("int") == 0) {
+                    setMessageProperty(msg, *i, getIntegralValue<int32_t>(val));
+                } else if (propertyValueType.compare("long") == 0) {
+                    setMessageProperty(msg, *i, getIntegralValue<int64_t>(val));
+                } else if (propertyValueType.compare("short") == 0) {
+                    setMessageProperty(msg, *i, getIntegralValue<int16_t>(val));
+                } else if (propertyValueType.compare("string") == 0) {
+                    setMessageProperty(msg, *i, val);
+                } else {
+                    throw qpidit::UnknownJmsPropertyTypeError(propertyValueType);
+                }
+            }
+            return msg;
+        }
+
+        //static
+        proton::binary Sender::getJavaObjectBinary(const std::string& javaClassName, const std::string& valAsString) {
+            proton::binary javaObjectBinary;
+            char buf[1024];
+            int bytesRead;
+            FILE* fp = ::popen("java -cp target/JavaObjUtils.jar org.apache.qpid.interop_test.obj_util.JavaObjToBytes javaClassStr", "rb");
+            if (fp == NULL) { throw qpidit::PopenError(errno); }
+            do {
+                bytesRead = ::fread(buf, 1, sizeof(buf), fp);
+                javaObjectBinary.insert(javaObjectBinary.end(), &buf[0], &buf[bytesRead-1]);
+            } while (bytesRead == sizeof(buf));
+            int status = ::pclose(fp);
+            if (status == -1) {
+                throw qpidit::PcloseError(errno);
+            }
+            return javaObjectBinary;
+        }
+
+        // static
+        uint32_t Sender::getTotalNumMessages(const Json::Value& testValueMap) {
+            uint32_t tot = 0;
+            for (Json::Value::const_iterator i = testValueMap.begin(); i != testValueMap.end(); ++i) {
+                tot += (*i).size();
+            }
+            return tot;
+        }
+
+    } /* namespace jms_hdrs_props_test */
+} /* namespace qpidit */
+
+
+
+/*
+ * --- main ---
+ * Args: 1: Broker address (ip-addr:port)
+ *       2: Queue name
+ *       3: AMQP type
+ *       4: JSON Test parameters containing 3 maps: [testValueMap, testHeadersMap, testPropertiesMap]
+ */
+
+int main(int argc, char** argv) {
+/*
+    for (int i=0; i<argc; ++i) {
+        std::cout << "*** argv[" << i << "] : " << argv[i] << std::endl;
+    }
+*/
+    // TODO: improve arg management a little...
+    if (argc != 5) {
+        throw qpidit::ArgumentError("Incorrect number of arguments");
+    }
+
+    std::ostringstream oss;
+    oss << argv[1] << "/" << argv[2];
+
+    try {
+        Json::Value testParams;
+        Json::Reader jsonReader;
+        if (not jsonReader.parse(argv[4], testParams, false)) {
+            throw qpidit::JsonParserError(jsonReader);
+        }
+
+        qpidit::jms_hdrs_props_test::Sender sender(oss.str(), argv[3], testParams);
+        proton::default_container(sender).run();
+    } catch (const std::exception& e) {
+        std::cout << "JmsSender error: " << e.what() << std::endl;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.hpp b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.hpp
new file mode 100644
index 0000000..8e3efe7
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_hdrs_props_test/Sender.hpp
@@ -0,0 +1,109 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_SENDER_HPP_
+#define SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_SENDER_HPP_
+
+#include "json/value.h"
+#include "proton/message.hpp"
+#include "proton/messaging_handler.hpp"
+#include "qpidit/JmsTestBase.hpp"
+#include "qpidit/QpidItErrors.hpp"
+#include <typeinfo>
+
+namespace proton {
+    class message;
+}
+
+namespace qpidit
+{
+    namespace jms_hdrs_props_test
+    {
+
+        class Sender : public qpidit::JmsTestBase
+        {
+        protected:
+            const std::string _brokerUrl;
+            const std::string _jmsMessageType;
+            const Json::Value _testValueMap;
+            const Json::Value _testHeadersMap;
+            const Json::Value _testPropertiesMap;
+            uint32_t _msgsSent;
+            uint32_t _msgsConfirmed;
+            uint32_t _totalMsgs;
+        public:
+            Sender(const std::string& brokerUrl, const std::string& jmsMessageType, const Json::Value& testParams);
+            virtual ~Sender();
+
+            void on_container_start(proton::container &c);
+            void on_sendable(proton::sender &s);
+            void on_tracker_accept(proton::tracker &t);
+            void on_transport_close(proton::transport &t);
+        protected:
+            void  sendMessages(proton::sender &s, const std::string& subType, const Json::Value& testValueMap);
+            proton::message& setMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr);
+            proton::message& setBytesMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr);
+            proton::message& setMapMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr, uint32_t valueNumber);
+            proton::message& setObjectMessage(proton::message& msg, const std::string& subType, const Json::Value& testValue);
+            proton::message& setStreamMessage(proton::message& msg, const std::string& subType, const std::string& testValue);
+            proton::message& setTextMessage(proton::message& msg, const Json::Value& testValue);
+
+            proton::message& addMessageHeaders(proton::message& msg);
+            static proton::message& setJmsTypeHeader(proton::message& msg, const std::string& t);
+            static proton::message& setJmsCorrelationId(proton::message& msg, const std::string& cid);
+            static proton::message& setJmsCorrelationId(proton::message& msg, const proton::binary cid);
+            static proton::message& setJmsReplyTo(proton::message& msg, const std::string& dt, const std::string& d);
+
+            proton::message& addMessageProperties(proton::message& msg);
+            template<typename T> proton::message& setMessageProperty(proton::message& msg, const std::string& propertyName, T val) {
+                msg.properties().put(propertyName, val);
+                return msg;
+            }
+
+            static proton::binary getJavaObjectBinary(const std::string& javaClassName, const std::string& valAsString);
+            static uint32_t getTotalNumMessages(const Json::Value& testValueMap);
+
+            template<typename T> static T numToBinary(T n, proton::binary& b) {
+                for (int i=0; i<sizeof(n); ++i) {
+                    b.push_back(* ((char*)&n + i));
+                }
+            }
+
+            // 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> T getFloatValue(const std::string& testValueStr) {
+                try {
+                    U ival(std::strtoul(testValueStr.data(), NULL, 16));
+                    return T(*reinterpret_cast<T*>(&ival));
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(typeid(T).name(), testValueStr); }
+            }
+
+            template<typename T> T getIntegralValue(const std::string& testValueStr) {
+                try {
+                    return T(std::strtol(testValueStr.data(), NULL, 16));
+                } catch (const std::exception& e) { throw qpidit::InvalidTestValueError(typeid(T).name(), testValueStr); }
+            }
+        };
+
+    } /* namespace jms_hdrs_props_test */
+} /* namespace qpidit */
+
+#endif /* SRC_QPIDIT_JMS_HEADERS_PROPERTIES_TEST_SENDER_HPP_ */

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/JmsDefinitions.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/JmsDefinitions.hpp b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/JmsDefinitions.hpp
deleted file mode 100644
index 6f99813..0000000
--- a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/JmsDefinitions.hpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * 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.
- *
- */
-
-#ifndef SRC_QPIDIT_JMS_MESSAGES_TEST_JMSDEFINTIONS_HPP_
-#define SRC_QPIDIT_JMS_MESSAGES_TEST_JMSDEFINTIONS_HPP_
-
-namespace qpidit
-{
-    namespace jms_messages_test
-    {
-        typedef enum {JMS_QUEUE = 0,
-                      JMS_TOPIC,
-                      JMS_TMEP_QUEUE,
-                      JMS_TEMP_TOPIC}
-        jmsDestinationType_t;
-
-        typedef enum {JMS_MESSAGE_TYPE=0,
-                      JMS_OBJECTMESSAGE_TYPE,
-                      JMS_MAPMESSAGE_TYPE,
-                      JMS_BYTESMESSAGE_TYPE,
-                      JMS_STREAMMESSAGE_TYPE,
-                      JMS_TEXTMESSAGE_TYPE}
-        jmsMessageType_t;
-
-    }
-}
-
-#endif /* SRC_QPIDIT_JMS_MESSAGES_TEST_JMSDEFINTIONS_HPP_ */

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.cpp b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.cpp
index ed1dfa5..43bd34f 100644
--- a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.cpp
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.cpp
@@ -33,27 +33,18 @@ namespace qpidit
 {
     namespace jms_messages_test
     {
-        //static
-        proton::symbol Receiver::s_jmsMessageTypeAnnotationKey("x-opt-jms-msg-type");
-        std::map<std::string, int8_t>Receiver::s_jmsMessageTypeAnnotationValues = initializeJmsMessageTypeAnnotationMap();
-
-
         Receiver::Receiver(const std::string& brokerUrl,
                            const std::string& jmsMessageType,
-                           const Json::Value& testNumberMap,
-                           const Json::Value& flagMap):
+                           const Json::Value& testNumberMap):
                             _brokerUrl(brokerUrl),
                             _jmsMessageType(jmsMessageType),
                             _testNumberMap(testNumberMap),
-                            _flagMap(flagMap),
                             _subTypeList(testNumberMap.getMemberNames()),
                             _subTypeIndex(0),
                             _expected(getTotalNumExpectedMsgs(testNumberMap)),
                             _received(0UL),
                             _receivedSubTypeList(Json::arrayValue),
-                            _receivedValueMap(Json::objectValue),
-                            _receivedHeadersMap(Json::objectValue),
-                            _receivedPropertiesMap(Json::objectValue)
+                            _receivedValueMap(Json::objectValue)
         {}
 
         Receiver::~Receiver() {}
@@ -62,14 +53,6 @@ namespace qpidit
             return _receivedValueMap;
         }
 
-        Json::Value& Receiver::getReceivedHeadersMap() {
-            return _receivedHeadersMap;
-        }
-
-        Json::Value& Receiver::getReceivedPropertiesMap() {
-            return _receivedPropertiesMap;
-        }
-
         void Receiver::on_container_start(proton::container &c) {
             c.open_receiver(_brokerUrl);
         }
@@ -77,38 +60,35 @@ namespace qpidit
         void Receiver::on_message(proton::delivery &d, proton::message &m) {
             try {
                 if (_received < _expected) {
-                    int8_t t = JMS_MESSAGE_TYPE;
+                    int8_t t = qpidit::JMS_MESSAGE_TYPE;
                     try {t = m.message_annotations().get(proton::symbol("x-opt-jms-msg-type")).get<int8_t>();}
                     catch (const std::exception& e) {
                         std::cout << "JmsReceiver::on_message(): Missing annotation \"x-opt-jms-msg-type\"" << std::endl;
                         throw;
                     }
                     switch (t) {
-                    case JMS_MESSAGE_TYPE:
+                    case qpidit::JMS_MESSAGE_TYPE:
                         receiveJmsMessage(m);
                         break;
-                    case JMS_OBJECTMESSAGE_TYPE:
+                    case qpidit::JMS_OBJECTMESSAGE_TYPE:
                         receiveJmsObjectMessage(m);
                         break;
-                    case JMS_MAPMESSAGE_TYPE:
+                    case qpidit::JMS_MAPMESSAGE_TYPE:
                         receiveJmsMapMessage(m);
                         break;
-                    case JMS_BYTESMESSAGE_TYPE:
+                    case qpidit::JMS_BYTESMESSAGE_TYPE:
                         receiveJmsBytesMessage(m);
                         break;
-                    case JMS_STREAMMESSAGE_TYPE:
+                    case qpidit::JMS_STREAMMESSAGE_TYPE:
                         receiveJmsStreamMessage(m);
                         break;
-                    case JMS_TEXTMESSAGE_TYPE:
+                    case qpidit::JMS_TEXTMESSAGE_TYPE:
                         receiveJmsTextMessage(m);
                         break;
                     default:;
                         // TODO: handle error - no known JMS message type
                     }
 
-                    processMessageHeaders(m);
-                    processMessageProperties(m);
-
                     std::string subType(_subTypeList[_subTypeIndex]);
                     // Increment the subtype if the required number of messages have been received
                     if (_receivedSubTypeList.size() >= _testNumberMap[subType].asInt() &&
@@ -130,26 +110,6 @@ namespace qpidit
             }
         }
 
-        void Receiver::on_connection_error(proton::connection &c) {
-            std::cerr << "JmsReceiver::on_connection_error(): " << c.error() << std::endl;
-        }
-
-        void Receiver::on_receiver_error(proton::receiver& r) {
-            std::cerr << "JmsReceiver::on_receiver_error(): " << r.error() << std::endl;
-        }
-
-        void Receiver::on_session_error(proton::session &s) {
-            std::cerr << "JmsReceiver::on_session_error(): " << s.error() << std::endl;
-        }
-
-        void Receiver::on_transport_error(proton::transport &t) {
-            std::cerr << "JmsReceiver::on_transport_error(): " << t.error() << std::endl;
-        }
-
-        void Receiver::on_error(const proton::error_condition &ec) {
-            std::cerr << "JmsReceiver::on_error(): " << ec << std::endl;
-        }
-
         //static
         uint32_t Receiver::getTotalNumExpectedMsgs(const Json::Value testNumberMap) {
             uint32_t total(0UL);
@@ -309,85 +269,6 @@ namespace qpidit
             _receivedSubTypeList.append(Json::Value(msg.body().get<std::string>()));
         }
 
-        void Receiver::processMessageHeaders(const proton::message& msg) {
-            addMessageHeaderString("JMS_TYPE_HEADER", msg.subject());
-            if (_flagMap.isMember("JMS_CORRELATIONID_AS_BYTES") && _flagMap["JMS_CORRELATIONID_AS_BYTES"].asBool()) {
-                addMessageHeaderByteArray("JMS_CORRELATIONID_HEADER", proton::get<proton::binary>(msg.correlation_id()));
-            } else {
-                try {
-                    addMessageHeaderString("JMS_CORRELATIONID_HEADER", proton::get<std::string>(msg.correlation_id()));
-                } catch (const std::exception& e) {} // TODO: UGLY, how do you check if there _is_ a correlation id?
-            }
-
-            std::string reply_to = msg.reply_to();
-            // Some brokers prepend 'queue://' and 'topic://' to reply_to addresses, strip these when present
-            if (_flagMap.isMember("JMS_REPLYTO_AS_TOPIC") && _flagMap["JMS_REPLYTO_AS_TOPIC"].asBool()) {
-                if (reply_to.find("topic://") == 0) {
-                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_TOPIC, reply_to.substr(8));
-                } else {
-                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_TOPIC, reply_to);
-                }
-            } else {
-                if (reply_to.find("queue://") == 0) {
-                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_QUEUE, reply_to.substr(8));
-                } else {
-                    addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_QUEUE, reply_to);
-                }
-            }
-        }
-
-        void Receiver::addMessageHeaderString(const char* headerName, const std::string& value) {
-            if (!value.empty()) { // TODO: Remove this test when PROTON-1288 is fixed as empty strings are allowed in headers
-                Json::Value valueMap(Json::objectValue);
-                valueMap["string"] = value;
-                _receivedHeadersMap[headerName] = valueMap;
-            }
-        }
-
-        void Receiver::addMessageHeaderByteArray(const std::string& headerName, const proton::binary ba) {
-            if (!ba.empty()) { // TODO: Remove this test when PROTON-1288 is fixed as empty binaries are allowed in headers
-                Json::Value valueMap(Json::objectValue);
-                valueMap["bytes"] = std::string(ba);
-                _receivedHeadersMap[headerName] = valueMap;
-            }
-        }
-
-        void Receiver::addMessageHeaderDestination(const std::string& headerName, jmsDestinationType_t dt, const std::string& d) {
-            if (!d.empty()) {
-                Json::Value valueMap(Json::objectValue);
-                switch (dt) {
-                case JMS_QUEUE:
-                    valueMap["queue"] = d;
-                    break;
-                case JMS_TOPIC:
-                    valueMap["topic"] = d;
-                    break;
-                default:
-                    ; // TODO: Handle error: remaining JMS destinations not handled.
-                }
-                _receivedHeadersMap[headerName] = valueMap;
-            }
-        }
-
-        void Receiver::processMessageProperties(const proton::message& msg) {
-            // TODO: Add this function when PROTON-1284 is fixed
-//            std::map<proton::value, proton::value> props;
-//            msg.properties().value() >> props;
-        }
-
-        //static
-        std::map<std::string, int8_t> Receiver::initializeJmsMessageTypeAnnotationMap() {
-            std::map<std::string, int8_t> m;
-            m["JMS_MESSAGE_TYPE"] = JMS_MESSAGE_TYPE;
-            m["JMS_OBJECTMESSAGE_TYPE"] = JMS_OBJECTMESSAGE_TYPE;
-            m["JMS_MAPMESSAGE_TYPE"] = JMS_MAPMESSAGE_TYPE;
-            m["JMS_BYTESMESSAGE_TYPE"] = JMS_BYTESMESSAGE_TYPE;
-            m["JMS_STREAMMESSAGE_TYPE"] = JMS_STREAMMESSAGE_TYPE;
-            m["JMS_TEXTMESSAGE_TYPE"] = JMS_TEXTMESSAGE_TYPE;
-            return m;
-        }
-
-
     } /* namespace jms_messages_test */
 } /* namespace qpidit */
 
@@ -418,14 +299,12 @@ int main(int argc, char** argv) {
             throw qpidit::JsonParserError(jsonReader);
         }
 
-        qpidit::jms_messages_test::Receiver receiver(oss.str(), argv[3], testParams[0], testParams[1]);
+        qpidit::jms_messages_test::Receiver receiver(oss.str(), argv[3], testParams);
         proton::default_container(receiver).run();
 
         Json::FastWriter fw;
         std::cout << argv[3] << std::endl;
         std::cout << fw.write(receiver.getReceivedValueMap());
-        std::cout << fw.write(receiver.getReceivedHeadersMap());
-        std::cout << fw.write(receiver.getReceivedPropertiesMap());
     } catch (const std::exception& e) {
         std::cout << "JmsReceiver error: " << e.what() << std::endl;
     }

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.hpp b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.hpp
index 696b9dd..d7c183b 100644
--- a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.hpp
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Receiver.hpp
@@ -26,7 +26,7 @@
 #include <json/value.h>
 #include "proton/messaging_handler.hpp"
 #include "proton/types.hpp"
-#include "qpidit/jms_messages_test/JmsDefinitions.hpp"
+#include "qpidit/JmsTestBase.hpp"
 #include <sstream>
 
 namespace qpidit
@@ -34,42 +34,28 @@ namespace qpidit
     namespace jms_messages_test
     {
 
-        class Receiver : public proton::messaging_handler
+        class Receiver : public qpidit::JmsTestBase
         {
         protected:
-            static proton::symbol s_jmsMessageTypeAnnotationKey;
-            static std::map<std::string, int8_t>s_jmsMessageTypeAnnotationValues;
-
             const std::string _brokerUrl;
             const std::string _jmsMessageType;
             const Json::Value _testNumberMap;
-            const Json::Value _flagMap;
             Json::Value::Members _subTypeList;
             int _subTypeIndex;
             uint32_t _expected;
             uint32_t _received;
             Json::Value _receivedSubTypeList;
             Json::Value _receivedValueMap;
-            Json::Value _receivedHeadersMap;
-            Json::Value _receivedPropertiesMap;
+
         public:
             Receiver(const std::string& brokerUrl,
                      const std::string& jmsMessageType,
-                     const Json::Value& testNumberMap,
-                     const Json::Value& flagMap);
+                     const Json::Value& testNumberMap);
             virtual ~Receiver();
             Json::Value& getReceivedValueMap();
-            Json::Value& getReceivedHeadersMap();
-            Json::Value& getReceivedPropertiesMap();
             void on_container_start(proton::container &c);
             void on_message(proton::delivery &d, proton::message &m);
 
-            void on_connection_error(proton::connection &c);
-            void on_receiver_error(proton::receiver& r);
-            void on_session_error(proton::session &s);
-            void on_transport_error(proton::transport &t);
-            void on_error(const proton::error_condition &c);
-
             static uint32_t getTotalNumExpectedMsgs(const Json::Value testNumberMap);
 
         protected:
@@ -80,14 +66,6 @@ namespace qpidit
             void receiveJmsStreamMessage(const proton::message& msg);
             void receiveJmsTextMessage(const proton::message& msg);
 
-            void processMessageHeaders(const proton::message& msg);
-            void addMessageHeaderString(const char* headerName, const std::string& value);
-            void addMessageHeaderByteArray(const std::string& headerName, const proton::binary ba);
-            void addMessageHeaderDestination(const std::string& headerName, jmsDestinationType_t dt, const std::string& d);
-            void processMessageProperties(const proton::message& msg);
-
-            static std::map<std::string, int8_t> initializeJmsMessageTypeAnnotationMap();
-
             // Format signed numbers in negative hex format if signedFlag is true, ie -0xNNNN, positive numbers in 0xNNNN format
             template<typename T> static std::string toHexStr(T val, bool fillFlag = false, bool signedFlag = true) {
                 std::ostringstream oss;

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.cpp b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.cpp
index dbe2c0d..42ba558 100644
--- a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.cpp
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.cpp
@@ -35,18 +35,12 @@ namespace qpidit
 {
     namespace jms_messages_test
     {
-        //static
-        proton::symbol Sender::s_jmsMessageTypeAnnotationKey("x-opt-jms-msg-type");
-        std::map<std::string, int8_t>Sender::s_jmsMessageTypeAnnotationValues = initializeJmsMessageTypeAnnotationMap();
-
         Sender::Sender(const std::string& brokerUrl,
                        const std::string& jmsMessageType,
                        const Json::Value& testParams) :
                 _brokerUrl(brokerUrl),
                 _jmsMessageType(jmsMessageType),
-                _testValueMap(testParams[0]),
-                _testHeadersMap(testParams[1]),
-                _testPropertiesMap(testParams[2]),
+                _testValueMap(testParams),
                 _msgsSent(0),
                 _msgsConfirmed(0),
                 _totalMsgs(getTotalNumMessages(_testValueMap))
@@ -85,26 +79,6 @@ namespace qpidit
             _msgsSent = _msgsConfirmed;
         }
 
-        void Sender::on_connection_error(proton::connection &c) {
-            std::cerr << "JmsSender::on_connection_error(): " << c.error() << std::endl;
-        }
-
-        void Sender::on_sender_error(proton::sender &s) {
-            std::cerr << "JmsSender::on_sender_error(): " << s.error() << std::endl;
-        }
-
-        void Sender::on_session_error(proton::session &s) {
-            std::cerr << "JmsSender::on_session_error(): " << s.error() << std::endl;
-        }
-
-        void Sender::on_transport_error(proton::transport &t) {
-            std::cerr << "JmsSender::on_transport_error(): " << t.error() << std::endl;
-        }
-
-        void Sender::on_error(const proton::error_condition &ec) {
-            std::cerr << "JmsSender::on_error(): " << ec << std::endl;
-        }
-
         // protected
 
         void Sender::sendMessages(proton::sender &s, const std::string& subType, const Json::Value& testValues) {
@@ -127,8 +101,6 @@ namespace qpidit
                     } else {
                         throw qpidit::UnknownJmsMessageTypeError(_jmsMessageType);
                     }
-                    addMessageHeaders(msg);
-                    addMessageProperties(msg);
                     s.send(msg);
                     _msgsSent += 1;
                     valueNumber += 1;
@@ -310,102 +282,6 @@ namespace qpidit
             return msg;
         }
 
-        proton::message& Sender::addMessageHeaders(proton::message& msg) {
-            Json::Value::Members headerNames = _testHeadersMap.getMemberNames();
-            for (std::vector<std::string>::const_iterator i=headerNames.begin(); i!=headerNames.end(); ++i) {
-                const Json::Value _subMap = _testHeadersMap[*i];
-                const std::string headerValueType = _subMap.getMemberNames()[0]; // There is always only one entry in map
-                std::string val = _subMap[headerValueType].asString();
-                if (i->compare("JMS_TYPE_HEADER") == 0) {
-                    setJmsTypeHeader(msg, val);
-                } else if (i->compare("JMS_CORRELATIONID_HEADER") == 0) {
-                    if (headerValueType.compare("bytes") == 0) {
-                        setJmsCorrelationId(msg, proton::binary(val));
-                    } else {
-                        setJmsCorrelationId(msg, val);
-                    }
-                } else if (i->compare("JMS_REPLYTO_HEADER") == 0) {
-                    setJmsReplyTo(msg, headerValueType, val);
-                } else {
-                    throw qpidit::UnknownJmsHeaderTypeError(*i);
-                }
-            }
-            return msg;
-        }
-
-        //static
-        proton::message& Sender::setJmsTypeHeader(proton::message& msg, const std::string& t) {
-            msg.subject(t);
-            return msg;
-        }
-
-        //static
-        proton::message& Sender::setJmsCorrelationId(proton::message& msg, const std::string& cid) {
-            proton::message_id mid(cid);
-            msg.correlation_id(mid);
-            msg.message_annotations().put(proton::symbol("x-opt-app-correlation-id"), true);
-            return msg;
-        }
-
-        //static
-        proton::message& Sender::setJmsCorrelationId(proton::message& msg, const proton::binary cid) {
-            proton::message_id mid(cid);
-            msg.correlation_id(cid);
-            msg.message_annotations().put(proton::symbol("x-opt-app-correlation-id"), true);
-            return msg;
-        }
-
-        //static
-        proton::message& Sender::setJmsReplyTo(proton::message& msg, const std::string& dts, const std::string& d) {
-            if (dts.compare("queue") == 0) {
-                msg.reply_to(/*std::string("queue://") + */d);
-                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(JMS_QUEUE));
-            } else if (dts.compare("temp_queue") == 0) {
-                msg.reply_to(/*std::string("queue://") + */d);
-                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(JMS_TMEP_QUEUE));
-            } else if (dts.compare("topic") == 0) {
-                msg.reply_to(/*std::string("topic://") + */d);
-                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(JMS_TOPIC));
-            } else if (dts.compare("temp_topic") == 0) {
-                msg.reply_to(/*std::string("topic://") + */d);
-                msg.message_annotations().put(proton::symbol("x-opt-jms-reply-to"), int8_t(JMS_TEMP_TOPIC));
-            } else {
-                throw qpidit::UnknownJmsDestinationTypeError(dts);
-            }
-            return msg;
-        }
-
-        proton::message& Sender::addMessageProperties(proton::message& msg) {
-            Json::Value::Members propertyNames = _testPropertiesMap.getMemberNames();
-            for (std::vector<std::string>::const_iterator i=propertyNames.begin(); i!=propertyNames.end(); ++i) {
-                const Json::Value _subMap = _testPropertiesMap[*i];
-                const std::string propertyValueType = _subMap.getMemberNames()[0]; // There is always only one entry in map
-                std::string val = _subMap[propertyValueType].asString();
-                if (propertyValueType.compare("boolean") == 0) {
-                    if (val.compare("False") == 0) setMessageProperty(msg, *i, false);
-                    else if (val.compare("True") == 0) setMessageProperty(msg, *i, true);
-                    else throw InvalidTestValueError(propertyValueType, val);
-                } else if (propertyValueType.compare("byte") == 0) {
-                    setMessageProperty(msg, *i, getIntegralValue<int8_t>(val));
-                } else if (propertyValueType.compare("double") == 0) {
-                    setMessageProperty(msg, *i, getFloatValue<double, uint64_t>(val));
-                } else if (propertyValueType.compare("float") == 0) {
-                    setMessageProperty(msg, *i, getFloatValue<float, uint64_t>(val));
-                } else if (propertyValueType.compare("int") == 0) {
-                    setMessageProperty(msg, *i, getIntegralValue<int32_t>(val));
-                } else if (propertyValueType.compare("long") == 0) {
-                    setMessageProperty(msg, *i, getIntegralValue<int64_t>(val));
-                } else if (propertyValueType.compare("short") == 0) {
-                    setMessageProperty(msg, *i, getIntegralValue<int16_t>(val));
-                } else if (propertyValueType.compare("string") == 0) {
-                    setMessageProperty(msg, *i, val);
-                } else {
-                    throw qpidit::UnknownJmsPropertyTypeError(propertyValueType);
-                }
-            }
-            return msg;
-        }
-
         //static
         proton::binary Sender::getJavaObjectBinary(const std::string& javaClassName, const std::string& valAsString) {
             proton::binary javaObjectBinary;
@@ -433,18 +309,6 @@ namespace qpidit
             return tot;
         }
 
-        //static
-        std::map<std::string, int8_t> Sender::initializeJmsMessageTypeAnnotationMap() {
-            std::map<std::string, int8_t> m;
-            m["JMS_MESSAGE_TYPE"] = JMS_MESSAGE_TYPE;
-            m["JMS_OBJECTMESSAGE_TYPE"] = JMS_OBJECTMESSAGE_TYPE;
-            m["JMS_MAPMESSAGE_TYPE"] = JMS_MAPMESSAGE_TYPE;
-            m["JMS_BYTESMESSAGE_TYPE"] = JMS_BYTESMESSAGE_TYPE;
-            m["JMS_STREAMMESSAGE_TYPE"] = JMS_STREAMMESSAGE_TYPE;
-            m["JMS_TEXTMESSAGE_TYPE"] = JMS_TEXTMESSAGE_TYPE;
-            return m;
-        }
-
     } /* namespace jms_messages_test */
 } /* namespace qpidit */
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.hpp b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.hpp
index 5e41120..551edbf 100644
--- a/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.hpp
+++ b/shims/qpid-proton-cpp/src/qpidit/jms_messages_test/Sender.hpp
@@ -25,8 +25,8 @@
 #include "json/value.h"
 #include "proton/message.hpp"
 #include "proton/messaging_handler.hpp"
+#include "qpidit/JmsTestBase.hpp"
 #include "qpidit/QpidItErrors.hpp"
-#include "qpidit/jms_messages_test/JmsDefinitions.hpp"
 #include <typeinfo>
 
 namespace proton {
@@ -38,17 +38,12 @@ namespace qpidit
     namespace jms_messages_test
     {
 
-        class Sender : public proton::messaging_handler
+        class Sender : public qpidit::JmsTestBase
         {
         protected:
-            static proton::symbol s_jmsMessageTypeAnnotationKey;
-            static std::map<std::string, int8_t>s_jmsMessageTypeAnnotationValues;
-
             const std::string _brokerUrl;
             const std::string _jmsMessageType;
             const Json::Value _testValueMap;
-            const Json::Value _testHeadersMap;
-            const Json::Value _testPropertiesMap;
             uint32_t _msgsSent;
             uint32_t _msgsConfirmed;
             uint32_t _totalMsgs;
@@ -60,12 +55,6 @@ namespace qpidit
             void on_sendable(proton::sender &s);
             void on_tracker_accept(proton::tracker &t);
             void on_transport_close(proton::transport &t);
-
-            void on_connection_error(proton::connection &c);
-            void on_session_error(proton::session &s);
-            void on_sender_error(proton::sender& s);
-            void on_transport_error(proton::transport &t);
-            void on_error(const proton::error_condition &c);
         protected:
             void  sendMessages(proton::sender &s, const std::string& subType, const Json::Value& testValueMap);
             proton::message& setMessage(proton::message& msg, const std::string& subType, const std::string& testValueStr);
@@ -75,23 +64,9 @@ namespace qpidit
             proton::message& setStreamMessage(proton::message& msg, const std::string& subType, const std::string& testValue);
             proton::message& setTextMessage(proton::message& msg, const Json::Value& testValue);
 
-            proton::message& addMessageHeaders(proton::message& msg);
-            static proton::message& setJmsTypeHeader(proton::message& msg, const std::string& t);
-            static proton::message& setJmsCorrelationId(proton::message& msg, const std::string& cid);
-            static proton::message& setJmsCorrelationId(proton::message& msg, const proton::binary cid);
-            static proton::message& setJmsReplyTo(proton::message& msg, const std::string& dt, const std::string& d);
-
-            proton::message& addMessageProperties(proton::message& msg);
-            template<typename T> proton::message& setMessageProperty(proton::message& msg, const std::string& propertyName, T val) {
-                msg.properties().put(propertyName, val);
-                return msg;
-            }
-
             static proton::binary getJavaObjectBinary(const std::string& javaClassName, const std::string& valAsString);
             static uint32_t getTotalNumMessages(const Json::Value& testValueMap);
 
-            static std::map<std::string, int8_t> initializeJmsMessageTypeAnnotationMap();
-
             template<typename T> static T numToBinary(T n, proton::binary& b) {
                 for (int i=0; i<sizeof(n); ++i) {
                     b.push_back(* ((char*)&n + i));

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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 2876f51..7bb6355 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Receiver.py
@@ -26,13 +26,14 @@ AMQP type test receiver shim for qpid-interop-test
 # Issues:
 # * Capturing errors from client or broker
 
-import sys
 from json import dumps
-from proton.handlers import MessagingHandler
-from proton.reactor import Container
-from traceback import format_exc
 from string import digits, letters, punctuation
 from struct import pack, unpack
+import sys
+from traceback import format_exc
+
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
 
 class AmqpTypesReceiverShim(MessagingHandler):
     """

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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 19d183f..b760467 100755
--- a/shims/qpid-proton-python/src/amqp_types_test/Sender.py
+++ b/shims/qpid-proton-python/src/amqp_types_test/Sender.py
@@ -26,16 +26,17 @@ AMQP type test sender shim for qpid-interop-test
 # Issues:
 # * Capturing errors from client or broker
 
-import sys
-import os.path
 from json import loads
+import os.path
+from struct import unpack
+import sys
+from traceback import format_exc
+from uuid import UUID
+
 from proton import byte, char, decimal32, decimal64, decimal128, float32, int32, Message, short, symbol, timestamp, \
                    ubyte, uint, ulong, ushort
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
-from struct import unpack
-from traceback import format_exc
-from uuid import UUID
 
 class AmqpTypesSenderShim(MessagingHandler):
     """


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


[5/5] qpid-interop-test git commit: QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parame

Posted by kp...@apache.org.
QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parameters sent to shims to the same format for all shims, only one JSON string to and returned from receiver shim.


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

Branch: refs/heads/master
Commit: 514bac7511be39c2ceb25eb31c3234ccd9c1ae74
Parents: 83b89fe
Author: Kim van der Riet <kp...@apache.org>
Authored: Fri Oct 7 12:49:53 2016 -0400
Committer: Kim van der Riet <kp...@apache.org>
Committed: Fri Oct 7 12:49:53 2016 -0400

----------------------------------------------------------------------
 .pydevproject                                   |   5 +-
 .../jms_hdrs_props_test/Receiver.java           | 525 +++++++++++++++++++
 .../jms_hdrs_props_test/Sender.java             | 508 ++++++++++++++++++
 .../jms_messages_test/Receiver.java             | 126 +----
 .../jms_messages_test/Sender.java               | 109 +---
 shims/qpid-proton-cpp/src/CMakeLists.txt        |  44 ++
 .../qpid-proton-cpp/src/qpidit/JmsTestBase.cpp  |  69 +++
 .../qpid-proton-cpp/src/qpidit/JmsTestBase.hpp  |  64 +++
 .../src/qpidit/jms_hdrs_props_test/Receiver.cpp | 396 ++++++++++++++
 .../src/qpidit/jms_hdrs_props_test/Receiver.hpp | 100 ++++
 .../src/qpidit/jms_hdrs_props_test/Sender.cpp   | 451 ++++++++++++++++
 .../src/qpidit/jms_hdrs_props_test/Sender.hpp   | 109 ++++
 .../qpidit/jms_messages_test/JmsDefinitions.hpp |  46 --
 .../src/qpidit/jms_messages_test/Receiver.cpp   | 141 +----
 .../src/qpidit/jms_messages_test/Receiver.hpp   |  30 +-
 .../src/qpidit/jms_messages_test/Sender.cpp     | 138 +----
 .../src/qpidit/jms_messages_test/Sender.hpp     |  29 +-
 .../src/amqp_types_test/Receiver.py             |   9 +-
 .../src/amqp_types_test/Sender.py               |  11 +-
 .../src/jms_hdrs_props_test/Receiver.py         | 357 +++++++++++++
 .../src/jms_hdrs_props_test/Sender.py           | 388 ++++++++++++++
 .../src/jms_messages_test/Receiver.py           |  84 +--
 .../src/jms_messages_test/Sender.py             | 105 +---
 src/python/qpid-interop-test/.gitignore         |   4 -
 src/python/qpid-interop-test/__init__.py        |  26 -
 src/python/qpid-interop-test/amqp_types_test.py | 435 ---------------
 .../qpid-interop-test/broker_properties.py      |  54 --
 .../qpid-interop-test/interop_test_errors.py    |  29 -
 .../qpid-interop-test/jms_messages_test.py      | 511 ------------------
 src/python/qpid-interop-test/shims.py           | 229 --------
 src/python/qpid-interop-test/test_type_map.py   |  85 ---
 src/python/qpid_interop_test/.gitignore         |   4 +
 src/python/qpid_interop_test/__init__.py        |  23 +
 src/python/qpid_interop_test/amqp_types_test.py | 443 ++++++++++++++++
 .../qpid_interop_test/broker_properties.py      |  55 ++
 .../qpid_interop_test/interop_test_errors.py    |  29 +
 .../qpid_interop_test/jms_hdrs_props_test.py    | 520 ++++++++++++++++++
 .../qpid_interop_test/jms_messages_test.py      | 402 ++++++++++++++
 src/python/qpid_interop_test/shims.py           | 227 ++++++++
 src/python/qpid_interop_test/test_type_map.py   |  86 +++
 40 files changed, 4852 insertions(+), 2154 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/.pydevproject
----------------------------------------------------------------------
diff --git a/.pydevproject b/.pydevproject
index 037bd25..a279738 100644
--- a/.pydevproject
+++ b/.pydevproject
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?eclipse-pydev version="1.0"?><pydev_project>
-<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
-<path>/${PROJECT_DIR_NAME}</path>
-</pydev_pathproperty>
+
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
 <pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+
 </pydev_project>

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Receiver.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Receiver.java b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Receiver.java
new file mode 100644
index 0000000..27b5e7e
--- /dev/null
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Receiver.java
@@ -0,0 +1,525 @@
+/**
+ * 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.
+ */
+package org.apache.qpid.interop_test.jms_hdrs_props_test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.StreamMessage;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
+import javax.json.JsonWriter;
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class Receiver {
+    private static final String USER = "guest";
+    private static final String PASSWORD = "guest";
+    private static final int TIMEOUT = 1000;
+    private static final String[] SUPPORTED_JMS_MESSAGE_TYPES = {"JMS_MESSAGE_TYPE",
+                                                                 "JMS_BYTESMESSAGE_TYPE",
+                                                                 "JMS_MAPMESSAGE_TYPE",
+                                                                 "JMS_OBJECTMESSAGE_TYPE",
+                                                                 "JMS_STREAMMESSAGE_TYPE",
+                                                                 "JMS_TEXTMESSAGE_TYPE"};
+    private static enum JMS_DESTINATION_TYPE {JMS_QUEUE, JMS_TEMPORARY_QUEUE, JMS_TOPIC, JMS_TEMPORARY_TOPIC};
+    
+    Connection _connection;
+    Session _session;
+    Queue _queue;
+    MessageConsumer _messageConsumer;
+    JsonObjectBuilder _jsonTestValueMapBuilder;
+    JsonObjectBuilder _jsonMessageHeaderMapBuilder;
+    JsonObjectBuilder _jsonMessagePropertiesMapBuilder;
+    
+    // args[0]: Broker URL
+    // args[1]: Queue name
+    // args[2]: JMS message type
+    // args[3]: JSON Test parameters containing 2 maps: [testValuesMap, flagMap]
+    public static void main(String[] args) throws Exception {
+        if (args.length != 4) {
+            System.out.println("JmsReceiverShim: Incorrect number of arguments");
+            System.out.println("JmsReceiverShim: Expected arguments: broker_address, queue_name, JMS_msg_type, JSON_receive_params");
+            System.exit(1);
+        }
+        String brokerAddress = "amqp://" + args[0];
+        String queueName = args[1];
+        String jmsMessageType = args[2];
+        if (!isSupportedJmsMessageType(jmsMessageType)) {
+            System.out.println("ERROR: JmsReceiverShim: Unknown or unsupported JMS message type \"" + jmsMessageType + "\"");
+            System.exit(1);
+        }
+
+        JsonReader jsonReader = Json.createReader(new StringReader(args[3]));
+        JsonArray testParamsList = jsonReader.readArray();
+        jsonReader.close();
+
+        if (testParamsList.size() != 2) {
+            System.err.println("ERROR: Incorrect number of JSON parameters: Expected 2, got " + Integer.toString(testParamsList.size()));
+            System.exit(1);
+        }
+
+        JsonObject numTestValuesMap = testParamsList.getJsonObject(0);
+        JsonObject flagMap = testParamsList.getJsonObject(1);
+        
+        Receiver shim = new Receiver(brokerAddress, queueName);
+        shim.run(jmsMessageType, numTestValuesMap, flagMap);
+    }
+
+    public Receiver(String brokerAddress, String queueName) {
+        try {
+            _connection = null;
+            ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress);
+            _connection = factory.createConnection(USER, PASSWORD);
+            _connection.setExceptionListener(new MyExceptionListener());
+            _connection.start();
+
+            _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+            _queue = _session.createQueue(queueName);
+
+            _messageConsumer = _session.createConsumer(_queue);
+
+            _jsonTestValueMapBuilder = Json.createObjectBuilder();
+            _jsonMessageHeaderMapBuilder = Json.createObjectBuilder();
+            _jsonMessagePropertiesMapBuilder = Json.createObjectBuilder();
+        } catch (Exception exc) {
+            if (_connection != null)
+                try { _connection.close(); } catch (JMSException e) {}
+            System.out.println("Caught exception, exiting.");
+            exc.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+    
+    public void run(String jmsMessageType, JsonObject numTestValuesMap, JsonObject flagMap) {
+        try {
+            List<String> subTypeKeyList = new ArrayList<String>(numTestValuesMap.keySet());
+            Collections.sort(subTypeKeyList);
+            
+            Message message = null;
+            
+            for (String subType: subTypeKeyList) {
+                JsonArrayBuilder jasonTestValuesArrayBuilder = Json.createArrayBuilder();
+                for (int i=0; i<numTestValuesMap.getJsonNumber(subType).intValue(); ++i) {
+                    message = _messageConsumer.receive(TIMEOUT);
+                    if (message == null) break;
+                    switch (jmsMessageType) {
+                    case "JMS_MESSAGE_TYPE":
+                        processJMSMessage(jasonTestValuesArrayBuilder);
+                        break;
+                    case "JMS_BYTESMESSAGE_TYPE":
+                        processJMSBytesMessage(jmsMessageType, subType, message, jasonTestValuesArrayBuilder);
+                        break;
+                    case "JMS_STREAMMESSAGE_TYPE":
+                        processJMSStreamMessage(jmsMessageType, subType, message, jasonTestValuesArrayBuilder);
+                        break;
+                    case "JMS_MAPMESSAGE_TYPE":
+                        processJMSMapMessage(jmsMessageType, subType, i, message, jasonTestValuesArrayBuilder);
+                        break;
+                    case "JMS_OBJECTMESSAGE_TYPE":
+                        processJMSObjectMessage(subType, message, jasonTestValuesArrayBuilder);
+                        break;
+                    case "JMS_TEXTMESSAGE_TYPE":
+                        processJMSTextMessage(message, jasonTestValuesArrayBuilder);
+                        break;
+                    default:
+                        _connection.close();
+                        throw new Exception("JmsReceiverShim: Internal error: Unknown or unsupported JMS message type \"" + jmsMessageType + "\"");
+                    }
+                    
+                    processMessageHeaders(message, flagMap);
+                    processMessageProperties(message);
+                }
+                _jsonTestValueMapBuilder.add(subType, jasonTestValuesArrayBuilder);
+            }
+            _connection.close();
+    
+            System.out.println(jmsMessageType);
+            StringWriter out = new StringWriter();
+            JsonArrayBuilder returnList = Json.createArrayBuilder();
+            returnList.add(_jsonTestValueMapBuilder);
+            returnList.add(_jsonMessageHeaderMapBuilder);
+            returnList.add(_jsonMessagePropertiesMapBuilder);
+            writeJsonArray(returnList, out);
+            System.out.println(out.toString());        
+        } catch (Exception exp) {
+            try { _connection.close(); } catch (JMSException e) {}
+            System.out.println("Caught exception, exiting.");
+            exp.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+    
+    protected void processJMSMessage(JsonArrayBuilder jasonTestValuesArrayBuilder) {
+        jasonTestValuesArrayBuilder.addNull();        
+    }
+    
+    protected void processJMSBytesMessage(String jmsMessageType, String subType, Message message, JsonArrayBuilder jasonTestValuesArrayBuilder) throws Exception, JMSException, IOException, ClassNotFoundException {
+        switch (subType) {
+        case "boolean":
+            jasonTestValuesArrayBuilder.add(((BytesMessage)message).readBoolean()?"True":"False");
+            break;
+        case "byte":
+            jasonTestValuesArrayBuilder.add(formatByte(((BytesMessage)message).readByte()));
+            break;
+        case "bytes":
+            {
+                byte[] bytesBuff = new byte[65536];
+                int numBytesRead = ((BytesMessage)message).readBytes(bytesBuff);
+                if (numBytesRead >= 0) {
+                    jasonTestValuesArrayBuilder.add(new String(Arrays.copyOfRange(bytesBuff, 0, numBytesRead)));
+                } else {
+                    // NOTE: For this case, an empty byte array has nothing to return
+                    jasonTestValuesArrayBuilder.add(new String());
+                }
+            }
+            break;
+        case "char":
+            jasonTestValuesArrayBuilder.add(formatChar(((BytesMessage)message).readChar()));
+            break;
+        case "double":
+            long l = Double.doubleToRawLongBits(((BytesMessage)message).readDouble());
+            jasonTestValuesArrayBuilder.add(String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
+            break;
+        case "float":
+            int i0 = Float.floatToRawIntBits(((BytesMessage)message).readFloat());
+            jasonTestValuesArrayBuilder.add(String.format("0x%8s", Integer.toHexString(i0)).replace(' ', '0'));
+            break;
+        case "int":
+            jasonTestValuesArrayBuilder.add(formatInt(((BytesMessage)message).readInt()));
+            break;
+        case "long":
+            jasonTestValuesArrayBuilder.add(formatLong(((BytesMessage)message).readLong()));
+            break;
+        case "object":
+            {
+                byte[] bytesBuff = new byte[65536];
+                int numBytesRead = ((BytesMessage)message).readBytes(bytesBuff);
+                if (numBytesRead >= 0) {
+                    ByteArrayInputStream bais = new ByteArrayInputStream(Arrays.copyOfRange(bytesBuff, 0, numBytesRead));
+                    ObjectInputStream ois = new ObjectInputStream(bais);
+                    Object obj = ois.readObject();
+                    jasonTestValuesArrayBuilder.add(obj.getClass().getName() + ":" + obj.toString());
+                } else {
+                    jasonTestValuesArrayBuilder.add("<object error>");
+                }
+            }
+            break;
+        case "short":
+            jasonTestValuesArrayBuilder.add(formatShort(((BytesMessage)message).readShort()));
+            break;
+        case "string":
+            jasonTestValuesArrayBuilder.add(((BytesMessage)message).readUTF());
+            break;
+        default:
+            throw new Exception("JmsReceiverShim: Unknown subtype for " + jmsMessageType + ": \"" + subType + "\"");
+        }        
+    }
+    
+    protected void processJMSMapMessage(String jmsMessageType, String subType, int count, Message message, JsonArrayBuilder jasonTestValuesArrayBuilder) throws Exception, JMSException {
+        String name = String.format("%s%03d", subType, count);
+        switch (subType) {
+        case "boolean":
+            jasonTestValuesArrayBuilder.add(((MapMessage)message).getBoolean(name)?"True":"False");
+            break;
+        case "byte":
+            jasonTestValuesArrayBuilder.add(formatByte(((MapMessage)message).getByte(name)));
+            break;
+        case "bytes":
+            jasonTestValuesArrayBuilder.add(new String(((MapMessage)message).getBytes(name)));
+            break;
+        case "char":
+            jasonTestValuesArrayBuilder.add(formatChar(((MapMessage)message).getChar(name)));
+            break;
+        case "double":
+            long l = Double.doubleToRawLongBits(((MapMessage)message).getDouble(name));
+            jasonTestValuesArrayBuilder.add(String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
+            break;
+        case "float":
+            int i0 = Float.floatToRawIntBits(((MapMessage)message).getFloat(name));
+            jasonTestValuesArrayBuilder.add(String.format("0x%8s", Integer.toHexString(i0)).replace(' ', '0'));
+            break;
+        case "int":
+            jasonTestValuesArrayBuilder.add(formatInt(((MapMessage)message).getInt(name)));
+            break;
+        case "long":
+            jasonTestValuesArrayBuilder.add(formatLong(((MapMessage)message).getLong(name)));
+            break;
+        case "object":
+            Object obj = ((MapMessage)message).getObject(name);
+            jasonTestValuesArrayBuilder.add(obj.getClass().getName() + ":" + obj.toString());
+            break;
+        case "short":
+            jasonTestValuesArrayBuilder.add(formatShort(((MapMessage)message).getShort(name)));
+            break;
+        case "string":
+            jasonTestValuesArrayBuilder.add(((MapMessage)message).getString(name));
+            break;
+        default:
+            throw new Exception("JmsReceiverShim: Unknown subtype for " + jmsMessageType + ": \"" + subType + "\"");
+        }        
+    }
+    
+    protected void processJMSObjectMessage(String subType, Message message, JsonArrayBuilder jasonTestValuesArrayBuilder) throws JMSException {
+        jasonTestValuesArrayBuilder.add(((ObjectMessage)message).getObject().toString());
+    }
+    
+    protected void processJMSStreamMessage(String jmsMessageType, String subType, Message message, JsonArrayBuilder jasonTestValuesArrayBuilder) throws Exception, JMSException {
+        switch (subType) {
+        case "boolean":
+            jasonTestValuesArrayBuilder.add(((StreamMessage)message).readBoolean()?"True":"False");
+            break;
+        case "byte":
+            jasonTestValuesArrayBuilder.add(formatByte(((StreamMessage)message).readByte()));
+            break;
+        case "bytes":
+            byte[] bytesBuff = new byte[65536];
+            int numBytesRead = ((StreamMessage)message).readBytes(bytesBuff);
+            if (numBytesRead >= 0) {
+                jasonTestValuesArrayBuilder.add(new String(Arrays.copyOfRange(bytesBuff, 0, numBytesRead)));
+            } else {
+                System.out.println("StreamMessage.readBytes() returned " + numBytesRead);
+                jasonTestValuesArrayBuilder.add("<bytes error>");
+            }
+            break;
+        case "char":
+            jasonTestValuesArrayBuilder.add(formatChar(((StreamMessage)message).readChar()));
+            break;
+        case "double":
+            long l = Double.doubleToRawLongBits(((StreamMessage)message).readDouble());
+            jasonTestValuesArrayBuilder.add(String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
+            break;
+        case "float":
+            int i0 = Float.floatToRawIntBits(((StreamMessage)message).readFloat());
+            jasonTestValuesArrayBuilder.add(String.format("0x%8s", Integer.toHexString(i0)).replace(' ', '0'));
+            break;
+        case "int":
+            jasonTestValuesArrayBuilder.add(formatInt(((StreamMessage)message).readInt()));
+            break;
+        case "long":
+            jasonTestValuesArrayBuilder.add(formatLong(((StreamMessage)message).readLong()));
+            break;
+        case "object":
+            Object obj = ((StreamMessage)message).readObject();
+            jasonTestValuesArrayBuilder.add(obj.getClass().getName() + ":" + obj.toString());
+            break;
+        case "short":
+            jasonTestValuesArrayBuilder.add(formatShort(((StreamMessage)message).readShort()));
+            break;
+        case "string":
+            jasonTestValuesArrayBuilder.add(((StreamMessage)message).readString());
+            break;
+        default:
+            throw new Exception("JmsReceiverShim: Unknown subtype for " + jmsMessageType + ": \"" + subType + "\"");
+        }        
+    }
+
+    protected void processJMSTextMessage(Message message, JsonArrayBuilder jasonTestValuesArrayBuilder) throws JMSException {
+        jasonTestValuesArrayBuilder.add(((TextMessage)message).getText());
+    }
+
+    protected void processMessageHeaders(Message message, JsonObject flagMap) throws Exception, JMSException {
+        addMessageHeaderString("JMS_TYPE_HEADER", message.getJMSType());
+        if (flagMap.containsKey("JMS_CORRELATIONID_AS_BYTES") && flagMap.getBoolean("JMS_CORRELATIONID_AS_BYTES")) {
+            addMessageHeaderByteArray("JMS_CORRELATIONID_HEADER", message.getJMSCorrelationIDAsBytes());
+        } else {
+            addMessageHeaderString("JMS_CORRELATIONID_HEADER", message.getJMSCorrelationID());
+        }
+        if (flagMap.containsKey("JMS_REPLYTO_AS_TOPIC") && flagMap.getBoolean("JMS_REPLYTO_AS_TOPIC")) {
+            addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_DESTINATION_TYPE.JMS_TOPIC, message.getJMSReplyTo());
+        } else {
+            addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_DESTINATION_TYPE.JMS_QUEUE, message.getJMSReplyTo());
+        }
+    }
+
+    protected void addMessageHeaderString(String headerName, String value) {
+        if (value != null) {
+            JsonObjectBuilder valueMap = Json.createObjectBuilder();
+            valueMap.add("string", value);
+            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
+        }
+    }
+
+    protected void addMessageHeaderByteArray(String headerName, byte[] value) {
+        if (value != null) {
+            JsonObjectBuilder valueMap = Json.createObjectBuilder();
+            valueMap.add("bytes", new String(value));
+            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
+        }        
+    }
+
+    protected void addMessageHeaderDestination(String headerName, JMS_DESTINATION_TYPE destinationType, Destination destination) throws Exception {
+        if (destination != null) {
+            JsonObjectBuilder valueMap = Json.createObjectBuilder();
+            switch (destinationType) {
+            case JMS_QUEUE:
+                valueMap.add("queue", ((Queue)destination).getQueueName());
+                break;
+            case JMS_TOPIC:
+                valueMap.add("topic", ((Topic)destination).getTopicName());
+                break;
+            default:
+                throw new Exception("Internal error: JMSDestination type not supported");
+            }
+            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
+        }
+    }
+
+    protected void processMessageProperties(Message message) throws Exception, JMSException {
+        Enumeration<String> propertyNames = message.getPropertyNames(); 
+        while (propertyNames.hasMoreElements()) {
+            JsonObjectBuilder valueMap = Json.createObjectBuilder();
+            String propertyName = propertyNames.nextElement();
+            int underscoreIndex = propertyName.indexOf('_');
+            if (underscoreIndex >= 0) {
+                String propType = propertyName.substring(0, underscoreIndex);
+                switch (propType) {
+                case "boolean":
+                    valueMap.add(propType, message.getBooleanProperty(propertyName) ? "True" : "False");
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "byte":
+                    valueMap.add(propType, formatByte(message.getByteProperty(propertyName)));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "double":
+                    long l = Double.doubleToRawLongBits(message.getDoubleProperty(propertyName));
+                    valueMap.add(propType, String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "float":
+                    int i = Float.floatToRawIntBits(message.getFloatProperty(propertyName));
+                    valueMap.add(propType, String.format("0x%8s", Integer.toHexString(i)).replace(' ', '0'));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "int":
+                    valueMap.add(propType, formatInt(message.getIntProperty(propertyName)));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "long":
+                    valueMap.add(propType, formatLong(message.getLongProperty(propertyName)));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "short":
+                    valueMap.add(propType, formatShort(message.getShortProperty(propertyName)));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                case "string":
+                    valueMap.add(propType, message.getStringProperty(propertyName));
+                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
+                    break;
+                default:
+                    ; // Ignore any other property the broker may add
+                }
+            } else {
+                // TODO: handle other non-test properties that might exist here
+            }
+        }
+    }
+
+    protected static void writeJsonArray(JsonArrayBuilder builder, StringWriter out) {
+        JsonWriter jsonWriter = Json.createWriter(out);
+        jsonWriter.writeArray(builder.build());
+        jsonWriter.close();        
+    }
+
+    protected static String formatByte(byte b) {
+        boolean neg = false;
+        if (b < 0) {
+            neg = true;
+            b = (byte)-b;
+        }
+        return String.format("%s0x%x", neg?"-":"", b);
+    }
+    
+    protected static String formatChar(char c) {
+        if (Character.isLetterOrDigit(c)) {
+            return String.format("%c", c);
+        }
+        char[] ca = {c};
+        return new String(ca);
+    }
+    
+    protected static String formatInt(int i) {
+        boolean neg = false;
+        if (i < 0) {
+            neg = true;
+            i = -i;
+        }
+        return String.format("%s0x%x", neg?"-":"", i);
+    }
+    
+    protected static String formatLong(long l) {
+        boolean neg = false;
+        if (l < 0) {
+            neg = true;
+            l = -l;
+        }
+        return String.format("%s0x%x", neg?"-":"", l);
+    }
+    
+    protected static String formatShort(int s) {
+        boolean neg = false;
+        if (s < 0) {
+            neg = true;
+            s = -s;
+        }
+        return String.format("%s0x%x", neg?"-":"", s);
+    }
+        
+    protected static boolean isSupportedJmsMessageType(String jmsMessageType) {
+        for (String supportedJmsMessageType: SUPPORTED_JMS_MESSAGE_TYPES) {
+            if (jmsMessageType.equals(supportedJmsMessageType))
+                return true;
+        }
+    return false;
+    }
+
+    private static class MyExceptionListener implements ExceptionListener {
+        @Override
+        public void onException(JMSException exception) {
+            System.out.println("Connection ExceptionListener fired, exiting.");
+            exception.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Sender.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Sender.java b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Sender.java
new file mode 100644
index 0000000..2f38991
--- /dev/null
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_hdrs_props_test/Sender.java
@@ -0,0 +1,508 @@
+/**
+ * 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.
+ */
+package org.apache.qpid.interop_test.jms_hdrs_props_test;
+
+import java.io.Serializable;
+import java.io.StringReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.DeliveryMode;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.StreamMessage;
+import javax.jms.TextMessage;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+import org.apache.qpid.jms.JmsConnectionFactory;
+
+public class Sender {
+    private static final String USER = "guest";
+    private static final String PASSWORD = "guest";
+    private static final String[] SUPPORTED_JMS_MESSAGE_TYPES = {"JMS_MESSAGE_TYPE",
+                                                                 "JMS_BYTESMESSAGE_TYPE",
+                                                                 "JMS_MAPMESSAGE_TYPE",
+                                                                 "JMS_OBJECTMESSAGE_TYPE",
+                                                                 "JMS_STREAMMESSAGE_TYPE",
+                                                                 "JMS_TEXTMESSAGE_TYPE"};
+    Connection _connection;
+    Session _session;
+    Queue _queue;
+    MessageProducer _messageProducer;
+    int _msgsSent;
+    
+
+    // args[0]: Broker URL
+    // args[1]: Queue name
+    // args[2]: JMS message type
+    // args[3]: JSON Test parameters containing 3 maps: [testValueMap, testHeadersMap, testPropertiesMap]
+    public static void main(String[] args) throws Exception {
+        if (args.length != 4) {
+            System.out.println("JmsSenderShim: Incorrect number of arguments");
+            System.out.println("JmsSenderShim: Expected arguments: broker_address, queue_name, JMS_msg_type, JSON_send_params");
+            System.exit(1);
+        }
+        String brokerAddress = "amqp://" + args[0];
+        String queueName = args[1];
+        String jmsMessageType = args[2];
+        if (!isSupportedJmsMessageType(jmsMessageType)) {
+            System.err.println("ERROR: JmsSender: Unknown or unsupported JMS message type \"" + jmsMessageType + "\"");
+            System.exit(1);
+        }
+
+        JsonReader jsonReader = Json.createReader(new StringReader(args[3]));
+        JsonArray testParamsList = jsonReader.readArray();
+        jsonReader.close();
+
+        if (testParamsList.size() != 3) {
+            System.err.println("ERROR: Incorrect number of JSON parameters: Expected 3, got " + Integer.toString(testParamsList.size()));
+            System.err.println("  JSON parameters found: \"" + testParamsList + "\"");
+            System.exit(1);
+        }
+        JsonObject testValuesMap = testParamsList.getJsonObject(0);
+        JsonObject testHeadersMap = testParamsList.getJsonObject(1);
+        JsonObject testPropertiesMap = testParamsList.getJsonObject(2);
+
+        Sender shim = new Sender(brokerAddress, queueName);
+        shim.runTests(jmsMessageType, testValuesMap, testHeadersMap, testPropertiesMap);
+    }
+
+    public Sender(String brokerAddress, String queueName) {
+        try {
+            ConnectionFactory factory = (ConnectionFactory)new JmsConnectionFactory(brokerAddress);
+
+            _connection = factory.createConnection();
+            _connection.setExceptionListener(new MyExceptionListener());
+            _connection.start();
+
+            _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+            _queue = _session.createQueue(queueName);
+
+            _messageProducer = _session.createProducer(_queue);
+            
+            _msgsSent = 0;
+        } catch (Exception exp) {
+            System.out.println("Caught exception, exiting.");
+            exp.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+
+    public void runTests(String jmsMessageType, JsonObject testValuesMap, JsonObject testHeadersMap, JsonObject testPropertiesMap) throws Exception {
+        List<String> testValuesKeyList = new ArrayList<String>(testValuesMap.keySet());
+        Collections.sort(testValuesKeyList);
+        for (String key: testValuesKeyList) {
+            JsonArray testValues = testValuesMap.getJsonArray(key);
+            for (int i=0; i<testValues.size(); ++i) {
+                String testValue = "";
+                if (!testValues.isNull(i)) {
+                    testValue = testValues.getJsonString(i).getString();
+                }
+                
+                // Send message
+                Message msg = createMessage(jmsMessageType, key, testValue, i);
+                addMessageHeaders(msg, testHeadersMap);
+                addMessageProperties(msg, testPropertiesMap);
+                _messageProducer.send(msg, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
+                _msgsSent++;
+            }
+        }
+        _connection.close();
+    }
+    
+    protected Message createMessage(String jmsMessageType, String key, String testValue, int i) throws Exception {
+        Message message = null;
+        switch (jmsMessageType) {
+        case "JMS_MESSAGE_TYPE":
+            message = createJMSMessage(key, testValue);
+            break;
+        case "JMS_BYTESMESSAGE_TYPE":
+            message = createJMSBytesMessage(key, testValue);
+            break;
+        case "JMS_MAPMESSAGE_TYPE":
+            message = createJMSMapMessage(key, testValue, i);
+            break;
+        case "JMS_OBJECTMESSAGE_TYPE":
+            message = createJMSObjectMessage(key, testValue);
+            break;
+        case "JMS_STREAMMESSAGE_TYPE":
+            message = createJMSStreamMessage(key, testValue);
+            break;
+        case "JMS_TEXTMESSAGE_TYPE":
+            message = createTextMessage(testValue);
+            break;
+        default:
+            throw new Exception("Internal exception: Unexpected JMS message type \"" + jmsMessageType + "\"");
+        }
+        return message;
+    }
+
+
+    protected void addMessageHeaders(Message msg, JsonObject testHeadersMap) throws Exception, JMSException {
+        List<String> testHeadersKeyList = new ArrayList<String>(testHeadersMap.keySet());
+        for (String key: testHeadersKeyList) {
+            JsonObject subMap = testHeadersMap.getJsonObject(key);
+            List<String> subMapKeyList = new ArrayList<String>(subMap.keySet());
+            String subMapKey = subMapKeyList.get(0); // There is always only one entry in map
+            String subMapVal = subMap.getString(subMapKey);
+            switch (key) {
+            case "JMS_TYPE_HEADER":
+                if (subMapKey.compareTo("string") == 0) {
+                    msg.setJMSType(subMapVal);
+                } else {
+                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
+                }
+                break;
+            case "JMS_CORRELATIONID_HEADER":
+                if (subMapKey.compareTo("string") == 0) {
+                    msg.setJMSCorrelationID(subMapVal);
+                } else if (subMapKey.compareTo("bytes") == 0) {
+                    msg.setJMSCorrelationIDAsBytes(subMapVal.getBytes());
+                } else {
+                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
+                }
+                break;
+            case "JMS_REPLYTO_HEADER":
+                switch (subMapKey) {
+                case "queue":
+                    msg.setJMSReplyTo(_session.createQueue(subMapVal));
+                    break;
+                case "temp_queue":
+                    msg.setJMSReplyTo(_session.createTemporaryQueue());
+                    break;
+                case "topic":
+                    msg.setJMSReplyTo(_session.createTopic(subMapVal));
+                    break;
+                case "temp_topic":
+                    msg.setJMSReplyTo(_session.createTemporaryTopic());
+                    break;
+                default:
+                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
+                }
+                break;
+            default:
+                throw new Exception("Internal exception: Unknown or unsupported message header \"" + key + "\"");
+            }
+        }
+    }
+
+    protected void addMessageProperties(Message msg, JsonObject testPropertiesMap) throws Exception, JMSException {
+        List<String> testPropertiesKeyList = new ArrayList<String>(testPropertiesMap.keySet());
+        for (String key: testPropertiesKeyList) {
+            JsonObject subMap = testPropertiesMap.getJsonObject(key);
+            List<String> subMapKeyList = new ArrayList<String>(subMap.keySet());
+            String subMapKey = subMapKeyList.get(0); // There is always only one entry in map
+            String subMapVal = subMap.getString(subMapKey);
+            switch (subMapKey) {
+            case "boolean":
+                msg.setBooleanProperty(key, Boolean.parseBoolean(subMapVal));
+                break;
+            case "byte":
+                msg.setByteProperty(key, Byte.decode(subMapVal));
+                break;
+            case "double":
+                Long l1 = Long.parseLong(subMapVal.substring(2, 3), 16) << 60;
+                Long l2 = Long.parseLong(subMapVal.substring(3), 16);
+                msg.setDoubleProperty(key, Double.longBitsToDouble(l1 | l2));
+                break;
+            case "float":
+                Long i = Long.parseLong(subMapVal.substring(2), 16);
+                msg.setFloatProperty(key, Float.intBitsToFloat(i.intValue()));
+                break;
+            case "int":
+                msg.setIntProperty(key, Integer.decode(subMapVal));
+                break;
+            case "long":
+                msg.setLongProperty(key, Long.decode(subMapVal));
+                break;
+            case "short":
+                msg.setShortProperty(key, Short.decode(subMapVal));
+                break;
+            case "string":
+                msg.setStringProperty(key, subMapVal);
+                break;
+            default:
+                throw new Exception("Internal exception: Unknown or unsupported message property type \"" + subMapKey + "\"");
+            }
+        }
+    }
+
+    protected Message createJMSMessage(String testValueType, String testValue) throws Exception, JMSException {
+        if (testValueType.compareTo("none") != 0) {
+            throw new Exception("Internal exception: Unexpected JMS message sub-type \"" + testValueType + "\"");
+        }
+        if (testValue.length() > 0) {
+            throw new Exception("Internal exception: Unexpected JMS message value \"" + testValue + "\" for sub-type \"" + testValueType + "\"");
+        }
+        return _session.createMessage();
+    }
+
+    protected BytesMessage createJMSBytesMessage(String testValueType, String testValue) throws Exception, JMSException {
+        BytesMessage message = _session.createBytesMessage();
+        switch (testValueType) {
+        case "boolean":
+            message.writeBoolean(Boolean.parseBoolean(testValue));
+            break;
+        case "byte":
+            message.writeByte(Byte.decode(testValue));
+            break;
+        case "bytes":
+            message.writeBytes(testValue.getBytes());
+            break;
+        case "char":
+            if (testValue.length() == 1) { // Char format: "X" or "\xNN"
+                message.writeChar(testValue.charAt(0));
+            } else {
+                throw new Exception("JmsSenderShim.createJMSBytesMessage() Malformed char string: \"" + testValue + "\" of length " + testValue.length());
+            }
+            break;
+        case "double":
+            Long l1 = Long.parseLong(testValue.substring(2, 3), 16) << 60;
+            Long l2 = Long.parseLong(testValue.substring(3), 16);
+            message.writeDouble(Double.longBitsToDouble(l1 | l2));
+            break;
+        case "float":
+            Long i = Long.parseLong(testValue.substring(2), 16);
+            message.writeFloat(Float.intBitsToFloat(i.intValue()));
+            break;
+        case "int":
+            message.writeInt(Integer.decode(testValue));
+            break;
+        case "long":
+            message.writeLong(Long.decode(testValue));
+            break;
+        case "object":
+            Object obj = (Object)createObject(testValue);
+            message.writeObject(obj);
+            break;
+        case "short":
+            message.writeShort(Short.decode(testValue));
+            break;
+        case "string":
+            message.writeUTF(testValue);
+            break;
+        default:
+            throw new Exception("Internal exception: Unexpected JMS message sub-type \"" + testValueType + "\"");
+        }
+        return message;
+    }
+    
+    protected MapMessage createJMSMapMessage(String testValueType, String testValue, int testValueNum) throws Exception, JMSException {
+        MapMessage message = _session.createMapMessage();
+        String name = String.format("%s%03d", testValueType, testValueNum);
+        switch (testValueType) {
+        case "boolean":
+            message.setBoolean(name, Boolean.parseBoolean(testValue));
+            break;
+        case "byte":
+            message.setByte(name, Byte.decode(testValue));
+            break;
+        case "bytes":
+            message.setBytes(name, testValue.getBytes());
+            break;
+        case "char":
+            if (testValue.length() == 1) { // Char format: "X"
+                message.setChar(name, testValue.charAt(0));
+            } else if (testValue.length() == 6) { // Char format: "\xNNNN"
+                message.setChar(name, (char)Integer.parseInt(testValue.substring(2), 16));
+            } else {
+                throw new Exception("JmsSenderShim.createJMSMapMessage() Malformed char string: \"" + testValue + "\"");
+            }
+            break;
+        case "double":
+            Long l1 = Long.parseLong(testValue.substring(2, 3), 16) << 60;
+            Long l2 = Long.parseLong(testValue.substring(3), 16);
+            message.setDouble(name, Double.longBitsToDouble(l1 | l2));
+            break;
+        case "float":
+            Long i = Long.parseLong(testValue.substring(2), 16);
+            message.setFloat(name, Float.intBitsToFloat(i.intValue()));
+            break;
+        case "int":
+            message.setInt(name, Integer.decode(testValue));
+            break;
+        case "long":
+            message.setLong(name, Long.decode(testValue));
+            break;
+        case "object":
+            Object obj = (Object)createObject(testValue);
+            message.setObject(name, obj);
+            break;
+        case "short":
+            message.setShort(name, Short.decode(testValue));
+            break;
+        case "string":
+            message.setString(name, testValue);
+            break;
+        default:
+            throw new Exception("Internal exception: Unexpected JMS message sub-type \"" + testValueType + "\"");
+        }
+        return message;
+    }
+    
+    protected ObjectMessage createJMSObjectMessage(String className, String testValue) throws Exception, JMSException {
+        Serializable obj = createJavaObject(className, testValue);
+        if (obj == null) {
+            // TODO: Handle error here
+            System.out.println("JmsSenderShim.createJMSObjectMessage: obj == null");
+            return null;
+        }
+        ObjectMessage message = _session.createObjectMessage();
+        message.setObject(obj);
+        return message;
+    }
+    
+    protected StreamMessage createJMSStreamMessage(String testValueType, String testValue) throws Exception, JMSException {
+        StreamMessage message = _session.createStreamMessage();
+        switch (testValueType) {
+        case "boolean":
+            message.writeBoolean(Boolean.parseBoolean(testValue));
+            break;
+        case "byte":
+            message.writeByte(Byte.decode(testValue));
+            break;
+        case "bytes":
+            message.writeBytes(testValue.getBytes());
+            break;
+        case "char":
+            if (testValue.length() == 1) { // Char format: "X"
+                message.writeChar(testValue.charAt(0));
+            } else if (testValue.length() == 6) { // Char format: "\xNNNN"
+                message.writeChar((char)Integer.parseInt(testValue.substring(2), 16));
+            } else {
+                throw new Exception("JmsSenderShim.createJMSStreamMessage() Malformed char string: \"" + testValue + "\"");
+            }
+            break;
+        case "double":
+            Long l1 = Long.parseLong(testValue.substring(2, 3), 16) << 60;
+            Long l2 = Long.parseLong(testValue.substring(3), 16);
+            message.writeDouble(Double.longBitsToDouble(l1 | l2));
+            break;
+        case "float":
+            Long i = Long.parseLong(testValue.substring(2), 16);
+            message.writeFloat(Float.intBitsToFloat(i.intValue()));
+            break;
+        case "int":
+            message.writeInt(Integer.decode(testValue));
+            break;
+        case "long":
+            message.writeLong(Long.decode(testValue));
+            break;
+        case "object":
+            Object obj = (Object)createObject(testValue);
+            message.writeObject(obj);
+            break;
+        case "short":
+            message.writeShort(Short.decode(testValue));
+            break;
+        case "string":
+            message.writeString(testValue);
+            break;
+        default:
+            throw new Exception("JmsSenderShim.createJMSStreamMessage(): Unexpected JMS message sub-type \"" + testValueType + "\"");
+        }
+        return message;
+    }
+
+    protected static Serializable createJavaObject(String className, String testValue) throws Exception {
+        Serializable obj = null;
+        try {
+            Class<?> c = Class.forName(className);
+            if (className.compareTo("java.lang.Character") == 0) {
+                Constructor ctor = c.getConstructor(char.class);
+                if (testValue.length() == 1) {
+                    // Use first character of string
+                    obj = (Serializable)ctor.newInstance(testValue.charAt(0));
+                } else if (testValue.length() == 4 || testValue.length() == 6) {
+                    // Format '\xNN' or '\xNNNN'
+                    obj = (Serializable)ctor.newInstance((char)Integer.parseInt(testValue.substring(2), 16));
+                } else {
+                    throw new Exception("JmsSenderShim.createJavaObject(): Malformed char string: \"" + testValue + "\"");
+                }
+            } else {
+                // Use string constructor
+                Constructor ctor = c.getConstructor(String.class);
+                obj = (Serializable)ctor.newInstance(testValue);
+            }
+        }
+        catch (ClassNotFoundException e) {
+            e.printStackTrace(System.out);
+        }
+        catch (NoSuchMethodException e) {
+            e.printStackTrace(System.out);
+        }
+        catch (InstantiationException e) {
+            e.printStackTrace(System.out);
+        }
+        catch (IllegalAccessException e) {
+            e.printStackTrace(System.out);
+        }
+        catch (InvocationTargetException e) {
+            e.printStackTrace(System.out);
+        }
+        return obj;
+    }
+    
+    // value has format "classname:ctorstrvalue"
+    protected static Serializable createObject(String value) throws Exception {
+        Serializable obj = null;
+        int colonIndex = value.indexOf(":");
+        if (colonIndex >= 0) {
+            String className = value.substring(0, colonIndex);
+            String testValue = value.substring(colonIndex+1);
+            obj = createJavaObject(className, testValue);
+        } else {
+            throw new Exception("createObject(): Malformed value string");
+        }
+        return obj;
+    }
+    
+    protected TextMessage createTextMessage(String valueStr) throws JMSException {
+        return _session.createTextMessage(valueStr);
+    }
+    
+    protected static boolean isSupportedJmsMessageType(String jmsMessageType) {
+        for (String supportedJmsMessageType: SUPPORTED_JMS_MESSAGE_TYPES) {
+            if (jmsMessageType.equals(supportedJmsMessageType))
+                return true;
+        }
+        return false;
+    }
+
+    private static class MyExceptionListener implements ExceptionListener {
+        @Override
+        public void onException(JMSException exception) {
+            System.out.println("Connection ExceptionListener fired, exiting.");
+            exception.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Receiver.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Receiver.java b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Receiver.java
index 29e8ddc..46b6baf 100644
--- a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Receiver.java
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Receiver.java
@@ -67,13 +67,11 @@ public class Receiver {
     Queue _queue;
     MessageConsumer _messageConsumer;
     JsonObjectBuilder _jsonTestValueMapBuilder;
-    JsonObjectBuilder _jsonMessageHeaderMapBuilder;
-    JsonObjectBuilder _jsonMessagePropertiesMapBuilder;
     
     // args[0]: Broker URL
     // args[1]: Queue name
     // args[2]: JMS message type
-    // args[3]: JSON Test parameters containing 2 maps: [testValuesMap, flagMap]
+    // args[3]: JSON Test parameters containing testValuesMap
     public static void main(String[] args) throws Exception {
         if (args.length != 4) {
             System.out.println("JmsReceiverShim: Incorrect number of arguments");
@@ -89,19 +87,11 @@ public class Receiver {
         }
 
         JsonReader jsonReader = Json.createReader(new StringReader(args[3]));
-        JsonArray testParamsList = jsonReader.readArray();
+        JsonObject numTestValuesMap = jsonReader.readObject();
         jsonReader.close();
-
-        if (testParamsList.size() != 2) {
-            System.err.println("ERROR: Incorrect number of JSON parameters: Expected 2, got " + Integer.toString(testParamsList.size()));
-            System.exit(1);
-        }
-
-        JsonObject numTestValuesMap = testParamsList.getJsonObject(0);
-        JsonObject flagMap = testParamsList.getJsonObject(1);
         
         Receiver shim = new Receiver(brokerAddress, queueName);
-        shim.run(jmsMessageType, numTestValuesMap, flagMap);
+        shim.run(jmsMessageType, numTestValuesMap);
     }
 
     public Receiver(String brokerAddress, String queueName) {
@@ -119,8 +109,6 @@ public class Receiver {
             _messageConsumer = _session.createConsumer(_queue);
 
             _jsonTestValueMapBuilder = Json.createObjectBuilder();
-            _jsonMessageHeaderMapBuilder = Json.createObjectBuilder();
-            _jsonMessagePropertiesMapBuilder = Json.createObjectBuilder();
         } catch (Exception exc) {
             if (_connection != null)
                 try { _connection.close(); } catch (JMSException e) {}
@@ -130,7 +118,7 @@ public class Receiver {
         }
     }
     
-    public void run(String jmsMessageType, JsonObject numTestValuesMap, JsonObject flagMap) {
+    public void run(String jmsMessageType, JsonObject numTestValuesMap) {
         try {
             List<String> subTypeKeyList = new ArrayList<String>(numTestValuesMap.keySet());
             Collections.sort(subTypeKeyList);
@@ -165,9 +153,6 @@ public class Receiver {
                         _connection.close();
                         throw new Exception("JmsReceiverShim: Internal error: Unknown or unsupported JMS message type \"" + jmsMessageType + "\"");
                     }
-                    
-                    processMessageHeaders(message, flagMap);
-                    processMessageProperties(message);
                 }
                 _jsonTestValueMapBuilder.add(subType, jasonTestValuesArrayBuilder);
             }
@@ -176,10 +161,6 @@ public class Receiver {
             System.out.println(jmsMessageType);
             StringWriter out = new StringWriter();
             writeJsonObject(_jsonTestValueMapBuilder, out);
-            out.append('\n');
-            writeJsonObject(_jsonMessageHeaderMapBuilder, out);
-            out.append('\n');
-            writeJsonObject(_jsonMessagePropertiesMapBuilder, out);
             System.out.println(out.toString());        
         } catch (Exception exp) {
             try { _connection.close(); } catch (JMSException e) {}
@@ -357,105 +338,6 @@ public class Receiver {
         jasonTestValuesArrayBuilder.add(((TextMessage)message).getText());
     }
 
-    protected void processMessageHeaders(Message message, JsonObject flagMap) throws Exception, JMSException {
-        addMessageHeaderString("JMS_TYPE_HEADER", message.getJMSType());
-        if (flagMap.containsKey("JMS_CORRELATIONID_AS_BYTES") && flagMap.getBoolean("JMS_CORRELATIONID_AS_BYTES")) {
-            addMessageHeaderByteArray("JMS_CORRELATIONID_HEADER", message.getJMSCorrelationIDAsBytes());
-        } else {
-            addMessageHeaderString("JMS_CORRELATIONID_HEADER", message.getJMSCorrelationID());
-        }
-        if (flagMap.containsKey("JMS_REPLYTO_AS_TOPIC") && flagMap.getBoolean("JMS_REPLYTO_AS_TOPIC")) {
-            addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_DESTINATION_TYPE.JMS_TOPIC, message.getJMSReplyTo());
-        } else {
-            addMessageHeaderDestination("JMS_REPLYTO_HEADER", JMS_DESTINATION_TYPE.JMS_QUEUE, message.getJMSReplyTo());
-        }
-    }
-
-    protected void addMessageHeaderString(String headerName, String value) {
-        if (value != null) {
-            JsonObjectBuilder valueMap = Json.createObjectBuilder();
-            valueMap.add("string", value);
-            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
-        }
-    }
-
-    protected void addMessageHeaderByteArray(String headerName, byte[] value) {
-        if (value != null) {
-            JsonObjectBuilder valueMap = Json.createObjectBuilder();
-            valueMap.add("bytes", new String(value));
-            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
-        }        
-    }
-
-    protected void addMessageHeaderDestination(String headerName, JMS_DESTINATION_TYPE destinationType, Destination destination) throws Exception {
-        if (destination != null) {
-            JsonObjectBuilder valueMap = Json.createObjectBuilder();
-            switch (destinationType) {
-            case JMS_QUEUE:
-                valueMap.add("queue", ((Queue)destination).getQueueName());
-                break;
-            case JMS_TOPIC:
-                valueMap.add("topic", ((Topic)destination).getTopicName());
-                break;
-            default:
-                throw new Exception("Internal error: JMSDestination type not supported");
-            }
-            _jsonMessageHeaderMapBuilder.add(headerName, valueMap);
-        }
-    }
-
-    protected void processMessageProperties(Message message) throws Exception, JMSException {
-        Enumeration<String> propertyNames = message.getPropertyNames(); 
-        while (propertyNames.hasMoreElements()) {
-            JsonObjectBuilder valueMap = Json.createObjectBuilder();
-            String propertyName = propertyNames.nextElement();
-            int underscoreIndex = propertyName.indexOf('_');
-            if (underscoreIndex >= 0) {
-                String propType = propertyName.substring(0, underscoreIndex);
-                switch (propType) {
-                case "boolean":
-                    valueMap.add(propType, message.getBooleanProperty(propertyName) ? "True" : "False");
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "byte":
-                    valueMap.add(propType, formatByte(message.getByteProperty(propertyName)));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "double":
-                    long l = Double.doubleToRawLongBits(message.getDoubleProperty(propertyName));
-                    valueMap.add(propType, String.format("0x%16s", Long.toHexString(l)).replace(' ', '0'));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "float":
-                    int i = Float.floatToRawIntBits(message.getFloatProperty(propertyName));
-                    valueMap.add(propType, String.format("0x%8s", Integer.toHexString(i)).replace(' ', '0'));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "int":
-                    valueMap.add(propType, formatInt(message.getIntProperty(propertyName)));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "long":
-                    valueMap.add(propType, formatLong(message.getLongProperty(propertyName)));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "short":
-                    valueMap.add(propType, formatShort(message.getShortProperty(propertyName)));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                case "string":
-                    valueMap.add(propType, message.getStringProperty(propertyName));
-                    _jsonMessagePropertiesMapBuilder.add(propertyName, valueMap);
-                    break;
-                default:
-                    ; // Ignore any other property the broker may add
-                }
-            } else {
-                // TODO: handle other non-test properties that might exist here
-            }
-        }
-    }
-
     protected static void writeJsonObject(JsonObjectBuilder builder, StringWriter out) {
         JsonWriter jsonWriter = Json.createWriter(out);
         jsonWriter.writeObject(builder.build());

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Sender.java
----------------------------------------------------------------------
diff --git a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Sender.java b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Sender.java
index 0a0539c..0cccc97 100644
--- a/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Sender.java
+++ b/shims/qpid-jms/src/main/java/org/apache/qpid/qpid_interop_test/jms_messages_test/Sender.java
@@ -62,7 +62,7 @@ public class Sender {
     // args[0]: Broker URL
     // args[1]: Queue name
     // args[2]: JMS message type
-    // args[3]: JSON Test parameters containing 3 maps: [testValueMap, testHeadersMap, testPropertiesMap]
+    // args[3]: JSON Test parameters containing testValueMap
     public static void main(String[] args) throws Exception {
         if (args.length != 4) {
             System.out.println("JmsSenderShim: Incorrect number of arguments");
@@ -78,20 +78,11 @@ public class Sender {
         }
 
         JsonReader jsonReader = Json.createReader(new StringReader(args[3]));
-        JsonArray testParamsList = jsonReader.readArray();
+        JsonObject testValuesMap = jsonReader.readObject();
         jsonReader.close();
 
-        if (testParamsList.size() != 3) {
-            System.err.println("ERROR: Incorrect number of JSON parameters: Expected 3, got " + Integer.toString(testParamsList.size()));
-            System.err.println("  JSON parameters found: \"" + testParamsList + "\"");
-            System.exit(1);
-        }
-        JsonObject testValuesMap = testParamsList.getJsonObject(0);
-        JsonObject testHeadersMap = testParamsList.getJsonObject(1);
-        JsonObject testPropertiesMap = testParamsList.getJsonObject(2);
-
         Sender shim = new Sender(brokerAddress, queueName);
-        shim.runTests(jmsMessageType, testValuesMap, testHeadersMap, testPropertiesMap);
+        shim.runTests(jmsMessageType, testValuesMap);
     }
 
     public Sender(String brokerAddress, String queueName) {
@@ -116,7 +107,7 @@ public class Sender {
         }
     }
 
-    public void runTests(String jmsMessageType, JsonObject testValuesMap, JsonObject testHeadersMap, JsonObject testPropertiesMap) throws Exception {
+    public void runTests(String jmsMessageType, JsonObject testValuesMap) throws Exception {
         List<String> testValuesKeyList = new ArrayList<String>(testValuesMap.keySet());
         Collections.sort(testValuesKeyList);
         for (String key: testValuesKeyList) {
@@ -129,8 +120,6 @@ public class Sender {
                 
                 // Send message
                 Message msg = createMessage(jmsMessageType, key, testValue, i);
-                addMessageHeaders(msg, testHeadersMap);
-                addMessageProperties(msg, testPropertiesMap);
                 _messageProducer.send(msg, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
                 _msgsSent++;
             }
@@ -165,96 +154,6 @@ public class Sender {
         return message;
     }
 
-
-    protected void addMessageHeaders(Message msg, JsonObject testHeadersMap) throws Exception, JMSException {
-        List<String> testHeadersKeyList = new ArrayList<String>(testHeadersMap.keySet());
-        for (String key: testHeadersKeyList) {
-            JsonObject subMap = testHeadersMap.getJsonObject(key);
-            List<String> subMapKeyList = new ArrayList<String>(subMap.keySet());
-            String subMapKey = subMapKeyList.get(0); // There is always only one entry in map
-            String subMapVal = subMap.getString(subMapKey);
-            switch (key) {
-            case "JMS_TYPE_HEADER":
-                if (subMapKey.compareTo("string") == 0) {
-                    msg.setJMSType(subMapVal);
-                } else {
-                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
-                }
-                break;
-            case "JMS_CORRELATIONID_HEADER":
-                if (subMapKey.compareTo("string") == 0) {
-                    msg.setJMSCorrelationID(subMapVal);
-                } else if (subMapKey.compareTo("bytes") == 0) {
-                    msg.setJMSCorrelationIDAsBytes(subMapVal.getBytes());
-                } else {
-                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
-                }
-                break;
-            case "JMS_REPLYTO_HEADER":
-                switch (subMapKey) {
-                case "queue":
-                    msg.setJMSReplyTo(_session.createQueue(subMapVal));
-                    break;
-                case "temp_queue":
-                    msg.setJMSReplyTo(_session.createTemporaryQueue());
-                    break;
-                case "topic":
-                    msg.setJMSReplyTo(_session.createTopic(subMapVal));
-                    break;
-                case "temp_topic":
-                    msg.setJMSReplyTo(_session.createTemporaryTopic());
-                    break;
-                default:
-                    throw new Exception("Internal exception: Invalid message header type \"" + subMapKey + "\" for message header \"" + key + "\"");
-                }
-                break;
-            default:
-                throw new Exception("Internal exception: Unknown or unsupported message header \"" + key + "\"");
-            }
-        }
-    }
-
-    protected void addMessageProperties(Message msg, JsonObject testPropertiesMap) throws Exception, JMSException {
-        List<String> testPropertiesKeyList = new ArrayList<String>(testPropertiesMap.keySet());
-        for (String key: testPropertiesKeyList) {
-            JsonObject subMap = testPropertiesMap.getJsonObject(key);
-            List<String> subMapKeyList = new ArrayList<String>(subMap.keySet());
-            String subMapKey = subMapKeyList.get(0); // There is always only one entry in map
-            String subMapVal = subMap.getString(subMapKey);
-            switch (subMapKey) {
-            case "boolean":
-                msg.setBooleanProperty(key, Boolean.parseBoolean(subMapVal));
-                break;
-            case "byte":
-                msg.setByteProperty(key, Byte.decode(subMapVal));
-                break;
-            case "double":
-                Long l1 = Long.parseLong(subMapVal.substring(2, 3), 16) << 60;
-                Long l2 = Long.parseLong(subMapVal.substring(3), 16);
-                msg.setDoubleProperty(key, Double.longBitsToDouble(l1 | l2));
-                break;
-            case "float":
-                Long i = Long.parseLong(subMapVal.substring(2), 16);
-                msg.setFloatProperty(key, Float.intBitsToFloat(i.intValue()));
-                break;
-            case "int":
-                msg.setIntProperty(key, Integer.decode(subMapVal));
-                break;
-            case "long":
-                msg.setLongProperty(key, Long.decode(subMapVal));
-                break;
-            case "short":
-                msg.setShortProperty(key, Short.decode(subMapVal));
-                break;
-            case "string":
-                msg.setStringProperty(key, subMapVal);
-                break;
-            default:
-                throw new Exception("Internal exception: Unknown or unsupported message property type \"" + subMapKey + "\"");
-            }
-        }
-    }
-
     protected Message createJMSMessage(String testValueType, String testValue) throws Exception, JMSException {
         if (testValueType.compareTo("none") != 0) {
             throw new Exception("Internal exception: Unexpected JMS message sub-type \"" + testValueType + "\"");

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/CMakeLists.txt b/shims/qpid-proton-cpp/src/CMakeLists.txt
index 4f58163..f6b11a0 100644
--- a/shims/qpid-proton-cpp/src/CMakeLists.txt
+++ b/shims/qpid-proton-cpp/src/CMakeLists.txt
@@ -31,6 +31,11 @@ set(Common_SOURCES
     qpidit/QpidItErrors.cpp
 )
 
+set(Common_Jms_SOURCES
+    qpidit/JmsTestBase.hpp
+    qpidit/JmsTestBase.cpp
+)
+
 set(Common_LIBS
     qpid-proton-cpp
     jsoncpp
@@ -72,6 +77,43 @@ set_target_properties(amqp_types_test_Receiver PROPERTIES
 )
 
 
+# ---------------------------
+# --- jms_hdrs_props_test ---
+# ---------------------------
+
+# --- Sender ---
+
+set(jms_hdrs_props_test_Sender_SOURCES
+    ${Common_SOURCES}
+    ${Common_Jms_SOURCES}
+    qpidit/jms_hdrs_props_test/Sender.hpp
+    qpidit/jms_hdrs_props_test/Sender.cpp
+)
+
+add_executable(jms_hdrs_props_test_Sender ${jms_hdrs_props_test_Sender_SOURCES})
+target_link_libraries(jms_hdrs_props_test_Sender ${Common_LIBS})
+set_target_properties(jms_hdrs_props_test_Sender PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/jms_hdrs_props_test"
+    OUTPUT_NAME Sender
+)
+
+# --- Receiver ---
+
+set(jms_hdrs_props_test_Receiver_SOURCES
+    ${Common_SOURCES}
+    ${Common_Jms_SOURCES}
+    qpidit/jms_hdrs_props_test/Receiver.hpp
+    qpidit/jms_hdrs_props_test/Receiver.cpp
+)
+
+add_executable(jms_hdrs_props_test_Receiver ${jms_hdrs_props_test_Receiver_SOURCES})
+target_link_libraries(jms_hdrs_props_test_Receiver ${Common_LIBS})
+set_target_properties(jms_hdrs_props_test_Receiver PROPERTIES
+    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/jms_hdrs_props_test"
+    OUTPUT_NAME Receiver
+)
+
+
 # -------------------------
 # --- jms_messages_test ---
 # -------------------------
@@ -80,6 +122,7 @@ set_target_properties(amqp_types_test_Receiver PROPERTIES
 
 set(jms_messages_test_Sender_SOURCES
     ${Common_SOURCES}
+    ${Common_Jms_SOURCES}
     qpidit/jms_messages_test/Sender.hpp
     qpidit/jms_messages_test/Sender.cpp
 )
@@ -95,6 +138,7 @@ set_target_properties(jms_messages_test_Sender PROPERTIES
 
 set(jms_messages_test_Receiver_SOURCES
     ${Common_SOURCES}
+    ${Common_Jms_SOURCES}
     qpidit/jms_messages_test/Receiver.hpp
     qpidit/jms_messages_test/Receiver.cpp
 )

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.cpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.cpp b/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.cpp
new file mode 100644
index 0000000..010e8ba
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.cpp
@@ -0,0 +1,69 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "JmsTestBase.hpp"
+
+#include <iostream>
+#include "proton/connection.hpp"
+
+namespace qpidit {
+
+    // static
+    proton::symbol JmsTestBase::s_jmsMessageTypeAnnotationKey("x-opt-jms-msg-type");
+    std::map<std::string, int8_t>JmsTestBase::s_jmsMessageTypeAnnotationValues = initializeJmsMessageTypeAnnotationMap();
+
+    JmsTestBase::JmsTestBase() {
+
+    }
+
+    void JmsTestBase::on_connection_error(proton::connection &c) {
+        std::cerr << "JmsSender::on_connection_error(): " << c.error() << std::endl;
+    }
+
+    void JmsTestBase::on_sender_error(proton::sender &s) {
+        std::cerr << "JmsSender::on_sender_error(): " << s.error() << std::endl;
+    }
+
+    void JmsTestBase::on_session_error(proton::session &s) {
+        std::cerr << "JmsSender::on_session_error(): " << s.error() << std::endl;
+    }
+
+    void JmsTestBase::on_transport_error(proton::transport &t) {
+        std::cerr << "JmsSender::on_transport_error(): " << t.error() << std::endl;
+    }
+
+    void JmsTestBase::on_error(const proton::error_condition &ec) {
+        std::cerr << "JmsSender::on_error(): " << ec << std::endl;
+    }
+
+    // static
+    std::map<std::string, int8_t> JmsTestBase::initializeJmsMessageTypeAnnotationMap() {
+        std::map<std::string, int8_t> m;
+        m["JMS_MESSAGE_TYPE"] = JMS_MESSAGE_TYPE;
+        m["JMS_OBJECTMESSAGE_TYPE"] = JMS_OBJECTMESSAGE_TYPE;
+        m["JMS_MAPMESSAGE_TYPE"] = JMS_MAPMESSAGE_TYPE;
+        m["JMS_BYTESMESSAGE_TYPE"] = JMS_BYTESMESSAGE_TYPE;
+        m["JMS_STREAMMESSAGE_TYPE"] = JMS_STREAMMESSAGE_TYPE;
+        m["JMS_TEXTMESSAGE_TYPE"] = JMS_TEXTMESSAGE_TYPE;
+        return m;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.hpp
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.hpp b/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.hpp
new file mode 100644
index 0000000..7352ca2
--- /dev/null
+++ b/shims/qpid-proton-cpp/src/qpidit/JmsTestBase.hpp
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef SRC_QPIDIT_JMS_JMSDEFINTIONS_HPP_
+#define SRC_QPIDIT_JMS_JMSDEFINTIONS_HPP_
+
+#include <map>
+#include "proton/messaging_handler.hpp"
+#include "proton/symbol.hpp"
+#include "proton/transport.hpp"
+
+namespace qpidit
+{
+    typedef enum {JMS_QUEUE = 0,
+                  JMS_TOPIC,
+                  JMS_TMEP_QUEUE,
+                  JMS_TEMP_TOPIC}
+    jmsDestinationType_t;
+
+    typedef enum {JMS_MESSAGE_TYPE=0,
+                  JMS_OBJECTMESSAGE_TYPE,
+                  JMS_MAPMESSAGE_TYPE,
+                  JMS_BYTESMESSAGE_TYPE,
+                  JMS_STREAMMESSAGE_TYPE,
+                  JMS_TEXTMESSAGE_TYPE}
+    jmsMessageType_t;
+
+    class JmsTestBase: public proton::messaging_handler {
+    protected:
+        static proton::symbol s_jmsMessageTypeAnnotationKey;
+        static std::map<std::string, int8_t>s_jmsMessageTypeAnnotationValues;
+
+        void on_connection_error(proton::connection &c);
+        void on_session_error(proton::session &s);
+        void on_sender_error(proton::sender& s);
+        void on_transport_error(proton::transport &t);
+        void on_error(const proton::error_condition &c);
+    public:
+        JmsTestBase();
+    protected:
+        static std::map<std::string, int8_t> initializeJmsMessageTypeAnnotationMap();
+    };
+
+}
+
+#endif /* SRC_QPIDIT_JMS_JMSDEFINTIONS_HPP_ */


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


[3/5] qpid-interop-test git commit: QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parame

Posted by kp...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py b/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
new file mode 100755
index 0000000..5740c16
--- /dev/null
+++ b/shims/qpid-proton-python/src/jms_hdrs_props_test/Receiver.py
@@ -0,0 +1,357 @@
+#!/usr/bin/env python
+
+"""
+JMS message headers and properties test receiver shim for qpid-interop-test
+"""
+
+#
+# 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 json import dumps, loads
+from struct import pack, unpack
+from subprocess import check_output
+import sys
+from traceback import format_exc
+
+from qpid_interop_test.interop_test_errors import InteropTestError
+from proton import byte, symbol
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
+
+# These values must tie in with the Qpid-JMS client values found in
+# org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport
+QPID_JMS_TYPE_ANNOTATION_NAME = symbol(u'x-opt-jms-msg-type')
+
+class JmsReceiverShim(MessagingHandler):
+    """
+    Receiver shim: This shim receives JMS messages sent by the Sender shim and prints the contents of the received
+    messages onto the terminal in JSON format for retrieval by the test harness. The JMS messages type and, where
+    applicable, body values, as well as the combinations of JMS headers and properties which may be attached to
+    the message are received on the command-line in JSON format when this program is launched.
+    """
+    def __init__(self, url, jms_msg_type, test_parameters_list):
+        super(JmsReceiverShim, self).__init__()
+        self.url = url
+        self.jms_msg_type = jms_msg_type
+        self.expteced_msg_map = test_parameters_list[0]
+        self.flag_map = test_parameters_list[1]
+        self.subtype_itr = iter(sorted(self.expteced_msg_map.keys()))
+        self.expected = self._get_tot_num_messages()
+        self.received = 0
+        self.received_value_map = {}
+        self.current_subtype = None
+        self.current_subtype_msg_list = None
+        self.jms_header_map = {}
+        self.jms_property_map = {}
+
+    def get_received_value_map(self):
+        """"Return the collected message values received"""
+        return self.received_value_map
+
+    def get_jms_header_map(self):
+        """Return the collected message headers received"""
+        return self.jms_header_map
+
+    def get_jms_property_map(self):
+        """Return the collected message properties received"""
+        return self.jms_property_map
+
+    def on_start(self, event):
+        """Event callback for when the client starts"""
+        event.container.create_receiver(self.url)
+
+    def on_message(self, event):
+        """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.expected == 0 or self.received < self.expected:
+            if self.current_subtype is None:
+                self.current_subtype = self.subtype_itr.next()
+                self.current_subtype_msg_list = []
+            self.current_subtype_msg_list.append(self._handle_message(event.message))
+            self._process_jms_headers(event.message)
+            self._process_jms_properties(event.message)
+            if len(self.current_subtype_msg_list) >= self.expteced_msg_map[self.current_subtype]:
+                self.received_value_map[self.current_subtype] = self.current_subtype_msg_list
+                self.current_subtype = None
+                self.current_subtype_msg_list = []
+            self.received += 1
+            if self.received == self.expected:
+                event.receiver.close()
+                event.connection.close()
+
+    def on_connection_error(self, event):
+        print 'JmsReceiverShim.on_connection_error'
+
+    def on_session_error(self, event):
+        print 'JmsReceiverShim.on_session_error'
+
+    def on_link_error(self, event):
+        print 'JmsReceiverShim.on_link_error'
+
+    def _handle_message(self, message):
+        """Handles the analysis of a received message"""
+        if self.jms_msg_type == 'JMS_MESSAGE_TYPE':
+            return self._receive_jms_message(message)
+        if self.jms_msg_type == 'JMS_BYTESMESSAGE_TYPE':
+            return self._receive_jms_bytesmessage(message)
+        if self.jms_msg_type == 'JMS_MAPMESSAGE_TYPE':
+            return self._recieve_jms_mapmessage(message)
+        if self.jms_msg_type == 'JMS_OBJECTMESSAGE_TYPE':
+            return self._recieve_jms_objectmessage(message)
+        if self.jms_msg_type == 'JMS_STREAMMESSAGE_TYPE':
+            return self._receive_jms_streammessage(message)
+        if self.jms_msg_type == 'JMS_TEXTMESSAGE_TYPE':
+            return self._receive_jms_textmessage(message)
+        print 'jms-receive: Unsupported JMS message type "%s"' % self.jms_msg_type
+        return None
+
+    def _get_tot_num_messages(self):
+        """"Counts up the total number of messages which should be received from the expected message map"""
+        total = 0
+        for key in self.expteced_msg_map:
+            total += int(self.expteced_msg_map[key])
+        return total
+
+    def _receive_jms_message(self, message):
+        """"Receives a JMS message (without a body)"""
+        assert self.jms_msg_type == 'JMS_MESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(0)
+        if message.body is not None:
+            raise InteropTestError('_receive_jms_message: Invalid body for type JMS_MESSAGE_TYPE: %s' %
+                                   str(message.body))
+        return None
+
+    def _receive_jms_bytesmessage(self, message):
+        """"Receives a JMS bytes message"""
+        assert self.jms_msg_type == 'JMS_BYTESMESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(3)
+        if self.current_subtype == 'boolean':
+            if message.body == b'\x00':
+                return 'False'
+            if message.body == b'\x01':
+                return 'True'
+            raise InteropTestError('_receive_jms_bytesmessage: Invalid encoding for subtype boolean: %s' %
+                                   str(message.body))
+        if self.current_subtype == 'byte':
+            return hex(unpack('b', message.body)[0])
+        if self.current_subtype == 'bytes':
+            return str(message.body)
+        if self.current_subtype == 'char':
+            if len(message.body) == 2: # format 'a' or '\xNN'
+                return str(message.body[1]) # strip leading '\x00' char
+            raise InteropTestError('Unexpected strring length for type char: %d' % len(message.body))
+        if self.current_subtype == 'double':
+            return '0x%016x' % unpack('!Q', message.body)[0]
+        if self.current_subtype == 'float':
+            return '0x%08x' % unpack('!L', message.body)[0]
+        if self.current_subtype == 'int':
+            return hex(unpack('!i', message.body)[0])
+        if self.current_subtype == 'long':
+            return hex(unpack('!q', message.body)[0])
+        if self.current_subtype == 'short':
+            return hex(unpack('!h', message.body)[0])
+        if self.current_subtype == 'string':
+            # NOTE: first 2 bytes are string length, must be present
+            if len(message.body) >= 2:
+                str_len = unpack('!H', message.body[:2])[0]
+                str_body = str(message.body[2:])
+                if len(str_body) != str_len:
+                    raise InteropTestError('String length mismatch: size=%d, but len(\'%s\')=%d' %
+                                           (str_len, str_body, len(str_body)))
+                return str_body
+            else:
+                raise InteropTestError('Malformed string binary: len(\'%s\')=%d' %
+                                       (repr(message.body), len(message.body)))
+        raise InteropTestError('JMS message type %s: Unknown or unsupported subtype \'%s\'' %
+                               (self.jms_msg_type, self.current_subtype))
+
+    def _recieve_jms_mapmessage(self, message):
+        """"Receives a JMS map message"""
+        assert self.jms_msg_type == 'JMS_MAPMESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(2)
+        key, value = message.body.items()[0]
+        assert key[:-3] == self.current_subtype
+        if self.current_subtype == 'boolean':
+            return str(value)
+        if self.current_subtype == 'byte':
+            return hex(value)
+        if self.current_subtype == 'bytes':
+            return str(value)
+        if self.current_subtype == 'char':
+            return str(value)
+        if self.current_subtype == 'double':
+            return '0x%016x' % unpack('!Q', pack('!d', value))[0]
+        if self.current_subtype == 'float':
+            return '0x%08x' % unpack('!L', pack('!f', value))[0]
+        if self.current_subtype == 'int':
+            return hex(value)
+        if self.current_subtype == 'long':
+            return hex(int(value))
+        if self.current_subtype == 'short':
+            return hex(value)
+        if self.current_subtype == 'string':
+            return str(value)
+        raise InteropTestError('JMS message type %s: Unknown or unsupported subtype \'%s\'' %
+                               (self.jms_msg_type, self.current_subtype))
+
+    def _recieve_jms_objectmessage(self, message):
+        """"Receives a JMS Object message"""
+        assert self.jms_msg_type == 'JMS_OBJECTMESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(1)
+        return self._get_java_obj(message.body)
+
+    def _get_java_obj(self, java_obj_bytes):
+        """
+        Take bytes from serialized Java object and construct a Java object, then return its toString() value. The
+        work of 'translating' the bytes to a Java object and obtaining its class and value is done in a Java
+        utility org.apache.qpid.interop_test.obj_util.BytesToJavaObj located in jar JavaObjUtils.jar.
+        java_obj_bytes: hex string representation of bytes from Java object (eg 'aced00057372...')
+        returns: string containing Java class value as returned by the toString() method
+        """
+        java_obj_bytes_str = ''.join(["%02x" % ord(x) for x in java_obj_bytes]).strip()
+        out_str = check_output(['java',
+                                '-cp',
+                                'target/JavaObjUtils.jar',
+                                'org.apache.qpid.interop_test.obj_util.BytesToJavaObj',
+                                java_obj_bytes_str])
+        out_str_list = out_str.split('\n')[:-1] # remove trailing \n
+        if len(out_str_list) > 1:
+            raise InteropTestError('Unexpected return from JavaObjUtils: %s' % out_str)
+        colon_index = out_str_list[0].index(':')
+        if colon_index < 0:
+            raise InteropTestError('Unexpected format from JavaObjUtils: %s' % out_str)
+        java_class_name = out_str_list[0][:colon_index]
+        java_class_value_str = out_str_list[0][colon_index+1:]
+        if java_class_name != self.current_subtype:
+            raise InteropTestError('Unexpected class name from JavaObjUtils: expected %s, recieved %s' %
+                                   (self.current_subtype, java_class_name))
+        return java_class_value_str
+
+    def _receive_jms_streammessage(self, message):
+        """Receives a JMS stream message"""
+        assert self.jms_msg_type == 'JMS_STREAMMESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(4)
+        # Every message is a list with one item [value]
+        assert len(message.body) == 1
+        value = message.body[0]
+        if self.current_subtype == 'boolean':
+            return str(value)
+        if self.current_subtype == 'byte':
+            return hex(value)
+        if self.current_subtype == 'bytes':
+            return str(value)
+        if self.current_subtype == 'char':
+            return str(value)
+        if self.current_subtype == 'double':
+            return '0x%016x' % unpack('!Q', pack('!d', value))[0]
+        if self.current_subtype == 'float':
+            return '0x%08x' % unpack('!L', pack('!f', value))[0]
+        if self.current_subtype == 'int':
+            return hex(value)
+        if self.current_subtype == 'long':
+            return hex(int(value))
+        if self.current_subtype == 'short':
+            return hex(value)
+        if self.current_subtype == 'string':
+            return str(value)
+        raise InteropTestError('JmsRecieverShim._receive_jms_streammessage(): ' +
+                               'JMS message type %s: Unknown or unsupported subtype \'%s\'' %
+                               (self.jms_msg_type, self.current_subtype))
+
+    def _receive_jms_textmessage(self, message):
+        """"Receives a JMS text message"""
+        assert self.jms_msg_type == 'JMS_TEXTMESSAGE_TYPE'
+        assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(5)
+        return message.body
+
+    def _process_jms_headers(self, message):
+        """"Checks the supplied message for three JMS headers: message type, correlation-id and reply-to"""
+        # JMS message type header
+        message_type_header = message._get_subject()
+        if message_type_header is not None:
+            self.jms_header_map['JMS_TYPE_HEADER'] = {'string': message_type_header}
+
+        # JMS correlation ID
+        correlation_id = message._get_correlation_id()
+        if correlation_id is not None:
+            if 'JMS_CORRELATIONID_AS_BYTES' in self.flag_map and self.flag_map['JMS_CORRELATIONID_AS_BYTES']:
+                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'bytes': correlation_id}
+            else:
+                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'string': correlation_id}
+
+        # JMS reply-to
+        reply_to = message._get_reply_to()
+        if reply_to is not None:
+            if 'JMS_REPLYTO_AS_TOPIC' in self.flag_map and self.flag_map['JMS_REPLYTO_AS_TOPIC']:
+                # Some brokers prepend 'queue://' and 'topic://' to reply_to addresses, strip these when present
+                if len(reply_to) > 8 and reply_to[0:8] == 'topic://':
+                    reply_to = reply_to[8:]
+                self.jms_header_map['JMS_REPLYTO_HEADER'] = {'topic': reply_to}
+            else:
+                if len(reply_to) > 8 and reply_to[0:8] == 'queue://':
+                    reply_to = reply_to[8:]
+                self.jms_header_map['JMS_REPLYTO_HEADER'] = {'queue': reply_to}
+
+    def _process_jms_properties(self, message):
+        """"Checks the supplied message for JMS message properties and decodes them"""
+        if message.properties is not None:
+            for jms_property_name in message.properties:
+                underscore_index = jms_property_name.find('_')
+                if underscore_index >= 0: # Ignore any other properties without '_'
+                    jms_property_type = jms_property_name[0:underscore_index]
+                    value = message.properties[jms_property_name]
+                    if jms_property_type == 'boolean':
+                        self.jms_property_map[jms_property_name] = {'boolean': str(value)}
+                    elif jms_property_type == 'byte':
+                        self.jms_property_map[jms_property_name] = {'byte': hex(value)}
+                    elif jms_property_type == 'double':
+                        self.jms_property_map[jms_property_name] = {'double': '0x%016x' %
+                                                                              unpack('!Q', pack('!d', value))[0]}
+                    elif jms_property_type == 'float':
+                        self.jms_property_map[jms_property_name] = {'float': '0x%08x' %
+                                                                             unpack('!L', pack('!f', value))[0]}
+                    elif jms_property_type == 'int':
+                        self.jms_property_map[jms_property_name] = {'int': hex(value)}
+                    elif jms_property_type == 'long':
+                        self.jms_property_map[jms_property_name] = {'long': hex(int(value))}
+                    elif jms_property_type == 'short':
+                        self.jms_property_map[jms_property_name] = {'short': hex(value)}
+                    elif jms_property_type == 'string':
+                        self.jms_property_map[jms_property_name] = {'string': str(value)}
+                    else:
+                        pass # Ignore any other properties, brokers can add them and we don't know what they may be
+
+
+# --- main ---
+# Args: 1: Broker address (ip-addr:port)
+#       2: Queue name
+#       3: JMS message type
+#       4: JSON Test parameters containing 2 maps: [testValuesMap, flagMap]
+#print '#### sys.argv=%s' % sys.argv
+try:
+    RECEIVER = JmsReceiverShim('%s/%s' % (sys.argv[1], sys.argv[2]), sys.argv[3], loads(sys.argv[4]))
+    Container(RECEIVER).run()
+    print sys.argv[3]
+    print dumps([RECEIVER.get_received_value_map(), RECEIVER.get_jms_header_map(), RECEIVER.get_jms_property_map()])
+except KeyboardInterrupt:
+    pass
+except Exception as exc:
+    print 'jms-receiver-shim EXCEPTION:', exc
+    print format_exc()

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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
new file mode 100755
index 0000000..89abf25
--- /dev/null
+++ b/shims/qpid-proton-python/src/jms_hdrs_props_test/Sender.py
@@ -0,0 +1,388 @@
+#!/usr/bin/env python
+
+"""
+JMS message headers and properties test sender shim for qpid-interop-test
+"""
+
+#
+# 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 json import loads
+from struct import pack, unpack
+from subprocess import check_output
+import sys
+from traceback import format_exc
+
+from proton import byte, char, float32, int32, Message, short, symbol
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
+from qpid_interop_test.interop_test_errors import InteropTestError
+from qpid_interop_test.test_type_map import TestTypeMap
+
+# These values must tie in with the Qpid-JMS client values found in
+# org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport
+QPID_JMS_TYPE_ANNOTATION_NAME = symbol(u'x-opt-jms-msg-type')
+QPID_JMS_TYPE_ANNOTATIONS = {
+    'JMS_MESSAGE_TYPE': byte(0),
+    'JMS_BYTESMESSAGE_TYPE': byte(3),
+    'JMS_MAPMESSAGE_TYPE': byte(2),
+    'JMS_OBJECTMESSAGE_TYPE': byte(1),
+    'JMS_STREAMMESSAGE_TYPE': byte(4),
+    'JMS_TEXTMESSAGE_TYPE': byte(5)
+    }
+def create_annotation(jms_msg_type):
+    """Function which creates a message annotation for JMS message type as used by the Qpid JMS client"""
+    return {QPID_JMS_TYPE_ANNOTATION_NAME: QPID_JMS_TYPE_ANNOTATIONS[jms_msg_type]}
+
+class JmsSenderShim(MessagingHandler):
+    """
+    This shim sends JMS messages of a particular JMS message type according to the test parameters list. This list
+    contains three maps:
+    0: The test value map, which contains test value types as keys, and lists of values of that type;
+    1. The test headers map, which contains the JMS headers as keys and a submap conatining types and values;
+    2. The test proprties map, which contains the name of the properties as keys, and a submap containing types
+       and values
+    This shim takes the combinations of the above map and creates test cases, each of which sends a single message
+    with (or without) JMS headers and properties.
+    """
+    def __init__(self, broker_ip_addr, queue_name, jms_msg_type, test_parameters_list):
+        super(JmsSenderShim, self).__init__()
+        self.broker_ip_addr = broker_ip_addr
+        self.queue_name = queue_name
+        self.jms_msg_type = jms_msg_type
+        self.test_value_map = test_parameters_list[0]
+        self.test_headers_map = test_parameters_list[1]
+        self.test_properties_map = test_parameters_list[2]
+        self.sent = 0
+        self.confirmed = 0
+        self.total = self._get_total_num_msgs()
+
+    def on_start(self, event):
+        """Event callback for when the client starts"""
+        event.container.create_sender('%s/%s' % (self.broker_ip_addr, self.queue_name))
+
+    def on_sendable(self, event):
+        """Event callback for when send credit is received, allowing the sending of messages"""
+        if self.sent == 0:
+            # These types expect a test_values Python string representation of a map: '{type:[val, val, val], ...}'
+            for sub_type in sorted(self.test_value_map.keys()):
+                if self._send_test_values(event, sub_type, self.test_value_map[sub_type]):
+                    return
+
+    def on_connection_error(self, event):
+        print 'JmsSenderShim.on_connection_error'
+
+    def on_session_error(self, event):
+        print 'JmsSenderShim.on_session_error'
+
+    def on_link_error(self, event):
+        print 'JmsSenderShim.on_link_error'
+
+    def on_accepted(self, event):
+        """Event callback for when a sent message is accepted by the broker"""
+        self.confirmed += 1
+        if self.confirmed == self.total:
+            event.connection.close()
+
+    def on_disconnected(self, event):
+        """Event callback for when the broker disconnects with the client"""
+        self.sent = self.confirmed
+
+    def _get_total_num_msgs(self):
+        """
+        Calculates the total number of messages to be sent based on the message parameters received on the command-line
+        """
+        total = 0
+        for key in self.test_value_map.keys():
+            total += len(self.test_value_map[key])
+        return total
+
+    def _send_test_values(self, event, test_value_type, test_values):
+        """Method which loops through recieved parameters and sends the corresponding messages"""
+        value_num = 0
+        for test_value in test_values:
+            if event.sender.credit:
+                hdr_kwargs, hdr_annotations = self._get_jms_message_header_kwargs()
+                message = self._create_message(test_value_type, test_value, value_num, hdr_kwargs, hdr_annotations)
+                # TODO: set message to address
+                if message is not None:
+                    #self._add_jms_message_headers(message)
+                    self._add_jms_message_properties(message)
+                    event.sender.send(message)
+                    self.sent += 1
+                    value_num += 1
+                else:
+                    event.connection.close()
+                    return True
+        return False
+
+    # TODO: Change this to return a list of messages. That way each test can return more than one message
+    def _create_message(self, test_value_type, test_value, value_num, hdr_kwargs, hdr_annotations):
+        """Create a single message of the appropriate JMS message type"""
+        if self.jms_msg_type == 'JMS_MESSAGE_TYPE':
+            return self._create_jms_message(test_value_type, test_value, hdr_kwargs, hdr_annotations)
+        elif self.jms_msg_type == 'JMS_BYTESMESSAGE_TYPE':
+            return self._create_jms_bytesmessage(test_value_type, test_value, hdr_kwargs, hdr_annotations)
+        elif self.jms_msg_type == 'JMS_MAPMESSAGE_TYPE':
+            return self._create_jms_mapmessage(test_value_type, test_value, "%s%03d" % (test_value_type, value_num),
+                                               hdr_kwargs, hdr_annotations)
+        elif self.jms_msg_type == 'JMS_OBJECTMESSAGE_TYPE':
+            return self._create_jms_objectmessage('%s:%s' % (test_value_type, test_value), hdr_kwargs, hdr_annotations)
+        elif self.jms_msg_type == 'JMS_STREAMMESSAGE_TYPE':
+            return self._create_jms_streammessage(test_value_type, test_value, hdr_kwargs, hdr_annotations)
+        elif self.jms_msg_type == 'JMS_TEXTMESSAGE_TYPE':
+            return self._create_jms_textmessage(test_value, hdr_kwargs, hdr_annotations)
+        else:
+            print 'jms-send: Unsupported JMS message type "%s"' % self.jms_msg_type
+            return None
+
+    def _create_jms_message(self, test_value_type, test_value, hdr_kwargs, hdr_annotations):
+        """Create a JMS message type (without message body)"""
+        if test_value_type != 'none':
+            raise InteropTestError('JmsSenderShim._create_jms_message: Unknown or unsupported subtype "%s"' %
+                                   test_value_type)
+        if test_value is not None:
+            raise InteropTestError('JmsSenderShim._create_jms_message: Invalid value "%s" for subtype "%s"' %
+                                   (test_value, test_value_type))
+        return Message(id=(self.sent+1),
+                       content_type='application/octet-stream',
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_MESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    def _create_jms_bytesmessage(self, test_value_type, test_value, hdr_kwargs, hdr_annotations):
+        """Create a JMS bytes message"""
+        # NOTE: test_value contains all unicode strings u'...' as returned by json
+        body_bytes = None
+        if test_value_type == 'boolean':
+            body_bytes = b'\x01' if test_value == 'True' else b'\x00'
+        elif test_value_type == 'byte':
+            body_bytes = pack('b', int(test_value, 16))
+        elif test_value_type == 'bytes':
+            body_bytes = str(test_value) # remove unicode
+        elif test_value_type == 'char':
+            # JMS expects two-byte chars, ASCII chars can be prefixed with '\x00'
+            body_bytes = '\x00' + str(test_value) # remove unicode
+        elif test_value_type == 'double' or test_value_type == 'float':
+            body_bytes = test_value[2:].decode('hex')
+        elif test_value_type == 'int':
+            body_bytes = pack('!i', int(test_value, 16))
+        elif test_value_type == 'long':
+            body_bytes = pack('!q', long(test_value, 16))
+        elif test_value_type == 'short':
+            body_bytes = pack('!h', short(test_value, 16))
+        elif test_value_type == 'string':
+            # NOTE: First two bytes must be string length
+            test_value_str = str(test_value) # remove unicode
+            body_bytes = pack('!H', len(test_value_str)) + test_value_str
+        else:
+            raise InteropTestError('JmsSenderShim._create_jms_bytesmessage: Unknown or unsupported subtype "%s"' %
+                                   test_value_type)
+        return Message(id=(self.sent+1),
+                       body=body_bytes,
+                       inferred=True,
+                       content_type='application/octet-stream',
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_BYTESMESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    def _create_jms_mapmessage(self, test_value_type, test_value, name, hdr_kwargs, hdr_annotations):
+        """Create a JMS map message"""
+        if test_value_type == 'boolean':
+            value = test_value == 'True'
+        elif test_value_type == 'byte':
+            value = byte(int(test_value, 16))
+        elif test_value_type == 'bytes':
+            value = str(test_value) # remove unicode
+        elif test_value_type == 'char':
+            value = char(test_value)
+        elif test_value_type == 'double':
+            value = unpack('!d', test_value[2:].decode('hex'))[0]
+        elif test_value_type == 'float':
+            value = float32(unpack('!f', test_value[2:].decode('hex'))[0])
+        elif test_value_type == 'int':
+            value = int32(int(test_value, 16))
+        elif test_value_type == 'long':
+            value = long(test_value, 16)
+        elif test_value_type == 'short':
+            value = short(int(test_value, 16))
+        elif test_value_type == 'string':
+            value = test_value
+        else:
+            raise InteropTestError('JmsSenderShim._create_jms_mapmessage: Unknown or unsupported subtype "%s"' %
+                                   test_value_type)
+        return Message(id=(self.sent+1),
+                       body={name: value},
+                       inferred=False,
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_MAPMESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    def _create_jms_objectmessage(self, test_value, hdr_kwargs, hdr_annotations):
+        """Create a JMS object message"""
+        java_binary = self._s_get_java_obj_binary(test_value)
+        return Message(id=(self.sent+1),
+                       body=java_binary,
+                       inferred=True,
+                       content_type='application/x-java-serialized-object',
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_MAPMESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    @staticmethod
+    def _s_get_java_obj_binary(java_class_str):
+        """Call external utility to create Java object and stringify it, returning the string representation"""
+        out_str = check_output(['java',
+                                '-cp',
+                                'target/JavaObjUtils.jar',
+                                'org.apache.qpid.interop_test.obj_util.JavaObjToBytes',
+                                java_class_str])
+        out_str_list = out_str.split('\n')[:-1] # remove trailing \n
+        if out_str_list[0] != java_class_str:
+            raise InteropTestError('JmsSenderShim._s_get_java_obj_binary(): Call to JavaObjToBytes failed\n%s' %
+                                   out_str)
+        return out_str_list[1].decode('hex')
+
+    def _create_jms_streammessage(self, test_value_type, test_value, hdr_kwargs, hdr_annotations):
+        """Create a JMS stream message"""
+        if test_value_type == 'boolean':
+            body_list = [test_value == 'True']
+        elif test_value_type == 'byte':
+            body_list = [byte(int(test_value, 16))]
+        elif test_value_type == 'bytes':
+            body_list = [str(test_value)]
+        elif test_value_type == 'char':
+            body_list = [char(test_value)]
+        elif test_value_type == 'double':
+            body_list = [unpack('!d', test_value[2:].decode('hex'))[0]]
+        elif test_value_type == 'float':
+            body_list = [float32(unpack('!f', test_value[2:].decode('hex'))[0])]
+        elif test_value_type == 'int':
+            body_list = [int32(int(test_value, 16))]
+        elif test_value_type == 'long':
+            body_list = [long(test_value, 16)]
+        elif test_value_type == 'short':
+            body_list = [short(int(test_value, 16))]
+        elif test_value_type == 'string':
+            body_list = [test_value]
+        else:
+            raise InteropTestError('JmsSenderShim._create_jms_streammessage: Unknown or unsupported subtype "%s"' %
+                                   test_value_type)
+        return Message(id=(self.sent+1),
+                       body=body_list,
+                       inferred=True,
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_STREAMMESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    def _create_jms_textmessage(self, test_value_text, hdr_kwargs, hdr_annotations):
+        """Create a JMS text message"""
+        return Message(id=(self.sent+1),
+                       body=unicode(test_value_text),
+                       annotations=TestTypeMap.merge_dicts(create_annotation('JMS_TEXTMESSAGE_TYPE'),
+                                                           hdr_annotations),
+                       **hdr_kwargs)
+
+    def _get_jms_message_header_kwargs(self):
+        hdr_kwargs = {}
+        hdr_annotations = {}
+        for jms_header in self.test_headers_map.iterkeys():
+            value_map = self.test_headers_map[jms_header]
+            value_type = value_map.keys()[0] # There is only ever one value in map
+            value = value_map[value_type]
+            if jms_header == 'JMS_TYPE_HEADER':
+                if value_type == 'string':
+                    hdr_kwargs['subject'] = value
+                else:
+                    raise InteropTestError('JmsSenderShim._get_jms_message_header_kwargs(): ' +
+                                           'JMS_TYPE_HEADER requires value type "string", type "%s" found' %
+                                           value_type)
+            elif jms_header == 'JMS_CORRELATIONID_HEADER':
+                if value_type == 'string':
+                    hdr_kwargs['correlation_id'] = value
+                elif value_type == 'bytes':
+                    hdr_kwargs['correlation_id'] = str(value)
+                else:
+                    raise InteropTestError('JmsSenderShim._get_jms_message_header_kwargs(): ' +
+                                           'JMS_CORRELATIONID_HEADER requires value type "string" or "bytes", ' +
+                                           'type "%s" found' % value_type)
+                hdr_annotations[symbol(u'x-opt-app-correlation-id')] = True
+            elif jms_header == 'JMS_REPLYTO_HEADER':
+                if value_type == 'queue':
+                    hdr_kwargs['reply_to'] = value
+                    hdr_annotations[symbol(u'x-opt-jms-reply-to')] = byte(0)
+                elif value_type == 'topic':
+                    hdr_kwargs['reply_to'] = value
+                    hdr_annotations[symbol(u'x-opt-jms-reply-to')] = byte(1)
+                elif value_type == 'temp_queue' or value_type == 'temp_topic':
+                    raise InteropTestError('JmsSenderShim._get_jms_message_header_kwargs(): ' +
+                                           'JMS_REPLYTO_HEADER type "temp_queue" or "temp_topic" not handled')
+                else:
+                    raise InteropTestError('JmsSenderShim._get_jms_message_header_kwargs(): ' +
+                                           'JMS_REPLYTO_HEADER requires value type "queue" or "topic", ' +
+                                           'type "%s" found' % value_type)
+            else:
+                raise InteropTestError('JmsSenderShim._add_jms_message_headers(): Invalid JMS message header "%s"' %
+                                       jms_header)
+        return (hdr_kwargs, hdr_annotations)
+
+    def _add_jms_message_properties(self, message):
+        """Adds message properties to the supplied message from self.test_properties_map"""
+        for property_name in self.test_properties_map.iterkeys():
+            value_map = self.test_properties_map[property_name]
+            value_type = value_map.keys()[0] # There is only ever one value in map
+            value = value_map[value_type]
+            if message.properties is None:
+                message.properties = {}
+            if value_type == 'boolean':
+                message.properties[property_name] = value == 'True'
+            elif value_type == 'byte':
+                message.properties[property_name] = byte(int(value, 16))
+            elif value_type == 'double':
+                message.properties[property_name] = unpack('!d', value[2:].decode('hex'))[0]
+            elif value_type == 'float':
+                message.properties[property_name] = float32(unpack('!f', value[2:].decode('hex'))[0])
+            elif value_type == 'int':
+                message.properties[property_name] = int(value, 16)
+            elif value_type == 'long':
+                message.properties[property_name] = long(value, 16)
+            elif value_type == 'short':
+                message.properties[property_name] = short(int(value, 16))
+            elif value_type == 'string':
+                message.properties[property_name] = value
+            else:
+                raise InteropTestError('JmsSenderShim._add_jms_message_properties: ' +
+                                       'Unknown or unhandled message property type ?%s"' % value_type)
+
+
+
+# --- main ---
+# Args: 1: Broker address (ip-addr:port)
+#       2: Queue name
+#       3: JMS message type
+#       4: JSON Test parameters containing 3 maps: [testValueMap, testHeadersMap, testPropertiesMap]
+#print '#### sys.argv=%s' % sys.argv
+#print '>>> test_values=%s' % loads(sys.argv[4])
+try:
+    Container(JmsSenderShim(sys.argv[1], sys.argv[2], sys.argv[3], loads(sys.argv[4]))).run()
+except KeyboardInterrupt:
+    pass
+except Exception as exc:
+    print 'jms-sender-shim EXCEPTION:', exc
+    print format_exc()

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
----------------------------------------------------------------------
diff --git a/shims/qpid-proton-python/src/jms_messages_test/Receiver.py b/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
index 9140db1..eff67c1 100755
--- a/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
+++ b/shims/qpid-proton-python/src/jms_messages_test/Receiver.py
@@ -23,16 +23,17 @@ JMS receiver shim for qpid-interop-test
 # under the License.
 #
 
-import sys
-from interop_test_errors import InteropTestError
 from json import dumps, loads
-from proton import byte, symbol
-from proton.handlers import MessagingHandler
-from proton.reactor import Container
 from struct import pack, unpack
 from subprocess import check_output
+import sys
 from traceback import format_exc
 
+from proton import byte, symbol
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
+from qpid_interop_test.interop_test_errors import InteropTestError
+
 # These values must tie in with the Qpid-JMS client values found in
 # org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport
 QPID_JMS_TYPE_ANNOTATION_NAME = symbol(u'x-opt-jms-msg-type')
@@ -48,29 +49,18 @@ class JmsReceiverShim(MessagingHandler):
         super(JmsReceiverShim, self).__init__()
         self.url = url
         self.jms_msg_type = jms_msg_type
-        self.expteced_msg_map = test_parameters_list[0]
-        self.flag_map = test_parameters_list[1]
+        self.expteced_msg_map = test_parameters_list
         self.subtype_itr = iter(sorted(self.expteced_msg_map.keys()))
         self.expected = self._get_tot_num_messages()
         self.received = 0
         self.received_value_map = {}
         self.current_subtype = None
         self.current_subtype_msg_list = None
-        self.jms_header_map = {}
-        self.jms_property_map = {}
 
     def get_received_value_map(self):
         """"Return the collected message values received"""
         return self.received_value_map
 
-    def get_jms_header_map(self):
-        """Return the collected message headers received"""
-        return self.jms_header_map
-
-    def get_jms_property_map(self):
-        """Return the collected message properties received"""
-        return self.jms_property_map
-
     def on_start(self, event):
         """Event callback for when the client starts"""
         event.container.create_receiver(self.url)
@@ -84,8 +74,6 @@ class JmsReceiverShim(MessagingHandler):
                 self.current_subtype = self.subtype_itr.next()
                 self.current_subtype_msg_list = []
             self.current_subtype_msg_list.append(self._handle_message(event.message))
-            self._process_jms_headers(event.message)
-            self._process_jms_properties(event.message)
             if len(self.current_subtype_msg_list) >= self.expteced_msg_map[self.current_subtype]:
                 self.received_value_map[self.current_subtype] = self.current_subtype_msg_list
                 self.current_subtype = None
@@ -280,62 +268,6 @@ class JmsReceiverShim(MessagingHandler):
         assert message.annotations[QPID_JMS_TYPE_ANNOTATION_NAME] == byte(5)
         return message.body
 
-    def _process_jms_headers(self, message):
-        """"Checks the supplied message for three JMS headers: message type, correlation-id and reply-to"""
-        # JMS message type header
-        message_type_header = message._get_subject()
-        if message_type_header is not None:
-            self.jms_header_map['JMS_TYPE_HEADER'] = {'string': message_type_header}
-
-        # JMS correlation ID
-        correlation_id = message._get_correlation_id()
-        if correlation_id is not None:
-            if 'JMS_CORRELATIONID_AS_BYTES' in self.flag_map and self.flag_map['JMS_CORRELATIONID_AS_BYTES']:
-                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'bytes': correlation_id}
-            else:
-                self.jms_header_map['JMS_CORRELATIONID_HEADER'] = {'string': correlation_id}
-
-        # JMS reply-to
-        reply_to = message._get_reply_to()
-        if reply_to is not None:
-            if 'JMS_REPLYTO_AS_TOPIC' in self.flag_map and self.flag_map['JMS_REPLYTO_AS_TOPIC']:
-                # Some brokers prepend 'queue://' and 'topic://' to reply_to addresses, strip these when present
-                if len(reply_to) > 8 and reply_to[0:8] == 'topic://':
-                    reply_to = reply_to[8:]
-                self.jms_header_map['JMS_REPLYTO_HEADER'] = {'topic': reply_to}
-            else:
-                if len(reply_to) > 8 and reply_to[0:8] == 'queue://':
-                    reply_to = reply_to[8:]
-                self.jms_header_map['JMS_REPLYTO_HEADER'] = {'queue': reply_to}
-
-    def _process_jms_properties(self, message):
-        """"Checks the supplied message for JMS message properties and decodes them"""
-        if message.properties is not None:
-            for jms_property_name in message.properties:
-                underscore_index = jms_property_name.find('_')
-                if underscore_index >= 0: # Ignore any other properties without '_'
-                    jms_property_type = jms_property_name[0:underscore_index]
-                    value = message.properties[jms_property_name]
-                    if jms_property_type == 'boolean':
-                        self.jms_property_map[jms_property_name] = {'boolean': str(value)}
-                    elif jms_property_type == 'byte':
-                        self.jms_property_map[jms_property_name] = {'byte': hex(value)}
-                    elif jms_property_type == 'double':
-                        self.jms_property_map[jms_property_name] = {'double': '0x%016x' %
-                                                                              unpack('!Q', pack('!d', value))[0]}
-                    elif jms_property_type == 'float':
-                        self.jms_property_map[jms_property_name] = {'float': '0x%08x' %
-                                                                             unpack('!L', pack('!f', value))[0]}
-                    elif jms_property_type == 'int':
-                        self.jms_property_map[jms_property_name] = {'int': hex(value)}
-                    elif jms_property_type == 'long':
-                        self.jms_property_map[jms_property_name] = {'long': hex(int(value))}
-                    elif jms_property_type == 'short':
-                        self.jms_property_map[jms_property_name] = {'short': hex(value)}
-                    elif jms_property_type == 'string':
-                        self.jms_property_map[jms_property_name] = {'string': str(value)}
-                    else:
-                        pass # Ignore any other properties, brokers can add them and we don't know what they may be
 
 
 # --- main ---
@@ -349,8 +281,6 @@ try:
     Container(RECEIVER).run()
     print sys.argv[3]
     print dumps(RECEIVER.get_received_value_map())
-    print dumps(RECEIVER.get_jms_header_map())
-    print dumps(RECEIVER.get_jms_property_map())
 except KeyboardInterrupt:
     pass
 except Exception as exc:

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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 5a1108a..33a6acd 100755
--- a/shims/qpid-proton-python/src/jms_messages_test/Sender.py
+++ b/shims/qpid-proton-python/src/jms_messages_test/Sender.py
@@ -23,16 +23,17 @@ JMS sender shim for qpid-interop-test
 # under the License.
 #
 
-import sys
 from json import loads
-from proton import byte, char, float32, int32, Message, short, symbol
-from proton.handlers import MessagingHandler
-from proton.reactor import Container
-from interop_test_errors import InteropTestError
 from subprocess import check_output
 from struct import pack, unpack
+import sys
 from traceback import format_exc
 
+from proton import byte, char, float32, int32, Message, short, symbol
+from proton.handlers import MessagingHandler
+from proton.reactor import Container
+from qpid_interop_test.interop_test_errors import InteropTestError
+
 # These values must tie in with the Qpid-JMS client values found in
 # org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport
 QPID_JMS_TYPE_ANNOTATION_NAME = symbol(u'x-opt-jms-msg-type')
@@ -64,9 +65,7 @@ class JmsSenderShim(MessagingHandler):
         self.broker_ip_addr = broker_ip_addr
         self.queue_name = queue_name
         self.jms_msg_type = jms_msg_type
-        self.test_value_map = test_parameters_list[0]
-        self.test_headers_map = test_parameters_list[1]
-        self.test_properties_map = test_parameters_list[2]
+        self.test_value_map = test_parameters_list
         self.sent = 0
         self.confirmed = 0
         self.total = self._get_total_num_msgs()
@@ -119,8 +118,6 @@ class JmsSenderShim(MessagingHandler):
                 message = self._create_message(test_value_type, test_value, value_num)
                 # TODO: set message to address
                 if message is not None:
-                    self._add_jms_message_headers(message)
-                    self._add_jms_message_properties(message)
                     event.sender.send(message)
                     self.sent += 1
                     value_num += 1
@@ -283,94 +280,6 @@ class JmsSenderShim(MessagingHandler):
                        body=unicode(test_value_text),
                        annotations=create_annotation('JMS_TEXTMESSAGE_TYPE'))
 
-    def _add_jms_message_headers(self, message):
-        """Add JMS headers to the supplied message from self.test_headers_map"""
-        for jms_header in self.test_headers_map.iterkeys():
-            value_map = self.test_headers_map[jms_header]
-            value_type = value_map.keys()[0] # There is only ever one value in map
-            value = value_map[value_type]
-            if jms_header == 'JMS_TYPE_HEADER':
-                if value_type == 'string':
-                    self._s_set_jms_type_header(message, value)
-                else:
-                    raise InteropTestError('JmsSenderShim._add_jms_message_headers(): ' +
-                                           'JMS_TYPE_HEADER requires value type "string", type "%s" found' %
-                                           value_type)
-            elif jms_header == 'JMS_CORRELATIONID_HEADER':
-                if value_type == 'string':
-                    self._s_set_jms_correlation_id(message, value)
-                elif value_type == 'bytes':
-                    self._s_set_jms_correlation_id(message, str(value))
-                else:
-                    raise InteropTestError('JmsSenderShim._add_jms_message_headers(): ' +
-                                           'JMS_CORRELATIONID_HEADER requires value type "string" or "bytes", ' +
-                                           'type "%s" found' % value_type)
-            elif jms_header == 'JMS_REPLYTO_HEADER':
-                if value_type == 'queue' or value_type == 'topic':
-                    self._s_set_jms_reply_to(message, value_type, value)
-                elif value_type == 'temp_queue' or value_type == 'temp_topic':
-                    raise InteropTestError('JmsSenderShim._add_jms_message_headers(): ' +
-                                           'JMS_REPLYTO_HEADER type "temp_queue" or "temp_topic" not handled')
-                else:
-                    raise InteropTestError('JmsSenderShim._add_jms_message_headers(): ' +
-                                           'JMS_REPLYTO_HEADER requires value type "queue" or "topic", ' +
-                                           'type "%s" found' % value_type)
-            else:
-                raise InteropTestError('JmsSenderShim._add_jms_message_headers(): Invalid JMS message header "%s"' %
-                                       jms_header)
-
-
-    @staticmethod
-    def _s_set_jms_type_header(message, message_type):
-        """Adds a JMS message type header"""
-        message._set_subject(message_type)
-
-    @staticmethod
-    def _s_set_jms_correlation_id(message, correlation_id):
-        """Adds a JMS correlation id header"""
-        message._set_correlation_id(correlation_id)
-        message.annotations[symbol(u'x-opt-app-correlation-id')] = True
-
-    @staticmethod
-    def _s_set_jms_reply_to(message, jms_destination_type_str, destination):
-        """Adds a JMS reply-to header"""
-        if jms_destination_type_str == 'queue':
-            message._set_reply_to(destination)
-            message.annotations[symbol(u'x-opt-jms-reply-to')] = byte(0)
-        elif jms_destination_type_str == 'topic':
-            message._set_reply_to(destination)
-            message.annotations[symbol(u'x-opt-jms-reply-to')] = byte(1)
-        else:
-            raise InteropTestError('JmsSenderShim._s_set_jms_reply_to(): ' +
-                                   'Invalid value for jms_destination_type_str "%s"' % jms_destination_type_str)
-
-    def _add_jms_message_properties(self, message):
-        """Adds message properties to the supplied message from self.test_properties_map"""
-        for property_name in self.test_properties_map.iterkeys():
-            value_map = self.test_properties_map[property_name]
-            value_type = value_map.keys()[0] # There is only ever one value in map
-            value = value_map[value_type]
-            if message.properties is None:
-                message.properties = {}
-            if value_type == 'boolean':
-                message.properties[property_name] = value == 'True'
-            elif value_type == 'byte':
-                message.properties[property_name] = byte(int(value, 16))
-            elif value_type == 'double':
-                message.properties[property_name] = unpack('!d', value[2:].decode('hex'))[0]
-            elif value_type == 'float':
-                message.properties[property_name] = float32(unpack('!f', value[2:].decode('hex'))[0])
-            elif value_type == 'int':
-                message.properties[property_name] = int(value, 16)
-            elif value_type == 'long':
-                message.properties[property_name] = long(value, 16)
-            elif value_type == 'short':
-                message.properties[property_name] = short(int(value, 16))
-            elif value_type == 'string':
-                message.properties[property_name] = value
-            else:
-                raise InteropTestError('JmsSenderShim._add_jms_message_properties: ' +
-                                       'Unknown or unhandled message property type ?%s"' % value_type)
 
 
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/.gitignore
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/.gitignore b/src/python/qpid-interop-test/.gitignore
deleted file mode 100644
index 835fca3..0000000
--- a/src/python/qpid-interop-test/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/interop_test_errors.pyc
-/shim_utils.pyc
-/broker_properties.pyc
-/test_type_map.pyc

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/__init__.py b/src/python/qpid-interop-test/__init__.py
deleted file mode 100644
index a94c993..0000000
--- a/src/python/qpid-interop-test/__init__.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# 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 broker_properties
-import interop_test_errors
-import shims
-import test_type_map
-import types
-import jms
-

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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
deleted file mode 100755
index 30d0577..0000000
--- a/src/python/qpid-interop-test/amqp_types_test.py
+++ /dev/null
@@ -1,435 +0,0 @@
-#!/usr/bin/env python
-
-"""
-Module to test AMQP primitive types across different APIs
-"""
-
-#
-# 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 argparse
-import sys
-import unittest
-
-from itertools import product
-from json import dumps
-from os import getenv, path
-from sys import stdout
-from time import mktime, time
-from uuid import UUID, uuid4
-
-import broker_properties
-import shims
-from proton import symbol
-from test_type_map import TestTypeMap
-
-# TODO: propose a sensible default when installation details are worked out
-QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
-if QPID_INTEROP_TEST_HOME is None:
-    print 'ERROR: Environment variable QPID_INTEROP_TEST_HOME is not set'
-    sys.exit(1)
-
-
-class AmqpPrimitiveTypes(TestTypeMap):
-    """
-    Class which contains all the described AMQP primitive types and the test values to be used in testing.
-    """
-
-    TYPE_MAP = {
-        'null': ['None'],
-        'boolean': ['True',
-                    'False'],
-        'ubyte': ['0x0',
-                  '0x7f',
-                  '0x80',
-                  '0xff'],
-        'ushort': ['0x0',
-                   '0x7fff',
-                   '0x8000',
-                   '0xffff'],
-        'uint': ['0x0',
-                 '0x7fffffff',
-                 '0x80000000',
-                 '0xffffffff'],
-        'ulong': ['0x0',
-                  '0x1',
-                  '0xff',
-                  '0x100',
-                  '0x7fffffffffffffff',
-                  '0x8000000000000000',
-                  '0xffffffffffffffff'],
-        'byte': ['-0x80',
-                 '-0x1',
-                 '0x0',
-                 '0x7f'],
-        'short': ['-0x8000',
-                  '-0x1',
-                  '0x0',
-                  '0x7fff'],
-        'int': ['-0x80000000',
-                '-0x1',
-                '0x0',
-                '0x7fffffff'],
-        'long': ['-0x8000000000000000',
-                 '-0x81',
-                 '-0x80',
-                 '-0x1',
-                 '0x0',
-                 '0x7f',
-                 '0x80',
-                 '0x7fffffffffffffff'],
-        # float and double: Because of difficulty with rounding of floating point numbers, we use the binary
-        # representation instead which should be exact when comparing sent and received values.
-        'float': ['0x00000000', # 0.0
-                  '0x80000000', # -0.0
-                  '0x40490fdb', # pi (3.14159265359) positive decimal
-                  '0xc02df854', # -e (-2.71828182846) negative decimal
-                  '0x00000001', # Smallest positive denormalized number
-                  '0x80000001', # Smallest negative denormalized number
-                  '0x007fffff', # Largest positive denormalized number
-                  '0x807fffff', # Largest negative denormalized number
-                  '0x00800000', # Smallest positive normalized number
-                  '0x80800000', # Smallest negative normalized number
-                  '0x7f7fffff', # Largest positive normalized number
-                  '0xff7fffff', # Largest negative normalized number
-                  #'0x7f800000', # +Infinity # PROTON-1149 - fails on RHEL7
-                  #'0xff800000', # -Infinity # PROTON-1149 - fails on RHEL7
-                  '0x7fc00000', # +NaN
-                  '0xffc00000'], # -NaN
-        'double': ['0x0000000000000000', # 0.0
-                   '0x8000000000000000', # -0.0
-                   '0x400921fb54442eea', # pi (3.14159265359) positive decimal
-                   '0xc005bf0a8b145fcf', # -e (-2.71828182846) negative decimal
-                   '0x0000000000000001', # Smallest positive denormalized number
-                   '0x8000000000000001', # Smallest negative denormalized number
-                   '0x000fffffffffffff', # Largest positive denormalized number
-                   '0x800fffffffffffff', # Largest negative denormalized number
-                   '0x0010000000000000', # Smallest positive normalized number
-                   '0x8010000000000000', # Smallest negative normalized number
-                   '0x7fefffffffffffff', # Largest positive normalized number
-                   '0xffefffffffffffff', # Largest negative normalized number
-                   '0x7ff0000000000000', # +Infinity
-                   '0xfff0000000000000', # -Infinity
-                   '0x7ff8000000000000', # +NaN
-                   '0xfff8000000000000'], # -NaN
-        # decimal32, decimal64, decimal128:
-        # Until more formal support for decimal32, decimal64 and decimal128 are included in Python, we use
-        # a hex format for basic tests, and treat the data as a binary blob.
-        'decimal32': ['0x00000000',
-                      '0x40490fdb',
-                      '0xc02df854',
-                      '0xff7fffff'],
-        'decimal64': ['0x0000000000000000',
-                      '0x400921fb54442eea',
-                      '0xc005bf0a8b145fcf',
-                      '0xffefffffffffffff'],
-        'decimal128': ['0x00000000000000000000000000000000',
-                       '0xff0102030405060708090a0b0c0d0e0f'],
-        'char': [u'a',
-                 u'Z',
-                 u'0x1',
-                 u'0x7f',
-                 u'0x16b5', # Rune 'G'
-                 u'0x10ffff'],
-        # timestamp: Must be in milliseconds since the Unix epoch
-        'timestamp': ['0x0',
-                      '0x%x' % int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000),
-                      '0x%x' % int(time()*1000)
-                     ],
-        'uuid': [str(UUID(int=0x0)),
-                 str(UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')),
-                 str(uuid4())],
-        'binary': [bytes(),
-                   bytes(12345),
-                   b'Hello, world!',
-                   b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
-                   b'The quick brown fox jumped over the lazy dog 0123456789.' * 100
-                  ],
-        # strings must be unicode to comply with AMQP spec
-        'string': [u'',
-                   u'Hello, world!',
-                   u'"Hello, world!"',
-                   u"Charlie's peach",
-                   u'The quick brown fox jumped over the lazy dog 0123456789.' * 100
-                  ],
-        'symbol': ['',
-                   'myDomain.123',
-                   '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(),
-                  'symbol:a.b.c',
-                  'none:',
-                  'decimal64:0x400921fb54442eea'
-                 ],
-                 [[],
-                  'none',
-                  ['ubyte:1', 'ubyte:2', 'ubyte:3'],
-                  'boolean:True',
-                  'boolean:False',
-                  {'string:hello': 'long:1234', '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
-                ],
-        'map': [
-            # Enpty map
-            {},
-            # Map with string keys
-            {'string:one': 'ubyte:1',
-             'string:two': 'ushort:2'},
-            # Map with other AMQP simple types as keys
-            {'none:': 'string:None',
-             'string:None': 'none:',
-             'string:One': 'long:-1234567890',
-             'short:2': 'int:2',
-             'boolean:True': 'string:True',
-             'string:False': 'boolean:False',
-             #['string:AAA', 'ushort:5951']: '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'}},
-            ],
-        # TODO: Support all AMQP types in array (including keys)
-        #'array': [[],
-        #          [1, 2, 3],
-        #          ['Hello', 'world'],
-        #          [[1, 2, 3],
-        #           ['a', 'b', 'c'],
-        #           [2.3, 3.4, 4,5],
-        #           [True, False, True, True]]
-        #          ]
-        }
-
-    # This section contains tests that should be skipped because of know issues that would cause the test to fail.
-    # As the issues are resolved, these should be removed.
-    BROKER_SKIP = {'null': {'ActiveMQ': 'Null type not sent in Proton Python binding: PROTON-1091',
-                            'qpid-cpp': 'Null type not sent in Proton Python binding: PROTON-1091',},
-                   'decimal32': {'ActiveMQ': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160',
-                                 'qpid-cpp': 'decimal32 not supported on qpid-cpp broker: QPIDIT-5, QPID-6328',
-                                 'apache-activemq-artemis': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160',
-                                 'qpid-dispatch-router': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160'},
-                   'decimal64': {'ActiveMQ': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160',
-                                 'qpid-cpp': 'decimal64 not supported on qpid-cpp broker: QPIDIT-6, QPID-6328',
-                                 'apache-activemq-artemis': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160',
-                                 'qpid-dispatch-router': 'decimal32 and decimal64 are sent byte reversed: PROTON-1160'},
-                   'decimal128': {'qpid-cpp': 'decimal128 not supported on qpid-cpp broker: QPIDIT-3, QPID-6328',},
-                   'char': {'qpid-cpp': 'char not supported on qpid-cpp broker: QPIDIT-4, QPID-6328',
-                            'apache-activemq-artemis': 'char types > 16 bits truncated on Artemis: ENTMQ-1685'},
-                   'float': {'apache-activemq-artemis': '-NaN is stripped of its sign: ENTMQ-1686'},
-                   'double': {'apache-activemq-artemis': '-NaN is stripped of its sign: ENTMQ-1686'},
-                  }
-
-
-class AmqpTypeTestCase(unittest.TestCase):
-    """
-    Abstract base class for AMQP Type test cases
-    """
-
-    def run_test(self, broker_addr, amqp_type, test_value_list, send_shim, receive_shim):
-        """
-        Run 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.
-        """
-        if len(test_value_list) > 0:
-            # TODO: When Artemis can support it (in the next release), revert the queue name back to 'qpid-interop...'
-            # Currently, Artemis only supports auto-create queues for JMS, and the queue name must be prefixed by
-            # 'jms.queue.'
-            #queue_name = 'qpid-interop.simple_type_tests.%s.%s.%s' % (amqp_type, send_shim.NAME, receive_shim.NAME)
-            queue_name = 'jms.queue.qpid-interop.simple_type_tests.%s.%s.%s' % \
-                         (amqp_type, send_shim.NAME, receive_shim.NAME)
-
-            # Start the receive shim first (for queueless brokers/dispatch)
-            receiver = receive_shim.create_receiver(broker_addr, queue_name, amqp_type,
-                                                    str(len(test_value_list)))
-            receiver.start()
-
-            # Start the send shim
-            sender = send_shim.create_sender(broker_addr, queue_name, amqp_type,
-                                             dumps(test_value_list))
-            sender.start()
-
-            # Wait for both shims to finish
-            sender.join_or_kill(shims.THREAD_TIMEOUT)
-            receiver.join_or_kill(shims.THREAD_TIMEOUT)
-
-            # Process return string from sender
-            send_obj = sender.get_return_object()
-            if send_obj is not None:
-                if isinstance(send_obj, str) and len(send_obj) > 0:
-                    self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
-                else:
-                    self.fail('Sender error: %s' % str(send_obj))
-
-            # Process return string from receiver
-            receive_obj = receiver.get_return_object()
-            if isinstance(receive_obj, list):
-                self.assertEqual(receive_obj, test_value_list, msg='\n    sent:%s\nreceived:%s' % \
-                                 (test_value_list, receive_obj))
-            else:
-                self.fail('Receiver error: %s' % str(receive_obj))
-
-def create_testcase_class(broker_name, types, broker_addr, amqp_type, shim_product):
-    """
-    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):
-        """Function which creates a new test method in class cls"""
-
-        @unittest.skipIf(types.skip_test(amqp_type, broker_name),
-                         types.skip_test_message(amqp_type, broker_name))
-        def inner_test_method(self):
-            self.run_test(self.broker_addr, self.amqp_type, self.test_value_list, send_shim, receive_shim)
-
-        inner_test_method.__name__ = 'test_%s_%s->%s' % (amqp_type, 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,
-                  'broker_addr': broker_addr,
-                  'test_value_list': types.get_test_values(amqp_type)}
-    new_class = type(class_name, (AmqpTypeTestCase,), class_dict)
-    for send_shim, receive_shim in shim_product:
-        add_test_method(new_class, send_shim, receive_shim)
-    return new_class
-
-
-# SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
-# every shim in this list, a test is dynamically constructed which tests it against itself as well as every
-# other shim in the list.
-#
-# As new shims are added, add them into this map to have them included in the test cases.
-PROTON_CPP_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'amqp_types_test',
-                                     'Receiver')
-PROTON_CPP_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'amqp_types_test',
-                                   'Sender')
-PROTON_PYTHON_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'amqp_types_test',
-                                        'Receiver.py')
-PROTON_PYTHON_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'amqp_types_test',
-                                      'Sender.py')
-
-SHIM_MAP = {shims.ProtonCppShim.NAME: shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
-            shims.ProtonPythonShim.NAME: shims.ProtonPythonShim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-           }
-
-
-class TestOptions(object):
-    """
-    Class controlling command-line arguments used to control the test.
-    """
-    def __init__(self):
-        parser = argparse.ArgumentParser(description='Qpid-interop AMQP client interoparability test suite '
-                                         'for AMQP simple types')
-        parser.add_argument('--broker', action='store', default='localhost:5672', metavar='BROKER:PORT',
-                            help='Broker against which to run test suite.')
-#        test_group = parser.add_mutually_exclusive_group()
-#        test_group.add_argument('--include-test', action='append', metavar='TEST-NAME',
-#                                help='Name of test to include')
-#        test_group.add_argument('--exclude-test', action='append', metavar='TEST-NAME',
-#                                help='Name of test to exclude')
-#        type_group = test_group.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(AmqpPrimitiveTypes.TYPE_MAP.keys()))
-        parser.add_argument('--exclude-type', action='append', metavar='AMQP-TYPE',
-                            help='Name of AMQP type to exclude. Supported types:\n%s' %
-                            sorted(AmqpPrimitiveTypes.TYPE_MAP.keys()))
-#        shim_group = test_group.add_mutually_exclusive_group()
-#        shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',
-#                                help='Name of shim to include. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
-        parser.add_argument('--exclude-shim', action='append', metavar='SHIM-NAME',
-                            help='Name of shim to exclude. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
-        self.args = parser.parse_args()
-
-
-#--- Main program start ---
-
-if __name__ == '__main__':
-
-    ARGS = TestOptions().args
-    #print 'ARGS:', ARGS # debug
-
-    # Connect to broker to find broker type
-    CONNECTION_PROPS = broker_properties.getBrokerProperties(ARGS.broker)
-    if CONNECTION_PROPS is None:
-        print 'WARNING: Unable to get connection properties - unknown broker'
-        BROKER = 'unknown'
-    else:
-        BROKER = CONNECTION_PROPS[symbol(u'product')] if symbol(u'product') in CONNECTION_PROPS \
-                 else '<product not found>'
-        BROKER_VERSION = CONNECTION_PROPS[symbol(u'version')] if symbol(u'version') in CONNECTION_PROPS \
-                         else '<version not found>'
-        BROKER_PLATFORM = CONNECTION_PROPS[symbol(u'platform')] if symbol(u'platform') in CONNECTION_PROPS \
-                          else '<platform not found>'
-        print 'Test Broker: %s v.%s on %s' % (BROKER, BROKER_VERSION, BROKER_PLATFORM)
-        print
-        stdout.flush()
-
-    TYPES = AmqpPrimitiveTypes()
-
-    # TEST_CASE_CLASSES is a list that collects all the test classes that are constructed. One class is constructed
-    # per AMQP type used as the key in map AmqpPrimitiveTypes.TYPE_MAP.
-    TEST_CASE_CLASSES = []
-
-    # TEST_SUITE is the final suite of tests that will be run and which contains all the dynamically created
-    # type classes, each of which contains a test for the combinations of client shims
-    TEST_SUITE = unittest.TestSuite()
-
-    # Remove shims excluded from the command-line
-    if ARGS.exclude_shim is not None:
-        for shim in ARGS.exclude_shim:
-            SHIM_MAP.pop(shim)
-    # Create test classes dynamically
-    for at in sorted(TYPES.get_type_list()):
-        if ARGS.exclude_type is None or at not in ARGS.exclude_type:
-            test_case_class = create_testcase_class(BROKER,
-                                                    TYPES,
-                                                    ARGS.broker,
-                                                    at,
-                                                    product(SHIM_MAP.values(), repeat=2))
-            TEST_CASE_CLASSES.append(test_case_class)
-            TEST_SUITE.addTest(unittest.makeSuite(test_case_class))
-
-    # Finally, run all the dynamically created tests
-    RES = unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
-    if not RES.wasSuccessful():
-        sys.exit(1) # Errors or failures present

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/broker_properties.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/broker_properties.py b/src/python/qpid-interop-test/broker_properties.py
deleted file mode 100644
index 08cc9cc..0000000
--- a/src/python/qpid-interop-test/broker_properties.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-Module containing a small client which connects to the broker and
-gets the broker connection properties so as to identify the broker.
-"""
-
-#
-# 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 proton.handlers import MessagingHandler
-from proton.reactor import Container
-
-class Client(MessagingHandler):
-    """
-    Client to connect to broker and collect connection properties, used to identify the test broker
-    """
-    def __init__(self, url):
-        super(Client, self).__init__()
-        self.url = url
-        self.remote_properties = None
-
-    def on_connection_remote_open(self, event):
-        self.remote_properties = event.connection.remote_properties
-        event.connection.close()
-
-    def on_start(self, event):
-        """Event loop start"""
-        event.container.connect(url=self.url)
-
-    def get_connection_properties(self):
-        """Return the connection properties"""
-        return self.remote_properties
-
-
-def getBrokerProperties(broker_url):
-    """Start client, then return its connection properties"""
-    MSG_HANDLER = Client(broker_url)
-    Container(MSG_HANDLER).run()
-    return MSG_HANDLER.get_connection_properties()

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/interop_test_errors.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/interop_test_errors.py b/src/python/qpid-interop-test/interop_test_errors.py
deleted file mode 100644
index 6be8959..0000000
--- a/src/python/qpid-interop-test/interop_test_errors.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-Module containing Error classes for interop testing
-"""
-
-#
-# 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.
-#
-
-class InteropTestError(StandardError):
-    """
-    Generic simple error class for use in interop tests
-    """
-    def __init__(self, error_message):
-        super(InteropTestError, self).__init__(error_message)


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


[2/5] qpid-interop-test git commit: QPIDIT-41: Reorganized dir structure and tidied up the test code. Copied the old jms_messages_test to a new jms_hdrs_props_test and simplified the jms_messages_test to include only message body tests. Simplified parame

Posted by kp...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/jms_messages_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/jms_messages_test.py b/src/python/qpid-interop-test/jms_messages_test.py
deleted file mode 100755
index 56cb203..0000000
--- a/src/python/qpid-interop-test/jms_messages_test.py
+++ /dev/null
@@ -1,511 +0,0 @@
-#!/usr/bin/env python
-
-"""
-Module to test JMS message types across different APIs
-"""
-
-#
-# 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 argparse
-import sys
-import unittest
-
-from itertools import product
-from json import dumps
-from os import getenv, path
-from sys import stdout
-
-import broker_properties
-import shims
-from proton import symbol
-from test_type_map import TestTypeMap
-
-
-# TODO: propose a sensible default when installation details are worked out
-QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
-if QPID_INTEROP_TEST_HOME is None:
-    print 'ERROR: Environment variable QPID_INTEROP_TEST_HOME is not set'
-    sys.exit(1)
-MAVEN_REPO_PATH = getenv('MAVEN_REPO_PATH', path.join(getenv('HOME'), '.m2', 'repository'))
-
-class JmsMessageTypes(TestTypeMap):
-    """
-    Class which contains all the described JMS message types and the test values to be used in testing.
-    """
-
-    COMMON_SUBMAP = {
-        'boolean': ['True',
-                    'False'],
-        'byte': ['-0x80',
-                 '-0x1',
-                 '0x0',
-                 '0x7f'],
-        'double': ['0x0000000000000000', # 0.0
-                   '0x8000000000000000', # -0.0
-                   '0x400921fb54442eea', # pi (3.14159265359) positive decimal
-                   '0xc005bf0a8b145fcf', # -e (-2.71828182846) negative decimal
-                   '0x0000000000000001', # Smallest positive denormalized number
-                   '0x8000000000000001', # Smallest negative denormalized number
-                   '0x000fffffffffffff', # Largest positive denormalized number
-                   '0x8010000000000000', # Largest negative denormalized number
-                   '0x7fefffffffffffff', # Largest positive normalized number
-                   '0xffefffffffffffff', # Largest negative normalized number
-                   '0x7ff0000000000000', # +Infinity
-                   '0xfff0000000000000', # -Infinity
-                   '0x7ff8000000000000'], # +NaN
-        'float': ['0x00000000', # 0.0
-                  '0x80000000', # -0.0
-                  '0x40490fdb', # pi (3.14159265359) positive decimal
-                  '0xc02df854', # -e (-2.71828182846) negative decimal
-                  '0x00000001', # Smallest positive denormalized number
-                  '0x80000001', # Smallest negative denormalized number
-                  '0x007fffff', # Largest positive denormalized number
-                  '0x807fffff', # Largest negative denormalized number
-                  '0x00800000', # Smallest positive normalized number
-                  '0x80800000', # Smallest negative normalized number
-                  '0x7f7fffff', # Largest positive normalized number
-                  '0xff7fffff', # Largest negative normalized number
-                  #'0x7f800000', # +Infinity  # PROTON-1149 - fails on RHEL7
-                  #'0xff800000', # -Infinity # PROTON-1149 - fails on RHEL7
-                  '0x7fc00000'], # +NaN
-        'int': ['-0x80000000',
-                '-0x81',
-                '-0x80',
-                '-0x1',
-                '0x0',
-                '0x7f',
-                '0x80',
-                '0x7fffffff'],
-        'long': ['-0x8000000000000000',
-                 '-0x81',
-                 '-0x80',
-                 '-0x1',
-                 '0x0',
-                 '0x7f',
-                 '0x80',
-                 '0x7fffffffffffffff'],
-        'short': ['-0x8000',
-                  '-0x1',
-                  '0x0',
-                  '0x7fff'],
-        'string': ['',
-                   'Hello, world',
-                   '"Hello, world"',
-                   "Charlie's \"peach\"",
-                   'Charlie\'s "peach"',
-                   'The quick brown fox jumped over the lazy dog 0123456789.'# * 100]
-                  ]
-        }
-
-    TYPE_ADDITIONAL_SUBMAP = {
-        'bytes': [b'',
-                  b'12345',
-                  b'Hello, world',
-                  b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
-                  b'The quick brown fox jumped over the lazy dog 0123456789.' #* 100],
-                 ],
-        'char': ['a',
-                 'Z',
-                 '\x01',
-                 '\x7f'],
-        }
-
-    # The TYPE_SUBMAP defines test values for JMS message types that allow typed message content. Note that the
-    # types defined here are understood to be *Java* types and the stringified values are to be interpreted
-    # as the appropriate Java type by the send shim.
-    TYPE_SUBMAP = TestTypeMap.merge_dicts(COMMON_SUBMAP, TYPE_ADDITIONAL_SUBMAP)
-
-    # Defines JMS headers that should be set by the send or publish API call of the client
-    HEADERS_PUBLISH_LIST = [
-        'JMS_DESTINATION',
-        'JMS_DELIVERY_MODE',
-        'JMS_EXPIRATION',
-        'JMS_PRIORITY',
-        'JMS_MESSAGEID',
-        'JMS_TIMESTAMP',
-        ]
-
-    # Defines JMS headers that are modified by the broker when he message is consumed
-    HEADERS_BROKER_LIST = [
-        'JMS_REDELIVERED',
-        ]
-
-    # JMS headers that can be set by the client prior to send / publish, and that should be preserved byt he broker
-    HEADERS_MAP = {
-        'JMS_CORRELATIONID_HEADER': {'string': ['Hello, world',
-                                                '"Hello, world"',
-                                                "Charlie's \"peach\"",
-                                                'Charlie\'s "peach"',
-                                                'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
-                                                #'', # TODO: Re-enable when PROTON-1288 is fixed
-                                               ],
-                                     'bytes': [b'12345\\x006789',
-                                               b'Hello, world',
-                                               b'"Hello, world"',
-                                               b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
-                                               b'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
-                                               #b'', # TODO: Re-enable when PROTON-1288 is fixed
-                                              ],
-                                    },
-        'JMS_REPLYTO_HEADER': {'queue': ['q_aaa', 'q_bbb'],
-                               'topic': ['t_aaa', 't_bbb'],
-                              },
-        'JMS_TYPE_HEADER': {'string': ['Hello, world',
-                                       '"Hello, world"',
-                                       "Charlie's \"peach\"",
-                                       'Charlie\'s "peach"',
-                                       'The quick brown fox jumped over the lazy dog 0123456789.' * 10,
-                                       #'', # TODO: Re-enable when PROTON-1288 is fixed
-                                      ],
-                           },
-        }
-
-    PROPERTIES_MAP = COMMON_SUBMAP # disabled until PROTON-1284 is fixed
-
-    TYPE_MAP = {
-        'JMS_MESSAGE_TYPE': {'none': [None]},
-        'JMS_BYTESMESSAGE_TYPE': TYPE_SUBMAP,
-        'JMS_MAPMESSAGE_TYPE': TYPE_SUBMAP,
-        'JMS_STREAMMESSAGE_TYPE': TYPE_SUBMAP,
-        'JMS_TEXTMESSAGE_TYPE': {'text': ['',
-                                          'Hello, world',
-                                          '"Hello, world"',
-                                          "Charlie's \"peach\"",
-                                          'Charlie\'s "peach"',
-                                          'The quick brown fox jumped over the lazy dog 0123456789.' * 10
-                                         ]
-                                },
-        # TODO: Add Object messages when other (non-JMS clients) can generate Java class strings used in this message
-        # type
-        #'JMS_OBJECTMESSAGE_TYPE': {
-        #    'java.lang.Boolean': ['true',
-        #                          'false'],
-        #    'java.lang.Byte': ['-128',
-        #                       '0',
-        #                       '127'],
-        #    'java.lang.Character': [u'a',
-        #                            u'Z'],
-        #    'java.lang.Double': ['0.0',
-        #                         '3.141592654',
-        #                         '-2.71828182846'],
-        #    'java.lang.Float': ['0.0',
-        #                        '3.14159',
-        #                        '-2.71828'],
-        #    'java.lang.Integer': ['-2147483648',
-        #                          '-129',
-        #                          '-128',
-        #                          '-1',
-        #                          '0',
-        #                          '127',
-        #                          '128',
-        #                          '2147483647'],
-        #    'java.lang.Long' : ['-9223372036854775808',
-        #                        '-129',
-        #                        '-128',
-        #                        '-1',
-        #                        '0',
-        #                        '127',
-        #                        '128',
-        #                        '9223372036854775807'],
-        #    'java.lang.Short': ['-32768',
-        #                        '-129',
-        #                        '-128',
-        #                        '-1',
-        #                        '0',
-        #                        '127',
-        #                        '128',
-        #                        '32767'],
-        #    'java.lang.String': [u'',
-        #                         u'Hello, world',
-        #                         u'"Hello, world"',
-        #                         u"Charlie's \"peach\"",
-        #                         u'Charlie\'s "peach"']
-        #    },
-        }
-
-    BROKER_SKIP = {}
-
-
-class JmsMessageTypeTestCase(unittest.TestCase):
-    """
-    Abstract base class for JMS message type test cases
-    """
-
-    def run_test(self, broker_addr, jms_message_type, test_values, msg_hdrs, msg_props, send_shim, receive_shim):
-        """
-        Run 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.
-        """
-        queue_name = 'jms.queue.qpid-interop.jms_message_type_tests.%s.%s.%s' % (jms_message_type, send_shim.NAME,
-                                                                                 receive_shim.NAME)
-
-        # First create a map containing the numbers of expected mesasges for each JMS message type
-        num_test_values_map = {}
-        if len(test_values) > 0:
-            for index in test_values.keys():
-                num_test_values_map[index] = len(test_values[index])
-        # Create a map of flags which indicate to the receiver the details of some of the messages so that it can
-        # be correctly handled (as these require some prior knowledge)
-        flags_map = {}
-        if 'JMS_CORRELATIONID_HEADER' in msg_hdrs and 'bytes' in msg_hdrs['JMS_CORRELATIONID_HEADER']:
-            flags_map['JMS_CORRELATIONID_AS_BYTES'] = True
-        if 'JMS_REPLYTO_HEADER' in msg_hdrs and 'topic' in msg_hdrs['JMS_REPLYTO_HEADER']:
-            flags_map['JMS_REPLYTO_AS_TOPIC'] = True
-        # Start the receiver shim
-        receiver = receive_shim.create_receiver(broker_addr, queue_name, jms_message_type,
-                                                dumps([num_test_values_map, flags_map]))
-        receiver.start()
-
-        # Start the send shim
-        sender = send_shim.create_sender(broker_addr, queue_name, jms_message_type,
-                                         dumps([test_values, msg_hdrs, msg_props]))
-        sender.start()
-
-        # Wait for both shims to finish
-        sender.join_or_kill(shims.THREAD_TIMEOUT)
-        receiver.join_or_kill(shims.THREAD_TIMEOUT)
-
-        # Process return string from sender
-        send_obj = sender.get_return_object()
-        if send_obj is not None:
-            if isinstance(send_obj, str) and len(send_obj) > 0:
-                self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
-            else:
-                self.fail('Send shim \'%s\':\n%s' % str(send_obj))
-
-        # Process return string from receiver
-        receive_obj = receiver.get_return_object()
-        if receive_obj is None:
-            self.fail('JmsReceiver shim returned None')
-        else:
-            if isinstance(receive_obj, tuple):
-                if len(receive_obj) == 4:
-                    return_jms_message_type, return_test_values, return_msg_hdrs, return_msg_props = receive_obj
-                    self.assertEqual(return_jms_message_type, jms_message_type,
-                                     msg='JMS message type error:\n\n    sent:%s\n\n    received:%s' % \
-                                     (jms_message_type, return_jms_message_type))
-                    self.assertEqual(return_test_values, test_values,
-                                     msg='JMS message body error:\n\n    sent:%s\n\n    received:%s' % \
-                                     (test_values, return_test_values))
-                    self.assertEqual(return_msg_hdrs, msg_hdrs,
-                                     msg='JMS message headers error:\n\n    sent:%s\n\n    received:%s' % \
-                                     (msg_hdrs, return_msg_hdrs))
-                    self.assertEqual(return_msg_props, msg_props,
-                                     msg='JMS message properties error:\n\n    sent:%s\n\n    received:%s' % \
-                                     (msg_props, return_msg_props))
-            else:
-                self.fail(str(receive_obj))
-
-
-def create_testcase_class(broker_name, types, broker_addr, jms_message_type, shim_product):
-    """
-    Class factory function which creates new subclasses to JmsMessageTypeTestCase. Each call creates a single new
-    test case named and based on the parameters supplied to the method
-    """
-
-    def __repr__(self):
-        """Print the class name"""
-        return self.__class__.__name__
-
-    def add_test_method(cls, hdrs, props, send_shim, receive_shim):
-        """Function which creates a new test method in class cls"""
-
-        @unittest.skipIf(types.skip_test(jms_message_type, broker_name),
-                         types.skip_test_message(jms_message_type, broker_name))
-        def inner_test_method(self):
-            self.run_test(self.broker_addr,
-                          self.jms_message_type,
-                          self.test_values,
-                          hdrs[1],
-                          props[1],
-                          send_shim,
-                          receive_shim)
-
-        inner_test_method.__name__ = 'test_%s%s%s_%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0], send_shim.NAME,
-                                                             receive_shim.NAME)
-        setattr(cls, inner_test_method.__name__, inner_test_method)
-
-    class_name = jms_message_type[4:-5].title() + 'TestCase'
-    class_dict = {'__name__': class_name,
-                  '__repr__': __repr__,
-                  '__doc__': 'Test case for JMS message type \'%s\'' % jms_message_type,
-                  'jms_message_type': jms_message_type,
-                  'broker_addr': broker_addr,
-                  'test_values': types.get_test_values(jms_message_type)} # tuple (tot_size, {...}
-    new_class = type(class_name, (JmsMessageTypeTestCase,), class_dict)
-    for send_shim, receive_shim in shim_product:
-        # Message without any headers or properties
-        add_test_method(new_class, ('', {}), ('', {}), send_shim, receive_shim)
-
-        # Iterate through message headers, add one test per header value, no combinations
-        # Structure: {HEADER_NAME_1; {header_type_1: [val_1_1, val_1_2, val_1_3, ...],
-        #                             header_type_2: [val_2_1, val_2_2, val_2_3, ...],
-        #                             ...
-        #                            },
-        #             ...
-        #            }
-        for msg_header, header_type_dict in types.HEADERS_MAP.iteritems():
-            for header_type, header_val_list in header_type_dict.iteritems():
-                hdr_val_cnt = 0
-                for header_val in header_val_list:
-                    hdr_val_cnt += 1
-                    test_name = '_hdr.%s.%s.%02d' % (msg_header[4:-7], header_type, hdr_val_cnt)
-                    add_test_method(new_class,
-                                    (test_name, {msg_header: {header_type: header_val}}),
-                                    ('', {}),
-                                    send_shim,
-                                    receive_shim)
-
-        # One message with all the headers together using type[0] and val[0]
-        all_hdrs = {}
-        for msg_header in types.HEADERS_MAP.iterkeys():
-            header_type_dict = types.HEADERS_MAP[msg_header]
-            header_type, header_val_list = header_type_dict.iteritems().next()
-            header_val = header_val_list[0]
-            all_hdrs[msg_header] = {header_type: header_val}
-        add_test_method(new_class, ('_hdrs', all_hdrs), ('', {}), send_shim, receive_shim)
-
-        # Properties tests disabled until PROTON-1284 fixed
-        ## Iterate through properties
-        ## Structure: {prop_type_1: [val_1_1, val_1_2, ...],
-        ##             prop_type_2: [val_2_1, val_2_2, ...],
-        ##             ...
-        ##            }
-        #all_props = {}
-        #for prop_type, prop_val_list in types.PROPERTIES_MAP.iteritems():
-        #    prop_val_cnt = 0
-        #    for prop_val in prop_val_list:
-        #        prop_val_cnt += 1
-        #        all_props['%s_%02d' % (prop_type, prop_val_cnt)] = {prop_type: prop_val}
-
-        ## One message with all properties together
-        #add_test_method(new_class, ('', {}), ('_props', all_props), send_shim, receive_shim)
-
-        ## One message with all headers and all properties together
-        #add_test_method(new_class, ('_hdrs', all_hdrs), ('_props', all_props), send_shim, receive_shim)
-
-    return new_class
-
-
-PROTON_CPP_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_messages_test',
-                                     'Receiver')
-PROTON_CPP_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'jms_messages_test',
-                                   'Sender')
-PROTON_PYTHON_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'jms_messages_test',
-                                        'Receiver.py')
-PROTON_PYTHON_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'jms_messages_test',
-                                      'Sender.py')
-QIT_JMS_CLASSPATH_FILE = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'cp.txt')
-with open(QIT_JMS_CLASSPATH_FILE, 'r') as classpath_file:
-    QIT_JMS_CLASSPATH = classpath_file.read()
-QPID_JMS_RECEIVER_SHIM = 'org.apache.qpid.interop_test.jms_messages_test.Receiver'
-QPID_JMS_SENDER_SHIM = 'org.apache.qpid.interop_test.jms_messages_test.Sender'
-
-# SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
-# every shim in this list, a test is dynamically constructed which tests it against itself as well as every
-# other shim in the list.
-#
-# As new shims are added, add them into this map to have them included in the test cases.
-SHIM_MAP = {shims.ProtonCppShim.NAME: shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
-            shims.ProtonPythonShim.NAME: shims.ProtonPythonShim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
-            shims.QpidJmsShim.NAME: shims.QpidJmsShim(QIT_JMS_CLASSPATH, QPID_JMS_SENDER_SHIM, QPID_JMS_RECEIVER_SHIM),
-           }
-
-# TODO: Complete the test options to give fine control over running tests
-class TestOptions(object):
-    """
-    Class controlling command-line arguments used to control the test.
-    """
-    def __init__(self,):
-        parser = argparse.ArgumentParser(description='Qpid-interop AMQP client interoparability test suite '
-                                         'for JMS message types')
-        parser.add_argument('--broker', action='store', default='localhost:5672', metavar='BROKER:PORT',
-                            help='Broker against which to run test suite.')
-#        test_group = parser.add_mutually_exclusive_group()
-#        test_group.add_argument('--include-test', action='append', metavar='TEST-NAME',
-#                                help='Name of test to include')
-#        test_group.add_argument('--exclude-test', action='append', metavar='TEST-NAME',
-#                                help='Name of test to exclude')
-#        type_group = test_group.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(JmsMessageTypes.TYPE_MAP.keys()))
-        parser.add_argument('--exclude-type', action='append', metavar='JMS-MESSAGE-TYPE',
-                            help='Name of JMS message type to exclude. Supported types:\n%s' %
-                            sorted(JmsMessageTypes.TYPE_MAP.keys()))
-#        shim_group = test_group.add_mutually_exclusive_group()
-#        shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',
-#                                help='Name of shim to include. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
-        parser.add_argument('--exclude-shim', action='append', metavar='SHIM-NAME',
-                            help='Name of shim to exclude. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
-        self.args = parser.parse_args()
-
-
-#--- Main program start ---
-
-if __name__ == '__main__':
-    ARGS = TestOptions().args
-    #print 'ARGS:', ARGS # debug
-
-    # Connect to broker to find broker type
-    CONNECTION_PROPS = broker_properties.getBrokerProperties(ARGS.broker)
-    if CONNECTION_PROPS is None:
-        print 'WARNING: Unable to get connection properties - unknown broker'
-        BROKER = 'unknown'
-    else:
-        BROKER = CONNECTION_PROPS[symbol(u'product')] if symbol(u'product') in CONNECTION_PROPS \
-                 else '<product not found>'
-        BROKER_VERSION = CONNECTION_PROPS[symbol(u'version')] if symbol(u'version') in CONNECTION_PROPS \
-                         else '<version not found>'
-        BROKER_PLATFORM = CONNECTION_PROPS[symbol(u'platform')] if symbol(u'platform') in CONNECTION_PROPS \
-                          else '<platform not found>'
-        print 'Test Broker: %s v.%s on %s' % (BROKER, BROKER_VERSION, BROKER_PLATFORM)
-        print
-        stdout.flush()
-
-    TYPES = JmsMessageTypes()
-
-    # TEST_CASE_CLASSES is a list that collects all the test classes that are constructed. One class is constructed
-    # per AMQP type used as the key in map JmsMessageTypes.TYPE_MAP.
-    TEST_CASE_CLASSES = []
-
-    # TEST_SUITE is the final suite of tests that will be run and which contains all the dynamically created
-    # type classes, each of which contains a test for the combinations of client shims
-    TEST_SUITE = unittest.TestSuite()
-
-    # Remove shims excluded from the command-line
-    if ARGS.exclude_shim is not None:
-        for shim in ARGS.exclude_shim:
-            SHIM_MAP.pop(shim)
-    # Create test classes dynamically
-    for jmt in sorted(TYPES.get_type_list()):
-        if ARGS.exclude_type is None or jmt not in ARGS.exclude_type:
-            test_case_class = create_testcase_class(BROKER,
-                                                    TYPES,
-                                                    ARGS.broker,
-                                                    jmt,
-                                                    product(SHIM_MAP.values(), repeat=2))
-            TEST_CASE_CLASSES.append(test_case_class)
-            TEST_SUITE.addTest(unittest.makeSuite(test_case_class))
-
-    # Finally, run all the dynamically created tests
-    RES = unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
-    if not RES.wasSuccessful():
-        sys.exit(1)

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/shims.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/shims.py b/src/python/qpid-interop-test/shims.py
deleted file mode 100644
index 5e94d2d..0000000
--- a/src/python/qpid-interop-test/shims.py
+++ /dev/null
@@ -1,229 +0,0 @@
-"""
-Module containing worker thread classes and shims
-"""
-#
-# 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 json import loads
-from os import getenv, getpgid, killpg, path, setsid
-from signal import SIGKILL, SIGTERM
-from subprocess import Popen, PIPE, CalledProcessError
-from sys import stdout
-from threading import Thread
-from time import sleep
-
-
-THREAD_TIMEOUT = 10.0 # seconds to complete before join is forced
-
-
-class ShimWorkerThread(Thread):
-    """Parent class for shim worker threads and return a string once the thread has ended"""
-    def __init__(self, thread_name):
-        super(ShimWorkerThread, self).__init__(name=thread_name)
-        self.arg_list = []
-        self.return_obj = None
-        self.proc = None
-
-    def get_return_object(self):
-        """Get the return object from the completed thread"""
-        return self.return_obj
-
-    def join_or_kill(self, timeout):
-        """
-        Wait for thread to join after timeout (seconds). If still alive, it is then terminated, then if still alive,
-        killed
-        """
-        self.join(timeout)
-        if self.is_alive():
-            if self.proc is not None:
-                if self._terminate_pg_loop():
-                    if self._kill_pg_loop():
-                        print '\n  ERROR: Thread %s (pid=%d) alive after kill' % (self.name, self.proc.pid)
-                    else:
-                        print 'Killed'
-                        stdout.flush()
-                else:
-                    print 'Terminated'
-                    stdout.flush()
-            else:
-                print 'ERROR: shims.join_or_kill(): Process joined and is alive, yet proc is None.'
-
-    def _terminate_pg_loop(self, num_attempts=2, wait_time=2):
-        cnt = 0
-        while cnt < num_attempts and self.is_alive():
-            cnt += 1
-            print '\n  Thread %s (pid=%d) alive after timeout, terminating (try #%d)...' % (self.name, self.proc.pid,
-                                                                                            cnt),
-            stdout.flush()
-            killpg(getpgid(self.proc.pid), SIGTERM)
-            sleep(wait_time)
-        return self.is_alive()
-
-    def _kill_pg_loop(self, num_attempts=2, wait_time=5):
-        cnt = 0
-        while cnt < num_attempts and self.is_alive():
-            cnt += 1
-            print '\n  Thread %s (pid=%d) alive after terminate, killing (try #%d)...' % (self.name, self.proc.pid,
-                                                                                          cnt),
-            stdout.flush()
-            killpg(getpgid(self.proc.pid), SIGKILL)
-            sleep(wait_time)
-        return self.is_alive()
-
-
-class Sender(ShimWorkerThread):
-    """Sender class for multi-threaded send"""
-    def __init__(self, use_shell_flag, send_shim_args, broker_addr, queue_name, msg_type, json_test_str):
-        super(Sender, self).__init__('sender_thread_%s' % queue_name)
-        if send_shim_args is None:
-            print 'ERROR: Sender: send_shim_args == None'
-        self.use_shell_flag = use_shell_flag
-        self.arg_list.extend(send_shim_args)
-        self.arg_list.extend([broker_addr, queue_name, msg_type, json_test_str])
-
-    def run(self):
-        """Thread starts here"""
-        try:
-            #print '\n>>>', self.arg_list # DEBUG - useful to see command-line sent to shim
-            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, shell=self.use_shell_flag, preexec_fn=setsid)
-            (stdoutdata, stderrdata) = self.proc.communicate()
-            if len(stdoutdata) > 0 or len(stderrdata) > 0:
-                self.return_obj = (stdoutdata, stderrdata)
-        except CalledProcessError as exc:
-            self.return_obj = str(exc) + '\n\nOutput:\n' + exc.output
-
-
-class Receiver(ShimWorkerThread):
-    """Receiver class for multi-threaded receive"""
-    def __init__(self, receive_shim_args, broker_addr, queue_name, msg_type, json_test_str):
-        super(Receiver, self).__init__('receiver_thread_%s' % queue_name)
-        if receive_shim_args is None:
-            print 'ERROR: Receiver: receive_shim_args == None'
-        self.arg_list.extend(receive_shim_args)
-        self.arg_list.extend([broker_addr, queue_name, msg_type, json_test_str])
-
-    def run(self):
-        """Thread starts here"""
-        try:
-            #print '\n>>>', self.arg_list # DEBUG - useful to see command-line sent to shim
-            self.proc = Popen(self.arg_list, stdout=PIPE, stderr=PIPE, preexec_fn=setsid)
-            (stdoutdata, stderrdata) = self.proc.communicate()
-            if len(stderrdata) > 0:
-                self.return_obj = (stdoutdata, stderrdata)
-            else:
-                #print '<<<', stdoutdata # DEBUG - useful to see text received from shim
-                str_tvl = stdoutdata.split('\n')[0:-1] # remove trailing \n
-                #if len(str_tvl) == 1:
-                #    self.return_obj = output
-                if len(str_tvl) == 2: # AMQP type test return
-                    self.return_obj = loads(str_tvl[1])
-                elif len(str_tvl) == 4: # JMS test return
-                    self.return_obj = (str_tvl[0], loads(str_tvl[1]), loads(str_tvl[2]), loads(str_tvl[3]))
-                else: # Make a single line of all the bits and return that
-                    #self.return_obj = loads("".join(str_tvl[1:]))
-                    self.return_obj = stdoutdata
-        except CalledProcessError as exc:
-            self.return_obj = str(exc) + '\n\n' + exc.output
-
-class Shim(object):
-    """Abstract shim class, parent of all shims."""
-    NAME = None
-    def __init__(self, sender_shim, receiver_shim):
-        self.sender_shim = sender_shim
-        self.receiver_shim = receiver_shim
-        self.send_params = None
-        self.receive_params = None
-        self.use_shell_flag = False
-
-    def create_sender(self, broker_addr, queue_name, msg_type, json_test_str):
-        """Create a new sender instance"""
-        return Sender(self.use_shell_flag, self.send_params, broker_addr, queue_name, msg_type, json_test_str)
-
-    def create_receiver(self, broker_addr, queue_name, msg_type, json_test_str):
-        """Create a new receiver instance"""
-        return Receiver(self.receive_params, broker_addr, queue_name, msg_type, json_test_str)
-
-class ProtonPythonShim(Shim):
-    """Shim for qpid-proton Python client"""
-    NAME = 'ProtonPython'
-    def __init__(self, sender_shim, receiver_shim):
-        super(ProtonPythonShim, self).__init__(sender_shim, receiver_shim)
-        self.send_params = [self.sender_shim]
-        self.receive_params = [self.receiver_shim]
-
-
-class ProtonCppShim(Shim):
-    """Shim for qpid-proton C++ client"""
-    NAME = 'ProtonCpp'
-    def __init__(self, sender_shim, receiver_shim):
-        super(ProtonCppShim, self).__init__(sender_shim, receiver_shim)
-        self.send_params = [self.sender_shim]
-        self.receive_params = [self.receiver_shim]
-
-
-class QpidJmsShim(Shim):
-    """Shim for qpid-jms JMS client"""
-    NAME = 'QpidJms'
-
-    # Installed versions
-    # TODO: Automate this - it gets out of date quickly
-    # Maven works out all the deps, should use that
-    QPID_JMS_SHIM_VER = '0.1.0-SNAPSHOT'
-    QPID_JMS_VER = '0.20.0-SNAPSHOT'
-    QPID_PROTON_J_VER = '0.15.0-SNAPSHOT'
-    JMS_API_VER = '1.1.1'
-    LOGGER_API_VER = '1.7.21'
-    LOGGER_IMPL_VER = '1.7.21'
-    NETTY_VER = '4.0.40.Final'
-
-    # Classpath components
-    #QPID_INTEROP_TEST_SHIM_JAR = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-jms', 'target', 'qpid-jms-shim.jar')
-    MAVEN_REPO_PATH = path.join(getenv('HOME'), '.m2', 'repository')
-    JMS_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'geronimo', 'specs', 'geronimo-jms_1.1_spec', JMS_API_VER,
-                            'geronimo-jms_1.1_spec-%s.jar' % JMS_API_VER)
-    JMS_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-jms-client', QPID_JMS_VER,
-                             'qpid-jms-client-%s.jar' % QPID_JMS_VER)
-    LOGGER_API_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-api', LOGGER_API_VER,
-                               'slf4j-api-%s.jar' % LOGGER_API_VER)
-    LOGGER_IMPL_JAR = path.join(MAVEN_REPO_PATH, 'org', 'slf4j', 'slf4j-nop', LOGGER_IMPL_VER,
-                                'slf4j-nop-%s.jar' % LOGGER_IMPL_VER)
-    PROTON_J_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'proton-j', QPID_PROTON_J_VER,
-                             'proton-j-%s.jar' % QPID_PROTON_J_VER)
-    NETTY_JAR = path.join(MAVEN_REPO_PATH, 'io', 'netty', 'netty-all', NETTY_VER, 'netty-all-%s.jar' % NETTY_VER)
-    QPID_JMS_SHIM_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 'qpid-interop-test-jms-shim',
-                                  QPID_JMS_SHIM_VER, 'qpid-interop-test-jms-shim-%s.jar' % QPID_JMS_SHIM_VER)
-
-    JAVA_HOME = getenv('JAVA_HOME', '/usr/bin') # Default only works in Linux
-    JAVA_EXEC = path.join(JAVA_HOME, 'java')
-
-    def __init__(self, dependency_class_path, sender_shim, receiver_shim):
-        super(QpidJmsShim, self).__init__(sender_shim, receiver_shim)
-        self.dependency_class_path = dependency_class_path
-        self.send_params = [self.JAVA_EXEC, '-cp', self.get_java_class_path(), self.sender_shim]
-        self.receive_params = [self.JAVA_EXEC, '-cp', self.get_java_class_path(), self.receiver_shim]
-
-    def get_java_class_path(self):
-        """Method to construct and return the Java class path necessary to run the shim"""
-        return ':'.join([self.QPID_JMS_SHIM_JAR, self.dependency_class_path])
-    #                     self.JMS_API_JAR,
-    #                     self.JMS_IMPL_JAR,
-    #                     self.LOGGER_API_JAR,
-    #                     self.LOGGER_IMPL_JAR,
-    #                     self.PROTON_J_JAR,
-    #                     self.NETTY_JAR])

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid-interop-test/test_type_map.py
----------------------------------------------------------------------
diff --git a/src/python/qpid-interop-test/test_type_map.py b/src/python/qpid-interop-test/test_type_map.py
deleted file mode 100644
index b571ac8..0000000
--- a/src/python/qpid-interop-test/test_type_map.py
+++ /dev/null
@@ -1,85 +0,0 @@
-"""
-Module containing Error classes for interop testing
-"""
-#
-# 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.
-#
-
-class TestTypeMap(object):
-    """
-    Class which contains all the described types and the test values to be used in testing against those types.
-    """
-    
-    # TYPE_MAP: Map containing all described types as the indecies, and a list of values to be used in testing
-    # that type as a list of values.
-    #
-    # Format: {'type_1' : [val_1_1, val_1_2, ...],
-    #          'type_2' : [val_2_1, val_2_2, ...],
-    #          ...
-    #         }
-    TYPE_MAP = {}
-
-    # BROKER_SKIP: For know broker issues where a type would cause a test to fail or hang,
-    # entries in BROKER_SKIP will cause the test to be skipped with a message.
-    # This is a map containing AMQP types as a key, and a list of brokers for which this
-    # type should be skipped.
-    # Format: {'jms_msg_type_1' : {'broker_1' : 'skip msg for broker_1',
-    #                              'broker_2' : 'skip msg for broker_2',
-    #                               ...
-    #                             },
-    #          'jms_msg_type_2' : {'broker_1' : 'skip msg for broker_1',
-    #                              'broker_2' : 'skip msg for broker_2',
-    #                              ...
-    #                             },
-    #          ...
-    #         }
-    # where broker_1, broker_2, ... are broker product names as defined by the
-    # connection property string it returns.
-    BROKER_SKIP = {}
-
-    def __init__(self):
-        pass
-
-    def get_type_list(self):
-        """Return a list of types which this test suite supports"""
-        return self.TYPE_MAP.keys()
-
-    def get_test_values(self, test_type):
-        """Return test values to use when testing the supplied type."""
-        if test_type not in self.TYPE_MAP.keys():
-            return None
-        return self.TYPE_MAP[test_type]
-
-    def skip_test_message(self, test_type, broker_name):
-        """Return the message to use if a test is skipped"""
-        if test_type in self.BROKER_SKIP.keys():
-            if broker_name in self.BROKER_SKIP[test_type]:
-                return str(self.BROKER_SKIP[test_type][broker_name])
-        return None
-
-    def skip_test(self, test_type, broker_name):
-        """Return boolean True if test should be skipped"""
-        return test_type in self.BROKER_SKIP.keys() and \
-            broker_name in self.BROKER_SKIP[test_type]
-
-    @staticmethod
-    def merge_dicts(*dict_args):
-        res = {}
-        for d in dict_args:
-            res.update(d)
-        return res

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/.gitignore
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/.gitignore b/src/python/qpid_interop_test/.gitignore
new file mode 100644
index 0000000..835fca3
--- /dev/null
+++ b/src/python/qpid_interop_test/.gitignore
@@ -0,0 +1,4 @@
+/interop_test_errors.pyc
+/shim_utils.pyc
+/broker_properties.pyc
+/test_type_map.pyc

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/__init__.py b/src/python/qpid_interop_test/__init__.py
new file mode 100644
index 0000000..70204e4
--- /dev/null
+++ b/src/python/qpid_interop_test/__init__.py
@@ -0,0 +1,23 @@
+#
+# 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 broker_properties
+import interop_test_errors
+import shims
+import test_type_map

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/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
new file mode 100755
index 0000000..bde21f3
--- /dev/null
+++ b/src/python/qpid_interop_test/amqp_types_test.py
@@ -0,0 +1,443 @@
+#!/usr/bin/env python
+
+"""
+Module to test AMQP primitive types across different APIs
+"""
+
+#
+# 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 argparse
+import sys
+import unittest
+
+from itertools import product
+from json import dumps
+from os import getenv, path
+from time import mktime, time
+from uuid import UUID, uuid4
+
+from proton import symbol
+import qpid_interop_test.broker_properties
+import qpid_interop_test.shims
+from qpid_interop_test.test_type_map import TestTypeMap
+
+# TODO: propose a sensible default when installation details are worked out
+QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
+if QPID_INTEROP_TEST_HOME is None:
+    print 'ERROR: Environment variable QPID_INTEROP_TEST_HOME is not set'
+    sys.exit(1)
+
+
+class AmqpPrimitiveTypes(TestTypeMap):
+    """
+    Class which contains all the described AMQP primitive types and the test values to be used in testing.
+    """
+
+    TYPE_MAP = {
+        'null': ['None'],
+        'boolean': ['True',
+                    'False'],
+        'ubyte': ['0x0',
+                  '0x7f',
+                  '0x80',
+                  '0xff'],
+        'ushort': ['0x0',
+                   '0x7fff',
+                   '0x8000',
+                   '0xffff'],
+        'uint': ['0x0',
+                 '0x7fffffff',
+                 '0x80000000',
+                 '0xffffffff'],
+        'ulong': ['0x0',
+                  '0x1',
+                  '0xff',
+                  '0x100',
+                  '0x7fffffffffffffff',
+                  '0x8000000000000000',
+                  '0xffffffffffffffff'],
+        'byte': ['-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f'],
+        'short': ['-0x8000',
+                  '-0x1',
+                  '0x0',
+                  '0x7fff'],
+        'int': ['-0x80000000',
+                '-0x1',
+                '0x0',
+                '0x7fffffff'],
+        'long': ['-0x8000000000000000',
+                 '-0x81',
+                 '-0x80',
+                 '-0x1',
+                 '0x0',
+                 '0x7f',
+                 '0x80',
+                 '0x7fffffffffffffff'],
+        # float and double: Because of difficulty with rounding of floating point numbers, we use the binary
+        # representation instead which should be exact when comparing sent and received values.
+        'float': ['0x00000000', # 0.0
+                  '0x80000000', # -0.0
+                  '0x40490fdb', # pi (3.14159265359) positive decimal
+                  '0xc02df854', # -e (-2.71828182846) negative decimal
+                  '0x00000001', # Smallest positive denormalized number
+                  '0x80000001', # Smallest negative denormalized number
+                  '0x007fffff', # Largest positive denormalized number
+                  '0x807fffff', # Largest negative denormalized number
+                  '0x00800000', # Smallest positive normalized number
+                  '0x80800000', # Smallest negative normalized number
+                  '0x7f7fffff', # Largest positive normalized number
+                  '0xff7fffff', # Largest negative normalized number
+                  #'0x7f800000', # +Infinity # PROTON-1149 - fails on RHEL7
+                  #'0xff800000', # -Infinity # PROTON-1149 - fails on RHEL7
+                  '0x7fc00000', # +NaN
+                  '0xffc00000'], # -NaN
+        'double': ['0x0000000000000000', # 0.0
+                   '0x8000000000000000', # -0.0
+                   '0x400921fb54442eea', # pi (3.14159265359) positive decimal
+                   '0xc005bf0a8b145fcf', # -e (-2.71828182846) negative decimal
+                   '0x0000000000000001', # Smallest positive denormalized number
+                   '0x8000000000000001', # Smallest negative denormalized number
+                   '0x000fffffffffffff', # Largest positive denormalized number
+                   '0x800fffffffffffff', # Largest negative denormalized number
+                   '0x0010000000000000', # Smallest positive normalized number
+                   '0x8010000000000000', # Smallest negative normalized number
+                   '0x7fefffffffffffff', # Largest positive normalized number
+                   '0xffefffffffffffff', # Largest negative normalized number
+                   '0x7ff0000000000000', # +Infinity
+                   '0xfff0000000000000', # -Infinity
+                   '0x7ff8000000000000', # +NaN
+                   '0xfff8000000000000'], # -NaN
+        # decimal32, decimal64, decimal128:
+        # Until more formal support for decimal32, decimal64 and decimal128 are included in Python, we use
+        # a hex format for basic tests, and treat the data as a binary blob.
+        'decimal32': ['0x00000000',
+                      '0x40490fdb',
+                      '0xc02df854',
+                      '0xff7fffff'],
+        'decimal64': ['0x0000000000000000',
+                      '0x400921fb54442eea',
+                      '0xc005bf0a8b145fcf',
+                      '0xffefffffffffffff'],
+        'decimal128': ['0x00000000000000000000000000000000',
+                       '0xff0102030405060708090a0b0c0d0e0f'],
+        'char': [u'a',
+                 u'Z',
+                 u'0x1',
+                 u'0x7f',
+                 u'0x16b5', # Rune 'G'
+                 u'0x10ffff'],
+        # timestamp: Must be in milliseconds since the Unix epoch
+        'timestamp': ['0x0',
+                      '0x%x' % int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000),
+                      '0x%x' % int(time()*1000)
+                     ],
+        'uuid': [str(UUID(int=0x0)),
+                 str(UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')),
+                 str(uuid4())],
+        'binary': [bytes(),
+                   bytes(12345),
+                   b'Hello, world!',
+                   b'\\x01\\x02\\x03\\x04\\x05abcde\\x80\\x81\\xfe\\xff',
+                   b'The quick brown fox jumped over the lazy dog 0123456789.' * 100
+                  ],
+        # strings must be unicode to comply with AMQP spec
+        'string': [u'',
+                   u'Hello, world!',
+                   u'"Hello, world!"',
+                   u"Charlie's peach",
+                   u'The quick brown fox jumped over the lazy dog 0123456789.' * 100
+                  ],
+        'symbol': ['',
+                   'myDomain.123',
+                   '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(),
+                  'symbol:a.b.c',
+                  'none:',
+                  'decimal64:0x400921fb54442eea'
+                 ],
+                 [[],
+                  'none',
+                  ['ubyte:1', 'ubyte:2', 'ubyte:3'],
+                  'boolean:True',
+                  'boolean:False',
+                  {'string:hello': 'long:1234', '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
+                ],
+        'map': [
+            # Enpty map
+            {},
+            # Map with string keys
+            {'string:one': 'ubyte:1',
+             'string:two': 'ushort:2'},
+            # Map with other AMQP simple types as keys
+            {'none:': 'string:None',
+             'string:None': 'none:',
+             'string:One': 'long:-1234567890',
+             'short:2': 'int:2',
+             'boolean:True': 'string:True',
+             'string:False': 'boolean:False',
+             #['string:AAA', 'ushort:5951']: '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'}},
+            ],
+        # TODO: Support all AMQP types in array (including keys)
+        #'array': [[],
+        #          [1, 2, 3],
+        #          ['Hello', 'world'],
+        #          [[1, 2, 3],
+        #           ['a', 'b', 'c'],
+        #           [2.3, 3.4, 4,5],
+        #           [True, False, True, True]]
+        #          ]
+        }
+
+    # This section contains tests that should be skipped because of know issues that would cause the test to fail.
+    # As the issues are resolved, these should be removed.
+    BROKER_SKIP = {'null': {'ActiveMQ': 'Null type not sent in Proton Python binding: PROTON-1091',
+                            'qpid-cpp': 'Null type not sent in Proton Python binding: PROTON-1091',},
+                   'decimal32': {'ActiveMQ': 'decimal32 and decimal64 sent byte reversed: PROTON-1160',
+                                 'qpid-cpp': 'decimal32 not supported on qpid-cpp broker: QPIDIT-5, QPID-6328',
+                                 'apache-activemq-artemis': 'decimal32 and decimal64 sent byte reversed: PROTON-1160',
+                                 'qpid-dispatch-router': 'decimal32 and decimal64 sent byte reversed: PROTON-1160'},
+                   'decimal64': {'ActiveMQ': 'decimal32 and decimal64 sent byte reversed: PROTON-1160',
+                                 'qpid-cpp': 'decimal64 not supported on qpid-cpp broker: QPIDIT-6, QPID-6328',
+                                 'apache-activemq-artemis': 'decimal32 and decimal64 sent byte reversed: PROTON-1160',
+                                 'qpid-dispatch-router': 'decimal32 and decimal64 sent byte reversed: PROTON-1160'},
+                   'decimal128': {'qpid-cpp': 'decimal128 not supported on qpid-cpp broker: QPIDIT-3, QPID-6328',},
+                   'char': {'qpid-cpp': 'char not supported on qpid-cpp broker: QPIDIT-4, QPID-6328',
+                            'apache-activemq-artemis': 'char types > 16 bits truncated on Artemis: ENTMQ-1685'},
+                   'float': {'apache-activemq-artemis': '-NaN is stripped of its sign: ENTMQ-1686'},
+                   'double': {'apache-activemq-artemis': '-NaN is stripped of its sign: ENTMQ-1686'},
+                  }
+
+
+class AmqpTypeTestCase(unittest.TestCase):
+    """
+    Abstract base class for AMQP Type test cases
+    """
+
+    def run_test(self, broker_addr, amqp_type, test_value_list, send_shim, receive_shim):
+        """
+        Run 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.
+        """
+        if len(test_value_list) > 0:
+            # TODO: When Artemis can support it (in the next release), revert the queue name back to 'qpid-interop...'
+            # Currently, Artemis only supports auto-create queues for JMS, and the queue name must be prefixed by
+            # 'jms.queue.'
+            #queue_name = 'qpid-interop.simple_type_tests.%s.%s.%s' % (amqp_type, send_shim.NAME, receive_shim.NAME)
+            queue_name = 'jms.queue.qpid-interop.simple_type_tests.%s.%s.%s' % \
+                         (amqp_type, send_shim.NAME, receive_shim.NAME)
+
+            # Start the receive shim first (for queueless brokers/dispatch)
+            receiver = receive_shim.create_receiver(broker_addr, queue_name, amqp_type,
+                                                    str(len(test_value_list)))
+            receiver.start()
+
+            # Start the send shim
+            sender = send_shim.create_sender(broker_addr, queue_name, amqp_type,
+                                             dumps(test_value_list))
+            sender.start()
+
+            # Wait for both shims to finish
+            sender.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+            receiver.join_or_kill(qpid_interop_test.shims.THREAD_TIMEOUT)
+
+            # Process return string from sender
+            send_obj = sender.get_return_object()
+            if send_obj is not None:
+                if isinstance(send_obj, str) and len(send_obj) > 0:
+                    self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
+                else:
+                    self.fail('Sender error: %s' % str(send_obj))
+
+            # Process return string from receiver
+            receive_obj = receiver.get_return_object()
+            if isinstance(receive_obj, tuple):
+                if len(receive_obj) == 2:
+                    return_amqp_type, return_test_value_list = 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(return_test_value_list, test_value_list, msg='\n    sent:%s\nreceived:%s' % \
+                                     (test_value_list, return_test_value_list))
+                else:
+                    self.fail('Received incorrect tuple format: %s' % str(receive_obj))
+            else:
+                self.fail('Received non-tuple: %s' % str(receive_obj))
+
+def create_testcase_class(broker_name, types, broker_addr, amqp_type, shim_product):
+    """
+    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):
+        """Function which creates a new test method in class cls"""
+
+        @unittest.skipIf(types.skip_test(amqp_type, broker_name),
+                         types.skip_test_message(amqp_type, broker_name))
+        def inner_test_method(self):
+            self.run_test(self.broker_addr, self.amqp_type, self.test_value_list, send_shim, receive_shim)
+
+        inner_test_method.__name__ = 'test_%s_%s->%s' % (amqp_type, 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,
+                  'broker_addr': broker_addr,
+                  'test_value_list': types.get_test_values(amqp_type)}
+    new_class = type(class_name, (AmqpTypeTestCase,), class_dict)
+    for send_shim, receive_shim in shim_product:
+        add_test_method(new_class, send_shim, receive_shim)
+    return new_class
+
+
+# SHIM_MAP contains an instance of each client language shim that is to be tested as a part of this test. For
+# every shim in this list, a test is dynamically constructed which tests it against itself as well as every
+# other shim in the list.
+#
+# As new shims are added, add them into this map to have them included in the test cases.
+PROTON_CPP_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'amqp_types_test',
+                                     'Receiver')
+PROTON_CPP_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-cpp', 'build', 'amqp_types_test',
+                                   'Sender')
+PROTON_PYTHON_RECEIVER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'amqp_types_test',
+                                        'Receiver.py')
+PROTON_PYTHON_SENDER_SHIM = path.join(QPID_INTEROP_TEST_HOME, 'shims', 'qpid-proton-python', 'src', 'amqp_types_test',
+                                      'Sender.py')
+
+SHIM_MAP = {qpid_interop_test.shims.ProtonCppShim.NAME: \
+                qpid_interop_test.shims.ProtonCppShim(PROTON_CPP_SENDER_SHIM, PROTON_CPP_RECEIVER_SHIM),
+            qpid_interop_test.shims.ProtonPythonShim.NAME: \
+                qpid_interop_test.shims.ProtonPythonShim(PROTON_PYTHON_SENDER_SHIM, PROTON_PYTHON_RECEIVER_SHIM),
+           }
+
+
+class TestOptions(object):
+    """
+    Class controlling command-line arguments used to control the test.
+    """
+    def __init__(self):
+        parser = argparse.ArgumentParser(description='Qpid-interop AMQP client interoparability test suite '
+                                         'for AMQP simple types')
+        parser.add_argument('--broker', action='store', default='localhost:5672', metavar='BROKER:PORT',
+                            help='Broker against which to run test suite.')
+#        test_group = parser.add_mutually_exclusive_group()
+#        test_group.add_argument('--include-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to include')
+#        test_group.add_argument('--exclude-test', action='append', metavar='TEST-NAME',
+#                                help='Name of test to exclude')
+#        type_group = test_group.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(AmqpPrimitiveTypes.TYPE_MAP.keys()))
+        parser.add_argument('--exclude-type', action='append', metavar='AMQP-TYPE',
+                            help='Name of AMQP type to exclude. Supported types:\n%s' %
+                            sorted(AmqpPrimitiveTypes.TYPE_MAP.keys()))
+#        shim_group = test_group.add_mutually_exclusive_group()
+#        shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',
+#                                help='Name of shim to include. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        parser.add_argument('--exclude-shim', action='append', metavar='SHIM-NAME',
+                            help='Name of shim to exclude. Supported shims:\n%s' % sorted(SHIM_MAP.keys()))
+        self.args = parser.parse_args()
+
+
+#--- Main program start ---
+
+if __name__ == '__main__':
+
+    ARGS = TestOptions().args
+    #print 'ARGS:', ARGS # debug
+
+    # Connect to broker to find broker type
+    CONNECTION_PROPS = qpid_interop_test.broker_properties.get_broker_properties(ARGS.broker)
+    if CONNECTION_PROPS is None:
+        print 'WARNING: Unable to get connection properties - unknown broker'
+        BROKER = 'unknown'
+    else:
+        BROKER = CONNECTION_PROPS[symbol(u'product')] if symbol(u'product') in CONNECTION_PROPS \
+                 else '<product not found>'
+        BROKER_VERSION = CONNECTION_PROPS[symbol(u'version')] if symbol(u'version') in CONNECTION_PROPS \
+                         else '<version not found>'
+        BROKER_PLATFORM = CONNECTION_PROPS[symbol(u'platform')] if symbol(u'platform') in CONNECTION_PROPS \
+                          else '<platform not found>'
+        print 'Test Broker: %s v.%s on %s' % (BROKER, BROKER_VERSION, BROKER_PLATFORM)
+        print
+        sys.stdout.flush()
+
+    TYPES = AmqpPrimitiveTypes()
+
+    # TEST_CASE_CLASSES is a list that collects all the test classes that are constructed. One class is constructed
+    # per AMQP type used as the key in map AmqpPrimitiveTypes.TYPE_MAP.
+    TEST_CASE_CLASSES = []
+
+    # TEST_SUITE is the final suite of tests that will be run and which contains all the dynamically created
+    # type classes, each of which contains a test for the combinations of client shims
+    TEST_SUITE = unittest.TestSuite()
+
+    # Remove shims excluded from the command-line
+    if ARGS.exclude_shim is not None:
+        for shim in ARGS.exclude_shim:
+            SHIM_MAP.pop(shim)
+    # Create test classes dynamically
+    for at in sorted(TYPES.get_type_list()):
+        if ARGS.exclude_type is None or at not in ARGS.exclude_type:
+            test_case_class = create_testcase_class(BROKER,
+                                                    TYPES,
+                                                    ARGS.broker,
+                                                    at,
+                                                    product(SHIM_MAP.values(), repeat=2))
+            TEST_CASE_CLASSES.append(test_case_class)
+            TEST_SUITE.addTest(unittest.makeSuite(test_case_class))
+
+    # Finally, run all the dynamically created tests
+    RES = unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
+    if not RES.wasSuccessful():
+        sys.exit(1) # Errors or failures present

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/broker_properties.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/broker_properties.py b/src/python/qpid_interop_test/broker_properties.py
new file mode 100644
index 0000000..01a090f
--- /dev/null
+++ b/src/python/qpid_interop_test/broker_properties.py
@@ -0,0 +1,55 @@
+"""
+Module containing a small client which connects to the broker and
+gets the broker connection properties so as to identify the broker.
+"""
+
+#
+# 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 proton.handlers import MessagingHandler
+from proton.reactor import Container
+
+class Client(MessagingHandler):
+    """
+    Client to connect to broker and collect connection properties, used to identify the test broker
+    """
+    def __init__(self, url):
+        super(Client, self).__init__()
+        self.url = url
+        self.remote_properties = None
+
+    def on_connection_remote_open(self, event):
+        """Callback for remote connection open"""
+        self.remote_properties = event.connection.remote_properties
+        event.connection.close()
+
+    def on_start(self, event):
+        """Event loop start"""
+        event.container.connect(url=self.url)
+
+    def get_connection_properties(self):
+        """Return the connection properties"""
+        return self.remote_properties
+
+
+def get_broker_properties(broker_url):
+    """Start client, then return its connection properties"""
+    msg_handler = Client(broker_url)
+    Container(msg_handler).run()
+    return msg_handler.get_connection_properties()

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/514bac75/src/python/qpid_interop_test/interop_test_errors.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/interop_test_errors.py b/src/python/qpid_interop_test/interop_test_errors.py
new file mode 100644
index 0000000..6be8959
--- /dev/null
+++ b/src/python/qpid_interop_test/interop_test_errors.py
@@ -0,0 +1,29 @@
+"""
+Module containing Error classes for interop testing
+"""
+
+#
+# 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.
+#
+
+class InteropTestError(StandardError):
+    """
+    Generic simple error class for use in interop tests
+    """
+    def __init__(self, error_message):
+        super(InteropTestError, self).__init__(error_message)


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