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
_input
_port
_message
_iterator
(
39 self
._input
_ports
['in']
43 def _create_graph(src_comp_cls
, sink_comp_cls
, flt_comp_cls
=None):
46 src_comp
= graph
.add_component(src_comp_cls
, 'src')
47 sink_comp
= graph
.add_component(sink_comp_cls
, 'sink')
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'])
54 graph
.connect_ports(src_comp
.output_ports
['out'], sink_comp
.input_ports
['in'])
59 class UserMessageIteratorTestCase(unittest
.TestCase
):
61 the_output_port_from_source
= None
62 the_output_port_from_iter
= None
64 class MyIter(bt2
._UserMessageIterator
):
65 def __init__(self
, config
, self_port_output
):
67 nonlocal the_output_port_from_iter
69 the_output_port_from_iter
= self_port_output
71 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
72 def __init__(self
, config
, params
, obj
):
73 nonlocal the_output_port_from_source
74 the_output_port_from_source
= self
._add
_output
_port
('out', 'user data')
77 graph
= _create_graph(MySource
, SimpleSink
)
79 self
.assertTrue(initialized
)
81 the_output_port_from_source
.addr
, the_output_port_from_iter
.addr
83 self
.assertEqual(the_output_port_from_iter
.user_data
, 'user data')
85 def test_create_from_message_iterator(self
):
86 class MySourceIter(bt2
._UserMessageIterator
):
87 def __init__(self
, config
, self_port_output
):
88 nonlocal src_iter_initialized
89 src_iter_initialized
= True
91 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
92 def __init__(self
, config
, params
, obj
):
93 self
._add
_output
_port
('out')
95 class MyFilterIter(bt2
._UserMessageIterator
):
96 def __init__(self
, config
, self_port_output
):
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']
104 return next(self
._up
_iter
)
106 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
107 def __init__(self
, config
, params
, obj
):
108 self
._add
_input
_port
('in')
109 self
._add
_output
_port
('out')
111 src_iter_initialized
= False
112 flt_iter_initialized
= False
113 graph
= _create_graph(MySource
, SimpleSink
, MyFilter
)
115 self
.assertTrue(src_iter_initialized
)
116 self
.assertTrue(flt_iter_initialized
)
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
):
124 def __init__(self
, config
, self_port_output
):
125 raise ValueError('Very bad error')
127 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
128 def __init__(self
, config
, params
, obj
):
129 self
._add
_output
_port
('out')
131 class MyFilterIter(bt2
._UserMessageIterator
):
132 def __init__(self
, config
, self_port_output
):
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']
139 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
140 def __init__(self
, config
, params
, obj
):
141 self
._add
_input
_port
('in')
142 self
._add
_output
_port
('out')
144 graph
= _create_graph(MySource
, SimpleSink
, MyFilter
)
146 with self
.assertRaises(bt2
._Error
) as ctx
:
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
)
157 def test_finalize(self
):
158 class MyIter(bt2
._UserMessageIterator
):
159 def _user_finalize(self
):
163 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
164 def __init__(self
, config
, params
, obj
):
165 self
._add
_output
_port
('out')
168 graph
= _create_graph(MySource
, SimpleSink
)
171 self
.assertTrue(finalized
)
173 def test_config_parameter(self
):
174 class MyIter(bt2
._UserMessageIterator
):
175 def __init__(self
, config
, port
):
177 config_type
= type(config
)
179 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
180 def __init__(self
, config
, params
, obj
):
181 self
._add
_output
_port
('out')
184 graph
= _create_graph(MySource
, SimpleSink
)
186 self
.assertIs(config_type
, bt2_message_iterator
._MessageIteratorConfiguration
)
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
194 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
195 def __init__(self
, config
, params
, obj
):
196 self
._add
_output
_port
('out')
198 class MySink(bt2
._UserSinkComponent
):
199 def __init__(self
, config
, params
, obj
):
200 self
._add
_input
_port
('in')
202 def _user_graph_is_configured(self
):
203 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
204 self
._input
_ports
['in']
207 def _user_consume(self
):
208 nonlocal can_seek_forward
209 can_seek_forward
= self
._msg
_iter
.can_seek_forward
211 can_seek_forward
= None
212 graph
= _create_graph(MySource
, MySink
)
214 self
.assertIs(can_seek_forward
, set_can_seek_forward
)
216 def test_config_can_seek_forward_default(self
):
217 self
._test
_config
_can
_seek
_forward
(False)
219 def test_config_can_seek_forward(self
):
220 self
._test
_config
_can
_seek
_forward
(True)
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
227 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
228 def __init__(self
, config
, params
, obj
):
229 self
._add
_output
_port
('out')
231 graph
= _create_graph(MySource
, SimpleSink
)
232 with self
.assertRaises(bt2
._Error
) as ctx
:
235 root_cause
= ctx
.exception
[0]
236 self
.assertIn("TypeError: 'int' is not a 'bool' object", root_cause
.message
)
238 def test_component(self
):
239 class MyIter(bt2
._UserMessageIterator
):
240 def __init__(self
, config
, self_port_output
):
242 salut
= self
._component
._salut
244 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
245 def __init__(self
, config
, params
, obj
):
246 self
._add
_output
_port
('out')
250 graph
= _create_graph(MySource
, SimpleSink
)
252 self
.assertEqual(salut
, 23)
255 class MyIter(bt2
._UserMessageIterator
):
256 def __init__(self_iter
, config
, self_port_output
):
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
)
264 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
265 def __init__(self
, config
, params
, obj
):
266 self
._add
_output
_port
('out')
269 graph
= _create_graph(MySource
, SimpleSink
)
271 self
.assertTrue(called
)
274 class MyIter(bt2
._UserMessageIterator
):
275 def __init__(self
, config
, self_port_output
):
279 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
280 def __init__(self
, config
, params
, obj
):
281 self
._add
_output
_port
('out')
284 graph
= _create_graph(MySource
, SimpleSink
)
286 self
.assertIsNotNone(addr
)
287 self
.assertNotEqual(addr
, 0)
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
):
293 def __init__(self
, config
, port
):
294 tc
, sc
, ec
= port
.user_data
296 stream
= trace
.create_stream(sc
)
297 packet
= stream
.create_packet()
299 # This message will be returned twice by __next__.
300 event_message
= self
._create
_event
_message
(ec
, packet
)
303 self
._create
_stream
_beginning
_message
(stream
),
304 self
._create
_packet
_beginning
_message
(packet
),
310 return self
._msgs
.pop(0)
312 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
313 def __init__(self
, config
, params
, obj
):
314 tc
= self
._create
_trace
_class
()
315 sc
= tc
.create_stream_class(supports_packets
=True)
316 ec
= sc
.create_event_class()
317 self
._add
_output
_port
('out', (tc
, sc
, ec
))
320 src
= graph
.add_component(MySource
, 'src')
321 it
= TestOutputPortMessageIterator(graph
, src
.output_ports
['out'])
323 # Skip beginning messages.
325 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
327 self
.assertIs(type(msg
), bt2
._PacketBeginningMessageConst
)
332 self
.assertIs(type(msg_ev1
), bt2
._EventMessageConst
)
333 self
.assertIs(type(msg_ev2
), bt2
._EventMessageConst
)
334 self
.assertEqual(msg_ev1
.addr
, msg_ev2
.addr
)
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
):
344 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
345 def __init__(self
, config
, params
, obj
):
346 self
._add
_output
_port
('out')
348 class MyFilterIter(bt2
._UserMessageIterator
):
349 def __init__(self
, port
):
350 input_port
= port
.user_data
351 self
._upstream
_iter
= self
._create
_input
_port
_message
_iterator
(
356 return next(self
._upstream
_iter
)
358 def _user_seek_beginning(self
):
359 self
._upstream
_iter
.seek_beginning()
361 def _user_can_seek_beginning(self
):
362 return self
._upstream
_iter
.can_seek_beginning()
364 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
365 def __init__(self
, config
, params
, obj
):
366 input_port
= self
._add
_input
_port
('in')
367 self
._add
_output
_port
('out', input_port
)
370 src
= graph
.add_component(MySource
, 'src')
371 it
= TestOutputPortMessageIterator(graph
, src
.output_ports
['out'])
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
378 for i
in range(none_ref_count
):
379 with self
.assertRaises(bt2
.TryAgain
):
383 def _setup_seek_test(
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,
389 can_seek_forward
=False,
391 class MySourceIter(bt2
._UserMessageIterator
):
392 def __init__(self
, config
, port
):
393 tc
, sc
, ec
= port
.user_data
395 stream
= trace
.create_stream(sc
)
396 packet
= stream
.create_packet()
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
),
407 config
.can_seek_forward
= can_seek_forward
410 if self
._at
< len(self
._msgs
):
411 msg
= self
._msgs
[self
._at
]
417 if user_seek_beginning
is not None:
418 MySourceIter
._user
_seek
_beginning
= user_seek_beginning
420 if user_can_seek_beginning
is not None:
421 MySourceIter
._user
_can
_seek
_beginning
= user_can_seek_beginning
423 if user_seek_ns_from_origin
is not None:
424 MySourceIter
._user
_seek
_ns
_from
_origin
= user_seek_ns_from_origin
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
429 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
430 def __init__(self
, config
, params
, obj
):
431 tc
= self
._create
_trace
_class
()
432 sc
= tc
.create_stream_class(supports_packets
=True)
433 ec
= sc
.create_event_class()
435 self
._add
_output
_port
('out', (tc
, sc
, ec
))
437 class MyFilterIter(bt2
._UserMessageIterator
):
438 def __init__(self
, config
, port
):
439 self
._upstream
_iter
= self
._create
_input
_port
_message
_iterator
(
440 self
._component
._input
_ports
['in']
442 config
.can_seek_forward
= self
._upstream
_iter
.can_seek_forward
445 return next(self
._upstream
_iter
)
447 def _user_can_seek_beginning(self
):
448 return self
._upstream
_iter
.can_seek_beginning()
450 def _user_seek_beginning(self
):
451 self
._upstream
_iter
.seek_beginning()
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
)
456 def _user_seek_ns_from_origin(self
, ns_from_origin
):
457 self
._upstream
_iter
.seek_ns_from_origin(ns_from_origin
)
459 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
460 def __init__(self
, config
, params
, obj
):
461 self
._add
_input
_port
('in')
462 self
._add
_output
_port
('out')
464 return _create_graph(MySource
, sink_cls
, flt_comp_cls
=MyFilter
)
467 class UserMessageIteratorSeekBeginningTestCase(unittest
.TestCase
):
468 def test_can_seek_beginning(self
):
469 class MySink(bt2
._UserSinkComponent
):
470 def __init__(self
, config
, params
, obj
):
471 self
._add
_input
_port
('in')
473 def _user_graph_is_configured(self
):
474 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
475 self
._input
_ports
['in']
478 def _user_consume(self
):
479 nonlocal can_seek_beginning
480 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
482 def _user_can_seek_beginning(self
):
483 nonlocal input_port_iter_can_seek_beginning
484 return input_port_iter_can_seek_beginning
486 graph
= _setup_seek_test(
487 MySink
, user_can_seek_beginning
=_user_can_seek_beginning
490 input_port_iter_can_seek_beginning
= True
491 can_seek_beginning
= None
493 self
.assertIs(can_seek_beginning
, True)
495 input_port_iter_can_seek_beginning
= False
496 can_seek_beginning
= None
498 self
.assertIs(can_seek_beginning
, False)
500 def test_no_can_seek_beginning_with_seek_beginning(self
):
501 # Test an iterator without a _user_can_seek_beginning method, but with
502 # a _user_seek_beginning method.
503 class MySink(bt2
._UserSinkComponent
):
504 def __init__(self
, config
, params
, obj
):
505 self
._add
_input
_port
('in')
507 def _user_graph_is_configured(self
):
508 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
509 self
._input
_ports
['in']
512 def _user_consume(self
):
513 nonlocal can_seek_beginning
514 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
516 def _user_seek_beginning(self
):
519 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
520 can_seek_beginning
= None
522 self
.assertIs(can_seek_beginning
, True)
524 def test_no_can_seek_beginning(self
):
525 # Test an iterator without a _user_can_seek_beginning method, without
526 # a _user_seek_beginning method.
527 class MySink(bt2
._UserSinkComponent
):
528 def __init__(self
, config
, params
, obj
):
529 self
._add
_input
_port
('in')
531 def _user_graph_is_configured(self
):
532 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
533 self
._input
_ports
['in']
536 def _user_consume(self
):
537 nonlocal can_seek_beginning
538 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
540 graph
= _setup_seek_test(MySink
)
541 can_seek_beginning
= None
543 self
.assertIs(can_seek_beginning
, False)
545 def test_can_seek_beginning_user_error(self
):
546 class MySink(bt2
._UserSinkComponent
):
547 def __init__(self
, config
, params
, obj
):
548 self
._add
_input
_port
('in')
550 def _user_graph_is_configured(self
):
551 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
552 self
._input
_ports
['in']
555 def _user_consume(self
):
556 # This is expected to raise.
557 self
._msg
_iter
.can_seek_beginning()
559 def _user_can_seek_beginning(self
):
560 raise ValueError('moustiquaire')
562 graph
= _setup_seek_test(
563 MySink
, user_can_seek_beginning
=_user_can_seek_beginning
566 with self
.assertRaises(bt2
._Error
) as ctx
:
569 cause
= ctx
.exception
[0]
570 self
.assertIn('ValueError: moustiquaire', cause
.message
)
572 def test_can_seek_beginning_wrong_return_value(self
):
573 class MySink(bt2
._UserSinkComponent
):
574 def __init__(self
, config
, params
, obj
):
575 self
._add
_input
_port
('in')
577 def _user_graph_is_configured(self
):
578 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
579 self
._input
_ports
['in']
582 def _user_consume(self
):
583 # This is expected to raise.
584 self
._msg
_iter
.can_seek_beginning()
586 def _user_can_seek_beginning(self
):
589 graph
= _setup_seek_test(
590 MySink
, user_can_seek_beginning
=_user_can_seek_beginning
593 with self
.assertRaises(bt2
._Error
) as ctx
:
596 cause
= ctx
.exception
[0]
597 self
.assertIn("TypeError: 'str' is not a 'bool' object", cause
.message
)
599 def test_seek_beginning(self
):
600 class MySink(bt2
._UserSinkComponent
):
601 def __init__(self
, config
, params
, obj
):
602 self
._add
_input
_port
('in')
604 def _user_graph_is_configured(self
):
605 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
606 self
._input
_ports
['in']
609 def _user_consume(self
):
610 nonlocal do_seek_beginning
613 if do_seek_beginning
:
614 self
._msg
_iter
.seek_beginning()
617 msg
= next(self
._msg
_iter
)
619 def _user_seek_beginning(self
):
623 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
626 do_seek_beginning
= False
628 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
632 self
.assertIs(type(msg
), bt2
._PacketBeginningMessageConst
)
635 do_seek_beginning
= True
639 do_seek_beginning
= False
641 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
643 def test_seek_beginning_user_error(self
):
644 class MySink(bt2
._UserSinkComponent
):
645 def __init__(self
, config
, params
, obj
):
646 self
._add
_input
_port
('in')
648 def _user_graph_is_configured(self
):
649 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
650 self
._input
_ports
['in']
653 def _user_consume(self
):
654 self
._msg
_iter
.seek_beginning()
656 def _user_seek_beginning(self
):
657 raise ValueError('ouch')
659 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
661 with self
.assertRaises(bt2
._Error
):
665 class UserMessageIteratorSeekNsFromOriginTestCase(unittest
.TestCase
):
666 def test_can_seek_ns_from_origin_returns_true(self
):
667 # Test the case where:
669 # - can_seek_ns_from_origin: returns True
670 # - seek_ns_from_origin provided: Don't care
671 # - can the iterator seek beginning: Don't care
672 # - can the iterator seek forward: Don't care
674 # We expect iter.can_seek_ns_from_origin to return True.
675 for user_seek_ns_from_origin_provided
in (False, True):
676 for iter_can_seek_beginning
in (False, True):
677 for iter_can_seek_forward
in (False, True):
678 self
._can
_seek
_ns
_from
_origin
_test
(
679 expected_outcome
=True,
680 user_can_seek_ns_from_origin_ret_val
=True,
681 user_seek_ns_from_origin_provided
=user_seek_ns_from_origin_provided
,
682 iter_can_seek_beginning
=iter_can_seek_beginning
,
683 iter_can_seek_forward
=iter_can_seek_forward
,
686 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_forward_seekable(
689 # Test the case where:
691 # - can_seek_ns_from_origin: returns False
692 # - seek_ns_from_origin provided: Don't care
693 # - can the iterator seek beginning: Yes
694 # - can the iterator seek forward: Yes
696 # We expect iter.can_seek_ns_from_origin to return True.
697 for user_seek_ns_from_origin_provided
in (False, True):
698 self
._can
_seek
_ns
_from
_origin
_test
(
699 expected_outcome
=True,
700 user_can_seek_ns_from_origin_ret_val
=False,
701 user_seek_ns_from_origin_provided
=user_seek_ns_from_origin_provided
,
702 iter_can_seek_beginning
=True,
703 iter_can_seek_forward
=True,
706 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_not_forward_seekable(
709 # Test the case where:
711 # - can_seek_ns_from_origin: returns False
712 # - seek_ns_from_origin provided: Don't care
713 # - can the iterator seek beginning: Yes
714 # - can the iterator seek forward: No
716 # We expect iter.can_seek_ns_from_origin to return False.
717 for user_seek_ns_from_origin_provided
in (False, True):
718 self
._can
_seek
_ns
_from
_origin
_test
(
719 expected_outcome
=False,
720 user_can_seek_ns_from_origin_ret_val
=False,
721 user_seek_ns_from_origin_provided
=user_seek_ns_from_origin_provided
,
722 iter_can_seek_beginning
=True,
723 iter_can_seek_forward
=False,
726 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_forward_seekable(
729 # Test the case where:
731 # - can_seek_ns_from_origin: returns False
732 # - seek_ns_from_origin provided: Don't care
733 # - can the iterator seek beginning: No
734 # - can the iterator seek forward: Yes
736 # We expect iter.can_seek_ns_from_origin to return False.
737 # for user_seek_ns_from_origin_provided in (False, True):
738 self
._can
_seek
_ns
_from
_origin
_test
(
739 expected_outcome
=False,
740 user_can_seek_ns_from_origin_ret_val
=False,
741 user_seek_ns_from_origin_provided
=False,
742 iter_can_seek_beginning
=False,
743 iter_can_seek_forward
=True,
746 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_not_forward_seekable(
749 # Test the case where:
751 # - can_seek_ns_from_origin: returns False
752 # - seek_ns_from_origin provided: Don't care
753 # - can the iterator seek beginning: No
754 # - can the iterator seek forward: No
756 # We expect iter.can_seek_ns_from_origin to return False.
757 for user_seek_ns_from_origin_provided
in (False, True):
758 self
._can
_seek
_ns
_from
_origin
_test
(
759 expected_outcome
=False,
760 user_can_seek_ns_from_origin_ret_val
=False,
761 user_seek_ns_from_origin_provided
=user_seek_ns_from_origin_provided
,
762 iter_can_seek_beginning
=False,
763 iter_can_seek_forward
=False,
766 def test_no_can_seek_ns_from_origin_seek_ns_from_origin(self
):
767 # Test the case where:
769 # - can_seek_ns_from_origin: Not provided
770 # - seek_ns_from_origin provided: Yes
771 # - can the iterator seek beginning: Don't care
772 # - can the iterator seek forward: Don't care
774 # We expect iter.can_seek_ns_from_origin to return True.
775 for iter_can_seek_beginning
in (False, True):
776 for iter_can_seek_forward
in (False, True):
777 self
._can
_seek
_ns
_from
_origin
_test
(
778 expected_outcome
=True,
779 user_can_seek_ns_from_origin_ret_val
=None,
780 user_seek_ns_from_origin_provided
=True,
781 iter_can_seek_beginning
=iter_can_seek_beginning
,
782 iter_can_seek_forward
=iter_can_seek_forward
,
785 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_forward_seekable(
788 # Test the case where:
790 # - can_seek_ns_from_origin: Not provided
791 # - seek_ns_from_origin provided: Not provided
792 # - can the iterator seek beginning: Yes
793 # - can the iterator seek forward: Yes
795 # We expect iter.can_seek_ns_from_origin to return True.
796 self
._can
_seek
_ns
_from
_origin
_test
(
797 expected_outcome
=True,
798 user_can_seek_ns_from_origin_ret_val
=None,
799 user_seek_ns_from_origin_provided
=False,
800 iter_can_seek_beginning
=True,
801 iter_can_seek_forward
=True,
804 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_not_forward_seekable(
807 # Test the case where:
809 # - can_seek_ns_from_origin: Not provided
810 # - seek_ns_from_origin provided: Not provided
811 # - can the iterator seek beginning: Yes
812 # - can the iterator seek forward: No
814 # We expect iter.can_seek_ns_from_origin to return False.
815 self
._can
_seek
_ns
_from
_origin
_test
(
816 expected_outcome
=False,
817 user_can_seek_ns_from_origin_ret_val
=None,
818 user_seek_ns_from_origin_provided
=False,
819 iter_can_seek_beginning
=True,
820 iter_can_seek_forward
=False,
823 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_forward_seekable(
826 # Test the case where:
828 # - can_seek_ns_from_origin: Not provided
829 # - seek_ns_from_origin provided: Not provided
830 # - can the iterator seek beginning: No
831 # - can the iterator seek forward: Yes
833 # We expect iter.can_seek_ns_from_origin to return False.
834 self
._can
_seek
_ns
_from
_origin
_test
(
835 expected_outcome
=False,
836 user_can_seek_ns_from_origin_ret_val
=None,
837 user_seek_ns_from_origin_provided
=False,
838 iter_can_seek_beginning
=False,
839 iter_can_seek_forward
=True,
842 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_not_forward_seekable(
845 # Test the case where:
847 # - can_seek_ns_from_origin: Not provided
848 # - seek_ns_from_origin provided: Not provided
849 # - can the iterator seek beginning: No
850 # - can the iterator seek forward: No
852 # We expect iter.can_seek_ns_from_origin to return False.
853 self
._can
_seek
_ns
_from
_origin
_test
(
854 expected_outcome
=False,
855 user_can_seek_ns_from_origin_ret_val
=None,
856 user_seek_ns_from_origin_provided
=False,
857 iter_can_seek_beginning
=False,
858 iter_can_seek_forward
=False,
861 def _can_seek_ns_from_origin_test(
864 user_can_seek_ns_from_origin_ret_val
,
865 user_seek_ns_from_origin_provided
,
866 iter_can_seek_beginning
,
867 iter_can_seek_forward
,
869 class MySink(bt2
._UserSinkComponent
):
870 def __init__(self
, config
, params
, obj
):
871 self
._add
_input
_port
('in')
873 def _user_graph_is_configured(self
):
874 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
875 self
._input
_ports
['in']
878 def _user_consume(self
):
879 nonlocal can_seek_ns_from_origin
880 can_seek_ns_from_origin
= self
._msg
_iter
.can_seek_ns_from_origin(
881 passed_ns_from_origin
884 if user_can_seek_ns_from_origin_ret_val
is not None:
886 def user_can_seek_ns_from_origin(self
, ns_from_origin
):
887 nonlocal received_ns_from_origin
888 received_ns_from_origin
= ns_from_origin
889 return user_can_seek_ns_from_origin_ret_val
892 user_can_seek_ns_from_origin
= None
894 if user_seek_ns_from_origin_provided
:
896 def user_seek_ns_from_origin(self
, ns_from_origin
):
900 user_seek_ns_from_origin
= None
902 if iter_can_seek_beginning
:
904 def user_seek_beginning(self
):
908 user_seek_beginning
= None
910 graph
= _setup_seek_test(
912 user_can_seek_ns_from_origin
=user_can_seek_ns_from_origin
,
913 user_seek_ns_from_origin
=user_seek_ns_from_origin
,
914 user_seek_beginning
=user_seek_beginning
,
915 can_seek_forward
=iter_can_seek_forward
,
918 passed_ns_from_origin
= 77
919 received_ns_from_origin
= None
920 can_seek_ns_from_origin
= None
922 self
.assertIs(can_seek_ns_from_origin
, expected_outcome
)
924 if user_can_seek_ns_from_origin_ret_val
is not None:
925 self
.assertEqual(received_ns_from_origin
, passed_ns_from_origin
)
927 def test_can_seek_ns_from_origin_user_error(self
):
928 class MySink(bt2
._UserSinkComponent
):
929 def __init__(self
, config
, params
, obj
):
930 self
._add
_input
_port
('in')
932 def _user_graph_is_configured(self
):
933 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
934 self
._input
_ports
['in']
937 def _user_consume(self
):
938 # This is expected to raise.
939 self
._msg
_iter
.can_seek_ns_from_origin(2)
941 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
942 raise ValueError('Joutel')
944 graph
= _setup_seek_test(
945 MySink
, user_can_seek_ns_from_origin
=_user_can_seek_ns_from_origin
948 with self
.assertRaises(bt2
._Error
) as ctx
:
951 cause
= ctx
.exception
[0]
952 self
.assertIn('ValueError: Joutel', cause
.message
)
954 def test_can_seek_ns_from_origin_wrong_return_value(self
):
955 class MySink(bt2
._UserSinkComponent
):
956 def __init__(self
, config
, params
, obj
):
957 self
._add
_input
_port
('in')
959 def _user_graph_is_configured(self
):
960 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
961 self
._input
_ports
['in']
964 def _user_consume(self
):
965 # This is expected to raise.
966 self
._msg
_iter
.can_seek_ns_from_origin(2)
968 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
971 graph
= _setup_seek_test(
972 MySink
, user_can_seek_ns_from_origin
=_user_can_seek_ns_from_origin
975 with self
.assertRaises(bt2
._Error
) as ctx
:
978 cause
= ctx
.exception
[0]
979 self
.assertIn("TypeError: 'str' is not a 'bool' object", cause
.message
)
981 def test_seek_ns_from_origin(self
):
982 class MySink(bt2
._UserSinkComponent
):
983 def __init__(self
, config
, params
, obj
):
984 self
._add
_input
_port
('in')
986 def _user_graph_is_configured(self
):
987 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
988 self
._input
_ports
['in']
991 def _user_consume(self
):
992 self
._msg
_iter
.seek_ns_from_origin(17)
994 def _user_seek_ns_from_origin(self
, ns_from_origin
):
995 nonlocal actual_ns_from_origin
996 actual_ns_from_origin
= ns_from_origin
998 graph
= _setup_seek_test(
999 MySink
, user_seek_ns_from_origin
=_user_seek_ns_from_origin
1002 actual_ns_from_origin
= None
1004 self
.assertEqual(actual_ns_from_origin
, 17)
1007 if __name__
== '__main__':