Repository: qpid-interop-test
Updated Branches:
  refs/heads/master 4dfa2bd51 -> 899a9a863


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/899a9a86/src/py/qpid-interop-test/types/simple_type_tests.py
----------------------------------------------------------------------
diff --git a/src/py/qpid-interop-test/types/simple_type_tests.py 
b/src/py/qpid-interop-test/types/simple_type_tests.py
index aab369a..59d2790 100755
--- a/src/py/qpid-interop-test/types/simple_type_tests.py
+++ b/src/py/qpid-interop-test/types/simple_type_tests.py
@@ -26,17 +26,15 @@ Module to test AMQP primitive types across different APIs
 import argparse
 import unittest
 
-from ast import literal_eval
-from interop_test_errors import InteropTestError
 from itertools import product
+from json import dumps, loads
 from os import getenv, path
-from proton import char, int32, symbol, timestamp, ulong
-from shim_utils import StrToObj
 from subprocess import check_output, CalledProcessError
 from time import mktime, time
 from uuid import UUID, uuid4
 
-QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME') # TODO - propose a 
sensible default when installation details are worked out
+# TODO - propose a sensible default when installation details are worked out
+QPID_INTEROP_TEST_HOME = getenv('QPID_INTEROP_TEST_HOME')
 
 class AmqpPrimitiveTypes(object):
     """
@@ -44,18 +42,50 @@ class AmqpPrimitiveTypes(object):
     """
 
     TYPE_MAP = {
-        'null': [None],
-        'boolean': [True, False],
-        'ubyte': [0x0, 0x7f, 0x80, 0xff],
-        'ushort': [0x0, 0x7fff, 0x8000, 0xffff],
-        'uint': [0x0, 0x7fffffff, 0x80000000, 0xffffffff],
-        'ulong': [0x0, 0x01, 0xff, 0x100, 0x7fffffffffffffff, 
0x8000000000000000, 0xffffffffffffffff],
-        'byte': [-0x80, -0x01, 0x0, 0x7f],
-        'short': [-0x8000, -0x1, 0x0, 0x7fff],
-        'int': [-0x80000000, -0x1, 0x0, 0x7fffffff],
-        'long': [-0x8000000000000000, -0x81, -0x80, -0x01, 0x0, 0x7f, 0x80, 
0x7fffffffffffffff],
-        # Because of difficulty with rounding of floating point numbers, we 
use the binary representation instead
-        # which should be exact when comparing.
+        '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
@@ -70,8 +100,8 @@ class AmqpPrimitiveTypes(object):
                   '0xff7fffff', # Largest negative normalized number
                   '0x7f800000', # +Infinity
                   '0xff800000', # -Infinity
-                  '0x7fc00000', # +NaN 
-                  '0xffc00000'], # -NaN 
+                  '0x7fc00000', # +NaN
+                  '0xffc00000'], # -NaN
         'double': ['0x0000000000000000', # 0.0
                    '0x8000000000000000', # -0.0
                    '0x400921fb54442eea', # pi (3.14159265359) positive decimal
@@ -88,27 +118,68 @@ class AmqpPrimitiveTypes(object):
                    '0xfff0000000000000', # -Infinity
                    '0x7ff8000000000000', # +NaN
                    '0xfff8000000000000'], # -NaN
