Commit | Line | Data |
---|---|---|
d2d857a8 MJ |
1 | # |
2 | # Copyright (C) 2019 EfficiOS Inc. | |
3 | # | |
4 | # This program is free software; you can redistribute it and/or | |
5 | # modify it under the terms of the GNU General Public License | |
6 | # as published by the Free Software Foundation; only version 2 | |
7 | # of the License. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the GNU General Public License | |
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
17 | # | |
18 | ||
811644b8 | 19 | import unittest |
811644b8 | 20 | import bt2 |
8e97c333 | 21 | import sys |
6c373cc9 | 22 | from utils import TestOutputPortMessageIterator |
14503fb1 | 23 | from bt2 import port as bt2_port |
8d8b141d | 24 | from bt2 import message_iterator as bt2_message_iterator |
811644b8 PP |
25 | |
26 | ||
0a6d7302 SM |
27 | class SimpleSink(bt2._UserSinkComponent): |
28 | # Straightforward sink that creates one input port (`in`) and consumes from | |
29 | # it. | |
811644b8 | 30 | |
59225a3e | 31 | def __init__(self, config, params, obj): |
0a6d7302 | 32 | self._add_input_port('in') |
811644b8 | 33 | |
0a6d7302 SM |
34 | def _user_consume(self): |
35 | next(self._msg_iter) | |
811644b8 | 36 | |
0a6d7302 SM |
37 | def _user_graph_is_configured(self): |
38 | self._msg_iter = self._create_input_port_message_iterator( | |
39 | self._input_ports['in'] | |
40 | ) | |
ca02df0a | 41 | |
ca02df0a | 42 | |
0a6d7302 SM |
43 | def _create_graph(src_comp_cls, sink_comp_cls, flt_comp_cls=None): |
44 | graph = bt2.Graph() | |
ca02df0a | 45 | |
0a6d7302 SM |
46 | src_comp = graph.add_component(src_comp_cls, 'src') |
47 | sink_comp = graph.add_component(sink_comp_cls, 'sink') | |
ca02df0a | 48 | |
0a6d7302 SM |
49 | if flt_comp_cls is not None: |
50 | flt_comp = graph.add_component(flt_comp_cls, 'flt') | |
51 | graph.connect_ports(src_comp.output_ports['out'], flt_comp.input_ports['in']) | |
52 | graph.connect_ports(flt_comp.output_ports['out'], sink_comp.input_ports['in']) | |
53 | else: | |
54 | graph.connect_ports(src_comp.output_ports['out'], sink_comp.input_ports['in']) | |
811644b8 | 55 | |
0a6d7302 SM |
56 | return graph |
57 | ||
58 | ||
59 | class UserMessageIteratorTestCase(unittest.TestCase): | |
811644b8 | 60 | def test_init(self): |
c5f330cd SM |
61 | the_output_port_from_source = None |
62 | the_output_port_from_iter = None | |
63 | ||
5602ef81 | 64 | class MyIter(bt2._UserMessageIterator): |
8d8b141d | 65 | def __init__(self, config, self_port_output): |
811644b8 | 66 | nonlocal initialized |
c5f330cd | 67 | nonlocal the_output_port_from_iter |
811644b8 | 68 | initialized = True |
c5f330cd | 69 | the_output_port_from_iter = self_port_output |
811644b8 | 70 | |
cfbd7cf3 | 71 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): |
59225a3e | 72 | def __init__(self, config, params, obj): |
c5f330cd | 73 | nonlocal the_output_port_from_source |
2e00bc76 | 74 | the_output_port_from_source = self._add_output_port('out', 'user data') |
811644b8 PP |
75 | |
76 | initialized = False | |
0a6d7302 | 77 | graph = _create_graph(MySource, SimpleSink) |
c5f330cd | 78 | graph.run() |
811644b8 | 79 | self.assertTrue(initialized) |
cfbd7cf3 FD |
80 | self.assertEqual( |
81 | the_output_port_from_source.addr, the_output_port_from_iter.addr | |
82 | ) | |
2e00bc76 | 83 | self.assertEqual(the_output_port_from_iter.user_data, 'user data') |
811644b8 | 84 | |
ca02df0a PP |
85 | def test_create_from_message_iterator(self): |
86 | class MySourceIter(bt2._UserMessageIterator): | |
8d8b141d | 87 | def __init__(self, config, self_port_output): |
ca02df0a PP |
88 | nonlocal src_iter_initialized |
89 | src_iter_initialized = True | |
90 | ||
91 | class MySource(bt2._UserSourceComponent, message_iterator_class=MySourceIter): | |
59225a3e | 92 | def __init__(self, config, params, obj): |
ca02df0a PP |
93 | self._add_output_port('out') |
94 | ||
95 | class MyFilterIter(bt2._UserMessageIterator): | |
8d8b141d | 96 | def __init__(self, config, self_port_output): |
ca02df0a PP |
97 | nonlocal flt_iter_initialized |
98 | flt_iter_initialized = True | |
99 | self._up_iter = self._create_input_port_message_iterator( | |
100 | self._component._input_ports['in'] | |
101 | ) | |
102 | ||
103 | def __next__(self): | |
104 | return next(self._up_iter) | |
105 | ||
106 | class MyFilter(bt2._UserFilterComponent, message_iterator_class=MyFilterIter): | |
59225a3e | 107 | def __init__(self, config, params, obj): |
ca02df0a PP |
108 | self._add_input_port('in') |
109 | self._add_output_port('out') | |
110 | ||
111 | src_iter_initialized = False | |
112 | flt_iter_initialized = False | |
0a6d7302 | 113 | graph = _create_graph(MySource, SimpleSink, MyFilter) |
ca02df0a PP |
114 | graph.run() |
115 | self.assertTrue(src_iter_initialized) | |
116 | self.assertTrue(flt_iter_initialized) | |
117 | ||
e803df70 SM |
118 | def test_create_user_error(self): |
119 | # This tests both error handling by | |
120 | # _UserSinkComponent._create_input_port_message_iterator | |
121 | # and _UserMessageIterator._create_input_port_message_iterator, as they | |
122 | # are both used in the graph. | |
123 | class MySourceIter(bt2._UserMessageIterator): | |
8d8b141d | 124 | def __init__(self, config, self_port_output): |
e803df70 SM |
125 | raise ValueError('Very bad error') |
126 | ||
127 | class MySource(bt2._UserSourceComponent, message_iterator_class=MySourceIter): | |
59225a3e | 128 | def __init__(self, config, params, obj): |
e803df70 SM |
129 | self._add_output_port('out') |
130 | ||
131 | class MyFilterIter(bt2._UserMessageIterator): | |
8d8b141d | 132 | def __init__(self, config, self_port_output): |
e803df70 SM |
133 | # This is expected to raise because of the error in |
134 | # MySourceIter.__init__. | |
135 | self._create_input_port_message_iterator( | |
136 | self._component._input_ports['in'] | |
137 | ) | |
138 | ||
139 | class MyFilter(bt2._UserFilterComponent, message_iterator_class=MyFilterIter): | |
59225a3e | 140 | def __init__(self, config, params, obj): |
e803df70 SM |
141 | self._add_input_port('in') |
142 | self._add_output_port('out') | |
143 | ||
0a6d7302 | 144 | graph = _create_graph(MySource, SimpleSink, MyFilter) |
e803df70 SM |
145 | |
146 | with self.assertRaises(bt2._Error) as ctx: | |
147 | graph.run() | |
148 | ||
149 | exc = ctx.exception | |
150 | cause = exc[0] | |
151 | ||
152 | self.assertIsInstance(cause, bt2._MessageIteratorErrorCause) | |
153 | self.assertEqual(cause.component_name, 'src') | |
154 | self.assertEqual(cause.component_output_port_name, 'out') | |
155 | self.assertIn('ValueError: Very bad error', cause.message) | |
156 | ||
811644b8 | 157 | def test_finalize(self): |
5602ef81 | 158 | class MyIter(bt2._UserMessageIterator): |
6a91742b | 159 | def _user_finalize(self): |
811644b8 PP |
160 | nonlocal finalized |
161 | finalized = True | |
162 | ||
cfbd7cf3 | 163 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): |
59225a3e | 164 | def __init__(self, config, params, obj): |
811644b8 PP |
165 | self._add_output_port('out') |
166 | ||
167 | finalized = False | |
0a6d7302 | 168 | graph = _create_graph(MySource, SimpleSink) |
c5f330cd | 169 | graph.run() |
811644b8 PP |
170 | del graph |
171 | self.assertTrue(finalized) | |
172 | ||
8d8b141d SM |
173 | def test_config_parameter(self): |
174 | class MyIter(bt2._UserMessageIterator): | |
175 | def __init__(self, config, port): | |
176 | nonlocal config_type | |
177 | config_type = type(config) | |
178 | ||
179 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
180 | def __init__(self, config, params, obj): | |
181 | self._add_output_port('out') | |
182 | ||
183 | config_type = None | |
184 | graph = _create_graph(MySource, SimpleSink) | |
185 | graph.run() | |
186 | self.assertIs(config_type, bt2_message_iterator._MessageIteratorConfiguration) | |
187 | ||
188 | def _test_config_can_seek_forward(self, set_can_seek_forward): | |
189 | class MyIter(bt2._UserMessageIterator): | |
190 | def __init__(self, config, port): | |
191 | if set_can_seek_forward: | |
192 | config.can_seek_forward = True | |
193 | ||
194 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
195 | def __init__(self, config, params, obj): | |
196 | self._add_output_port('out') | |
197 | ||
198 | class MySink(bt2._UserSinkComponent): | |
199 | def __init__(self, config, params, obj): | |
200 | self._add_input_port('in') | |
201 | ||
202 | def _user_graph_is_configured(self): | |
203 | self._msg_iter = self._create_input_port_message_iterator( | |
204 | self._input_ports['in'] | |
205 | ) | |
206 | ||
207 | def _user_consume(self): | |
208 | nonlocal can_seek_forward | |
209 | can_seek_forward = self._msg_iter.can_seek_forward | |
210 | ||
211 | can_seek_forward = None | |
212 | graph = _create_graph(MySource, MySink) | |
213 | graph.run_once() | |
214 | self.assertIs(can_seek_forward, set_can_seek_forward) | |
215 | ||
216 | def test_config_can_seek_forward_default(self): | |
217 | self._test_config_can_seek_forward(False) | |
218 | ||
219 | def test_config_can_seek_forward(self): | |
220 | self._test_config_can_seek_forward(True) | |
221 | ||
222 | def test_config_can_seek_forward_wrong_type(self): | |
223 | class MyIter(bt2._UserMessageIterator): | |
224 | def __init__(self, config, port): | |
225 | config.can_seek_forward = 1 | |
226 | ||
227 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
228 | def __init__(self, config, params, obj): | |
229 | self._add_output_port('out') | |
230 | ||
231 | graph = _create_graph(MySource, SimpleSink) | |
232 | with self.assertRaises(bt2._Error) as ctx: | |
233 | graph.run() | |
234 | ||
235 | root_cause = ctx.exception[0] | |
236 | self.assertIn("TypeError: 'int' is not a 'bool' object", root_cause.message) | |
237 | ||
811644b8 | 238 | def test_component(self): |
5602ef81 | 239 | class MyIter(bt2._UserMessageIterator): |
8d8b141d | 240 | def __init__(self, config, self_port_output): |
811644b8 PP |
241 | nonlocal salut |
242 | salut = self._component._salut | |
243 | ||
cfbd7cf3 | 244 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): |
59225a3e | 245 | def __init__(self, config, params, obj): |
811644b8 PP |
246 | self._add_output_port('out') |
247 | self._salut = 23 | |
248 | ||
249 | salut = None | |
0a6d7302 | 250 | graph = _create_graph(MySource, SimpleSink) |
c5f330cd | 251 | graph.run() |
811644b8 PP |
252 | self.assertEqual(salut, 23) |
253 | ||
14503fb1 SM |
254 | def test_port(self): |
255 | class MyIter(bt2._UserMessageIterator): | |
8d8b141d | 256 | def __init__(self_iter, config, self_port_output): |
14503fb1 SM |
257 | nonlocal called |
258 | called = True | |
259 | port = self_iter._port | |
260 | self.assertIs(type(self_port_output), bt2_port._UserComponentOutputPort) | |
261 | self.assertIs(type(port), bt2_port._UserComponentOutputPort) | |
262 | self.assertEqual(self_port_output.addr, port.addr) | |
263 | ||
264 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
59225a3e | 265 | def __init__(self, config, params, obj): |
14503fb1 SM |
266 | self._add_output_port('out') |
267 | ||
268 | called = False | |
0a6d7302 | 269 | graph = _create_graph(MySource, SimpleSink) |
14503fb1 SM |
270 | graph.run() |
271 | self.assertTrue(called) | |
272 | ||
811644b8 | 273 | def test_addr(self): |
5602ef81 | 274 | class MyIter(bt2._UserMessageIterator): |
8d8b141d | 275 | def __init__(self, config, self_port_output): |
811644b8 PP |
276 | nonlocal addr |
277 | addr = self.addr | |
278 | ||
cfbd7cf3 | 279 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): |
59225a3e | 280 | def __init__(self, config, params, obj): |
811644b8 PP |
281 | self._add_output_port('out') |
282 | ||
283 | addr = None | |
0a6d7302 | 284 | graph = _create_graph(MySource, SimpleSink) |
c5f330cd | 285 | graph.run() |
811644b8 PP |
286 | self.assertIsNotNone(addr) |
287 | self.assertNotEqual(addr, 0) | |
288 | ||
d79a8353 SM |
289 | # Test that messages returned by _UserMessageIterator.__next__ remain valid |
290 | # and can be re-used. | |
291 | def test_reuse_message(self): | |
292 | class MyIter(bt2._UserMessageIterator): | |
8d8b141d | 293 | def __init__(self, config, port): |
d79a8353 SM |
294 | tc, sc, ec = port.user_data |
295 | trace = tc() | |
296 | stream = trace.create_stream(sc) | |
297 | packet = stream.create_packet() | |
298 | ||
299 | # This message will be returned twice by __next__. | |
300 | event_message = self._create_event_message(ec, packet) | |
301 | ||
302 | self._msgs = [ | |
303 | self._create_stream_beginning_message(stream), | |
d79a8353 SM |
304 | self._create_packet_beginning_message(packet), |
305 | event_message, | |
306 | event_message, | |
307 | ] | |
308 | ||
309 | def __next__(self): | |
310 | return self._msgs.pop(0) | |
311 | ||
312 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
59225a3e | 313 | def __init__(self, config, params, obj): |
d79a8353 | 314 | tc = self._create_trace_class() |
26fc5aed | 315 | sc = tc.create_stream_class(supports_packets=True) |
d79a8353 SM |
316 | ec = sc.create_event_class() |
317 | self._add_output_port('out', (tc, sc, ec)) | |
318 | ||
319 | graph = bt2.Graph() | |
320 | src = graph.add_component(MySource, 'src') | |
6c373cc9 | 321 | it = TestOutputPortMessageIterator(graph, src.output_ports['out']) |
d79a8353 SM |
322 | |
323 | # Skip beginning messages. | |
188edac1 | 324 | msg = next(it) |
f0a42b33 | 325 | self.assertIs(type(msg), bt2._StreamBeginningMessageConst) |
188edac1 | 326 | msg = next(it) |
f0a42b33 | 327 | self.assertIs(type(msg), bt2._PacketBeginningMessageConst) |
d79a8353 SM |
328 | |
329 | msg_ev1 = next(it) | |
330 | msg_ev2 = next(it) | |
331 | ||
f0a42b33 FD |
332 | self.assertIs(type(msg_ev1), bt2._EventMessageConst) |
333 | self.assertIs(type(msg_ev2), bt2._EventMessageConst) | |
d79a8353 SM |
334 | self.assertEqual(msg_ev1.addr, msg_ev2.addr) |
335 | ||
0a6d7302 SM |
336 | # Try consuming many times from an iterator that always returns TryAgain. |
337 | # This verifies that we are not missing an incref of Py_None, making the | |
338 | # refcount of Py_None reach 0. | |
339 | def test_try_again_many_times(self): | |
340 | class MyIter(bt2._UserMessageIterator): | |
f00b8d40 | 341 | def __next__(self): |
0a6d7302 | 342 | raise bt2.TryAgain |
f00b8d40 | 343 | |
0a6d7302 | 344 | class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter): |
59225a3e | 345 | def __init__(self, config, params, obj): |
0a6d7302 | 346 | self._add_output_port('out') |
f00b8d40 SM |
347 | |
348 | class MyFilterIter(bt2._UserMessageIterator): | |
349 | def __init__(self, port): | |
350 | input_port = port.user_data | |
ca02df0a PP |
351 | self._upstream_iter = self._create_input_port_message_iterator( |
352 | input_port | |
353 | ) | |
f00b8d40 SM |
354 | |
355 | def __next__(self): | |
356 | return next(self._upstream_iter) | |
357 | ||
6a91742b | 358 | def _user_seek_beginning(self): |
f00b8d40 SM |
359 | self._upstream_iter.seek_beginning() |
360 | ||
6a91742b | 361 | def _user_can_seek_beginning(self): |
14cfc8ce | 362 | return self._upstream_iter.can_seek_beginning() |
f00b8d40 SM |
363 | |
364 | class MyFilter(bt2._UserFilterComponent, message_iterator_class=MyFilterIter): | |
59225a3e | 365 | def __init__(self, config, params, obj): |
f00b8d40 SM |
366 | input_port = self._add_input_port('in') |
367 | self._add_output_port('out', input_port) | |
368 | ||
f00b8d40 SM |
369 | graph = bt2.Graph() |
370 | src = graph.add_component(MySource, 'src') | |
0a6d7302 SM |
371 | it = TestOutputPortMessageIterator(graph, src.output_ports['out']) |
372 | ||
373 | # Three times the initial ref count of `None` iterations should | |
374 | # be enough to catch the bug even if there are small differences | |
375 | # between configurations. | |
376 | none_ref_count = sys.getrefcount(None) * 3 | |
377 | ||
378 | for i in range(none_ref_count): | |
379 | with self.assertRaises(bt2.TryAgain): | |
380 | next(it) | |
381 | ||
382 | ||
c182d7dd SM |
383 | def _setup_seek_test( |
384 | sink_cls, | |
385 | user_seek_beginning=None, | |
386 | user_can_seek_beginning=None, | |
387 | user_seek_ns_from_origin=None, | |
388 | user_can_seek_ns_from_origin=None, | |
c0e46a7c | 389 | can_seek_forward=False, |
c182d7dd | 390 | ): |
0a6d7302 | 391 | class MySourceIter(bt2._UserMessageIterator): |
8d8b141d | 392 | def __init__(self, config, port): |
0a6d7302 SM |
393 | tc, sc, ec = port.user_data |
394 | trace = tc() | |
395 | stream = trace.create_stream(sc) | |
396 | packet = stream.create_packet() | |
397 | ||
398 | self._msgs = [ | |
399 | self._create_stream_beginning_message(stream), | |
400 | self._create_packet_beginning_message(packet), | |
401 | self._create_event_message(ec, packet), | |
402 | self._create_event_message(ec, packet), | |
403 | self._create_packet_end_message(packet), | |
404 | self._create_stream_end_message(stream), | |
405 | ] | |
406 | self._at = 0 | |
c0e46a7c | 407 | config.can_seek_forward = can_seek_forward |
0a6d7302 SM |
408 | |
409 | def __next__(self): | |
410 | if self._at < len(self._msgs): | |
411 | msg = self._msgs[self._at] | |
412 | self._at += 1 | |
413 | return msg | |
414 | else: | |
415 | raise StopIteration | |
416 | ||
417 | if user_seek_beginning is not None: | |
418 | MySourceIter._user_seek_beginning = user_seek_beginning | |
419 | ||
420 | if user_can_seek_beginning is not None: | |
14cfc8ce | 421 | MySourceIter._user_can_seek_beginning = user_can_seek_beginning |
0a6d7302 | 422 | |
c182d7dd SM |
423 | if user_seek_ns_from_origin is not None: |
424 | MySourceIter._user_seek_ns_from_origin = user_seek_ns_from_origin | |
425 | ||
426 | if user_can_seek_ns_from_origin is not None: | |
427 | MySourceIter._user_can_seek_ns_from_origin = user_can_seek_ns_from_origin | |
428 | ||
0a6d7302 | 429 | class MySource(bt2._UserSourceComponent, message_iterator_class=MySourceIter): |
59225a3e | 430 | def __init__(self, config, params, obj): |
0a6d7302 SM |
431 | tc = self._create_trace_class() |
432 | sc = tc.create_stream_class(supports_packets=True) | |
433 | ec = sc.create_event_class() | |
434 | ||
435 | self._add_output_port('out', (tc, sc, ec)) | |
436 | ||
437 | class MyFilterIter(bt2._UserMessageIterator): | |
8d8b141d | 438 | def __init__(self, config, port): |
0a6d7302 SM |
439 | self._upstream_iter = self._create_input_port_message_iterator( |
440 | self._component._input_ports['in'] | |
441 | ) | |
c0e46a7c | 442 | config.can_seek_forward = self._upstream_iter.can_seek_forward |
0a6d7302 SM |
443 | |
444 | def __next__(self): | |
445 | return next(self._upstream_iter) | |
446 | ||
0a6d7302 | 447 | def _user_can_seek_beginning(self): |
14cfc8ce | 448 | return self._upstream_iter.can_seek_beginning() |
0a6d7302 SM |
449 | |
450 | def _user_seek_beginning(self): | |
451 | self._upstream_iter.seek_beginning() | |
452 | ||
c182d7dd SM |
453 | def _user_can_seek_ns_from_origin(self, ns_from_origin): |
454 | return self._upstream_iter.can_seek_ns_from_origin(ns_from_origin) | |
455 | ||
456 | def _user_seek_ns_from_origin(self, ns_from_origin): | |
457 | self._upstream_iter.seek_ns_from_origin(ns_from_origin) | |
458 | ||
0a6d7302 | 459 | class MyFilter(bt2._UserFilterComponent, message_iterator_class=MyFilterIter): |
59225a3e | 460 | def __init__(self, config, params, obj): |
0a6d7302 SM |
461 | self._add_input_port('in') |
462 | self._add_output_port('out') | |
463 | ||
464 | return _create_graph(MySource, sink_cls, flt_comp_cls=MyFilter) | |
f00b8d40 | 465 | |
0a6d7302 SM |
466 | |
467 | class UserMessageIteratorSeekBeginningTestCase(unittest.TestCase): | |
2e1b5615 SM |
468 | def test_can_seek_beginning_without_seek_beginning(self): |
469 | with self.assertRaisesRegex( | |
470 | bt2._IncompleteUserClass, | |
471 | "cannot create component class 'MySource': message iterator class implements _user_can_seek_beginning but not _user_seek_beginning", | |
472 | ): | |
473 | _setup_seek_test(SimpleSink, user_can_seek_beginning=lambda: None) | |
474 | ||
f00b8d40 | 475 | def test_can_seek_beginning(self): |
6c373cc9 | 476 | class MySink(bt2._UserSinkComponent): |
59225a3e | 477 | def __init__(self, config, params, obj): |
6c373cc9 PP |
478 | self._add_input_port('in') |
479 | ||
480 | def _user_graph_is_configured(self): | |
481 | self._msg_iter = self._create_input_port_message_iterator( | |
482 | self._input_ports['in'] | |
483 | ) | |
484 | ||
485 | def _user_consume(self): | |
486 | nonlocal can_seek_beginning | |
14cfc8ce | 487 | can_seek_beginning = self._msg_iter.can_seek_beginning() |
6c373cc9 | 488 | |
6a91742b | 489 | def _user_can_seek_beginning(self): |
6c373cc9 PP |
490 | nonlocal input_port_iter_can_seek_beginning |
491 | return input_port_iter_can_seek_beginning | |
f00b8d40 | 492 | |
0a6d7302 | 493 | graph = _setup_seek_test( |
2e1b5615 SM |
494 | MySink, |
495 | user_can_seek_beginning=_user_can_seek_beginning, | |
496 | user_seek_beginning=lambda: None, | |
0a6d7302 | 497 | ) |
f00b8d40 | 498 | |
6c373cc9 PP |
499 | input_port_iter_can_seek_beginning = True |
500 | can_seek_beginning = None | |
501 | graph.run_once() | |
7f0c21bb | 502 | self.assertIs(can_seek_beginning, True) |
f00b8d40 | 503 | |
6c373cc9 PP |
504 | input_port_iter_can_seek_beginning = False |
505 | can_seek_beginning = None | |
506 | graph.run_once() | |
7f0c21bb | 507 | self.assertIs(can_seek_beginning, False) |
f00b8d40 | 508 | |
0a6d7302 SM |
509 | def test_no_can_seek_beginning_with_seek_beginning(self): |
510 | # Test an iterator without a _user_can_seek_beginning method, but with | |
511 | # a _user_seek_beginning method. | |
512 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 513 | def __init__(self, config, params, obj): |
0a6d7302 SM |
514 | self._add_input_port('in') |
515 | ||
516 | def _user_graph_is_configured(self): | |
517 | self._msg_iter = self._create_input_port_message_iterator( | |
518 | self._input_ports['in'] | |
519 | ) | |
520 | ||
521 | def _user_consume(self): | |
522 | nonlocal can_seek_beginning | |
14cfc8ce | 523 | can_seek_beginning = self._msg_iter.can_seek_beginning() |
0a6d7302 SM |
524 | |
525 | def _user_seek_beginning(self): | |
526 | pass | |
f00b8d40 | 527 | |
0a6d7302 | 528 | graph = _setup_seek_test(MySink, user_seek_beginning=_user_seek_beginning) |
6c373cc9 PP |
529 | can_seek_beginning = None |
530 | graph.run_once() | |
7f0c21bb | 531 | self.assertIs(can_seek_beginning, True) |
f00b8d40 | 532 | |
0a6d7302 SM |
533 | def test_no_can_seek_beginning(self): |
534 | # Test an iterator without a _user_can_seek_beginning method, without | |
535 | # a _user_seek_beginning method. | |
536 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 537 | def __init__(self, config, params, obj): |
0a6d7302 SM |
538 | self._add_input_port('in') |
539 | ||
540 | def _user_graph_is_configured(self): | |
541 | self._msg_iter = self._create_input_port_message_iterator( | |
542 | self._input_ports['in'] | |
543 | ) | |
544 | ||
545 | def _user_consume(self): | |
546 | nonlocal can_seek_beginning | |
14cfc8ce | 547 | can_seek_beginning = self._msg_iter.can_seek_beginning() |
0a6d7302 SM |
548 | |
549 | graph = _setup_seek_test(MySink) | |
6c373cc9 PP |
550 | can_seek_beginning = None |
551 | graph.run_once() | |
7f0c21bb | 552 | self.assertIs(can_seek_beginning, False) |
f00b8d40 | 553 | |
f2fb1b32 SM |
554 | def test_can_seek_beginning_user_error(self): |
555 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 556 | def __init__(self, config, params, obj): |
f2fb1b32 SM |
557 | self._add_input_port('in') |
558 | ||
559 | def _user_graph_is_configured(self): | |
560 | self._msg_iter = self._create_input_port_message_iterator( | |
561 | self._input_ports['in'] | |
562 | ) | |
563 | ||
564 | def _user_consume(self): | |
565 | # This is expected to raise. | |
14cfc8ce | 566 | self._msg_iter.can_seek_beginning() |
f2fb1b32 SM |
567 | |
568 | def _user_can_seek_beginning(self): | |
569 | raise ValueError('moustiquaire') | |
570 | ||
571 | graph = _setup_seek_test( | |
2e1b5615 SM |
572 | MySink, |
573 | user_can_seek_beginning=_user_can_seek_beginning, | |
574 | user_seek_beginning=lambda: None, | |
f2fb1b32 SM |
575 | ) |
576 | ||
577 | with self.assertRaises(bt2._Error) as ctx: | |
578 | graph.run_once() | |
579 | ||
580 | cause = ctx.exception[0] | |
581 | self.assertIn('ValueError: moustiquaire', cause.message) | |
582 | ||
583 | def test_can_seek_beginning_wrong_return_value(self): | |
584 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 585 | def __init__(self, config, params, obj): |
f2fb1b32 SM |
586 | self._add_input_port('in') |
587 | ||
588 | def _user_graph_is_configured(self): | |
589 | self._msg_iter = self._create_input_port_message_iterator( | |
590 | self._input_ports['in'] | |
591 | ) | |
592 | ||
593 | def _user_consume(self): | |
594 | # This is expected to raise. | |
14cfc8ce | 595 | self._msg_iter.can_seek_beginning() |
f2fb1b32 SM |
596 | |
597 | def _user_can_seek_beginning(self): | |
598 | return 'Amqui' | |
599 | ||
600 | graph = _setup_seek_test( | |
2e1b5615 SM |
601 | MySink, |
602 | user_can_seek_beginning=_user_can_seek_beginning, | |
603 | user_seek_beginning=lambda: None, | |
f2fb1b32 SM |
604 | ) |
605 | ||
606 | with self.assertRaises(bt2._Error) as ctx: | |
607 | graph.run_once() | |
608 | ||
609 | cause = ctx.exception[0] | |
610 | self.assertIn("TypeError: 'str' is not a 'bool' object", cause.message) | |
611 | ||
f00b8d40 | 612 | def test_seek_beginning(self): |
6c373cc9 | 613 | class MySink(bt2._UserSinkComponent): |
59225a3e | 614 | def __init__(self, config, params, obj): |
6c373cc9 | 615 | self._add_input_port('in') |
f00b8d40 | 616 | |
6c373cc9 PP |
617 | def _user_graph_is_configured(self): |
618 | self._msg_iter = self._create_input_port_message_iterator( | |
619 | self._input_ports['in'] | |
620 | ) | |
621 | ||
622 | def _user_consume(self): | |
623 | nonlocal do_seek_beginning | |
624 | nonlocal msg | |
625 | ||
626 | if do_seek_beginning: | |
627 | self._msg_iter.seek_beginning() | |
628 | return | |
629 | ||
630 | msg = next(self._msg_iter) | |
631 | ||
0a6d7302 SM |
632 | def _user_seek_beginning(self): |
633 | self._at = 0 | |
634 | ||
6c373cc9 | 635 | msg = None |
0a6d7302 SM |
636 | graph = _setup_seek_test(MySink, user_seek_beginning=_user_seek_beginning) |
637 | ||
638 | # Consume message. | |
639 | do_seek_beginning = False | |
6c373cc9 | 640 | graph.run_once() |
f0a42b33 | 641 | self.assertIs(type(msg), bt2._StreamBeginningMessageConst) |
0a6d7302 SM |
642 | |
643 | # Consume message. | |
6c373cc9 | 644 | graph.run_once() |
f0a42b33 | 645 | self.assertIs(type(msg), bt2._PacketBeginningMessageConst) |
0a6d7302 SM |
646 | |
647 | # Seek beginning. | |
6c373cc9 PP |
648 | do_seek_beginning = True |
649 | graph.run_once() | |
0a6d7302 SM |
650 | |
651 | # Consume message. | |
6c373cc9 PP |
652 | do_seek_beginning = False |
653 | graph.run_once() | |
f0a42b33 | 654 | self.assertIs(type(msg), bt2._StreamBeginningMessageConst) |
f00b8d40 | 655 | |
6c373cc9 PP |
656 | def test_seek_beginning_user_error(self): |
657 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 658 | def __init__(self, config, params, obj): |
6c373cc9 | 659 | self._add_input_port('in') |
f00b8d40 | 660 | |
6c373cc9 PP |
661 | def _user_graph_is_configured(self): |
662 | self._msg_iter = self._create_input_port_message_iterator( | |
663 | self._input_ports['in'] | |
664 | ) | |
f00b8d40 | 665 | |
6c373cc9 PP |
666 | def _user_consume(self): |
667 | self._msg_iter.seek_beginning() | |
f00b8d40 | 668 | |
0a6d7302 | 669 | def _user_seek_beginning(self): |
cfbd7cf3 | 670 | raise ValueError('ouch') |
f00b8d40 | 671 | |
0a6d7302 | 672 | graph = _setup_seek_test(MySink, user_seek_beginning=_user_seek_beginning) |
f00b8d40 | 673 | |
694c792b | 674 | with self.assertRaises(bt2._Error): |
6c373cc9 | 675 | graph.run_once() |
f00b8d40 SM |
676 | |
677 | ||
c182d7dd | 678 | class UserMessageIteratorSeekNsFromOriginTestCase(unittest.TestCase): |
2e1b5615 SM |
679 | def test_can_seek_ns_from_origin_without_seek_ns_from_origin(self): |
680 | # Test the case where: | |
681 | # | |
682 | # - can_seek_ns_from_origin: Returns True (don't really care, as long | |
683 | # as it's provided) | |
684 | # - seek_ns_from_origin provided: No | |
685 | # - can the iterator seek beginning: Don't care | |
686 | # - can the iterator seek forward: Don't care | |
687 | for can_seek_ns_from_origin in (False, True): | |
688 | for iter_can_seek_beginning in (False, True): | |
689 | for iter_can_seek_forward in (False, True): | |
690 | with self.assertRaisesRegex( | |
691 | bt2._IncompleteUserClass, | |
692 | "cannot create component class 'MySource': message iterator class implements _user_can_seek_ns_from_origin but not _user_seek_ns_from_origin", | |
693 | ): | |
694 | self._can_seek_ns_from_origin_test( | |
695 | None, | |
696 | user_can_seek_ns_from_origin_ret_val=True, | |
697 | user_seek_ns_from_origin_provided=False, | |
698 | iter_can_seek_beginning=iter_can_seek_beginning, | |
699 | iter_can_seek_forward=iter_can_seek_forward, | |
700 | ) | |
701 | ||
c0e46a7c SM |
702 | def test_can_seek_ns_from_origin_returns_true(self): |
703 | # Test the case where: | |
704 | # | |
705 | # - can_seek_ns_from_origin: returns True | |
2e1b5615 | 706 | # - seek_ns_from_origin provided: Yes |
c0e46a7c SM |
707 | # - can the iterator seek beginning: Don't care |
708 | # - can the iterator seek forward: Don't care | |
709 | # | |
710 | # We expect iter.can_seek_ns_from_origin to return True. | |
2e1b5615 SM |
711 | for iter_can_seek_beginning in (False, True): |
712 | for iter_can_seek_forward in (False, True): | |
713 | self._can_seek_ns_from_origin_test( | |
714 | expected_outcome=True, | |
715 | user_can_seek_ns_from_origin_ret_val=True, | |
716 | user_seek_ns_from_origin_provided=True, | |
717 | iter_can_seek_beginning=iter_can_seek_beginning, | |
718 | iter_can_seek_forward=iter_can_seek_forward, | |
719 | ) | |
c0e46a7c SM |
720 | |
721 | def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_forward_seekable( | |
75882e97 | 722 | self, |
c0e46a7c SM |
723 | ): |
724 | # Test the case where: | |
725 | # | |
726 | # - can_seek_ns_from_origin: returns False | |
2e1b5615 | 727 | # - seek_ns_from_origin provided: Yes |
c0e46a7c SM |
728 | # - can the iterator seek beginning: Yes |
729 | # - can the iterator seek forward: Yes | |
730 | # | |
731 | # We expect iter.can_seek_ns_from_origin to return True. | |
2e1b5615 SM |
732 | self._can_seek_ns_from_origin_test( |
733 | expected_outcome=True, | |
734 | user_can_seek_ns_from_origin_ret_val=False, | |
735 | user_seek_ns_from_origin_provided=True, | |
736 | iter_can_seek_beginning=True, | |
737 | iter_can_seek_forward=True, | |
738 | ) | |
c182d7dd | 739 | |
c0e46a7c | 740 | def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_not_forward_seekable( |
75882e97 | 741 | self, |
c0e46a7c SM |
742 | ): |
743 | # Test the case where: | |
744 | # | |
745 | # - can_seek_ns_from_origin: returns False | |
2e1b5615 | 746 | # - seek_ns_from_origin provided: Yes |
c0e46a7c SM |
747 | # - can the iterator seek beginning: Yes |
748 | # - can the iterator seek forward: No | |
749 | # | |
750 | # We expect iter.can_seek_ns_from_origin to return False. | |
2e1b5615 SM |
751 | self._can_seek_ns_from_origin_test( |
752 | expected_outcome=False, | |
753 | user_can_seek_ns_from_origin_ret_val=False, | |
754 | user_seek_ns_from_origin_provided=True, | |
755 | iter_can_seek_beginning=True, | |
756 | iter_can_seek_forward=False, | |
757 | ) | |
c182d7dd | 758 | |
c0e46a7c | 759 | def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_forward_seekable( |
75882e97 | 760 | self, |
c0e46a7c SM |
761 | ): |
762 | # Test the case where: | |
763 | # | |
764 | # - can_seek_ns_from_origin: returns False | |
2e1b5615 | 765 | # - seek_ns_from_origin provided: Yes |
c0e46a7c SM |
766 | # - can the iterator seek beginning: No |
767 | # - can the iterator seek forward: Yes | |
768 | # | |
769 | # We expect iter.can_seek_ns_from_origin to return False. | |
c0e46a7c SM |
770 | self._can_seek_ns_from_origin_test( |
771 | expected_outcome=False, | |
772 | user_can_seek_ns_from_origin_ret_val=False, | |
2e1b5615 | 773 | user_seek_ns_from_origin_provided=True, |
c0e46a7c SM |
774 | iter_can_seek_beginning=False, |
775 | iter_can_seek_forward=True, | |
776 | ) | |
777 | ||
778 | def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_not_forward_seekable( | |
75882e97 | 779 | self, |
c0e46a7c SM |
780 | ): |
781 | # Test the case where: | |
782 | # | |
783 | # - can_seek_ns_from_origin: returns False | |
2e1b5615 | 784 | # - seek_ns_from_origin provided: Yes |
c0e46a7c SM |
785 | # - can the iterator seek beginning: No |
786 | # - can the iterator seek forward: No | |
787 | # | |
788 | # We expect iter.can_seek_ns_from_origin to return False. | |
2e1b5615 SM |
789 | self._can_seek_ns_from_origin_test( |
790 | expected_outcome=False, | |
791 | user_can_seek_ns_from_origin_ret_val=False, | |
792 | user_seek_ns_from_origin_provided=True, | |
793 | iter_can_seek_beginning=False, | |
794 | iter_can_seek_forward=False, | |
795 | ) | |
c0e46a7c SM |
796 | |
797 | def test_no_can_seek_ns_from_origin_seek_ns_from_origin(self): | |
798 | # Test the case where: | |
799 | # | |
800 | # - can_seek_ns_from_origin: Not provided | |
801 | # - seek_ns_from_origin provided: Yes | |
802 | # - can the iterator seek beginning: Don't care | |
803 | # - can the iterator seek forward: Don't care | |
804 | # | |
805 | # We expect iter.can_seek_ns_from_origin to return True. | |
806 | for iter_can_seek_beginning in (False, True): | |
807 | for iter_can_seek_forward in (False, True): | |
808 | self._can_seek_ns_from_origin_test( | |
809 | expected_outcome=True, | |
810 | user_can_seek_ns_from_origin_ret_val=None, | |
811 | user_seek_ns_from_origin_provided=True, | |
812 | iter_can_seek_beginning=iter_can_seek_beginning, | |
813 | iter_can_seek_forward=iter_can_seek_forward, | |
c182d7dd SM |
814 | ) |
815 | ||
c0e46a7c | 816 | def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_forward_seekable( |
75882e97 | 817 | self, |
c0e46a7c SM |
818 | ): |
819 | # Test the case where: | |
820 | # | |
821 | # - can_seek_ns_from_origin: Not provided | |
822 | # - seek_ns_from_origin provided: Not provided | |
823 | # - can the iterator seek beginning: Yes | |
824 | # - can the iterator seek forward: Yes | |
825 | # | |
826 | # We expect iter.can_seek_ns_from_origin to return True. | |
827 | self._can_seek_ns_from_origin_test( | |
828 | expected_outcome=True, | |
829 | user_can_seek_ns_from_origin_ret_val=None, | |
830 | user_seek_ns_from_origin_provided=False, | |
831 | iter_can_seek_beginning=True, | |
832 | iter_can_seek_forward=True, | |
833 | ) | |
c182d7dd | 834 | |
c0e46a7c | 835 | def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_not_forward_seekable( |
75882e97 | 836 | self, |
c0e46a7c SM |
837 | ): |
838 | # Test the case where: | |
839 | # | |
840 | # - can_seek_ns_from_origin: Not provided | |
841 | # - seek_ns_from_origin provided: Not provided | |
842 | # - can the iterator seek beginning: Yes | |
843 | # - can the iterator seek forward: No | |
844 | # | |
845 | # We expect iter.can_seek_ns_from_origin to return False. | |
846 | self._can_seek_ns_from_origin_test( | |
847 | expected_outcome=False, | |
848 | user_can_seek_ns_from_origin_ret_val=None, | |
849 | user_seek_ns_from_origin_provided=False, | |
850 | iter_can_seek_beginning=True, | |
851 | iter_can_seek_forward=False, | |
c182d7dd SM |
852 | ) |
853 | ||
c0e46a7c | 854 | def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_forward_seekable( |
75882e97 | 855 | self, |
c0e46a7c SM |
856 | ): |
857 | # Test the case where: | |
858 | # | |
859 | # - can_seek_ns_from_origin: Not provided | |
860 | # - seek_ns_from_origin provided: Not provided | |
861 | # - can the iterator seek beginning: No | |
862 | # - can the iterator seek forward: Yes | |
863 | # | |
864 | # We expect iter.can_seek_ns_from_origin to return False. | |
865 | self._can_seek_ns_from_origin_test( | |
866 | expected_outcome=False, | |
867 | user_can_seek_ns_from_origin_ret_val=None, | |
868 | user_seek_ns_from_origin_provided=False, | |
869 | iter_can_seek_beginning=False, | |
870 | iter_can_seek_forward=True, | |
871 | ) | |
c182d7dd | 872 | |
c0e46a7c | 873 | def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_not_forward_seekable( |
75882e97 | 874 | self, |
c0e46a7c SM |
875 | ): |
876 | # Test the case where: | |
877 | # | |
878 | # - can_seek_ns_from_origin: Not provided | |
879 | # - seek_ns_from_origin provided: Not provided | |
880 | # - can the iterator seek beginning: No | |
881 | # - can the iterator seek forward: No | |
882 | # | |
883 | # We expect iter.can_seek_ns_from_origin to return False. | |
884 | self._can_seek_ns_from_origin_test( | |
885 | expected_outcome=False, | |
886 | user_can_seek_ns_from_origin_ret_val=None, | |
887 | user_seek_ns_from_origin_provided=False, | |
888 | iter_can_seek_beginning=False, | |
889 | iter_can_seek_forward=False, | |
890 | ) | |
c182d7dd | 891 | |
c0e46a7c SM |
892 | def _can_seek_ns_from_origin_test( |
893 | self, | |
894 | expected_outcome, | |
895 | user_can_seek_ns_from_origin_ret_val, | |
896 | user_seek_ns_from_origin_provided, | |
897 | iter_can_seek_beginning, | |
898 | iter_can_seek_forward, | |
899 | ): | |
c182d7dd | 900 | class MySink(bt2._UserSinkComponent): |
59225a3e | 901 | def __init__(self, config, params, obj): |
c182d7dd SM |
902 | self._add_input_port('in') |
903 | ||
904 | def _user_graph_is_configured(self): | |
905 | self._msg_iter = self._create_input_port_message_iterator( | |
906 | self._input_ports['in'] | |
907 | ) | |
908 | ||
909 | def _user_consume(self): | |
910 | nonlocal can_seek_ns_from_origin | |
c182d7dd | 911 | can_seek_ns_from_origin = self._msg_iter.can_seek_ns_from_origin( |
c0e46a7c | 912 | passed_ns_from_origin |
c182d7dd SM |
913 | ) |
914 | ||
c0e46a7c | 915 | if user_can_seek_ns_from_origin_ret_val is not None: |
c182d7dd | 916 | |
c0e46a7c SM |
917 | def user_can_seek_ns_from_origin(self, ns_from_origin): |
918 | nonlocal received_ns_from_origin | |
919 | received_ns_from_origin = ns_from_origin | |
920 | return user_can_seek_ns_from_origin_ret_val | |
c182d7dd | 921 | |
c0e46a7c SM |
922 | else: |
923 | user_can_seek_ns_from_origin = None | |
c182d7dd | 924 | |
c0e46a7c | 925 | if user_seek_ns_from_origin_provided: |
c182d7dd | 926 | |
c0e46a7c SM |
927 | def user_seek_ns_from_origin(self, ns_from_origin): |
928 | pass | |
c182d7dd | 929 | |
c0e46a7c SM |
930 | else: |
931 | user_seek_ns_from_origin = None | |
c182d7dd | 932 | |
c0e46a7c | 933 | if iter_can_seek_beginning: |
c182d7dd | 934 | |
c0e46a7c SM |
935 | def user_seek_beginning(self): |
936 | pass | |
c182d7dd | 937 | |
c0e46a7c SM |
938 | else: |
939 | user_seek_beginning = None | |
c182d7dd | 940 | |
c0e46a7c SM |
941 | graph = _setup_seek_test( |
942 | MySink, | |
943 | user_can_seek_ns_from_origin=user_can_seek_ns_from_origin, | |
944 | user_seek_ns_from_origin=user_seek_ns_from_origin, | |
945 | user_seek_beginning=user_seek_beginning, | |
946 | can_seek_forward=iter_can_seek_forward, | |
947 | ) | |
c182d7dd | 948 | |
c0e46a7c SM |
949 | passed_ns_from_origin = 77 |
950 | received_ns_from_origin = None | |
c182d7dd | 951 | can_seek_ns_from_origin = None |
c182d7dd | 952 | graph.run_once() |
c0e46a7c SM |
953 | self.assertIs(can_seek_ns_from_origin, expected_outcome) |
954 | ||
955 | if user_can_seek_ns_from_origin_ret_val is not None: | |
956 | self.assertEqual(received_ns_from_origin, passed_ns_from_origin) | |
c182d7dd SM |
957 | |
958 | def test_can_seek_ns_from_origin_user_error(self): | |
959 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 960 | def __init__(self, config, params, obj): |
c182d7dd SM |
961 | self._add_input_port('in') |
962 | ||
963 | def _user_graph_is_configured(self): | |
964 | self._msg_iter = self._create_input_port_message_iterator( | |
965 | self._input_ports['in'] | |
966 | ) | |
967 | ||
968 | def _user_consume(self): | |
969 | # This is expected to raise. | |
970 | self._msg_iter.can_seek_ns_from_origin(2) | |
971 | ||
972 | def _user_can_seek_ns_from_origin(self, ns_from_origin): | |
973 | raise ValueError('Joutel') | |
974 | ||
975 | graph = _setup_seek_test( | |
2e1b5615 SM |
976 | MySink, |
977 | user_can_seek_ns_from_origin=_user_can_seek_ns_from_origin, | |
978 | user_seek_ns_from_origin=lambda: None, | |
c182d7dd SM |
979 | ) |
980 | ||
981 | with self.assertRaises(bt2._Error) as ctx: | |
982 | graph.run_once() | |
983 | ||
984 | cause = ctx.exception[0] | |
985 | self.assertIn('ValueError: Joutel', cause.message) | |
986 | ||
987 | def test_can_seek_ns_from_origin_wrong_return_value(self): | |
988 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 989 | def __init__(self, config, params, obj): |
c182d7dd SM |
990 | self._add_input_port('in') |
991 | ||
992 | def _user_graph_is_configured(self): | |
993 | self._msg_iter = self._create_input_port_message_iterator( | |
994 | self._input_ports['in'] | |
995 | ) | |
996 | ||
997 | def _user_consume(self): | |
998 | # This is expected to raise. | |
999 | self._msg_iter.can_seek_ns_from_origin(2) | |
1000 | ||
1001 | def _user_can_seek_ns_from_origin(self, ns_from_origin): | |
1002 | return 'Nitchequon' | |
1003 | ||
1004 | graph = _setup_seek_test( | |
2e1b5615 SM |
1005 | MySink, |
1006 | user_can_seek_ns_from_origin=_user_can_seek_ns_from_origin, | |
1007 | user_seek_ns_from_origin=lambda: None, | |
c182d7dd SM |
1008 | ) |
1009 | ||
1010 | with self.assertRaises(bt2._Error) as ctx: | |
1011 | graph.run_once() | |
1012 | ||
1013 | cause = ctx.exception[0] | |
1014 | self.assertIn("TypeError: 'str' is not a 'bool' object", cause.message) | |
1015 | ||
1016 | def test_seek_ns_from_origin(self): | |
1017 | class MySink(bt2._UserSinkComponent): | |
59225a3e | 1018 | def __init__(self, config, params, obj): |
c182d7dd SM |
1019 | self._add_input_port('in') |
1020 | ||
1021 | def _user_graph_is_configured(self): | |
1022 | self._msg_iter = self._create_input_port_message_iterator( | |
1023 | self._input_ports['in'] | |
1024 | ) | |
1025 | ||
1026 | def _user_consume(self): | |
1027 | self._msg_iter.seek_ns_from_origin(17) | |
1028 | ||
1029 | def _user_seek_ns_from_origin(self, ns_from_origin): | |
1030 | nonlocal actual_ns_from_origin | |
1031 | actual_ns_from_origin = ns_from_origin | |
1032 | ||
c182d7dd SM |
1033 | graph = _setup_seek_test( |
1034 | MySink, user_seek_ns_from_origin=_user_seek_ns_from_origin | |
1035 | ) | |
1036 | ||
1037 | actual_ns_from_origin = None | |
1038 | graph.run_once() | |
1039 | self.assertEqual(actual_ns_from_origin, 17) | |
1040 | ||
1041 | ||
f00b8d40 SM |
1042 | if __name__ == '__main__': |
1043 | unittest.main() |