You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kp...@apache.org on 2018/02/26 22:04:38 UTC

qpid-interop-test git commit: QPIDIT-37: Added a default timeout to each test suite. This timeout applies to each test in the test suite. (For example, the default for amqp_types_test test suite has been set to 10 seconds, and each of its tests must comp

Repository: qpid-interop-test
Updated Branches:
  refs/heads/master e20ae3c8b -> 1820e98b5


QPIDIT-37: Added a default timeout to each test suite. This timeout applies to each test in the test suite. (For example, the default for amqp_types_test test suite has been set to 10 seconds, and each of its tests must complete within this time.) There is also a --timeout option which can be used to override the default timeout for a test suite if, for example, the test is being run on a slow (or a fast) machine. There is currently no way to set timeouts for individual tests, however. Each test within a test suite uses the same value. This could be addressed in a later fix.


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

Branch: refs/heads/master
Commit: 1820e98b5e8d35c1d3a8c8820ef0350254db5e05
Parents: e20ae3c
Author: Kim van der Riet <kv...@localhost.localdomain>
Authored: Mon Feb 26 17:04:14 2018 -0500
Committer: Kim van der Riet <kv...@localhost.localdomain>
Committed: Mon Feb 26 17:04:14 2018 -0500

----------------------------------------------------------------------
 .../amqp_large_content_test.py                  | 35 +++++-----
 src/python/qpid_interop_test/amqp_types_test.py | 33 +++++-----
 .../qpid_interop_test/interop_test_errors.py    |  6 ++
 .../qpid_interop_test/jms_hdrs_props_test.py    | 68 ++++++++++++--------
 .../qpid_interop_test/jms_messages_test.py      | 34 +++++-----
 src/python/qpid_interop_test/qit_common.py      |  5 +-
 src/python/qpid_interop_test/shims.py           | 31 +++++++--
 7 files changed, 128 insertions(+), 84 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/src/python/qpid_interop_test/amqp_large_content_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_large_content_test.py b/src/python/qpid_interop_test/amqp_large_content_test.py
index ec5ab7e..9b9d809 100755
--- a/src/python/qpid_interop_test/amqp_large_content_test.py
+++ b/src/python/qpid_interop_test/amqp_large_content_test.py
@@ -33,7 +33,9 @@ from json import dumps
 import qpid_interop_test.broker_properties
 import qpid_interop_test.qit_common
 import qpid_interop_test.shims
-from qpid_interop_test.interop_test_errors import InteropTestError
+from qpid_interop_test.interop_test_errors import InteropTestError, InteropTestTimeout
+
+DEFAULT_TEST_TIMEOUT = 180 # seconds
 
 
 class AmqpVariableSizeTypes(qpid_interop_test.qit_common.QitTestTypeMap):
@@ -74,16 +76,12 @@ class AmqpVariableSizeTypes(qpid_interop_test.qit_common.QitTestTypeMap):
 class AmqpLargeContentTestCase(qpid_interop_test.qit_common.QitTestCase):
     """Abstract base class for AMQP large content tests"""
 
-    def run_test(self, sender_addr, receiver_addr, amqp_type, test_value_list, send_shim, receive_shim):
+    def run_test(self, sender_addr, receiver_addr, amqp_type, test_value_list, send_shim, receive_shim, timeout):
         """
         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 test_value_list: # len > 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 = 'qit.amqp_large_content_test.%s.%s.%s' % \
                          (amqp_type, send_shim.NAME, receive_shim.NAME)
 
@@ -96,10 +94,10 @@ class AmqpLargeContentTestCase(qpid_interop_test.qit_common.QitTestCase):
 
             # Wait for sender, process return string
             try:
-                send_obj = sender.wait_for_completion()
-            except KeyboardInterrupt as err:
+                send_obj = sender.wait_for_completion(timeout)
+            except (KeyboardInterrupt, InteropTestTimeout):
                 receiver.send_signal(signal.SIGINT)
-                raise err
+                raise
             if send_obj is not None:
                 if isinstance(send_obj, str):
                     if send_obj: # len > 0
@@ -110,7 +108,7 @@ class AmqpLargeContentTestCase(qpid_interop_test.qit_common.QitTestCase):
                     raise InteropTestError('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
 
             # Wait for receiver, process return string
-            receive_obj = receiver.wait_for_completion()
+            receive_obj = receiver.wait_for_completion(timeout)
             if isinstance(receive_obj, tuple):
                 if len(receive_obj) == 2:
                     return_amqp_type, return_test_value_list = receive_obj
@@ -142,9 +140,10 @@ class AmqpLargeContentTestCase(qpid_interop_test.qit_common.QitTestCase):
 class TestOptions(qpid_interop_test.qit_common.QitCommonTestOptions):
     """Command-line arguments used to control the test"""
 
-    def __init__(self, shim_map, default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
+    def __init__(self, shim_map, default_timeout=DEFAULT_TEST_TIMEOUT,
+                 default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
         super(TestOptions, self).__init__('Qpid-interop AMQP client interoparability test suite for AMQP' +
-                                          ' messages with large content', shim_map, default_xunit_dir)
+                                          ' messages with large content', shim_map, default_timeout, default_xunit_dir)
         type_group = self._parser.add_mutually_exclusive_group()
         type_group.add_argument('--include-type', action='append', metavar='AMQP-TYPE',
                                 help='Name of AMQP type to include. Supported types:\n%s' %
@@ -167,10 +166,11 @@ class AmqpLargeContentTest(qpid_interop_test.qit_common.QitTest):
         # Create test classes dynamically
         for amqp_type in sorted(self.types.get_type_list()):
             if self.args.exclude_type is None or amqp_type not in self.args.exclude_type:
-                test_case_class = self.create_testcase_class(amqp_type, product(self.shim_map.values(), repeat=2))
+                test_case_class = self.create_testcase_class(amqp_type, product(self.shim_map.values(), repeat=2),
+                                                             int(self.args.timeout))
                 self.test_suite.addTest(unittest.makeSuite(test_case_class))
 
-    def create_testcase_class(self, amqp_type, shim_product):
+    def create_testcase_class(self, amqp_type, shim_product, timeout):
         """
         Class factory function which creates new subclasses to AmqpTypeTestCase.
         """
@@ -179,7 +179,7 @@ class AmqpLargeContentTest(qpid_interop_test.qit_common.QitTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, send_shim, receive_shim):
+        def add_test_method(cls, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             @unittest.skipIf(self.types.skip_test(amqp_type, self.broker),
@@ -194,7 +194,8 @@ class AmqpLargeContentTest(qpid_interop_test.qit_common.QitTest):
                               self.amqp_type,
                               self.test_value_list,
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             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)
@@ -209,7 +210,7 @@ class AmqpLargeContentTest(qpid_interop_test.qit_common.QitTest):
                       'test_value_list': self.types.get_test_values(amqp_type)}
         new_class = type(class_name, (AmqpLargeContentTestCase,), class_dict)
         for send_shim, receive_shim in shim_product:
-            add_test_method(new_class, send_shim, receive_shim)
+            add_test_method(new_class, send_shim, receive_shim, timeout)
         return new_class
 
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/src/python/qpid_interop_test/amqp_types_test.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/amqp_types_test.py b/src/python/qpid_interop_test/amqp_types_test.py
index 8a43cf6..38334df 100755
--- a/src/python/qpid_interop_test/amqp_types_test.py
+++ b/src/python/qpid_interop_test/amqp_types_test.py
@@ -35,8 +35,9 @@ from uuid import UUID, uuid4
 import qpid_interop_test.broker_properties
 import qpid_interop_test.qit_common
 import qpid_interop_test.shims
-from qpid_interop_test.interop_test_errors import InteropTestError
+from qpid_interop_test.interop_test_errors import InteropTestError, InteropTestTimeout
 
+DEFAULT_TEST_TIMEOUT = 10 # seconds
 
 class AmqpPrimitiveTypes(qpid_interop_test.qit_common.QitTestTypeMap):
     """
@@ -306,16 +307,13 @@ class AmqpPrimitiveTypes(qpid_interop_test.qit_common.QitTestTypeMap):
 class AmqpTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
     """Abstract base class for AMQP Type test cases"""
 
-    def run_test(self, sender_addr, receiver_addr, amqp_type, test_value_list, send_shim, receive_shim):
+    def run_test(self, sender_addr, receiver_addr, amqp_type, test_value_list, send_shim, receive_shim, timeout):
         """
         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 test_value_list: # len > 0
             test_name = 'amqp_types_test.%s.%s.%s' % (amqp_type, send_shim.NAME, receive_shim.NAME)
-            # 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 = 'qit.%s' % test_name
 
             # Start the receive shim first (for queueless brokers/dispatch)
@@ -326,10 +324,10 @@ class AmqpTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
 
             # Wait for sender, process return string
             try:
-                send_obj = sender.wait_for_completion()
-            except KeyboardInterrupt as err:
+                send_obj = sender.wait_for_completion(timeout)
+            except (KeyboardInterrupt, InteropTestTimeout):
                 receiver.send_signal(signal.SIGINT)
-                raise err
+                raise
             if send_obj is not None:
                 if isinstance(send_obj, str):
                     if send_obj: # len > 0
@@ -340,7 +338,7 @@ class AmqpTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
                     raise InteropTestError('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
 
             # Wait for receiver, process return string
-            receive_obj = receiver.wait_for_completion()
+            receive_obj = receiver.wait_for_completion(timeout)
             if isinstance(receive_obj, tuple):
                 if len(receive_obj) == 2:
                     return_amqp_type, return_test_value_list = receive_obj
@@ -358,9 +356,10 @@ class AmqpTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
 class TestOptions(qpid_interop_test.qit_common.QitCommonTestOptions):
     """Command-line arguments used to control the test"""
 
-    def __init__(self, shim_map, default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
+    def __init__(self, shim_map, default_timeout=DEFAULT_TEST_TIMEOUT,
+                 default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
         super(TestOptions, self).__init__('Qpid-interop AMQP client interoparability test suite for AMQP simple types',
-                                          shim_map, default_xunit_dir)
+                                          shim_map, default_timeout, default_xunit_dir)
         type_group = self._parser.add_mutually_exclusive_group()
         type_group.add_argument('--include-type', action='append', metavar='AMQP-TYPE',
                                 help='Name of AMQP type to include. Supported types:\n%s' %
@@ -383,10 +382,11 @@ class AmqpTypesTest(qpid_interop_test.qit_common.QitTest):
         # Create test classes dynamically
         for amqp_type in sorted(self.types.get_type_list()):
             if self.args.exclude_type is None or amqp_type not in self.args.exclude_type:
-                test_case_class = self.create_testcase_class(amqp_type, product(self.shim_map.values(), repeat=2))
+                test_case_class = self.create_testcase_class(amqp_type, product(self.shim_map.values(), repeat=2),
+                                                             int(self.args.timeout))
                 self.test_suite.addTest(unittest.makeSuite(test_case_class))
 
-    def create_testcase_class(self, amqp_type, shim_product):
+    def create_testcase_class(self, amqp_type, shim_product, timeout):
         """
         Class factory function which creates new subclasses to AmqpTypeTestCase.
         """
@@ -395,7 +395,7 @@ class AmqpTypesTest(qpid_interop_test.qit_common.QitTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, send_shim, receive_shim):
+        def add_test_method(cls, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             @unittest.skipIf(self.types.skip_test(amqp_type, self.broker),
@@ -410,7 +410,8 @@ class AmqpTypesTest(qpid_interop_test.qit_common.QitTest):
                               self.amqp_type,
                               self.test_value_list,
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             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)
@@ -425,7 +426,7 @@ class AmqpTypesTest(qpid_interop_test.qit_common.QitTest):
                       'test_value_list': self.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)
+            add_test_method(new_class, send_shim, receive_shim, timeout)
         return new_class
 
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/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
index 883d387..8f03ba1 100644
--- a/src/python/qpid_interop_test/interop_test_errors.py
+++ b/src/python/qpid_interop_test/interop_test_errors.py
@@ -26,3 +26,9 @@ class InteropTestError(Exception):
     Generic simple error class for use in interop tests
     """
     pass
+
+class InteropTestTimeout(InteropTestError):
+    """
+    Test timeout error
+    """
+    pass

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/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
index 6216e2f..d83a546 100755
--- a/src/python/qpid_interop_test/jms_hdrs_props_test.py
+++ b/src/python/qpid_interop_test/jms_hdrs_props_test.py
@@ -33,7 +33,9 @@ from json import dumps
 import qpid_interop_test.broker_properties
 import qpid_interop_test.qit_common
 import qpid_interop_test.shims
-from qpid_interop_test.interop_test_errors import InteropTestError
+from qpid_interop_test.interop_test_errors import InteropTestError, InteropTestTimeout
+
+DEFAULT_TEST_TIMEOUT = 10 # seconds
 
 
 class JmsHdrPropTypes(qpid_interop_test.qit_common.QitTestTypeMap):
@@ -272,7 +274,7 @@ class JmsMessageHdrsPropsTestCase(qpid_interop_test.qit_common.QitTestCase):
     """Abstract base class for JMS message headers and properties tests"""
 
     def run_test(self, sender_addr, receiver_addr, queue_name_fragment, jms_message_type, test_values, msg_hdrs,
-                 msg_props, send_shim, receive_shim):
+                 msg_props, send_shim, receive_shim, timeout):
         """
         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.
@@ -305,10 +307,10 @@ class JmsMessageHdrsPropsTestCase(qpid_interop_test.qit_common.QitTestCase):
 
         # Wait for sender, process return string
         try:
-            send_obj = sender.wait_for_completion()
-        except KeyboardInterrupt as err:
+            send_obj = sender.wait_for_completion(timeout)
+        except (KeyboardInterrupt, InteropTestTimeout):
             receiver.send_signal(signal.SIGINT)
-            raise err
+            raise
         if send_obj is not None:
             if isinstance(send_obj, str):
                 if send_obj: # len > 0
@@ -319,7 +321,7 @@ class JmsMessageHdrsPropsTestCase(qpid_interop_test.qit_common.QitTestCase):
                 raise InteropTestError('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
 
         # Wait for receiver, process return string
-        receive_obj = receiver.wait_for_completion()
+        receive_obj = receiver.wait_for_completion(timeout)
         if isinstance(receive_obj, tuple):
             if len(receive_obj) == 2:
                 return_jms_message_type, return_list = receive_obj
@@ -352,9 +354,10 @@ class JmsMessageHdrsPropsTestCase(qpid_interop_test.qit_common.QitTestCase):
 class TestOptions(qpid_interop_test.qit_common.QitCommonTestOptions):
     """Command-line arguments used to control the test"""
 
-    def __init__(self, shim_map, default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
+    def __init__(self, shim_map, default_timeout=DEFAULT_TEST_TIMEOUT,
+                 default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
         super(TestOptions, self).__init__('Qpid-interop AMQP client interoparability test suite for JMS headers '
-                                          'and properties', shim_map, default_xunit_dir)
+                                          'and properties', shim_map, default_timeout, default_xunit_dir)
 
         # Control over JMS message headers
         hdrs_group = self._parser.add_mutually_exclusive_group()
@@ -386,20 +389,21 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
     def _generate_tests(self):
         """Generate tests dynamically"""
         self.test_suite = unittest.TestSuite()
+        timeout = int(self.args.timeout)
         # Part A: Single message header on each message
-        test_case_class_a = self._generate_part_a()
+        test_case_class_a = self._generate_part_a(timeout)
         self.test_suite.addTest(unittest.makeSuite(test_case_class_a))
         # Part B: Combination of message headers, using first value in each value list
-        test_case_class_b = self._generate_part_b()
+        test_case_class_b = self._generate_part_b(timeout)
         self.test_suite.addTest(unittest.makeSuite(test_case_class_b))
         # Part C: Single message property on each message
-        test_case_class_c = self._generate_part_c()
+        test_case_class_c = self._generate_part_c(timeout)
         self.test_suite.addTest(unittest.makeSuite(test_case_class_c))
         # Part D: All headers and all properties on one of each type of JMS message
-        test_case_class_d = self._generate_part_d()
+        test_case_class_d = self._generate_part_d(timeout)
         self.test_suite.addTest(unittest.makeSuite(test_case_class_d))
 
-    def _generate_part_a(self):
+    def _generate_part_a(self, timeout):
         """
         Class factory function which creates new subclasses to JmsMessageTypeTestCase. Creates a test case class for
         a single JMS message type containing a single JMS header, one for each possible header