-        #'decimal32': [0, 100, -1000.001, 3.14159, 1.234e+56],
-        #'decimal64': [0, 100, -1000.001, 3.14159, 1.234e+56],
-        #'decimal128': [0, 100, -1000.001, 3.14159, 1.234e+56], # Hangs python 
shim, ok in jms shim
-        #'char': [u'a', u'Z', u'\u0001', u'\u007f'],            # Hangs python 
shim, ok in jms shim
-        # timestamp must be in milliseconds since the unix epoch
-        'timestamp': [0, int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000), 
int(time()*1000)],
-        'uuid': [UUID(int=0x0), UUID('00010203-0405-0607-0809-0a0b0c0d0e0f'), 
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.' * 1000],
+        # 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.
+        # Note that IEE-754 allows for two binary encodings of these numbers 
without any way to determine which
+        # of them is in use. Thus the encoding used must be by convention or 
agreed upon in advance by the clients.
+        'decimal32': ['0x00000000',
+                      '0x40490fdb',
+                      '0xc02df854',
+                      '0xff7fffff'],
+        'decimal64': ['0x0000000000000000',
+                      '0x400921fb54442eea',
+                      '0xc005bf0a8b145fcf',
+                      '0xffefffffffffffff'],
+        'decimal128': ['0x00000000000000000000000000000000',
+                       '0xff0102030405060708090a0b0c0d0e0f'],
+        'char': ['a',
+                 'Z',
+                 '\x01',
+                 '\x7f'],
+        # timestamp
+        # Must be in milliseconds since the unix epoch
+        'timestamp': ['0',
+                      '%d' % int(mktime((2000, 1, 1, 0, 0, 0, 5, 1, 0))*1000),
+                      '%d' % 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.' 
* 1000],
         # 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': [[],
-        #         [1, -2, 3.14],
-        #         [u'a', u'b', u'c'],
-        #         [ulong(12345), timestamp(int(time()*1000)), int32(-25), 
uuid4(), symbol('a.b.c')],
-        #         [[], None, [1,2,3], {1:'one', 2:'two', 3:'three', 4:True, 
5:False, 6:None}, True, False, char(u'5')],
-        #         [[],[[],[[],[],[]],[]],[]],
-        #         [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000],
-        #'map': [{}, {1:u'one', 2:u'two'}, {None:None, 1:1, '2':'2', 
True:False, False:True}]#, # TODO: Bug in handling maps
+        'string': [u'',
+                   u'Hello, world!',
+                   u'"Hello, world!"',
+                   u"Charlie's peach",
+                   u'The quick brown fox jumped over the lazy dog 0123456789.' 
* 1000],
+        'symbol': ['',
+                   'myDomain.123',
+                   'domain.0123456789.' * 100],
+        'list': [[],
+                 [1, -2, 3.14],
+                 [u'a', u'b', u'c'],
+                 #[ulong(12345), timestamp(int(time()*1000)), int32(-25), 
uuid4(), symbol('a.b.c')],
+                 [[], None, [1, 2, 3], True, False],
+                 [[], [[], [[], [], []], []], []],
+                 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] * 1000
+                ],
+        # TODO: Maps translate into object descriptions in JSON, so only 
string keys are allowed. Come up with
+        #       a method to represent a Python map in JSON.
+        'map': [{},
+                {u'one': 1,
+                 u'two': 2},
+                {u'None': None,
+                 u'One': 1,
+                 u'2': '2',
+                 u'True': True,
+                 u'False': False,
+                 u'map': {u'A': 1,
+                          u'B': 2}}
+               ],
         #'array': [[], [1,2,3], ['Hello', 'world']] # TODO: Not yet implemented
         }
 
@@ -137,11 +208,11 @@ class AmqpTypeTestCase(unittest.TestCase):
         """
         if len(test_value_list) > 0:
             queue_name = 'qpid-interop.simple_type_tests.%s.%s.%s' % 
(amqp_type, send_shim.NAME, receive_shim.NAME)
-            send_error_text = send_shim.send(broker_addr, queue_name, 
amqp_type, test_value_list)
+            send_error_text = send_shim.send(broker_addr, queue_name, 
amqp_type, dumps(test_value_list))
             if len(send_error_text) > 0:
                 self.fail('Send shim \'%s\':\n%s' % (send_shim.NAME, 
send_error_text))
             receive_text = receive_shim.receive(broker_addr, queue_name, 
amqp_type, len(test_value_list))
-            if type(receive_text) is list:
+            if isinstance(receive_text, list):
                 self.assertEqual(receive_text, test_value_list, msg='\n    
sent:%s\nreceived:%s' % \
                                  (test_value_list, receive_text))
             else:
@@ -159,7 +230,7 @@ def create_testcase_class(broker_addr, amqp_type, 
test_value_list, shim_product)
         """Print the class name"""
         return self.__class__.__name__
 
-    def add_test_method(cls, broker_addr, send_shim, receive_shim):
+    def add_test_method(cls, send_shim, receive_shim):
         """Function which creates a new test method in class cls"""
 
         def inner_test_method(self):
@@ -179,7 +250,7 @@ def create_testcase_class(broker_addr, amqp_type, 
test_value_list, shim_product)
                   'test_value_list': test_value_list}
     new_class = type(class_name, (AmqpTypeTestCase,), class_dict)
     for send_shim, receive_shim in shim_product:
-        add_test_method(new_class, broker_addr, send_shim, receive_shim)
+        add_test_method(new_class, send_shim, receive_shim)
     return new_class
 
 
@@ -192,27 +263,23 @@ class Shim(object):
     RECEIVE = None
     USE_SHELL = False
 
-    def send(self, broker_addr, queue_name, amqp_type, test_value_list):
+    def send(self, broker_addr, queue_name, amqp_type, json_test_values_str):
         """
         Send the values of type amqp_type in test_value_list to queue 
