bt2: stream activity messages: create with unknown/infinite default CS
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 14 Jun 2019 02:22:26 +0000 (22:22 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 18 Jun 2019 04:18:14 +0000 (00:18 -0400)
This patch makes it possible to create stream activity beginning and end
messages with unknown or infinite default clock snapshots. It was
already possible to create them with known default clock snapshots, that
is, with a value.

With this patch, you pass either `self._unknown_clock_snapshot` or
`self._infinite_clock_snapshot`, when implementing a
`bt2._UserMessageIterator`, as the default clock snapshot when you call
self._create_stream_activity_beginning_message() or
self._create_stream_activity_end_message(). They are instances of
internal types which are only used for this. The creation methods use
`_unknown_clock_snapshot` by default. This is similar to how
bt_message_stream_activity_beginning_create() and
bt_message_stream_activity_end_create() create messages with unknown
default clock snapshots.

`test_message.py` tests the new feature.

Also in this patch: `_BaseClockSnapshot` does not inherit
`object._UniqueObject` anymore so that `_UnknownClockSnapshot` and
`_InfiniteClockSnapshot` do not either. This is so that the default
clock snapshot properties of the stream activity beginning/end messages
can return instances of those types without having actual native
pointers, because there are none.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Change-Id: I56d5cd9fffb77d505f61522073aaf80ccd58eb8e
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1430
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
src/bindings/python/bt2/bt2/__init__.py.in
src/bindings/python/bt2/bt2/clock_snapshot.py
src/bindings/python/bt2/bt2/message.py
src/bindings/python/bt2/bt2/message_iterator.py
src/bindings/python/bt2/bt2/utils.py
tests/bindings/python/bt2/test_message.py

index f80cf658622ed876a13942d9f416449d1698b4de..1bebfd4e0ab2cc0171cb6739e55cfdc4d4918bf5 100644 (file)
@@ -62,6 +62,8 @@ from bt2.trace_collection_message_iterator import *
 from bt2.value import *
 from bt2.value import _Value
 from bt2.value import _IntegerValue
+from bt2.clock_snapshot import _UnknownClockSnapshot
+from bt2.clock_snapshot import _InfiniteClockSnapshot
 
 
 class Error(Exception):
index 4bf37d622b232917fedd69420c7d65ccfffdfa1f..89d7a11b5847413fac7209625a767b9cfa6dff5b 100644 (file)
@@ -26,16 +26,14 @@ import bt2
 import functools
 
 
-class _BaseClockSnapshot(object._UniqueObject):
+@functools.total_ordering
+class _ClockSnapshot(object._UniqueObject):
     @property
     def clock_class(self):
         cc_ptr = native_bt.clock_snapshot_borrow_clock_class_const(self._ptr)
         assert cc_ptr is not None
         return bt2.clock_class._ClockClass._create_from_ptr_and_get_ref(cc_ptr)
 
-
-@functools.total_ordering
-class _ClockSnapshot(_BaseClockSnapshot):
     @property
     def value(self):
         return native_bt.clock_snapshot_get_value(self._ptr)
@@ -62,9 +60,9 @@ class _ClockSnapshot(_BaseClockSnapshot):
         return self.value < int(other)
 
 
-class _UnknownClockSnapshot(_BaseClockSnapshot):
+class _UnknownClockSnapshot:
     pass
 
 
-class _InfiniteClockSnapshot(_BaseClockSnapshot):
+class _InfiniteClockSnapshot:
     pass
index 56b545daa98faf1c0220f424b5e2dd8f6cec7aec..9778265337aebccc93dfd45b05eab99d1dbd64c2 100644 (file)
@@ -110,28 +110,43 @@ class _StreamEndMessage(_StreamMessage):
     _borrow_stream_ptr = staticmethod(native_bt.message_stream_end_borrow_stream)
 
 
+# Specific type to pass an unknown clock snapshot when creating a stream
+# beginning/end message.
+class _StreamActivityMessageUnknownClockSnapshot:
+    pass
+
+
+# Specific type to pass an infinite clock snapshot when creating a
+# stream beginning/end message.
+class _StreamActivityMessageInfiniteClockSnapshot:
+    pass
+
+
 class _StreamActivityMessage(_Message):
     @property
     def default_clock_snapshot(self):
-        self._check_has_default_clock_class(self.stream.cls.default_clock_class)
         status, snapshot_ptr = self._borrow_default_clock_snapshot_ptr(self._ptr)
 
         if status == native_bt.MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN:
-            snapshot_type = bt2.clock_snapshot._ClockSnapshot
+            cs_type = bt2.clock_snapshot._ClockSnapshot
+            assert snapshot_ptr is not None
+            return cs_type._create_from_ptr_and_get_ref(snapshot_ptr, self._ptr,
+                                                        self._get_ref, self._put_ref)
         elif status == native_bt.MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN:
-            snapshot_type = bt2.clock_snapshot._UnknownClockSnapshot
+            return bt2.clock_snapshot._UnknownClockSnapshot()
         elif status == native_bt.MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE:
-            snapshot_type = bt2.clock_snapshot._InfiniteClockSnapshot
+            return bt2.clock_snapshot._InfiniteClockSnapshot()
         else:
             raise bt2.Error('cannot borrow default clock snapshot from message')
 
-        assert snapshot_ptr is not None
-
-        return snapshot_type._create_from_ptr_and_get_ref(
-            snapshot_ptr, self._ptr, self._get_ref, self._put_ref)
-
     def _default_clock_snapshot(self, value):
-        self._set_default_clock_snapshot_ptr(self._ptr, value)
+        if type(value) is _StreamActivityMessageUnknownClockSnapshot:
+            self._set_default_clock_snapshot_state(self._ptr, native_bt.MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_UNKNOWN)
+        elif type(value) is _StreamActivityMessageInfiniteClockSnapshot:
+            self._set_default_clock_snapshot_state(self._ptr, native_bt.MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_INFINITE)
+        else:
+            assert utils._is_uint64(value)
+            self._set_default_clock_snapshot_ptr(self._ptr, value)
 
     _default_clock_snapshot = property(fset=_default_clock_snapshot)
 
@@ -145,12 +160,14 @@ class _StreamActivityMessage(_Message):
 class _StreamActivityBeginningMessage(_StreamActivityMessage):
     _borrow_default_clock_snapshot_ptr = staticmethod(native_bt.message_stream_activity_beginning_borrow_default_clock_snapshot_const)
     _set_default_clock_snapshot_ptr = staticmethod(native_bt.message_stream_activity_beginning_set_default_clock_snapshot)
+    _set_default_clock_snapshot_state = staticmethod(native_bt.message_stream_activity_beginning_set_default_clock_snapshot_state)
     _borrow_stream_ptr = staticmethod(native_bt.message_stream_activity_beginning_borrow_stream)
 
 
 class _StreamActivityEndMessage(_StreamActivityMessage):
     _borrow_default_clock_snapshot_ptr = staticmethod(native_bt.message_stream_activity_end_borrow_default_clock_snapshot_const)
     _set_default_clock_snapshot_ptr = staticmethod(native_bt.message_stream_activity_end_set_default_clock_snapshot)
+    _set_default_clock_snapshot_state = staticmethod(native_bt.message_stream_activity_end_set_default_clock_snapshot_state)
     _borrow_stream_ptr = staticmethod(native_bt.message_stream_activity_end_borrow_stream)
 
 
index 7f996b007e1ec8353fb3537fd45d0fdd80823c66..e5199290b06b62ffa90df818b6d82cfe5215ad37 100644 (file)
@@ -135,30 +135,21 @@ class _UserMessageIterator(_MessageIterator):
         ptr = msg._release()
         return int(ptr)
 
-    # Validate that the presence or lack of presence of a
-    # `default_clock_snapshot` value is valid in the context of `stream_class`.
-    @staticmethod
-    def _validate_default_clock_snapshot(stream_class, default_clock_snapshot):
-        stream_class_has_default_clock_class = stream_class.default_clock_class is not None
-
-        if stream_class_has_default_clock_class and default_clock_snapshot is None:
-            raise bt2.Error(
-                'stream class has a default clock class, default_clock_snapshot should not be None')
-
-        if not stream_class_has_default_clock_class and default_clock_snapshot is not None:
-            raise bt2.Error(
-                'stream class has no default clock class, default_clock_snapshot should be None')
-
     def _create_event_message(self, event_class, packet, default_clock_snapshot=None):
         utils._check_type(event_class, bt2.event_class._EventClass)
         utils._check_type(packet, bt2.packet._Packet)
-        self._validate_default_clock_snapshot(packet.stream.cls, default_clock_snapshot)
 
         if default_clock_snapshot is not None:
+            if event_class.stream_class.default_clock_class is None:
+                raise ValueError('event messages in this stream must not have a default clock snapshot')
+
             utils._check_uint64(default_clock_snapshot)
             ptr = native_bt.message_event_create_with_default_clock_snapshot(
                 self._ptr, event_class._ptr, packet._ptr, default_clock_snapshot)
         else:
+            if event_class.stream_class.default_clock_class is not None:
+                raise ValueError('event messages in this stream must have a default clock snapshot')
+
             ptr = native_bt.message_event_create(
                 self._ptr, event_class._ptr, packet._ptr)
 
@@ -177,6 +168,26 @@ class _UserMessageIterator(_MessageIterator):
 
         return bt2.message._MessageIteratorInactivityMessage(ptr)
 
+    _unknown_clock_snapshot = bt2.message._StreamActivityMessageUnknownClockSnapshot()
+    _infinite_clock_snapshot = bt2.message._StreamActivityMessageInfiniteClockSnapshot()
+
+    @staticmethod
+    def _validate_stream_activity_message_default_clock_snapshot(stream, default_cs):
+        isinst_infinite = isinstance(default_cs, bt2.message._StreamActivityMessageInfiniteClockSnapshot)
+        isinst_unknown = isinstance(default_cs, bt2.message._StreamActivityMessageUnknownClockSnapshot)
+
+        if utils._is_uint64(default_cs):
+            pass
+        elif isinst_infinite or isinst_unknown:
+            if default_cs is not _UserMessageIterator._unknown_clock_snapshot and default_cs is not _UserMessageIterator._infinite_clock_snapshot:
+                raise ValueError('unexpected value for default clock snapshot')
+        else:
+            raise TypeError("unexpected type '{}' for default clock snapshot".format(default_cs.__class__.__name__))
+
+        if stream.cls.default_clock_class is None:
+            if utils._is_uint64(default_cs):
+                raise ValueError('stream activity messages in this stream cannot have a known default clock snapshot')
+
     def _create_stream_beginning_message(self, stream):
         utils._check_type(stream, bt2.stream._Stream)
 
@@ -186,10 +197,10 @@ class _UserMessageIterator(_MessageIterator):
 
         return bt2.message._StreamBeginningMessage(ptr)
 
-    def _create_stream_activity_beginning_message(self, stream, default_clock_snapshot=None):
+    def _create_stream_activity_beginning_message(self, stream,
+                                                  default_clock_snapshot=_unknown_clock_snapshot):
         utils._check_type(stream, bt2.stream._Stream)
-        self._validate_default_clock_snapshot(stream.cls, default_clock_snapshot)
-
+        self._validate_stream_activity_message_default_clock_snapshot(stream, default_clock_snapshot)
         ptr = native_bt.message_stream_activity_beginning_create(self._ptr, stream._ptr)
 
         if ptr is None:
@@ -197,16 +208,13 @@ class _UserMessageIterator(_MessageIterator):
                 'cannot create stream activity beginning message object')
 
         msg = bt2.message._StreamActivityBeginningMessage(ptr)
