lib: make can_seek_ns_from_origin logic use `can_seek_forward` property of iterator
authorSimon Marchi <simon.marchi@efficios.com>
Wed, 18 Sep 2019 20:22:16 +0000 (16:22 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 9 Oct 2019 18:14:29 +0000 (14:14 -0400)
This patch changes the behavior of
bt_self_component_port_input_message_iterator_can_seek_ns_from_origin to
make use of the new `can_seek_forward` property of iterators.

The current iterator "can seek ns from origin" logic works like this:

- If the iterator provides a `can_seek_ns_from_origin` method, call it
  and return that result.
- Otherwise, check if we can autoseek: if the iterator can seek
  beginning return true, else return false.

An issue with this is that if:

- an iterator doesn't provide the can_seek_ns_from_origin and
  seek_ns_from_origin methods
- the streams (and thus event messages) produced by this iterator don't
  have a timestamp
- the iterator can seek beginning

then
bt_self_component_port_input_message_iterator_can_seek_ns_from_origin
will report that this iterator can seek ns from origin, presumably
because it can use autoseek.  However, since the event messages don't
have a timestamp, we'll be able to seek beginning, but fast forwarding
to the desired point won't work.

To solve this, we need an additional property on message iterators,
whether the messages it produces have a timestamp, and therefore if the
"fast-forward" portion of autoseek will work.

This patch also brings another behavior change.  Previously, if the
can_seek_ns_from_origin method of the iterator was provided and returned
false, that was it.  With this patch, if that happens, we fall back to
checking if autoseek is supported.  That change is primarily in
bt_self_component_port_input_message_iterator_can_seek_ns_from_origin.
However,
bt_self_component_port_input_message_iterator_seek_ns_from_origin is
also updated accordingly, because we need to query the iterator to know
if it can seek ns from origin by itself, or if we should fall back on
autoseek.

Change-Id: I1848c87acf8ed75d4020a51e3be41dec2f144843
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/2066
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
src/bindings/python/bt2/bt2/message_iterator.py
src/lib/graph/iterator.c
src/plugins/ctf/fs-src/fs.c
src/plugins/lttng-utils/debug-info/debug-info.c
src/plugins/utils/muxer/muxer.c
src/plugins/utils/trimmer/trimmer.c
tests/bindings/python/bt2/test_message_iterator.py
tests/data/plugins/flt.utils.trimmer/bt_plugin_trimmer_test.py

index 3b46c6da5ef4d67071683054f734bb11ef25a931..253fbcc73c4c9cdd63488fd381dc2fc671274e3f 100644 (file)
@@ -224,22 +224,21 @@ class _UserMessageIterator(_MessageIterator):
         self._user_seek_beginning()
 
     def _bt_can_seek_ns_from_origin_from_native(self, ns_from_origin):
-        # Here, we mimic the behavior of the C API:
+        # Return whether the iterator can seek ns from origin using the
+        # user-implemented seek_ns_from_origin method.  We mimic the behavior
+        # of the C API:
         #
         # - If the iterator has a _user_can_seek_ns_from_origin method,
         #   call it and use its return value.
         # - Otherwise, if there is a `_user_seek_ns_from_origin` method,
         #   we presume it's possible.
-        # - Otherwise, check if we can seek to beginning (which allows us to
-        #   seek to beginning and then fast forward - aka auto-seek).
+
         if hasattr(self, '_user_can_seek_ns_from_origin'):
             can_seek_ns_from_origin = self._user_can_seek_ns_from_origin(ns_from_origin)
             utils._check_bool(can_seek_ns_from_origin)
             return can_seek_ns_from_origin
-        elif hasattr(self, '_user_seek_ns_from_origin'):
-            return True
         else:
-            return self._bt_can_seek_beginning_from_native()
+            return hasattr(self, '_user_seek_ns_from_origin')
 
     def _bt_seek_ns_from_origin_from_native(self, ns_from_origin):
         self._user_seek_ns_from_origin(ns_from_origin)
index cb0c6523fbca9cd7605e5523bb35d5a53a9a16e7..951776a11539082f0dac903c1209e1b375197092 100644 (file)
@@ -1001,25 +1001,46 @@ bt_self_component_port_input_message_iterator_can_seek_ns_from_origin(
                 */
                *can_seek = -1;
 
+               BT_LIB_LOGD("Calling user's \"can seek nanoseconds from origin\" method: %!+i",
+                       iterator);
+
                status = (int) iterator->methods.can_seek_ns_from_origin(iterator,
                        ns_from_origin, can_seek);
 
-               BT_ASSERT_POST(
-                       status != BT_FUNC_STATUS_OK ||
-                               *can_seek == BT_TRUE ||
-                               *can_seek == BT_FALSE,
+               if (status != BT_FUNC_STATUS_OK) {
+                       BT_LIB_LOGW_APPEND_CAUSE(
+                               "Component input port message iterator's \"can seek nanoseconds from origin\" method failed: "
+                               "%![iter-]+i, status=%s",
+                               iterator, bt_common_func_status_string(status));
+                       goto end;
+               }
+
+               BT_ASSERT_POST(*can_seek == BT_TRUE || *can_seek == BT_FALSE,
                        "Unexpected boolean value returned from user's \"can seek ns from origin\" method: val=%d, %![iter-]+i",
                        *can_seek, iterator);
 
-               goto end;
+               BT_LIB_LOGD(
+                       "User's \"can seek nanoseconds from origin\" returned successfully: "
+                       "%![iter-]+i, can-seek=%d",
+                       iterator, *can_seek);
+
+               if (*can_seek) {
+                       goto end;
+               }
        }
 
        /*
-        * Automatic seeking fall back: if we can seek to the beginning,
-        * then we can automatically seek to any message.
+        * Automatic seeking fall back: if we can seek to the beginning and the
+        * iterator supports forward seeking then we can automatically seek to
+        * any timestamp.
         */
        status = (int) bt_self_component_port_input_message_iterator_can_seek_beginning(
                iterator, can_seek);
+       if (status != BT_FUNC_STATUS_OK) {
+               goto end;
+       }
+
+       *can_seek = *can_seek && iterator->config.can_seek_forward;
 
 end:
        return status;
@@ -1686,6 +1707,7 @@ bt_self_component_port_input_message_iterator_seek_ns_from_origin(
 {
        int status;
        GHashTable *stream_states = NULL;
+       bt_bool can_seek_by_itself;
 
        BT_ASSERT_PRE_NON_NULL(iterator, "Message iterator");
        BT_ASSERT_PRE_ITER_HAS_STATE_TO_SEEK(iterator);
@@ -1694,6 +1716,7 @@ bt_self_component_port_input_message_iterator_seek_ns_from_origin(
                        BT_GRAPH_CONFIGURATION_STATE_CONFIGURING,
                "Graph is not configured: %!+g",
                bt_component_borrow_graph(iterator->upstream_component));
+       /* The iterator must be able to seek ns from origin one way or another. */
        BT_ASSERT_PRE(
                message_iterator_can_seek_ns_from_origin(iterator, ns_from_origin),
                "Message iterator cannot seek nanoseconds from origin: %!+i, "
@@ -1707,8 +1730,27 @@ bt_self_component_port_input_message_iterator_seek_ns_from_origin(
         */
        reset_iterator_expectations(iterator);
 
-       if (iterator->methods.seek_ns_from_origin) {
+       /* Check if the iterator can seek by itself.  If not we'll use autoseek. */
+       if (iterator->methods.can_seek_ns_from_origin) {
+               bt_component_class_message_iterator_can_seek_ns_from_origin_method_status
+                       can_seek_status;
+
+               can_seek_status =
+                       iterator->methods.can_seek_ns_from_origin(
+                               iterator, ns_from_origin, &can_seek_by_itself);
+               if (can_seek_status != BT_FUNC_STATUS_OK) {
+                       status = can_seek_status;
+                       goto end;
+               }
+       } else {
+               can_seek_by_itself = false;
+       }
+
+       if (can_seek_by_itself) {
                /* The iterator knows how to seek to a particular time, let it handle this. */
+               BT_ASSERT_PRE_DEV(iterator->methods.seek_ns_from_origin,
+                       "Message iterator does not implement `seek_ns_from_origin` method: %!+i",
+                       iterator);
                BT_LIB_LOGD("Calling user's \"seek nanoseconds from origin\" method: "
                        "%![iter-]+i, ns=%" PRId64, iterator, ns_from_origin);
                status = iterator->methods.seek_ns_from_origin(iterator,
@@ -1729,8 +1771,9 @@ bt_self_component_port_input_message_iterator_seek_ns_from_origin(
                }
        } else {
                /*
-                * The iterator doesn't know how to seek to a particular time.  We will
-                * seek to the beginning and fast forward to the right place.
+                * The iterator doesn't know how to seek by itself to a
+                * particular time.  We will seek to the beginning and fast
+                * forward to the right place.
                 */
                enum bt_component_class_message_iterator_can_seek_beginning_method_status
                        can_seek_status;
index c3b8a2ed9a0f6ee6acbc95e5cda19078d05771c2..08d2acfb9581286724199b56c430a6a40c58bd63 100644 (file)
@@ -293,12 +293,20 @@ bt_component_class_message_iterator_initialize_method_status ctf_fs_iterator_ini
                goto error;
        }
 
+       /*
+        * This iterator can seek forward if its stream class has a default
+        * clock class.
+        */
+       if (msg_iter_data->ds_file_group->sc->default_clock_class) {
+               bt_self_message_iterator_configuration_set_can_seek_forward(
+                       config, true);
+       }
+
        bt_self_message_iterator_set_data(self_msg_iter,
                msg_iter_data);
        if (ret != BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK) {
                goto error;
        }
-
        msg_iter_data = NULL;
        goto end;
 
index af6795965018e43351f331a1a9dbf107c150463b..c948df24b73b3719667f634a5e0255731a37e19a 100644 (file)
@@ -2031,6 +2031,10 @@ bt_component_class_message_iterator_initialize_method_status debug_info_msg_iter
                goto error;
        }
 
+       bt_self_message_iterator_configuration_set_can_seek_forward(config,
+               bt_self_component_port_input_message_iterator_can_seek_forward(
+                       debug_info_msg_iter->msg_iter));
+
        bt_self_message_iterator_set_data(self_msg_iter, debug_info_msg_iter);
        debug_info_msg_iter->input_iterator = self_msg_iter;
 
index 54238eb48f38ac2fc211efbe1784eb7ef20177a7..3e4d42057b1d49e0a00814cdd6f063f9f11da634 100644 (file)
@@ -1148,11 +1148,13 @@ void destroy_muxer_msg_iter(struct muxer_msg_iter *muxer_msg_iter)
 static
 bt_component_class_message_iterator_initialize_method_status
 muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp,
-               struct muxer_msg_iter *muxer_msg_iter)
+               struct muxer_msg_iter *muxer_msg_iter,
+               struct bt_self_message_iterator_configuration *config)
 {
        int64_t count;
        int64_t i;
        bt_component_class_message_iterator_initialize_method_status status;
+       bool can_seek_forward = true;
 
        count = bt_component_filter_get_input_port_count(
                bt_self_component_filter_as_component_filter(
@@ -1203,8 +1205,19 @@ muxer_msg_iter_init_upstream_iterators(struct muxer_comp *muxer_comp,
                        /* muxer_msg_iter_add_upstream_msg_iter() logs errors */
                        goto end;
                }
+
+               can_seek_forward = can_seek_forward &&
+                       bt_self_component_port_input_message_iterator_can_seek_forward(
+                               upstream_msg_iter);
        }
 
+       /*
+        * This iterator can seek forward if all of its iterators can seek
+        * forward.
+        */
+       bt_self_message_iterator_configuration_set_can_seek_forward(
+               config, can_seek_forward);
+
        status = BT_COMPONENT_CLASS_MESSAGE_ITERATOR_INITIALIZE_METHOD_STATUS_OK;
 
 end:
@@ -1272,7 +1285,7 @@ bt_component_class_message_iterator_initialize_method_status muxer_msg_iter_init
        }
 
        status = muxer_msg_iter_init_upstream_iterators(muxer_comp,
-               muxer_msg_iter);
+               muxer_msg_iter, config);
        if (status) {
                BT_COMP_LOGE("Cannot initialize connected input ports for muxer component's message iterator: "
                        "comp-addr=%p, muxer-comp-addr=%p, "
index 49fac604af901b68c44351955d0827f8b5a4ff19..5134fdc98152000bb5cfbe5f8cde3f0432f4205b 100644 (file)
@@ -720,6 +720,13 @@ bt_component_class_message_iterator_initialize_method_status trimmer_msg_iter_in
                goto error;
        }
 
+       /*
+        * The trimmer requires upstream messages to have times, so it can
+        * always seek forward.
+        */
+       bt_self_message_iterator_configuration_set_can_seek_forward(
+               config, BT_TRUE);
+
        trimmer_it->self_msg_iter = self_msg_iter;
        bt_self_message_iterator_set_data(self_msg_iter, trimmer_it);
 
index 21f95704b33d072e814f641f1e8c6766d2907699..37f6dc87798dcda7b32b4ef72b8e36b40b56b0f5 100644 (file)
@@ -386,6 +386,7 @@ def _setup_seek_test(
     user_can_seek_beginning=None,
     user_seek_ns_from_origin=None,
     user_can_seek_ns_from_origin=None,
+    can_seek_forward=False,
 ):
     class MySourceIter(bt2._UserMessageIterator):
         def __init__(self, config, port):
@@ -403,6 +404,7 @@ def _setup_seek_test(
                 self._create_stream_end_message(stream),
             ]
             self._at = 0
+            config.can_seek_forward = can_seek_forward
 
         def __next__(self):
             if self._at < len(self._msgs):
@@ -437,6 +439,7 @@ def _setup_seek_test(
             self._upstream_iter = self._create_input_port_message_iterator(
                 self._component._input_ports['in']
             )
+            config.can_seek_forward = self._upstream_iter.can_seek_forward
 
         def __next__(self):
             return next(self._upstream_iter)
@@ -660,48 +663,209 @@ class UserMessageIteratorSeekBeginningTestCase(unittest.TestCase):
 
 
 class UserMessageIteratorSeekNsFromOriginTestCase(unittest.TestCase):
-    def test_can_seek_ns_from_origin(self):
-        class MySink(bt2._UserSinkComponent):
-            def __init__(self, config, params, obj):
-                self._add_input_port('in')
+    def test_can_seek_ns_from_origin_returns_true(self):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: returns True
+        #   - seek_ns_from_origin provided: Don't care
+        #   - can the iterator seek beginning: Don't care
+        #   - can the iterator seek forward: Don't care
+        #
+        # We expect iter.can_seek_ns_from_origin to return True.
+        for user_seek_ns_from_origin_provided in (False, True):
+            for iter_can_seek_beginning in (False, True):
+                for iter_can_seek_forward in (False, True):
+                    self._can_seek_ns_from_origin_test(
+                        expected_outcome=True,
+                        user_can_seek_ns_from_origin_ret_val=True,
+                        user_seek_ns_from_origin_provided=user_seek_ns_from_origin_provided,
+                        iter_can_seek_beginning=iter_can_seek_beginning,
+                        iter_can_seek_forward=iter_can_seek_forward,
+                    )
+
+    def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: returns False
+        #   - seek_ns_from_origin provided: Don't care
+        #   - can the iterator seek beginning: Yes
+        #   - can the iterator seek forward: Yes
+        #
+        # We expect iter.can_seek_ns_from_origin to return True.
+        for user_seek_ns_from_origin_provided in (False, True):
+            self._can_seek_ns_from_origin_test(
+                expected_outcome=True,
+                user_can_seek_ns_from_origin_ret_val=False,
+                user_seek_ns_from_origin_provided=user_seek_ns_from_origin_provided,
+                iter_can_seek_beginning=True,
+                iter_can_seek_forward=True,
+            )
 
-            def _user_graph_is_configured(self):
-                self._msg_iter = self._create_input_port_message_iterator(
-                    self._input_ports['in']
-                )
+    def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_not_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: returns False
+        #   - seek_ns_from_origin provided: Don't care
+        #   - can the iterator seek beginning: Yes
+        #   - can the iterator seek forward: No
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        for user_seek_ns_from_origin_provided in (False, True):
+            self._can_seek_ns_from_origin_test(
+                expected_outcome=False,
+                user_can_seek_ns_from_origin_ret_val=False,
+                user_seek_ns_from_origin_provided=user_seek_ns_from_origin_provided,
+                iter_can_seek_beginning=True,
+                iter_can_seek_forward=False,
+            )
 
-            def _user_consume(self):
-                nonlocal can_seek_ns_from_origin
-                nonlocal test_ns_from_origin
-                can_seek_ns_from_origin = self._msg_iter.can_seek_ns_from_origin(
-                    test_ns_from_origin
+    def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: returns False
+        #   - seek_ns_from_origin provided: Don't care
+        #   - can the iterator seek beginning: No
+        #   - can the iterator seek forward: Yes
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        # for user_seek_ns_from_origin_provided in (False, True):
+        self._can_seek_ns_from_origin_test(
+            expected_outcome=False,
+            user_can_seek_ns_from_origin_ret_val=False,
+            user_seek_ns_from_origin_provided=False,
+            iter_can_seek_beginning=False,
+            iter_can_seek_forward=True,
+        )
+
+    def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_not_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: returns False
+        #   - seek_ns_from_origin provided: Don't care
+        #   - can the iterator seek beginning: No
+        #   - can the iterator seek forward: No
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        for user_seek_ns_from_origin_provided in (False, True):
+            self._can_seek_ns_from_origin_test(
+                expected_outcome=False,
+                user_can_seek_ns_from_origin_ret_val=False,
+                user_seek_ns_from_origin_provided=user_seek_ns_from_origin_provided,
+                iter_can_seek_beginning=False,
+                iter_can_seek_forward=False,
+            )
+
+    def test_no_can_seek_ns_from_origin_seek_ns_from_origin(self):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: Not provided
+        #   - seek_ns_from_origin provided: Yes
+        #   - can the iterator seek beginning: Don't care
+        #   - can the iterator seek forward: Don't care
+        #
+        # We expect iter.can_seek_ns_from_origin to return True.
+        for iter_can_seek_beginning in (False, True):
+            for iter_can_seek_forward in (False, True):
+                self._can_seek_ns_from_origin_test(
+                    expected_outcome=True,
+                    user_can_seek_ns_from_origin_ret_val=None,
+                    user_seek_ns_from_origin_provided=True,
+                    iter_can_seek_beginning=iter_can_seek_beginning,
+                    iter_can_seek_forward=iter_can_seek_forward,
                 )
 
-        def _user_can_seek_ns_from_origin(iter_self, ns_from_origin):
-            nonlocal input_port_iter_can_seek_ns_from_origin
-            nonlocal test_ns_from_origin
-            self.assertEqual(ns_from_origin, test_ns_from_origin)
-            return input_port_iter_can_seek_ns_from_origin
+    def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: Not provided
+        #   - seek_ns_from_origin provided: Not provided
+        #   - can the iterator seek beginning: Yes
+        #   - can the iterator seek forward: Yes
+        #
+        # We expect iter.can_seek_ns_from_origin to return True.
+        self._can_seek_ns_from_origin_test(
+            expected_outcome=True,
+            user_can_seek_ns_from_origin_ret_val=None,
+            user_seek_ns_from_origin_provided=False,
+            iter_can_seek_beginning=True,
+            iter_can_seek_forward=True,
+        )
 
-        graph = _setup_seek_test(
-            MySink, user_can_seek_ns_from_origin=_user_can_seek_ns_from_origin
+    def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_not_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: Not provided
+        #   - seek_ns_from_origin provided: Not provided
+        #   - can the iterator seek beginning: Yes
+        #   - can the iterator seek forward: No
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        self._can_seek_ns_from_origin_test(
+            expected_outcome=False,
+            user_can_seek_ns_from_origin_ret_val=None,
+            user_seek_ns_from_origin_provided=False,
+            iter_can_seek_beginning=True,
+            iter_can_seek_forward=False,
         )
 
-        input_port_iter_can_seek_ns_from_origin = True
-        can_seek_ns_from_origin = None
-        test_ns_from_origin = 1
-        graph.run_once()
-        self.assertIs(can_seek_ns_from_origin, True)
+    def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: Not provided
+        #   - seek_ns_from_origin provided: Not provided
+        #   - can the iterator seek beginning: No
+        #   - can the iterator seek forward: Yes
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        self._can_seek_ns_from_origin_test(
+            expected_outcome=False,
+            user_can_seek_ns_from_origin_ret_val=None,
+            user_seek_ns_from_origin_provided=False,
+            iter_can_seek_beginning=False,
+            iter_can_seek_forward=True,
+        )
 
-        input_port_iter_can_seek_ns_from_origin = False
-        can_seek_ns_from_origin = None
-        test_ns_from_origin = 2
-        graph.run_once()
-        self.assertIs(can_seek_ns_from_origin, False)
+    def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_not_forward_seekable(
+        self
+    ):
+        # Test the case where:
+        #
+        #   - can_seek_ns_from_origin: Not provided
+        #   - seek_ns_from_origin provided: Not provided
+        #   - can the iterator seek beginning: No
+        #   - can the iterator seek forward: No
+        #
+        # We expect iter.can_seek_ns_from_origin to return False.
+        self._can_seek_ns_from_origin_test(
+            expected_outcome=False,
+            user_can_seek_ns_from_origin_ret_val=None,
+            user_seek_ns_from_origin_provided=False,
+            iter_can_seek_beginning=False,
+            iter_can_seek_forward=False,
+        )
 
-    def test_no_can_seek_ns_from_origin_with_seek_ns_from_origin(self):
-        # Test an iterator without a _user_can_seek_ns_from_origin method, but
-        # with a _user_seek_ns_from_origin method.
+    def _can_seek_ns_from_origin_test(
+        self,
+        expected_outcome,
+        user_can_seek_ns_from_origin_ret_val,
+        user_seek_ns_from_origin_provided,
+        iter_can_seek_beginning,
+        iter_can_seek_forward,
+    ):
         class MySink(bt2._UserSinkComponent):
             def __init__(self, config, params, obj):
                 self._add_input_port('in')
@@ -713,74 +877,52 @@ class UserMessageIteratorSeekNsFromOriginTestCase(unittest.TestCase):
 
             def _user_consume(self):
                 nonlocal can_seek_ns_from_origin
-                nonlocal test_ns_from_origin
                 can_seek_ns_from_origin = self._msg_iter.can_seek_ns_from_origin(
-                    test_ns_from_origin
+                    passed_ns_from_origin
                 )
 
-        def _user_seek_ns_from_origin(self):
-            pass
+        if user_can_seek_ns_from_origin_ret_val is not None:
 
-        graph = _setup_seek_test(
-            MySink, user_seek_ns_from_origin=_user_seek_ns_from_origin
-        )
-        can_seek_ns_from_origin = None
-        test_ns_from_origin = 2
-        graph.run_once()
-        self.assertIs(can_seek_ns_from_origin, True)
+            def user_can_seek_ns_from_origin(self, ns_from_origin):
+                nonlocal received_ns_from_origin
+                received_ns_from_origin = ns_from_origin
+                return user_can_seek_ns_from_origin_ret_val
 
-    def test_no_can_seek_ns_from_origin_with_seek_beginning(self):
-        # Test an iterator without a _user_can_seek_ns_from_origin method, but
-        # with a _user_seek_beginning method.
-        class MySink(bt2._UserSinkComponent):
-            def __init__(self, config, params, obj):
-                self._add_input_port('in')
+        else:
+            user_can_seek_ns_from_origin = None
 
-            def _user_graph_is_configured(self):
-                self._msg_iter = self._create_input_port_message_iterator(
-                    self._input_ports['in']
-                )
+        if user_seek_ns_from_origin_provided:
 
-            def _user_consume(self):
-                nonlocal can_seek_ns_from_origin
-                nonlocal test_ns_from_origin
-                can_seek_ns_from_origin = self._msg_iter.can_seek_ns_from_origin(
-                    test_ns_from_origin
-                )
+            def user_seek_ns_from_origin(self, ns_from_origin):
+                pass
 
-        def _user_seek_beginning(self):
-            pass
+        else:
+            user_seek_ns_from_origin = None
 
-        graph = _setup_seek_test(MySink, user_seek_beginning=_user_seek_beginning)
-        can_seek_ns_from_origin = None
-        test_ns_from_origin = 2
-        graph.run_once()
-        self.assertIs(can_seek_ns_from_origin, True)
+        if iter_can_seek_beginning:
 
-    def test_no_can_seek_ns_from_origin(self):
-        # Test an iterator without a _user_can_seek_ns_from_origin method
-        # and no other related method.
-        class MySink(bt2._UserSinkComponent):
-            def __init__(self, config, params, obj):
-                self._add_input_port('in')
+            def user_seek_beginning(self):
+                pass
 
-            def _user_graph_is_configured(self):
-                self._msg_iter = self._create_input_port_message_iterator(
-                    self._input_ports['in']
-                )
+        else:
+            user_seek_beginning = None
 
-            def _user_consume(self):
-                nonlocal can_seek_ns_from_origin
-                nonlocal test_ns_from_origin
-                can_seek_ns_from_origin = self._msg_iter.can_seek_ns_from_origin(
-                    test_ns_from_origin
-                )
+        graph = _setup_seek_test(
+            MySink,
+            user_can_seek_ns_from_origin=user_can_seek_ns_from_origin,
+            user_seek_ns_from_origin=user_seek_ns_from_origin,
+            user_seek_beginning=user_seek_beginning,
+            can_seek_forward=iter_can_seek_forward,
+        )
 
-        graph = _setup_seek_test(MySink)
+        passed_ns_from_origin = 77
+        received_ns_from_origin = None
         can_seek_ns_from_origin = None
-        test_ns_from_origin = 2
         graph.run_once()
-        self.assertIs(can_seek_ns_from_origin, False)
+        self.assertIs(can_seek_ns_from_origin, expected_outcome)
+
+        if user_can_seek_ns_from_origin_ret_val is not None:
+            self.assertEqual(received_ns_from_origin, passed_ns_from_origin)
 
     def test_can_seek_ns_from_origin_user_error(self):
         class MySink(bt2._UserSinkComponent):
index 9f337356c8552e644a78833f5a4afe55754faecc..a59ea9bd1bebf432ea6fbb78356b960ac3d1f441 100644 (file)
@@ -32,6 +32,7 @@ class TheIteratorOfAllEvil(bt2._UserMessageIterator):
             se_msg,
         ]
         self._at = 0
+        config.can_seek_forward = True
 
     def _user_seek_beginning(self):
         self._at = 0
This page took 0.033192 seconds and 4 git commands to generate.