@@ -409,7 +413,7 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim):
+        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             def inner_test_method(self):
@@ -421,7 +425,8 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                               hdrs[1],
                               props[1],
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             inner_test_method.__name__ = 'test.A.%s.%s%s.%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0],
                                                                     send_shim.NAME, receive_shim.NAME)
@@ -451,11 +456,12 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                                         (method_subname, {msg_header: {header_type: header_val}}),
                                         ('', {}),
                                         send_shim,
-                                        receive_shim)
+                                        receive_shim,
+                                        timeout)
         return new_class
 
 
-    def _generate_part_b(self):
+    def _generate_part_b(self, timeout):
         """
         Class factory function which creates new subclasses to JmsMessageTypeTestCase. Creates a test case class for
         a single JMS message type containing a combination of JMS headers
@@ -465,7 +471,7 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim):
+        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             def inner_test_method(self):
@@ -477,7 +483,8 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                               hdrs[1],
                               props[1],
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             inner_test_method.__name__ = 'test.B.%s.%s%s.%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0],
                                                                     send_shim.NAME, receive_shim.NAME)
@@ -520,11 +527,12 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                                             (method_subname, header_map),
                                             ('', {}),
                                             send_shim,
-                                            receive_shim)
+                                            receive_shim,
+                                            timeout)
         return new_class
 
 
-    def _generate_part_c(self):
+    def _generate_part_c(self, timeout):
         """
         Class factory function which creates new subclasses to JmsMessageTypeTestCase. Creates a test case class for
         a single JMS message type containing a single JMS property