-
-        if default_clock_snapshot is not None:
-            msg._default_clock_snapshot = default_clock_snapshot
-
+        msg._default_clock_snapshot = default_clock_snapshot
         return msg
 
-    def _create_stream_activity_end_message(self, stream, default_clock_snapshot=None):
+    def _create_stream_activity_end_message(self, stream,
+                                            default_clock_snapshot=_unknown_clock_snapshot):
         utils._check_type(stream, bt2.stream._Stream)
-        self._validate_default_clock_snapshot(stream.cls, default_clock_snapshot)
-
+        self._validate_stream_activity_message_default_clock_snapshot(stream, default_clock_snapshot)
         ptr = native_bt.message_stream_activity_end_create(self._ptr, stream._ptr)
 
         if ptr is None:
@@ -214,10 +222,7 @@ class _UserMessageIterator(_MessageIterator):
                 'cannot create stream activity end message object')
 
         msg = bt2.message._StreamActivityEndMessage(ptr)
-
-        if default_clock_snapshot is not None:
-            msg._default_clock_snapshot = default_clock_snapshot
-
+        msg._default_clock_snapshot = default_clock_snapshot
         return msg
 
     def _create_stream_end_message(self, stream):
index bd8ebf8e9d841fdce79a7eff713b8f42d5646ea6..b564fcad1b486aa57ae2b27ca613d6ff3f517eb9 100644 (file)
@@ -49,18 +49,34 @@ def _check_type(o, expected_type):
                                                            expected_type))
 
 
