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_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",
473 _setup_seek_test(SimpleSink
, user_can_seek_beginning
=lambda: None)
475 def test_can_seek_beginning(self
):
476 class MySink(bt2
._UserSinkComponent
):
477 def __init__(self
, config
, params
, obj
):
478 self
._add
_input
_port
('in')
480 def _user_graph_is_configured(self
):
481 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
482 self
._input
_ports
['in']
485 def _user_consume(self
):
486 nonlocal can_seek_beginning
487 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
489 def _user_can_seek_beginning(self
):
490 nonlocal input_port_iter_can_seek_beginning
491 return input_port_iter_can_seek_beginning
493 graph
= _setup_seek_test(
495 user_can_seek_beginning
=_user_can_seek_beginning
,
496 user_seek_beginning
=lambda: None,
499 input_port_iter_can_seek_beginning
= True
500 can_seek_beginning
= None
502 self
.assertIs(can_seek_beginning
, True)
504 input_port_iter_can_seek_beginning
= False
505 can_seek_beginning
= None
507 self
.assertIs(can_seek_beginning
, False)
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
):
513 def __init__(self
, config
, params
, obj
):
514 self
._add
_input
_port
('in')
516 def _user_graph_is_configured(self
):
517 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
518 self
._input
_ports
['in']
521 def _user_consume(self
):
522 nonlocal can_seek_beginning
523 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
525 def _user_seek_beginning(self
):
528 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
529 can_seek_beginning
= None
531 self
.assertIs(can_seek_beginning
, True)
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
):
537 def __init__(self
, config
, params
, obj
):
538 self
._add
_input
_port
('in')
540 def _user_graph_is_configured(self
):
541 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
542 self
._input
_ports
['in']
545 def _user_consume(self
):
546 nonlocal can_seek_beginning
547 can_seek_beginning
= self
._msg
_iter
.can_seek_beginning()
549 graph
= _setup_seek_test(MySink
)
550 can_seek_beginning
= None
552 self
.assertIs(can_seek_beginning
, False)
554 def test_can_seek_beginning_user_error(self
):
555 class MySink(bt2
._UserSinkComponent
):
556 def __init__(self
, config
, params
, obj
):
557 self
._add
_input
_port
('in')
559 def _user_graph_is_configured(self
):
560 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
561 self
._input
_ports
['in']
564 def _user_consume(self
):
565 # This is expected to raise.
566 self
._msg
_iter
.can_seek_beginning()
568 def _user_can_seek_beginning(self
):
569 raise ValueError('moustiquaire')
571 graph
= _setup_seek_test(
573 user_can_seek_beginning
=_user_can_seek_beginning
,
574 user_seek_beginning
=lambda: None,
577 with self
.assertRaises(bt2
._Error
) as ctx
:
580 cause
= ctx
.exception
[0]
581 self
.assertIn('ValueError: moustiquaire', cause
.message
)
583 def test_can_seek_beginning_wrong_return_value(self
):
584 class MySink(bt2
._UserSinkComponent
):
585 def __init__(self
, config
, params
, obj
):
586 self
._add
_input
_port
('in')
588 def _user_graph_is_configured(self
):
589 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
590 self
._input
_ports
['in']
593 def _user_consume(self
):
594 # This is expected to raise.
595 self
._msg
_iter
.can_seek_beginning()
597 def _user_can_seek_beginning(self
):
600 graph
= _setup_seek_test(
602 user_can_seek_beginning
=_user_can_seek_beginning
,
603 user_seek_beginning
=lambda: None,
606 with self
.assertRaises(bt2
._Error
) as ctx
:
609 cause
= ctx
.exception
[0]
610 self
.assertIn("TypeError: 'str' is not a 'bool' object", cause
.message
)
612 def test_seek_beginning(self
):
613 class MySink(bt2
._UserSinkComponent
):
614 def __init__(self
, config
, params
, obj
):
615 self
._add
_input
_port
('in')
617 def _user_graph_is_configured(self
):
618 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
619 self
._input
_ports
['in']
622 def _user_consume(self
):
623 nonlocal do_seek_beginning
626 if do_seek_beginning
:
627 self
._msg
_iter
.seek_beginning()
630 msg
= next(self
._msg
_iter
)
632 def _user_seek_beginning(self
):
636 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
639 do_seek_beginning
= False
641 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
645 self
.assertIs(type(msg
), bt2
._PacketBeginningMessageConst
)
648 do_seek_beginning
= True
652 do_seek_beginning
= False
654 self
.assertIs(type(msg
), bt2
._StreamBeginningMessageConst
)
656 def test_seek_beginning_user_error(self
):
657 class MySink(bt2
._UserSinkComponent
):
658 def __init__(self
, config
, params
, obj
):
659 self
._add
_input
_port
('in')
661 def _user_graph_is_configured(self
):
662 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
663 self
._input
_ports
['in']
666 def _user_consume(self
):
667 self
._msg
_iter
.seek_beginning()
669 def _user_seek_beginning(self
):
670 raise ValueError('ouch')
672 graph
= _setup_seek_test(MySink
, user_seek_beginning
=_user_seek_beginning
)
674 with self
.assertRaises(bt2
._Error
):
678 class UserMessageIteratorSeekNsFromOriginTestCase(unittest
.TestCase
):
679 def test_can_seek_ns_from_origin_without_seek_ns_from_origin(self
):
680 # Test the case where:
682 # - can_seek_ns_from_origin: Returns True (don't really care, as long
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",
694 self
._can
_seek
_ns
_from
_origin
_test
(
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
,
702 def test_can_seek_ns_from_origin_returns_true(self
):
703 # Test the case where:
705 # - can_seek_ns_from_origin: returns True
706 # - seek_ns_from_origin provided: Yes
707 # - can the iterator seek beginning: Don't care
708 # - can the iterator seek forward: Don't care
710 # We expect iter.can_seek_ns_from_origin to return True.
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
,
721 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_forward_seekable(
724 # Test the case where:
726 # - can_seek_ns_from_origin: returns False
727 # - seek_ns_from_origin provided: Yes
728 # - can the iterator seek beginning: Yes
729 # - can the iterator seek forward: Yes
731 # We expect iter.can_seek_ns_from_origin to return True.
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,
740 def test_can_seek_ns_from_origin_returns_false_can_seek_beginning_not_forward_seekable(
743 # Test the case where:
745 # - can_seek_ns_from_origin: returns False
746 # - seek_ns_from_origin provided: Yes
747 # - can the iterator seek beginning: Yes
748 # - can the iterator seek forward: No
750 # We expect iter.can_seek_ns_from_origin to return False.
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,
759 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_forward_seekable(
762 # Test the case where:
764 # - can_seek_ns_from_origin: returns False
765 # - seek_ns_from_origin provided: Yes
766 # - can the iterator seek beginning: No
767 # - can the iterator seek forward: Yes
769 # We expect iter.can_seek_ns_from_origin to return False.
770 self
._can
_seek
_ns
_from
_origin
_test
(
771 expected_outcome
=False,
772 user_can_seek_ns_from_origin_ret_val
=False,
773 user_seek_ns_from_origin_provided
=True,
774 iter_can_seek_beginning
=False,
775 iter_can_seek_forward
=True,
778 def test_can_seek_ns_from_origin_returns_false_cant_seek_beginning_not_forward_seekable(
781 # Test the case where:
783 # - can_seek_ns_from_origin: returns False
784 # - seek_ns_from_origin provided: Yes
785 # - can the iterator seek beginning: No
786 # - can the iterator seek forward: No
788 # We expect iter.can_seek_ns_from_origin to return False.
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,
797 def test_no_can_seek_ns_from_origin_seek_ns_from_origin(self
):
798 # Test the case where:
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
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
,
816 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_forward_seekable(
819 # Test the case where:
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
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,
835 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_can_seek_beginning_not_forward_seekable(
838 # Test the case where:
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
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,
854 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_forward_seekable(
857 # Test the case where:
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
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,
873 def test_no_can_seek_ns_from_origin_no_seek_ns_from_origin_cant_seek_beginning_not_forward_seekable(
876 # Test the case where:
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
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,
892 def _can_seek_ns_from_origin_test(
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
,
900 class MySink(bt2
._UserSinkComponent
):
901 def __init__(self
, config
, params
, obj
):
902 self
._add
_input
_port
('in')
904 def _user_graph_is_configured(self
):
905 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
906 self
._input
_ports
['in']
909 def _user_consume(self
):
910 nonlocal can_seek_ns_from_origin
911 can_seek_ns_from_origin
= self
._msg
_iter
.can_seek_ns_from_origin(
912 passed_ns_from_origin
915 if user_can_seek_ns_from_origin_ret_val
is not None:
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
923 user_can_seek_ns_from_origin
= None
925 if user_seek_ns_from_origin_provided
:
927 def user_seek_ns_from_origin(self
, ns_from_origin
):
931 user_seek_ns_from_origin
= None
933 if iter_can_seek_beginning
:
935 def user_seek_beginning(self
):
939 user_seek_beginning
= None
941 graph
= _setup_seek_test(
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
,
949 passed_ns_from_origin
= 77
950 received_ns_from_origin
= None
951 can_seek_ns_from_origin
= None
953 self
.assertIs(can_seek_ns_from_origin
, expected_outcome
)
955 if user_can_seek_ns_from_origin_ret_val
is not None:
956 self
.assertEqual(received_ns_from_origin
, passed_ns_from_origin
)
958 def test_can_seek_ns_from_origin_user_error(self
):
959 class MySink(bt2
._UserSinkComponent
):
960 def __init__(self
, config
, params
, obj
):
961 self
._add
_input
_port
('in')
963 def _user_graph_is_configured(self
):
964 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
965 self
._input
_ports
['in']
968 def _user_consume(self
):
969 # This is expected to raise.
970 self
._msg
_iter
.can_seek_ns_from_origin(2)
972 def _user_can_seek_ns_from_origin(self
, ns_from_origin
):
973 raise ValueError('Joutel')
975 graph
= _setup_seek_test(
977 user_can_seek_ns_from_origin
=_user_can_seek_ns_from_origin
,
978 user_seek_ns_from_origin
=lambda: None,
981 with self
.assertRaises(bt2
._Error
) as ctx
:
984 cause
= ctx
.exception
[0]
985 self
.assertIn('ValueError: Joutel', cause
.message
)
987 def test_can_seek_ns_from_origin_wrong_return_value(self
):
988 class MySink(bt2
._UserSinkComponent
):
989 def __init__(self
, config
, params
, obj
):
990 self
._add
_input
_port
('in')
992 def _user_graph_is_configured(self
):
993 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
994 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
):
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("TypeError: 'str' is not a 'bool' object", cause
.message
)
1016 def test_seek_ns_from_origin(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
_input
_port
_message
_iterator
(
1023 self
._input
_ports
['in']
1026 def _user_consume(self
):
1027 self
._msg
_iter
.seek_ns_from_origin(17)
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
1033 graph
= _setup_seek_test(
1034 MySink
, user_seek_ns_from_origin
=_user_seek_ns_from_origin
1037 actual_ns_from_origin
= None
1039 self
.assertEqual(actual_ns_from_origin
, 17)
1042 if __name__
== '__main__':