queue_name. Return output (if any) from stdout.
         """
         arg_list = []
         arg_list.extend(self.SEND)
         arg_list.extend([broker_addr, queue_name, amqp_type])
-        for test_value in test_value_list:
-            if amqp_type == 'string' or amqp_type == 'char' or amqp_type == 
'float' or amqp_type == 'double':
-                arg_list.append(test_value) # Not using str() on strings 
preserves the unicode prefix u'...'
-            else:
-                arg_list.append(str(test_value))
+        arg_list.append(json_test_values_str)
+
         try:
-            #print
-            #print '>>>', arg_list
+            #print '\n>>>', arg_list # DEBUG - useful to see command-line sent 
to shim
             return check_output(arg_list, shell=self.USE_SHELL)
-        except CalledProcessError as e:
-            return str(e) + '\n\nOutput:\n' + e.output
-        except Exception as e:
-            return str(e)
-        
+        except CalledProcessError as exc:
+            return str(exc) + '\n\nOutput:\n' + exc.output
+        except Exception as exc:
+            return str(exc)
+
 
     def receive(self, broker_addr, queue_name, amqp_type, num_test_values):
         """
@@ -225,54 +292,15 @@ class Shim(object):
             arg_list = []
             arg_list.extend(self.RECEIVE)
             arg_list.extend([broker_addr, queue_name, amqp_type, 
str(num_test_values)])
-            #print
-            #print '>>>', arg_list
+            #print '\n>>>', arg_list # DEBUG - useful to see command-line sent 
to shim
             output = check_output(arg_list)
-            #print '<<<', output
+            #print '<<<', output # DEBUG - useful to see text received from 
shim
             str_tvl = output.split('\n')[0:-1] # remove trailing \n
-            if str_tvl[0] == amqp_type:
-                received_test_value_list = []
-                for stv in str_tvl[1:]:
-                    # Non-string types using literal_eval
-                    if amqp_type == 'null' or \
-                       amqp_type == 'boolean' or \
-                       amqp_type == 'ubyte' or \
-                       amqp_type == 'ushort' or \
-                       amqp_type == 'uint' or \
-                       amqp_type == 'ulong' or \
-                       amqp_type == 'byte' or \
-                       amqp_type == 'short' or \
-                       amqp_type == 'int' or \
-                       amqp_type == 'long' or \
-                       amqp_type == 'decimal32' or \
-                       amqp_type == 'decimal64' or \
-                       amqp_type == 'decimal128' or \
-                       amqp_type == 'timestamp':
-                        received_test_value_list.append(literal_eval(stv))
-                    # Non-string types not using literal_evel
-                    elif amqp_type == 'uuid':
-                        received_test_value_list.append(UUID(stv))
-                    elif amqp_type == 'binary':
-                        received_test_value_list.append(bytes(stv))
-                    # String  and float types used as-is
-                    elif amqp_type == 'float' or \
-                         amqp_type == 'double' or \
-                         amqp_type == 'char' or \
-                         amqp_type == 'string' or \
-                         amqp_type == 'symbol':
-                        received_test_value_list.append(stv)
-                    elif amqp_type == 'list' or \
-                         amqp_type == 'map':
-                        
received_test_value_list.append(StrToObj(list(stv).__iter__()).run())
-                    else:
-                        raise InteropTestError('ERROR: Shim.receive(): AMQP 
type \'%s\' not implemented' % amqp_type)
-                return received_test_value_list
-            else:
-                return output # return error string
-        except CalledProcessError as e:
-            return str(e) + '\n\n' + e.output
-        except Exception as e:
-            return str(e)
+            return loads(str_tvl[1])
+        except CalledProcessError as exc:
+            return str(exc) + '\n\n' + exc.output
+        except Exception as exc:
+            return str(exc)
 
 
 class ProtonPythonShim(Shim):