-def _is_int64(v):
-    _check_int(v)
+def _is_in_int64_range(v):
+    assert(isinstance(v, int))
     return v >= -(2**63) and v <= (2**63 - 1)
 
 
-def _is_uint64(v):
-    _check_int(v)
+def _is_int64(v):
+    if not isinstance(v, int):
+        return False
+
+    return _is_in_int64_range(v)
+
+
+def _is_in_uint64_range(v):
+    assert(isinstance(v, int))
     return v >= 0 and v <= (2**64 - 1)
 
 
+def _is_uint64(v):
+    if not isinstance(v, int):
+        return False
+
+    return _is_in_uint64_range(v)
+
+
 def _check_int64(v, msg=None):
-    if not _is_int64(v):
+    _check_int(v)
+
+    if not _is_in_int64_range(v):
         if msg is None:
             msg = 'expecting a signed 64-bit integral value'
 
@@ -69,7 +85,9 @@ def _check_int64(v, msg=None):
 
 
 def _check_uint64(v, msg=None):
-    if not _is_uint64(v):
+    _check_int(v)
+
+    if not _is_in_uint64_range(v):
         if msg is None:
             msg = 'expecting an unsigned 64-bit integral value'
 
index 5f11c9a9b5eb4b7046634940e6b39cc81e177b5b..ed6c31296b93a3158088f89a32d75389f1824793 100644 (file)
@@ -164,8 +164,8 @@ class AllMessagesTestCase(unittest.TestCase):
                 self.assertEqual(msg.stream.addr, self._stream.addr)
             elif i == 1:
                 self.assertIsInstance(msg, bt2.message._StreamActivityBeginningMessage)