@@ -534,7 +542,7 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim):
+        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             def inner_test_method(self):
@@ -546,7 +554,8 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                               hdrs[1],
                               props[1],
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             inner_test_method.__name__ = 'test.C.%s.%s%s.%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0],
                                                                     send_shim.NAME, receive_shim.NAME)
@@ -575,11 +584,12 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                                     ('', {}),
                                     (prop_name, {prop_name: {prop_type: prop_val}}),
                                     send_shim,
-                                    receive_shim)
+                                    receive_shim,
+                                    timeout)
         return new_class
 
 
-    def _generate_part_d(self):
+    def _generate_part_d(self, timeout):
         """
         Class factory function which creates new subclasses to JmsMessageTypeTestCase. Creates a test case class for
         all message headers and properties on each type of JMS message
@@ -589,7 +599,7 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim):
+        def add_test_method(cls, queue_name_fragment, hdrs, props, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             def inner_test_method(self):
@@ -601,7 +611,8 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                               hdrs[1],
                               props[1],
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             inner_test_method.__name__ = 'test.D.%s.%s%s.%s->%s' % (jms_message_type[4:-5], hdrs[0], props[0],
                                                                     send_shim.NAME, receive_shim.NAME)
@@ -639,7 +650,8 @@ class JmsHdrsPropsTest(qpid_interop_test.qit_common.QitJmsTest):
                             ('hdrs', all_hdrs),
                             ('props', all_props),
                             send_shim,
-                            receive_shim)
+                            receive_shim,
+                            timeout)
         return new_class
 
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/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
index 60dfde0..15f292c 100755
--- a/src/python/qpid_interop_test/jms_messages_test.py
+++ b/src/python/qpid_interop_test/jms_messages_test.py
@@ -33,7 +33,9 @@ from json import dumps
 import qpid_interop_test.broker_properties
 import qpid_interop_test.qit_common
 import qpid_interop_test.shims
-from qpid_interop_test.interop_test_errors import InteropTestError
+from qpid_interop_test.interop_test_errors import InteropTestError, InteropTestTimeout
+
+DEFAULT_TEST_TIMEOUT = 10 # seconds
 
 
 class JmsMessageTypes(qpid_interop_test.qit_common.QitTestTypeMap):
@@ -194,13 +196,12 @@ class JmsMessageTypes(qpid_interop_test.qit_common.QitTestTypeMap):
 class JmsMessageTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
     """Abstract base class for JMS message type tests"""
 
-    def run_test(self, sender_addr, receiver_addr, jms_message_type, test_values, send_shim, receive_shim):
+    def run_test(self, sender_addr, receiver_addr, jms_message_type, test_values, send_shim, receive_shim, timeout):
         """
         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 = 'qit.jms_messages_test.%s.%s.%s' % (jms_message_type, send_shim.NAME,
-                                                                                 receive_shim.NAME)
+        queue_name = 'qit.jms_messages_test.%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 = {}
@@ -216,10 +217,10 @@ class JmsMessageTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
 
         # Wait for sender, process return string
         try:
-            send_obj = sender.wait_for_completion()
-        except KeyboardInterrupt as err:
+            send_obj = sender.wait_for_completion(timeout)
+        except (KeyboardInterrupt, InteropTestTimeout):
             receiver.send_signal(signal.SIGINT)
-            raise err
+            raise
         if send_obj is not None:
             if isinstance(send_obj, str):
                 if send_obj: # len > 0
@@ -230,7 +231,7 @@ class JmsMessageTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
                 raise InteropTestError('Send shim \'%s\':\n%s' % (send_shim.NAME, send_obj))
 
         # Wait for receiver, process return string
-        receive_obj = receiver.wait_for_completion()
+        receive_obj = receiver.wait_for_completion(timeout)
         if isinstance(receive_obj, tuple):
             if len(receive_obj) == 2:
                 return_amqp_type, return_test_value_list = receive_obj
@@ -249,9 +250,10 @@ class JmsMessageTypeTestCase(qpid_interop_test.qit_common.QitTestCase):
 class TestOptions(qpid_interop_test.qit_common.QitCommonTestOptions):
     """Command-line arguments used to control the test"""
 
-    def __init__(self, shim_map, default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
+    def __init__(self, shim_map, default_timeout=DEFAULT_TEST_TIMEOUT,
+                 default_xunit_dir=qpid_interop_test.qit_common.DEFUALT_XUNIT_LOG_DIR):
         super(TestOptions, self).__init__('Qpid-interop AMQP client interoparability test suite '
-                                          'for JMS message types', shim_map, default_xunit_dir)
+                                          'for JMS message types', shim_map, default_timeout, default_xunit_dir)
         type_group = self._parser.add_mutually_exclusive_group()
         type_group.add_argument('--include-type', action='append', metavar='JMS_MESSAGE-TYPE',
                                 help='Name of JMS message type to include. Supported types:\n%s' %
@@ -274,11 +276,12 @@ class JmsMessagesTest(qpid_interop_test.qit_common.QitJmsTest):
         # Create test classes dynamically
         for jmt in sorted(self.types.get_type_list()):
             if self.args.exclude_type is None or jmt not in self.args.exclude_type:
-                test_case_class = self.create_testcase_class(jmt, product(self.shim_map.values(), repeat=2))
+                test_case_class = self.create_testcase_class(jmt, product(self.shim_map.values(), repeat=2),
+                                                             int(self.args.timeout))
                 self.test_suite.addTest(unittest.makeSuite(test_case_class))
 
 
-    def create_testcase_class(self, jms_message_type, shim_product):
+    def create_testcase_class(self, jms_message_type, shim_product, timeout):
         """
         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
@@ -289,7 +292,7 @@ class JmsMessagesTest(qpid_interop_test.qit_common.QitJmsTest):
             """Print the class name"""
             return self.__class__.__name__
 
-        def add_test_method(cls, send_shim, receive_shim):
+        def add_test_method(cls, send_shim, receive_shim, timeout):
             """Function which creates a new test method in class cls"""
 
             @unittest.skipIf(self.types.skip_test(jms_message_type, self.broker),
@@ -304,7 +307,8 @@ class JmsMessagesTest(qpid_interop_test.qit_common.QitJmsTest):
                               self.jms_message_type,
                               self.test_values,
                               send_shim,
-                              receive_shim)
+                              receive_shim,
+                              timeout)
 
             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)
@@ -319,7 +323,7 @@ class JmsMessagesTest(qpid_interop_test.qit_common.QitJmsTest):
                       'test_values': self.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)
+            add_test_method(new_class, send_shim, receive_shim, timeout)
 
         return new_class
 

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/src/python/qpid_interop_test/qit_common.py
----------------------------------------------------------------------
diff --git a/src/python/qpid_interop_test/qit_common.py b/src/python/qpid_interop_test/qit_common.py
index 43d2b58..07cd33a 100644
--- a/src/python/qpid_interop_test/qit_common.py
+++ b/src/python/qpid_interop_test/qit_common.py
@@ -161,7 +161,7 @@ class QitCommonTestOptions(object):
     """
     Class controlling common command-line arguments used to control tests.
     """
-    def __init__(self, test_description, shim_map, default_xunit_dir=DEFUALT_XUNIT_LOG_DIR):
+    def __init__(self, test_description, shim_map, default_timeout, default_xunit_dir=DEFUALT_XUNIT_LOG_DIR):
         self._parser = argparse.ArgumentParser(description=test_description)
         self._parser.add_argument('--sender', action='store', default='localhost:5672', metavar='IP-ADDR:PORT',
                                   help='Node to which test suite will send messages.')
@@ -178,6 +178,9 @@ class QitCommonTestOptions(object):
                                   metavar='LOG-DIR-PATH',
                                   help='Default xUnit log directory where xUnit logs are written [xunit_logs dir' +
                                   ' in current directory (%s)]' % default_xunit_dir)
+        self._parser.add_argument('--timeout', action='store', default=default_timeout, metavar='SEC',
+                                  help='Timeout for test in seconds (%d sec). If test is not ' % default_timeout +
+                                  'complete in this time, it will be terminated')
 
         shim_group = self._parser.add_mutually_exclusive_group()
         shim_group.add_argument('--include-shim', action='append', metavar='SHIM-NAME',

http://git-wip-us.apache.org/repos/asf/qpid-interop-test/blob/1820e98b/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
index e5977ee..0d369bb 100644
--- a/src/python/qpid_interop_test/shims.py
+++ b/src/python/qpid_interop_test/shims.py
@@ -25,21 +25,30 @@ import json
 import os
 import signal
 import subprocess
+import threading
+
+from qpid_interop_test.interop_test_errors import InteropTestTimeout
 
 
 class ShimProcess(subprocess.Popen):
     """Abstract parent class for Sender and Receiver shim process"""
-    def __init__(self, args, python3_flag):
+    def __init__(self, args, python3_flag, proc_name):
+        self.proc_name = proc_name
+        self.killed_flag = False
         self.env = copy.deepcopy(os.environ)
         if python3_flag:
             self.env['PYTHONPATH'] = self.env['PYTHON3PATH']
         super(ShimProcess, self).__init__(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid,
                                           env=self.env)
 
-    def wait_for_completion(self):
+    def wait_for_completion(self, timeout):
         """Wait for process to end and return tuple containing (stdout, stderr) from process"""
+        timer = threading.Timer(timeout, self._kill, [timeout])
         try:
+            timer.start()
             (stdoutdata, stderrdata) = self.communicate()
+            if self.killed_flag:
+                raise InteropTestTimeout('%s: Timeout after %d seconds' % (self.proc_name, timeout))
             if stderrdata: # length > 0
                 return stderrdata # ERROR: return single string
             if not stdoutdata: # zero length
@@ -51,21 +60,29 @@ class ShimProcess(subprocess.Popen):
                 except ValueError:
                     return stdoutdata # ERROR: return single string
             return stdoutdata # ERROR: return single string
-        except KeyboardInterrupt as err:
+        except (KeyboardInterrupt) as err:
             self.send_signal(signal.SIGINT)
             raise err
+        finally:
+            timer.cancel()
+
+    def _kill(self, timeout):
+        """Method called when timer expires"""
+        self.kill()
+        self.killed_flag = True
+
 
 class Sender(ShimProcess):
     """Sender shim process"""
-    def __init__(self, params, python3_flag):
+    def __init__(self, params, python3_flag, proc_name='Sender'):
         #print('\n>>>SNDR>>> %s python3_flag=%s' % (params, python3_flag))
-        super(Sender, self).__init__(params, python3_flag)
+        super(Sender, self).__init__(params, python3_flag, proc_name)
 
 class Receiver(ShimProcess):
     """Receiver shim process"""
-    def __init__(self, params, python3_flag):
+    def __init__(self, params, python3_flag, proc_name='Receiver'):
         #print('\n>>>RCVR>>> %s python3_flag=%s' % (params, python3_flag))
-        super(Receiver, self).__init__(params, python3_flag)
+        super(Receiver, self).__init__(params, python3_flag, proc_name)
 
 class Shim(object):
     """Abstract shim class, parent of all shims."""


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