@@ -281,8 +309,8 @@ class ProtonPythonShim(Shim):
     """
     NAME = 'ProtonPython'
     SHIM_LOC = path.join(QPID_INTEROP_TEST_HOME, 'shims', 
'qpid-proton-python', 'src')
-    SEND = [path.join(SHIM_LOC, 'amqp-send')]
-    RECEIVE = [path.join(SHIM_LOC, 'amqp-receive')]
+    SEND = [path.join(SHIM_LOC, 'TypesSenderShim.py')]
+    RECEIVE = [path.join(SHIM_LOC, 'TypesReceiverShim.py')]
 
 
 class QpidJmsShim(Shim):
@@ -290,11 +318,11 @@ class QpidJmsShim(Shim):
     Shim for qpid-jms JMS client
     """
     NAME = 'QpidJms'
-    
+
     # Installed qpid versions
     QPID_JMS_VER = '0.4.0-SNAPSHOT'
     QPID_PROTON_J_VER = '0.10-SNAPSHOT'
-    
+
     # 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')
@@ -307,14 +335,20 @@ class QpidJmsShim(Shim):
     PROTON_J_JAR = path.join(MAVEN_REPO_PATH, 'org', 'apache', 'qpid', 
'proton-j', QPID_PROTON_J_VER,
                              'proton-j-' + QPID_PROTON_J_VER + '.jar')
     NETTY_JAR = path.join(MAVEN_REPO_PATH, 'io', 'netty', 'netty-all', 
'4.0.17.Final', 'netty-all-4.0.17.Final.jar')
-    
-    CLASSPATH = ':'.join([QPID_INTEROP_TEST_SHIM_JAR, JMS_API_JAR, 
JMS_IMPL_JAR, LOGGER_API_JAR, LOGGER_IMPL_JAR, PROTON_J_JAR, NETTY_JAR])
+
+    CLASSPATH = ':'.join([QPID_INTEROP_TEST_SHIM_JAR,
+                          JMS_API_JAR,
+                          JMS_IMPL_JAR,
+                          LOGGER_API_JAR,
+                          LOGGER_IMPL_JAR,
+                          PROTON_J_JAR,
+                          NETTY_JAR])
     JAVA_HOME = getenv('JAVA_HOME', '/usr/bin') # Default only works in Linux
     JAVA_EXEC = path.join(JAVA_HOME, 'java')
     SEND = [JAVA_EXEC, '-cp', CLASSPATH, 
'org.apache.qpid.interop_test.shim.AmqpSender']
     RECEIVE = [JAVA_EXEC, '-cp', CLASSPATH, 
'org.apache.qpid.interop_test.shim.AmqpReceiver']
 
-    
+
 # 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.
@@ -328,8 +362,12 @@ SHIM_MAP = {ProtonPythonShim.NAME: ProtonPythonShim()}
 
 
 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 = 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()
@@ -348,16 +386,16 @@ class TestOptions(object):
 #        shim_group.add_argument('--include-shim', action='append', 
metavar='SHIM-NAME',
 #                                help='Name of shim to include. Supported 
shims:\n%s' % SHIM_NAMES)
         parser.add_argument('--exclude-shim', action='append', 
metavar='SHIM-NAME',
-                             help='Name of shim to exclude. Supported 
shims:\n%s' % sorted(SHIM_MAP.keys()))
+                            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
+    ARGS = TestOptions().args
+    #print 'ARGS:', ARGS
 
     # 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.
@@ -366,15 +404,15 @@ if __name__ == '__main__':
     # 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)          
+    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(AmqpPrimitiveTypes.get_type_list()):
-        if args.exclude_type is None or at not in args.exclude_type:
-            test_case_class = create_testcase_class(args.broker,
+        if ARGS.exclude_type is None or at not in ARGS.exclude_type:
+            test_case_class = create_testcase_class(ARGS.broker,
                                                     at,
                                                     
AmqpPrimitiveTypes.get_test_value_list(at),
                                                     product(SHIM_MAP.values(), 
repeat=2))
@@ -383,3 +421,4 @@ if __name__ == '__main__':
 
     # Finally, run all the dynamically created tests
     unittest.TextTestRunner(verbosity=2).run(TEST_SUITE)
+


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to