-                with self.assertRaises(bt2.NonexistentClockSnapshot):
-                    msg.default_clock_snapshot
+                self.assertIsInstance(msg.default_clock_snapshot,
+                                      bt2._UnknownClockSnapshot)
             elif i == 2:
                 self.assertIsInstance(msg, bt2.message._PacketBeginningMessage)
                 self.assertEqual(msg.packet.addr, self._packet.addr)
@@ -198,11 +198,228 @@ class AllMessagesTestCase(unittest.TestCase):
             elif i == 7:
                 self.assertIsInstance(msg, bt2.message._StreamActivityEndMessage)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
-                with self.assertRaises(bt2.NonexistentClockSnapshot):
-                    msg.default_clock_snapshot
+                self.assertIsInstance(msg.default_clock_snapshot,
+                                      bt2._UnknownClockSnapshot)
             elif i == 8:
                 self.assertIsInstance(msg, bt2.message._StreamEndMessage)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
             else:
                 raise Exception
 
+
+class StreamActivityMessagesTestCase(unittest.TestCase):
+    def _test_create_msg(self, with_cc, test_create_beginning_func, test_create_end_func):
+        class MyIter(bt2._UserMessageIterator):
+            def __init__(self, self_port_output):
+                self._at = 0
+
+            def __next__(self):
+                if self._at == 0:
+                    msg = self._create_stream_beginning_message(self._component._stream)
+                elif self._at == 1:
+                    msg = test_create_beginning_func(self, self._component._stream)
+                elif self._at == 2:
+                    msg = test_create_end_func(self, self._component._stream)
+                elif self._at == 3:
+                    msg = self._create_stream_end_message(self._component._stream)
+                elif self._at >= 4:
+                    raise bt2.Stop
+
+                self._at += 1
+                return msg
+
+        class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
+            def __init__(self, params):
+                self._add_output_port('out')
+                tc = self._create_trace_class()
+
+                if with_cc:
+                    cc = self._create_clock_class()
+                    sc = tc.create_stream_class(default_clock_class=cc)
+                else:
+                    sc = tc.create_stream_class()
+
+                # Create payload field class
+                trace = tc()
+                self._stream = trace.create_stream(sc)
+
+        graph = bt2.Graph()
+        src_comp = graph.add_component(MySrc, 'src')
+        msg_iter = graph.create_output_port_message_iterator(src_comp.output_ports['out'])
+
+        for msg in msg_iter:
+            pass
+
+    def test_create_beginning_with_cc_with_known_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_beginning_message(stream, 172)
+            self.assertEqual(msg.default_clock_snapshot.value, 172)
+            return msg
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream, 199)
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_end_with_cc_with_known_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream, 172)
+
+        def create_end(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_end_message(stream, 199)
+            self.assertEqual(msg.default_clock_snapshot.value, 199)
+            return msg
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_beginning_with_cc_with_unknown_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_beginning_message(stream,
+                                                                     msg_iter._unknown_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._UnknownClockSnapshot)
+            return msg
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream, 199)
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_end_with_cc_with_unknown_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream, 172)
+
+        def create_end(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_end_message(stream,
+                                                               msg_iter._unknown_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._UnknownClockSnapshot)
+            return msg
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_beginning_with_cc_with_infinite_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_beginning_message(stream,
+                                                                     msg_iter._infinite_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._InfiniteClockSnapshot)
+            return msg
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream, 199)
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_end_with_cc_with_infinite_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream, 172)
+
+        def create_end(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_end_message(stream,
+                                                               msg_iter._infinite_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._InfiniteClockSnapshot)
+            return msg
+
+        self._test_create_msg(True, create_beginning, create_end)
+
+    def test_create_beginning_without_cc_with_known_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            with self.assertRaises(ValueError):
+                msg_iter._create_stream_activity_beginning_message(stream, 172)
+
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_end_without_cc_with_known_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            with self.assertRaises(ValueError):
+                msg_iter._create_stream_activity_end_message(stream, 199)
+
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_beginning_without_cc_with_unknown_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_beginning_message(stream,
+                                                                     msg_iter._unknown_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._UnknownClockSnapshot)
+            return msg
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_end_without_cc_with_unknown_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_end_message(stream,
+                                                               msg_iter._unknown_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._UnknownClockSnapshot)
+            return msg
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_beginning_without_cc_with_infinite_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_beginning_message(stream,
+                                                                     msg_iter._infinite_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._InfiniteClockSnapshot)
+            return msg
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_end_without_cc_with_infinite_default_cs(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            msg = msg_iter._create_stream_activity_end_message(stream,
+                                                               msg_iter._infinite_clock_snapshot)
+            self.assertIsInstance(msg.default_clock_snapshot,
+                                  bt2._InfiniteClockSnapshot)
+            return msg
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_beginning_default_cs_wrong_type(self):
+        def create_beginning(msg_iter, stream):
+            with self.assertRaises(TypeError):
+                msg_iter._create_stream_activity_beginning_message(stream, 'infinite')
+
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
+
+    def test_create_end_without_default_cs_wrong_type(self):
+        def create_beginning(msg_iter, stream):
+            return msg_iter._create_stream_activity_beginning_message(stream)
+
+        def create_end(msg_iter, stream):
+            with self.assertRaises(TypeError):
+                msg_iter._create_stream_activity_end_message(stream, 'unknown')
+
+            return msg_iter._create_stream_activity_end_message(stream)
+
+        self._test_create_msg(False, create_beginning, create_end)
This page took 0.033151 seconds and 4 git commands to generate.