2 # Copyright (C) 2019 EfficiOS Inc.
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
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.
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.
22 from utils
import TestOutputPortMessageIterator
23 from bt2
import port
as bt2_port
24 from bt2
import message_iterator
as bt2_message_iterator
27 class SimpleSink(bt2
._UserSinkComponent
):
28 # Straightforward sink that creates one input port (`in`) and consumes from
31 def __init__(self
, config
, params
, obj
):
32 self
._add
_input
_port
('in')
34 def _user_consume(self
):
37 def _user_graph_is_configured(self
):
38 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
41 def _create_graph(src_comp_cls
, sink_comp_cls
, flt_comp_cls
=None):
44 src_comp
= graph
.add_component(src_comp_cls
, 'src')
45 sink_comp
= graph
.add_component(sink_comp_cls
, 'sink')
47 if flt_comp_cls
is not None:
48 flt_comp
= graph
.add_component(flt_comp_cls
, 'flt')
49 graph
.connect_ports(src_comp
.output_ports
['out'], flt_comp
.input_ports
['in'])
50 graph
.connect_ports(flt_comp
.output_ports
['out'], sink_comp
.input_ports
['in'])
52 graph
.connect_ports(src_comp
.output_ports
['out'], sink_comp
.input_ports
['in'])
57 class UserMessageIteratorTestCase(unittest
.TestCase
):
59 the_output_port_from_source
= None
60 the_output_port_from_iter
= None
62 class MyIter(bt2
._UserMessageIterator
):
63 def __init__(self
, config
, self_port_output
):
65 nonlocal the_output_port_from_iter
67 the_output_port_from_iter
= self_port_output
69 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
70 def __init__(self
, config
, params
, obj
):
71 nonlocal the_output_port_from_source
72 the_output_port_from_source
= self
._add
_output
_port
('out', 'user data')
75 graph
= _create_graph(MySource
, SimpleSink
)
77 self
.assertTrue(initialized
)
79 the_output_port_from_source
.addr
, the_output_port_from_iter
.addr
81 self
.assertEqual(the_output_port_from_iter
.user_data
, 'user data')
83 def test_create_from_message_iterator(self
):
84 class MySourceIter(bt2
._UserMessageIterator
):
85 def __init__(self
, config
, self_port_output
):
86 nonlocal src_iter_initialized
87 src_iter_initialized
= True
89 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
90 def __init__(self
, config
, params
, obj
):
91 self
._add
_output
_port
('out')
93 class MyFilterIter(bt2
._UserMessageIterator
):
94 def __init__(self
, config
, self_port_output
):
95 nonlocal flt_iter_initialized
96 flt_iter_initialized
= True
97 self
._up
_iter
= self
._create
_message
_iterator
(
98 self
._component
._input
_ports
['in']
102 return next(self
._up
_iter
)
104 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
105 def __init__(self
, config
, params
, obj
):
106 self
._add
_input
_port
('in')
107 self
._add
_output
_port
('out')
109 src_iter_initialized
= False
110 flt_iter_initialized
= False
111 graph
= _create_graph(MySource
, SimpleSink
, MyFilter
)
113 self
.assertTrue(src_iter_initialized
)
114 self
.assertTrue(flt_iter_initialized
)
116 def test_create_user_error(self
):
117 # This tests both error handling by
118 # _UserSinkComponent._create_message_iterator
119 # and _UserMessageIterator._create_message_iterator, as they
120 # are both used in the graph.
121 class MySourceIter(bt2
._UserMessageIterator
):
122 def __init__(self
, config
, self_port_output
):
123 raise ValueError('Very bad error')
125 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
126 def __init__(self
, config
, params
, obj
):
127 self
._add
_output
_port
('out')
129 class MyFilterIter(bt2
._UserMessageIterator
):
130 def __init__(self
, config
, self_port_output
):
131 # This is expected to raise because of the error in
132 # MySourceIter.__init__.
133 self
._create
_message
_iterator
(self
._component
._input
_ports
['in'])
135 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
136 def __init__(self
, config
, params
, obj
):
137 self
._add
_input
_port
('in')
138 self
._add
_output
_port
('out')
140 graph
= _create_graph(MySource
, SimpleSink
, MyFilter
)
142 with self
.assertRaises(bt2
._Error
) as ctx
:
148 self
.assertIsInstance(cause
, bt2
._MessageIteratorErrorCause
)
149 self
.assertEqual(cause
.component_name
, 'src')
150 self
.assertEqual(cause
.component_output_port_name
, 'out')
151 self
.assertIn('ValueError: Very bad error', cause
.message
)
153 def test_finalize(self
):
154 class MyIter(bt2
._UserMessageIterator
):
155 def _user_finalize(self
):
159 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
160 def __init__(self
, config
, params
, obj
):
161 self
._add
_output
_port
('out')
164 graph
= _create_graph(MySource
, SimpleSink
)
167 self
.assertTrue(finalized
)
169 def test_config_parameter(self
):
170 class MyIter(bt2
._UserMessageIterator
):
171 def __init__(self
, config
, port
):
173 config_type
= type(config
)
175 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
176 def __init__(self
, config
, params
, obj
):
177 self
._add
_output
_port
('out')
180 graph
= _create_graph(MySource
, SimpleSink
)
182 self
.assertIs(config_type
, bt2_message_iterator
._MessageIteratorConfiguration
)
184 def _test_config_can_seek_forward(self
, set_can_seek_forward
):
185 class MyIter(bt2
._UserMessageIterator
):
186 def __init__(self
, config
, port
):
187 if set_can_seek_forward
:
188 config
.can_seek_forward
= True
190 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
191 def __init__(self
, config
, params
, obj
):
192 self
._add
_output
_port
('out')
194 class MySink(bt2
._UserSinkComponent
):
195 def __init__(self
, config
, params
, obj
):
196 self
._add
_input
_port
('in')
198 def _user_graph_is_configured(self
):
199 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
201 def _user_consume(self
):
202 nonlocal can_seek_forward
203 can_seek_forward
= self
._msg
_iter
.can_seek_forward
205 can_seek_forward
= None
206 graph
= _create_graph(MySource
, MySink
)
208 self
.assertIs(can_seek_forward
, set_can_seek_forward
)
210 def test_config_can_seek_forward_default(self
):
211 self
._test
_config
_can
_seek
_forward
(False)
213 def test_config_can_seek_forward(self
):
214 self
._test
_config
_can
_seek
_forward
(True)
216 def test_config_can_seek_forward_wrong_type(self
):
217 class MyIter(bt2
._UserMessageIterator
):
218 def __init__(self
, config
, port
):
219 config
.can_seek_forward
= 1
221 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
222 def __init__(self
, config
, params
, obj
):
223 self
._add
_output
_port
('out')
225 graph
= _create_graph(MySource
, SimpleSink
)
226 with self
.assertRaises(bt2
._Error
) as ctx
:
229 root_cause
= ctx
.exception
[0]
230 self
.assertIn("TypeError: 'int' is not a 'bool' object", root_cause
.message
)
232 def test_component(self
):
233 class MyIter(bt2
._UserMessageIterator
):
234 def __init__(self
, config
, self_port_output
):
236 salut
= self
._component
._salut
238 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
239 def __init__(self
, config
, params
, obj
):
240 self
._add
_output
_port
('out')
244 graph
= _create_graph(MySource
, SimpleSink
)
246 self
.assertEqual(salut
, 23)
249 class MyIter(bt2
._UserMessageIterator
):
250 def __init__(self_iter
, config
, self_port_output
):
253 port
= self_iter
._port
254 self
.assertIs(type(self_port_output
), bt2_port
._UserComponentOutputPort
)
255 self
.assertIs(type(port
), bt2_port
._UserComponentOutputPort
)
256 self
.assertEqual(self_port_output
.addr
, port
.addr
)
258 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
259 def __init__(self
, config
, params
, obj
):
260 self
._add
_output
_port
('out')
263 graph
= _create_graph(MySource
, SimpleSink
)
265 self
.assertTrue(called
)
268 class MyIter(bt2
._UserMessageIterator
):
269 def __init__(self
, config
, self_port_output
):
273 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
274 def __init__(self
, config
, params
, obj
):
275 self
._add
_output
_port
('out')
278 graph
= _create_graph(MySource
, SimpleSink
)
280 self
.assertIsNotNone(addr
)
281 self
.assertNotEqual(addr
, 0)
283 # Test that messages returned by _UserMessageIterator.__next__ remain valid
284 # and can be re-used.
285 def test_reuse_message(self
):
286 class MyIter(bt2
._UserMessageIterator
):
287 def __init__(self
, config
, port
):
288 tc
, sc
, ec
= port
.user_data
290 stream
= trace
.create_stream(sc
)
291 packet
= stream
.create_packet()
293 # This message will be returned twice by __next__.
294 event_message
= self
._create
_event
_message
(ec
, packet
)
297 self
._create
_stream
_beginning
_message
(stream
),
298 self
._create
_packet
_beginning
_message
(packet
),
304 return self
._msgs
.pop(0)
306 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
307 def __init__(self
, config
, params
, obj
):
308 tc
= self
._create
_trace
_class
()
309 sc
= tc
.create_stream_class(supports_packets
=True)
310 ec
= sc
.create_event_class()
311 self
._add
_output
_port
('out', (tc
, sc
, ec
))
314 src
= graph
.add_component(MySource
, 'src')
315 it
= TestOutputPortMessageIterator(graph
, src
.output_ports
['out'])
317 # Skip beginning messages.
319 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
321 self
.assertIs(type(msg
), bt2
._PacketBeginningMessageConst
)
326 self
.assertIs(type(msg_ev1
), bt2
._EventMessageConst
)
327 self
.assertIs(type(msg_ev2
), bt2
._EventMessageConst
)
328 self
.assertEqual(msg_ev1
.addr
, msg_ev2
.addr
)
330 # Try consuming many times from an iterator that always returns TryAgain.
331 # This verifies that we are not missing an incref of Py_None, making the
332 # refcount of Py_None reach 0.
333 def test_try_again_many_times(self
):
334 class MyIter(bt2
._UserMessageIterator
):
338 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
339 def __init__(self
, config
, params
, obj
):
340 self
._add
_output
_port
('out')
342 class MyFilterIter(bt2
._UserMessageIterator
):
343 def __init__(self
, port
):
344 input_port
= port
.user_data
345 self
._upstream
_iter
= self
._create
_message
_iterator
(input_port
)
348 return next(self
._upstream
_iter
)
350 def _user_seek_beginning(self
):
351 self
._upstream
_iter
.seek_beginning()
353 def _user_can_seek_beginning(self
):
354 return self
._upstream
_iter
.can_seek_beginning()
356 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
357 def __init__(self
, config
, params
, obj
):
358 input_port
= self
._add
_input
_port
('in')
359 self
._add
_output
_port
('out', input_port
)
362 src
= graph
.add_component(MySource
, 'src')
363 it
= TestOutputPortMessageIterator(graph
, src
.output_ports
['out'])
365 # Three times the initial ref count of `None` iterations should
366 # be enough to catch the bug even if there are small differences
367 # between configurations.
368 none_ref_count
= sys
.getrefcount(None) * 3
370 for i
in range(none_ref_count
):
371 with self
.assertRaises(bt2
.TryAgain
):
374 def test_error_in_iterator_with_cycle_after_having_created_upstream_iterator(self
):
375 # Test a failure that triggered an abort in libbabeltrace2, in this situation:
377 # - The filter iterator creates an upstream iterator.
378 # - The filter iterator creates a reference cycle, including itself.
379 # - An exception is raised, causing the filter iterator's
380 # initialization method to fail.
381 class MySourceIter(bt2
._UserMessageIterator
):
384 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
385 def __init__(self
, config
, params
, obj
):
386 self
._add
_output
_port
('out')
388 class MyFilterIter(bt2
._UserMessageIterator
):
389 def __init__(self
, config
, port
):
390 # First, create an upstream iterator.
391 self
._upstream
_iter
= self
._create
_message
_iterator
(
392 self
._component
._input
_ports
['in']
395 # Then, voluntarily make a reference cycle that will keep this
396 # Python object alive, which will keep the upstream iterator
397 # Babeltrace object alive.
400 # Finally, raise an exception to make __init__ fail.
401 raise ValueError('woops')
403 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
404 def __init__(self
, config
, params
, obj
):
405 self
._in
= self
._add
_input
_port
('in')
406 self
._out
= self
._add
_output
_port
('out')
408 class MySink(bt2
._UserSinkComponent
):
409 def __init__(self
, config
, params
, obj
):
410 self
._input
_port
= self
._add
_input
_port
('in')
412 def _user_graph_is_configured(self
):
413 self
._upstream
_iter
= self
._create
_message
_iterator
(self
._input
_port
)
415 def _user_consume(self
):
416 # We should not reach this.
420 src
= g
.add_component(MySource
, 'src')
421 flt
= g
.add_component(MyFilter
, 'flt')
422 snk
= g
.add_component(MySink
, 'snk')
423 g
.connect_ports(src
.output_ports
['out'], flt
.input_ports
['in'])
424 g
.connect_ports(flt
.output_ports
['out'], snk
.input_ports
['in'])
426 with self
.assertRaisesRegex(bt2
._Error
, 'ValueError: woops'):
430 def _setup_seek_test(
432 user_seek_beginning
=None,
433 user_can_seek_beginning
=None,
434 user_seek_ns_from_origin
=None,
435 user_can_seek_ns_from_origin
=None,
436 can_seek_forward
=False,
438 class MySourceIter(bt2
._UserMessageIterator
):
439 def __init__(self
, config
, port
):
440 tc
, sc
, ec
= port
.user_data
442 stream
= trace
.create_stream(sc
)
443 packet
= stream
.create_packet()
446 self
._create
_stream
_beginning
_message
(stream
),
447 self
._create
_packet
_beginning
_message
(packet
),
448 self
._create
_event
_message
(ec
, packet
),
449 self
._create
_event
_message
(ec
, packet
),
450 self
._create
_packet
_end
_message
(packet
),
451 self
._create
_stream
_end
_message
(stream
),
454 config
.can_seek_forward
= can_seek_forward
457 if self
._at
< len(self
._msgs
):
458 msg
= self
._msgs
[self
._at
]
464 if user_seek_beginning
is not None:
465 MySourceIter
._user
_seek
_beginning
= user_seek_beginning
467 if user_can_seek_beginning
is not None:
468 MySourceIter
._user
_can
_seek
_beginning
= user_can_seek_beginning
470 if user_seek_ns_from_origin
is not None:
471 MySourceIter
._user
_seek
_ns
_from
_origin
= user_seek_ns_from_origin
473 if user_can_seek_ns_from_origin
is not None:
474 MySourceIter
._user
_can
_seek
_ns
_from
_origin
= user_can_seek_ns_from_origin
476 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
477 def __init__(self
, config
, params
, obj
):
478 tc
= self
._create
_trace
_class
()
479 sc
= tc
.create_stream_class(supports_packets
=True)
480 ec
= sc
.create_event_class()
482 self
._add
_output
_port
('out', (tc
, sc
, ec
))
484 class MyFilterIter(bt2
._UserMessageIterator
):
485 def __init__(self
, config
, port
):
486 self
._upstream
_iter
= self
._create
_message
_iterator
(
487 self
._component
._input
_ports
['in']
489 config
.can_seek_forward
= self
._upstream
_iter
.can_seek_forward
492 return next(self
._upstream
_iter
)
494 def _user_can_seek_beginning(self
):
495 return self
._upstream
_iter
.can_seek_beginning()
497 def _user_seek_beginning(self
):
498 self
._upstream
_iter
.seek_beginning()
500 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
501 return self
._upstream
_iter
.can_seek_ns_from_origin(ns_from_origin
)
503 def _user_seek_ns_from_origin(self
, ns_from_origin
):
504 self
._upstream
_iter
.seek_ns_from_origin(ns_from_origin
)
506 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
507 def __init__(self
, config
, params
, obj
):
508 self
._add
_input
_port
('in')
509 self
._add
_output
_port
('out')
511 return _create_graph(MySource
, sink_cls
, flt_comp_cls
=MyFilter
)
514 class UserMessageIteratorSeekBeginningTestCase(unittest
.TestCase
):
515 def test_can_seek_beginning_without_seek_beginning(self
):
516 with self
.assertRaisesRegex(
517 bt2
._IncompleteUserClass
,
518 "cannot create component class 'MySource': message iterator class implements _user_can_seek_beginning but not _user_seek_beginning",
520 _setup_seek_test(SimpleSink
, user_can_seek_beginning
=lambda: None)
522 def test_can_seek_beginning(self
):
523 class MySink(bt2
._UserSinkComponent
):
524 def __init__(self
, config
, params
, obj
):
525 self
._add
_input
_port
('in')
527 def _user_graph_is_configured(self
):
528 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
530 def _user_consume(self
):
531 nonlocal can_seek_beginning
532 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
534 def _user_can_seek_beginning(self
):
535 nonlocal input_port_iter_can_seek_beginning
536 return input_port_iter_can_seek_beginning
538 graph
= _setup_seek_test(
540 user_can_seek_beginning
=_user_can_seek_beginning
,
541 user_seek_beginning
=lambda: None,
544 input_port_iter_can_seek_beginning
= True
545 can_seek_beginning
= None
547 self
.assertIs(can_seek_beginning
, True)
549 input_port_iter_can_seek_beginning
= False
550 can_seek_beginning
= None
552 self
.assertIs(can_seek_beginning
, False)
554 def test_no_can_seek_beginning_with_seek_beginning(self
):
555 # Test an iterator without a _user_can_seek_beginning method, but with
556 # a _user_seek_beginning method.
557 class MySink(bt2
._UserSinkComponent
):
558 def __init__(self
, config
, params
, obj
):
559 self
._add
_input
_port
('in')
561 def _user_graph_is_configured(self
):
562 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
564 def _user_consume(self
):
565 nonlocal can_seek_beginning
566 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
568 def _user_seek_beginning(self
):
571 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
572 can_seek_beginning
= None
574 self
.assertIs(can_seek_beginning
, True)
576 def test_no_can_seek_beginning(self
):
577 # Test an iterator without a _user_can_seek_beginning method, without
578 # a _user_seek_beginning method.
579 class MySink(bt2
._UserSinkComponent
):
580 def __init__(self
, config
, params
, obj
):
581 self
._add
_input
_port
('in')
583 def _user_graph_is_configured(self
):
584 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
586 def _user_consume(self
):
587 nonlocal can_seek_beginning
588 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
590 graph
= _setup_seek_test(MySink
)
591 can_seek_beginning
= None
593 self
.assertIs(can_seek_beginning
, False)
595 def test_can_seek_beginning_user_error(self
):
596 class MySink(bt2
._UserSinkComponent
):
597 def __init__(self
, config
, params
, obj
):
598 self
._add
_input
_port
('in')
600 def _user_graph_is_configured(self
):
601 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
603 def _user_consume(self
):
604 # This is expected to raise.
605 self
._msg
_iter
.can_seek_beginning()
607 def _user_can_seek_beginning(self
):
608 raise ValueError('moustiquaire')
610 graph
= _setup_seek_test(
612 user_can_seek_beginning
=_user_can_seek_beginning
,
613 user_seek_beginning
=lambda: None,
616 with self
.assertRaises(bt2
._Error
) as ctx
:
619 cause
= ctx
.exception
[0]
620 self
.assertIn('ValueError: moustiquaire', cause
.message
)
622 def test_can_seek_beginning_wrong_return_value(self
):
623 class MySink(bt2
._UserSinkComponent
):
624 def __init__(self
, config
, params
, obj
):
625 self
._add
_input
_port
('in')
627 def _user_graph_is_configured(self
):
628 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
630 def _user_consume(self
):
631 # This is expected to raise.
632 self
._msg
_iter
.can_seek_beginning()
634 def _user_can_seek_beginning(self
):
637 graph
= _setup_seek_test(
639 user_can_seek_beginning
=_user_can_seek_beginning
,
640 user_seek_beginning
=lambda: None,
643 with self
.assertRaises(bt2
._Error
) as ctx
:
646 cause
= ctx
.exception
[0]
647 self
.assertIn("TypeError: 'str' is not a 'bool' object", cause
.message
)
649 def test_seek_beginning(self
):
650 class MySink(bt2
._UserSinkComponent
):
651 def __init__(self
, config
, params
, obj
):
652 self
._add
_input
_port
('in')
654 def _user_graph_is_configured(self
):
655 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
657 def _user_consume(self
):
658 nonlocal do_seek_beginning
661 if do_seek_beginning
:
662 self
._msg
_iter
.seek_beginning()
665 msg
= next(self
._msg
_iter
)
667 def _user_seek_beginning(self
):
671 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
674 do_seek_beginning
= False
676 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
680 self
.assertIs(type(msg
), bt2
._PacketBeginningMessageConst
)
683 do_seek_beginning
= True
687 do_seek_beginning
= False
689 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
691 def test_seek_beginning_user_error(self
):
692 class MySink(bt2
._UserSinkComponent
):
693 def __init__(self
, config
, params
, obj
):
694 self
._add
_input
_port
('in')
696 def _user_graph_is_configured(self
):
697 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
699 def _user_consume(self
):
700 self
._msg
_iter
.seek_beginning()
702 def _user_seek_beginning(self
):
703 raise ValueError('ouch')
705 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
707 with self
.assertRaises(bt2
._Error
):
711 class UserMessageIteratorSeekNsFromOriginTestCase(unittest
.TestCase
):
712 def test_can_seek_ns_from_origin_without_seek_ns_from_origin(self
):
713 # Test the case where:
715 # - can_seek_ns_from_origin: Returns True (don't really care, as long
717 # - seek_ns_from_origin provided: No
718 # - can the iterator seek beginning: Don't care
719 # - can the iterator seek forward: Don't care
720 for can_seek_ns_from_origin
in (False, True):
721 for iter_can_seek_beginning
in (False, True):
722 for iter_can_seek_forward
in (False, True):
723 with self
.assertRaisesRegex(
724 bt2
._IncompleteUserClass
,
725 "cannot create component class 'MySource': message iterator class implements _user_can_seek_ns_from_origin but not _user_seek_ns_from_origin",
727 self
._can
_seek
_ns
_from
_origin
_test
(
729 user_can_seek_ns_from_origin_ret_val
=True,
730 user_seek_ns_from_origin_provided
=False,
731 iter_can_seek_beginning
=iter_can_seek_beginning
,
732 iter_can_seek_forward
=iter_can_seek_forward
,
735 def test_can_seek_ns_from_origin_returns_true(self
):
736 # Test the case where:
738 # - can_seek_ns_from_origin: returns True
739 # - seek_ns_from_origin provided: Yes
740 # - can the iterator seek beginning: Don't care
741 # - can the iterator seek forward: Don't care
743 # We expect iter.can_seek_ns_from_origin to return True.
744 for iter_can_seek_beginning
in (False, True):
745 for iter_can_seek_forward
in (False, True):
746 self
._can
_seek
_ns
_from
_origin
_test
(
747 expected_outcome
=True,
748 user_can_seek_ns_from_origin_ret_val
=True,
749 user_seek_ns_from_origin_provided
=True,
750 iter_can_seek_beginning
=iter_can_seek_beginning
,
751 iter_can_seek_forward
=iter_can_seek_forward
,
754 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_forward_seekable(
757 # Test the case where:
759 # - can_seek_ns_from_origin: returns False
760 # - seek_ns_from_origin provided: Yes
761 # - can the iterator seek beginning: Yes
762 # - can the iterator seek forward: Yes
764 # We expect iter.can_seek_ns_from_origin to return True.
765 self
._can
_seek
_ns
_from
_origin
_test
(
766 expected_outcome
=True,
767 user_can_seek_ns_from_origin_ret_val
=False,
768 user_seek_ns_from_origin_provided
=True,
769 iter_can_seek_beginning
=True,
770 iter_can_seek_forward
=True,
773 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_not_forward_seekable(
776 # Test the case where:
778 # - can_seek_ns_from_origin: returns False
779 # - seek_ns_from_origin provided: Yes
780 # - can the iterator seek beginning: Yes
781 # - can the iterator seek forward: No
783 # We expect iter.can_seek_ns_from_origin to return False.
784 self
._can
_seek
_ns
_from
_origin
_test
(
785 expected_outcome
=False,
786 user_can_seek_ns_from_origin_ret_val
=False,
787 user_seek_ns_from_origin_provided
=True,
788 iter_can_seek_beginning
=True,
789 iter_can_seek_forward
=False,
792 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_forward_seekable(
795 # Test the case where:
797 # - can_seek_ns_from_origin: returns False
798 # - seek_ns_from_origin provided: Yes
799 # - can the iterator seek beginning: No
800 # - can the iterator seek forward: Yes
802 # We expect iter.can_seek_ns_from_origin to return False.
803 self
._can
_seek
_ns
_from
_origin
_test
(
804 expected_outcome
=False,
805 user_can_seek_ns_from_origin_ret_val
=False,
806 user_seek_ns_from_origin_provided
=True,
807 iter_can_seek_beginning
=False,
808 iter_can_seek_forward
=True,
811 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_not_forward_seekable(
814 # Test the case where:
816 # - can_seek_ns_from_origin: returns False
817 # - seek_ns_from_origin provided: Yes
818 # - can the iterator seek beginning: No
819 # - can the iterator seek forward: No
821 # We expect iter.can_seek_ns_from_origin to return False.
822 self
._can
_seek
_ns
_from
_origin
_test
(
823 expected_outcome
=False,
824 user_can_seek_ns_from_origin_ret_val
=False,
825 user_seek_ns_from_origin_provided
=True,
826 iter_can_seek_beginning
=False,
827 iter_can_seek_forward
=False,
830 def test_no_can_seek_ns_from_origin_seek_ns_from_origin(self
):
831 # Test the case where:
833 # - can_seek_ns_from_origin: Not provided
834 # - seek_ns_from_origin provided: Yes
835 # - can the iterator seek beginning: Don't care
836 # - can the iterator seek forward: Don't care
838 # We expect iter.can_seek_ns_from_origin to return True.
839 for iter_can_seek_beginning
in (False, True):
840 for iter_can_seek_forward
in (False, True):
841 self
._can
_seek
_ns
_from
_origin
_test
(
842 expected_outcome
=True,
843 user_can_seek_ns_from_origin_ret_val
=None,
844 user_seek_ns_from_origin_provided
=True,
845 iter_can_seek_beginning
=iter_can_seek_beginning
,
846 iter_can_seek_forward
=iter_can_seek_forward
,
849 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_forward_seekable(
852 # Test the case where:
854 # - can_seek_ns_from_origin: Not provided
855 # - seek_ns_from_origin provided: Not provided
856 # - can the iterator seek beginning: Yes
857 # - can the iterator seek forward: Yes
859 # We expect iter.can_seek_ns_from_origin to return True.
860 self
._can
_seek
_ns
_from
_origin
_test
(
861 expected_outcome
=True,
862 user_can_seek_ns_from_origin_ret_val
=None,
863 user_seek_ns_from_origin_provided
=False,
864 iter_can_seek_beginning
=True,
865 iter_can_seek_forward
=True,
868 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_not_forward_seekable(
871 # Test the case where:
873 # - can_seek_ns_from_origin: Not provided
874 # - seek_ns_from_origin provided: Not provided
875 # - can the iterator seek beginning: Yes
876 # - can the iterator seek forward: No
878 # We expect iter.can_seek_ns_from_origin to return False.
879 self
._can
_seek
_ns
_from
_origin
_test
(
880 expected_outcome
=False,
881 user_can_seek_ns_from_origin_ret_val
=None,
882 user_seek_ns_from_origin_provided
=False,
883 iter_can_seek_beginning
=True,
884 iter_can_seek_forward
=False,
887 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_forward_seekable(
890 # Test the case where:
892 # - can_seek_ns_from_origin: Not provided
893 # - seek_ns_from_origin provided: Not provided
894 # - can the iterator seek beginning: No
895 # - can the iterator seek forward: Yes
897 # We expect iter.can_seek_ns_from_origin to return False.
898 self
._can
_seek
_ns
_from
_origin
_test
(
899 expected_outcome
=False,
900 user_can_seek_ns_from_origin_ret_val
=None,
901 user_seek_ns_from_origin_provided
=False,
902 iter_can_seek_beginning
=False,
903 iter_can_seek_forward
=True,
906 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_not_forward_seekable(
909 # Test the case where:
911 # - can_seek_ns_from_origin: Not provided
912 # - seek_ns_from_origin provided: Not provided
913 # - can the iterator seek beginning: No
914 # - can the iterator seek forward: No
916 # We expect iter.can_seek_ns_from_origin to return False.
917 self
._can
_seek
_ns
_from
_origin
_test
(
918 expected_outcome
=False,
919 user_can_seek_ns_from_origin_ret_val
=None,
920 user_seek_ns_from_origin_provided
=False,
921 iter_can_seek_beginning
=False,
922 iter_can_seek_forward
=False,
925 def _can_seek_ns_from_origin_test(
928 user_can_seek_ns_from_origin_ret_val
,
929 user_seek_ns_from_origin_provided
,
930 iter_can_seek_beginning
,
931 iter_can_seek_forward
,
933 class MySink(bt2
._UserSinkComponent
):
934 def __init__(self
, config
, params
, obj
):
935 self
._add
_input
_port
('in')
937 def _user_graph_is_configured(self
):
938 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
940 def _user_consume(self
):
941 nonlocal can_seek_ns_from_origin
942 can_seek_ns_from_origin
= self
._msg
_iter
.can_seek_ns_from_origin(
943 passed_ns_from_origin
946 if user_can_seek_ns_from_origin_ret_val
is not None:
948 def user_can_seek_ns_from_origin(self
, ns_from_origin
):
949 nonlocal received_ns_from_origin
950 received_ns_from_origin
= ns_from_origin
951 return user_can_seek_ns_from_origin_ret_val
954 user_can_seek_ns_from_origin
= None
956 if user_seek_ns_from_origin_provided
:
958 def user_seek_ns_from_origin(self
, ns_from_origin
):
962 user_seek_ns_from_origin
= None
964 if iter_can_seek_beginning
:
966 def user_seek_beginning(self
):
970 user_seek_beginning
= None
972 graph
= _setup_seek_test(
974 user_can_seek_ns_from_origin
=user_can_seek_ns_from_origin
,
975 user_seek_ns_from_origin
=user_seek_ns_from_origin
,
976 user_seek_beginning
=user_seek_beginning
,
977 can_seek_forward
=iter_can_seek_forward
,
980 passed_ns_from_origin
= 77
981 received_ns_from_origin
= None
982 can_seek_ns_from_origin
= None
984 self
.assertIs(can_seek_ns_from_origin
, expected_outcome
)
986 if user_can_seek_ns_from_origin_ret_val
is not None:
987 self
.assertEqual(received_ns_from_origin
, passed_ns_from_origin
)
989 def test_can_seek_ns_from_origin_user_error(self
):
990 class MySink(bt2
._UserSinkComponent
):
991 def __init__(self
, config
, params
, obj
):
992 self
._add
_input
_port
('in')
994 def _user_graph_is_configured(self
):
995 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
997 def _user_consume(self
):
998 # This is expected to raise.
999 self
._msg
_iter
.can_seek_ns_from_origin(2)
1001 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
1002 raise ValueError('Joutel')
1004 graph
= _setup_seek_test(
1006 user_can_seek_ns_from_origin
=_user_can_seek_ns_from_origin
,
1007 user_seek_ns_from_origin
=lambda: None,
1010 with self
.assertRaises(bt2
._Error
) as ctx
:
1013 cause
= ctx
.exception
[0]
1014 self
.assertIn('ValueError: Joutel', cause
.message
)
1016 def test_can_seek_ns_from_origin_wrong_return_value(self
):
1017 class MySink(bt2
._UserSinkComponent
):
1018 def __init__(self
, config
, params
, obj
):
1019 self
._add
_input
_port
('in')
1021 def _user_graph_is_configured(self
):
1022 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
1024 def _user_consume(self
):
1025 # This is expected to raise.
1026 self
._msg
_iter
.can_seek_ns_from_origin(2)
1028 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
1031 graph
= _setup_seek_test(
1033 user_can_seek_ns_from_origin
=_user_can_seek_ns_from_origin
,
1034 user_seek_ns_from_origin
=lambda: None,
1037 with self
.assertRaises(bt2
._Error
) as ctx
:
1040 cause
= ctx
.exception
[0]
1041 self
.assertIn("TypeError: 'str' is not a 'bool' object", cause
.message
)
1043 def test_seek_ns_from_origin(self
):
1044 class MySink(bt2
._UserSinkComponent
):
1045 def __init__(self
, config
, params
, obj
):
1046 self
._add
_input
_port
('in')
1048 def _user_graph_is_configured(self
):
1049 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
1051 def _user_consume(self
):
1052 self
._msg
_iter
.seek_ns_from_origin(17)
1054 def _user_seek_ns_from_origin(self
, ns_from_origin
):
1055 nonlocal actual_ns_from_origin
1056 actual_ns_from_origin
= ns_from_origin
1058 graph
= _setup_seek_test(
1059 MySink
, user_seek_ns_from_origin
=_user_seek_ns_from_origin
1062 actual_ns_from_origin
= None
1064 self
.assertEqual(actual_ns_from_origin
, 17)
1067 if __name__
== '__main__':