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.
26 class _MyIter(bt2
._UserMessageIterator
):
27 def __init__(self
, self_output_port
):
31 def _build_meta(self
):
32 self
._tc
= self
._component
._create
_trace
_class
()
34 self
._sc
= self
._tc
.create_stream_class(supports_packets
=True)
35 self
._ec
= self
._sc
.create_event_class(name
='salut')
36 self
._my
_int
_ft
= self
._tc
.create_signed_integer_field_class(32)
37 payload_ft
= self
._tc
.create_structure_field_class()
38 payload_ft
+= [('my_int', self
._my
_int
_ft
)]
39 self
._ec
.payload_field_type
= payload_ft
40 self
._stream
= self
._t
.create_stream(self
._sc
)
41 self
._packet
= self
._stream
.create_packet()
43 def _create_event(self
, value
):
45 ev
.payload_field
['my_int'] = value
46 ev
.packet
= self
._packet
50 class GraphTestCase(unittest
.TestCase
):
52 self
._graph
= bt2
.Graph()
57 def test_create_empty(self
):
60 def test_add_component_user_cls(self
):
61 class MySink(bt2
._UserSinkComponent
):
62 def _user_consume(self
):
65 comp
= self
._graph
.add_component(MySink
, 'salut')
66 self
.assertEqual(comp
.name
, 'salut')
68 def test_add_component_gen_cls(self
):
69 class MySink(bt2
._UserSinkComponent
):
70 def _user_consume(self
):
73 comp
= self
._graph
.add_component(MySink
, 'salut')
75 comp2
= self
._graph
.add_component(comp
.cls
, 'salut2')
76 self
.assertEqual(comp2
.name
, 'salut2')
78 def test_add_component_params(self
):
81 class MySink(bt2
._UserSinkComponent
):
82 def __init__(self
, params
, obj
):
86 def _user_consume(self
):
89 params
= {'hello': 23, 'path': '/path/to/stuff'}
90 comp
= self
._graph
.add_component(MySink
, 'salut', params
)
91 self
.assertEqual(params
, comp_params
)
94 def test_add_component_obj_python_comp_cls(self
):
97 class MySink(bt2
._UserSinkComponent
):
98 def __init__(self
, params
, obj
):
102 def _user_consume(self
):
106 comp
= self
._graph
.add_component(MySink
, 'salut', obj
=obj
)
107 self
.assertIs(comp_obj
, obj
)
110 def test_add_component_obj_none_python_comp_cls(self
):
113 class MySink(bt2
._UserSinkComponent
):
114 def __init__(self
, params
, obj
):
118 def _user_consume(self
):
121 comp
= self
._graph
.add_component(MySink
, 'salut')
122 self
.assertIsNone(comp_obj
)
125 def test_add_component_obj_non_python_comp_cls(self
):
128 plugin
= bt2
.find_plugin('text', find_in_user_dir
=False, find_in_sys_dir
=False)
129 assert plugin
is not None
130 cc
= plugin
.source_component_classes
['dmesg']
131 assert cc
is not None
133 with self
.assertRaises(ValueError):
134 comp
= self
._graph
.add_component(cc
, 'salut', obj
=57)
136 def test_add_component_invalid_cls_type(self
):
137 with self
.assertRaises(TypeError):
138 self
._graph
.add_component(int, 'salut')
140 def test_add_component_invalid_logging_level_type(self
):
141 class MySink(bt2
._UserSinkComponent
):
142 def _user_consume(self
):
145 with self
.assertRaises(TypeError):
146 self
._graph
.add_component(MySink
, 'salut', logging_level
='yo')
148 def test_add_component_invalid_logging_level_value(self
):
149 class MySink(bt2
._UserSinkComponent
):
150 def _user_consume(self
):
153 with self
.assertRaises(ValueError):
154 self
._graph
.add_component(MySink
, 'salut', logging_level
=12345)
156 def test_add_component_logging_level(self
):
157 class MySink(bt2
._UserSinkComponent
):
158 def _user_consume(self
):
161 comp
= self
._graph
.add_component(
162 MySink
, 'salut', logging_level
=bt2
.LoggingLevel
.DEBUG
164 self
.assertEqual(comp
.logging_level
, bt2
.LoggingLevel
.DEBUG
)
166 def test_connect_ports(self
):
167 class MyIter(bt2
._UserMessageIterator
):
171 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
172 def __init__(self
, params
, obj
):
173 self
._add
_output
_port
('out')
175 class MySink(bt2
._UserSinkComponent
):
176 def __init__(self
, params
, obj
):
177 self
._add
_input
_port
('in')
179 def _user_consume(self
):
182 src
= self
._graph
.add_component(MySource
, 'src')
183 sink
= self
._graph
.add_component(MySink
, 'sink')
185 conn
= self
._graph
.connect_ports(
186 src
.output_ports
['out'], sink
.input_ports
['in']
188 self
.assertTrue(src
.output_ports
['out'].is_connected
)
189 self
.assertTrue(sink
.input_ports
['in'].is_connected
)
190 self
.assertEqual(src
.output_ports
['out'].connection
.addr
, conn
.addr
)
191 self
.assertEqual(sink
.input_ports
['in'].connection
.addr
, conn
.addr
)
193 def test_connect_ports_invalid_direction(self
):
194 class MyIter(bt2
._UserMessageIterator
):
198 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
199 def __init__(self
, params
, obj
):
200 self
._add
_output
_port
('out')
202 class MySink(bt2
._UserSinkComponent
):
203 def __init__(self
, params
, obj
):
204 self
._add
_input
_port
('in')
206 def _user_consume(self
):
209 src
= self
._graph
.add_component(MySource
, 'src')
210 sink
= self
._graph
.add_component(MySink
, 'sink')
212 with self
.assertRaises(TypeError):
213 conn
= self
._graph
.connect_ports(
214 sink
.input_ports
['in'], src
.output_ports
['out']
217 def test_add_interrupter(self
):
218 class MyIter(bt2
._UserMessageIterator
):
222 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
223 def __init__(self
, params
, obj
):
224 self
._add
_output
_port
('out')
226 class MySink(bt2
._UserSinkComponent
):
227 def __init__(self
, params
, obj
):
228 self
._add
_input
_port
('in')
230 def _user_consume(self
):
233 def _user_graph_is_configured(self
):
234 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
235 self
._input
_ports
['in']
238 # add two interrupters, set one of them
239 interrupter1
= bt2
.Interrupter()
240 interrupter2
= bt2
.Interrupter()
241 self
._graph
.add_interrupter(interrupter1
)
242 src
= self
._graph
.add_component(MySource
, 'src')
243 sink
= self
._graph
.add_component(MySink
, 'sink')
244 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
245 self
._graph
.add_interrupter(interrupter2
)
247 with self
.assertRaises(bt2
._Error
):
252 with self
.assertRaises(bt2
.TryAgain
):
257 with self
.assertRaises(bt2
._Error
):
260 # Test that Graph.run() raises bt2.Interrupted if the graph gets
261 # interrupted during execution.
262 def test_interrupt_while_running(self
):
263 class MyIter(_MyIter
):
265 return self
._create
_stream
_beginning
_message
(self
._stream
)
267 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
268 def __init__(self
, params
, obj
):
269 self
._add
_output
_port
('out')
271 class MySink(bt2
._UserSinkComponent
):
272 def __init__(self
, params
, obj
):
273 self
._add
_input
_port
('in')
275 def _user_consume(self
):
276 # Pretend that somebody asynchronously interrupted the graph.
279 return next(self
._msg
_iter
)
281 def _user_graph_is_configured(self
):
282 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
283 self
._input
_ports
['in']
287 up
= self
._graph
.add_component(MySource
, 'down')
288 down
= self
._graph
.add_component(MySink
, 'up')
289 self
._graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
291 with self
.assertRaises(bt2
.TryAgain
):
295 class MyIter(_MyIter
):
301 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
303 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
305 msg
= self
._create
_packet
_end
_message
(self
._packet
)
307 msg
= self
._create
_stream
_end
_message
(self
._stream
)
309 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
314 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
315 def __init__(self
, params
, obj
):
316 self
._add
_output
_port
('out')
318 class MySink(bt2
._UserSinkComponent
):
319 def __init__(self
, params
, obj
):
320 self
._input
_port
= self
._add
_input
_port
('in')
323 def _user_consume(comp_self
):
324 msg
= next(comp_self
._msg
_iter
)
326 if comp_self
._at
== 0:
327 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
328 elif comp_self
._at
== 1:
329 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
330 elif comp_self
._at
>= 2 and comp_self
._at
<= 6:
331 self
.assertIsInstance(msg
, bt2
._EventMessage
)
332 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
333 elif comp_self
._at
== 7:
334 self
.assertIsInstance(msg
, bt2
._PacketEndMessage
)
335 elif comp_self
._at
== 8:
336 self
.assertIsInstance(msg
, bt2
._StreamEndMessage
)
340 def _user_graph_is_configured(self
):
341 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
345 src
= self
._graph
.add_component(MySource
, 'src')
346 sink
= self
._graph
.add_component(MySink
, 'sink')
347 conn
= self
._graph
.connect_ports(
348 src
.output_ports
['out'], sink
.input_ports
['in']
352 def test_run_once(self
):
353 class MyIter(_MyIter
):
356 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
357 def __init__(self
, params
, obj
):
358 self
._add
_output
_port
('out')
360 class MySink(bt2
._UserSinkComponent
):
361 def __init__(self
, params
, obj
):
362 self
._input
_port
= self
._add
_input
_port
('in')
364 def _user_consume(comp_self
):
370 src
= self
._graph
.add_component(MySource
, 'src')
371 sink
= self
._graph
.add_component(MySink
, 'sink')
372 conn
= self
._graph
.connect_ports(
373 src
.output_ports
['out'], sink
.input_ports
['in']
376 with self
.assertRaises(bt2
.TryAgain
):
377 self
._graph
.run_once()
379 self
.assertEqual(run_count
, 1)
381 def test_run_once_stops(self
):
382 class MyIter(_MyIter
):
385 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
386 def __init__(self
, params
, obj
):
387 self
._add
_output
_port
('out')
389 class MySink(bt2
._UserSinkComponent
):
390 def __init__(self
, params
, obj
):
391 self
._input
_port
= self
._add
_input
_port
('in')
393 def _user_consume(comp_self
):
396 src
= self
._graph
.add_component(MySource
, 'src')
397 sink
= self
._graph
.add_component(MySink
, 'sink')
398 conn
= self
._graph
.connect_ports(
399 src
.output_ports
['out'], sink
.input_ports
['in']
402 with self
.assertRaises(bt2
.Stop
):
403 self
._graph
.run_once()
405 def test_run_again(self
):
406 class MyIter(_MyIter
):
412 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
414 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
416 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
421 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
422 def __init__(self
, params
, obj
):
423 self
._add
_output
_port
('out')
425 class MySink(bt2
._UserSinkComponent
):
426 def __init__(self
, params
, obj
):
427 self
._input
_port
= self
._add
_input
_port
('in')
430 def _user_consume(comp_self
):
431 msg
= next(comp_self
._msg
_iter
)
432 if comp_self
._at
== 0:
433 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
434 elif comp_self
._at
== 1:
435 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
436 elif comp_self
._at
== 2:
437 self
.assertIsInstance(msg
, bt2
._EventMessage
)
444 def _user_graph_is_configured(self
):
445 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
449 src
= self
._graph
.add_component(MySource
, 'src')
450 sink
= self
._graph
.add_component(MySink
, 'sink')
451 conn
= self
._graph
.connect_ports(
452 src
.output_ports
['out'], sink
.input_ports
['in']
455 with self
.assertRaises(bt2
.TryAgain
):
458 def test_run_error(self
):
459 raised_in_sink
= False
461 class MyIter(_MyIter
):
463 # If this gets called after the sink raised an exception, it is
465 nonlocal raised_in_sink
466 assert raised_in_sink
is False
469 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
471 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
472 elif self
._at
== 2 or self
._at
== 3:
473 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
479 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
480 def __init__(self
, params
, obj
):
481 self
._add
_output
_port
('out')
483 class MySink(bt2
._UserSinkComponent
):
484 def __init__(self
, params
, obj
):
485 self
._input
_port
= self
._add
_input
_port
('in')
488 def _user_consume(comp_self
):
489 msg
= next(comp_self
._msg
_iter
)
490 if comp_self
._at
== 0:
491 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
492 elif comp_self
._at
== 1:
493 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
494 elif comp_self
._at
== 2:
495 self
.assertIsInstance(msg
, bt2
._EventMessage
)
496 elif comp_self
._at
== 3:
497 nonlocal raised_in_sink
498 raised_in_sink
= True
499 raise RuntimeError('error!')
503 def _user_graph_is_configured(self
):
504 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
508 src
= self
._graph
.add_component(MySource
, 'src')
509 sink
= self
._graph
.add_component(MySink
, 'sink')
510 conn
= self
._graph
.connect_ports(
511 src
.output_ports
['out'], sink
.input_ports
['in']
514 with self
.assertRaises(bt2
._Error
):
517 def test_listeners(self
):
518 class MyIter(bt2
._UserMessageIterator
):
522 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
523 def __init__(self
, params
, obj
):
524 self
._add
_output
_port
('out')
525 self
._add
_output
_port
('zero')
527 class MySink(bt2
._UserSinkComponent
):
528 def __init__(self
, params
, obj
):
529 self
._add
_input
_port
('in')
531 def _user_consume(self
):
534 def _user_port_connected(self
, port
, other_port
):
535 self
._add
_input
_port
('taste')
537 def port_added_listener(component
, port
):
539 calls
.append((port_added_listener
, component
, port
))
541 def ports_connected_listener(
542 upstream_component
, upstream_port
, downstream_component
, downstream_port
547 ports_connected_listener
,
550 downstream_component
,
556 self
._graph
.add_port_added_listener(port_added_listener
)
557 self
._graph
.add_ports_connected_listener(ports_connected_listener
)
558 src
= self
._graph
.add_component(MySource
, 'src')
559 sink
= self
._graph
.add_component(MySink
, 'sink')
560 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
562 self
.assertEqual(len(calls
), 5)
564 self
.assertIs(calls
[0][0], port_added_listener
)
565 self
.assertEqual(calls
[0][1].name
, 'src')
566 self
.assertEqual(calls
[0][2].name
, 'out')
568 self
.assertIs(calls
[1][0], port_added_listener
)
569 self
.assertEqual(calls
[1][1].name
, 'src')
570 self
.assertEqual(calls
[1][2].name
, 'zero')
572 self
.assertIs(calls
[2][0], port_added_listener
)
573 self
.assertEqual(calls
[2][1].name
, 'sink')
574 self
.assertEqual(calls
[2][2].name
, 'in')
576 self
.assertIs(calls
[3][0], port_added_listener
)
577 self
.assertEqual(calls
[3][1].name
, 'sink')
578 self
.assertEqual(calls
[3][2].name
, 'taste')
580 self
.assertIs(calls
[4][0], ports_connected_listener
)
581 self
.assertEqual(calls
[4][1].name
, 'src')
582 self
.assertEqual(calls
[4][2].name
, 'out')
583 self
.assertEqual(calls
[4][3].name
, 'sink')
584 self
.assertEqual(calls
[4][4].name
, 'in')
586 def test_invalid_listeners(self
):
587 class MyIter(bt2
._UserMessageIterator
):
591 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
592 def __init__(self
, params
, obj
):
593 self
._add
_output
_port
('out')
594 self
._add
_output
_port
('zero')
596 class MySink(bt2
._UserSinkComponent
):
597 def __init__(self
, params
, obj
):
598 self
._add
_input
_port
('in')
600 def _user_consume(self
):
603 def _user_port_connected(self
, port
, other_port
):
604 self
._add
_input
_port
('taste')
606 with self
.assertRaises(TypeError):
607 self
._graph
.add_port_added_listener(1234)
608 with self
.assertRaises(TypeError):
609 self
._graph
.add_ports_connected_listener(1234)
611 def test_raise_in_component_init(self
):
612 class MySink(bt2
._UserSinkComponent
):
613 def __init__(self
, params
, obj
):
614 raise ValueError('oops!')
616 def _user_consume(self
):
621 with self
.assertRaises(bt2
._Error
):
622 graph
.add_component(MySink
, 'comp')
624 def test_raise_in_port_added_listener(self
):
625 class MySink(bt2
._UserSinkComponent
):
626 def __init__(self
, params
, obj
):
627 self
._add
_input
_port
('in')
629 def _user_consume(self
):
632 def port_added_listener(component
, port
):
633 raise ValueError('oh noes!')
636 graph
.add_port_added_listener(port_added_listener
)
638 with self
.assertRaises(bt2
._Error
):
639 graph
.add_component(MySink
, 'comp')
641 def test_raise_in_ports_connected_listener(self
):
642 class MyIter(bt2
._UserMessageIterator
):
646 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
647 def __init__(self
, params
, obj
):
648 self
._add
_output
_port
('out')
650 class MySink(bt2
._UserSinkComponent
):
651 def __init__(self
, params
, obj
):
652 self
._add
_input
_port
('in')
654 def _user_consume(self
):
657 def ports_connected_listener(
658 upstream_component
, upstream_port
, downstream_component
, downstream_port
660 raise ValueError('oh noes!')
663 graph
.add_ports_connected_listener(ports_connected_listener
)
664 up
= graph
.add_component(MySource
, 'down')
665 down
= graph
.add_component(MySink
, 'up')
667 with self
.assertRaises(bt2
._Error
):
668 graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
This page took 0.058634 seconds and 4 git commands to generate.