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.
23 class _MyIter(bt2
._UserMessageIterator
):
24 def __init__(self
, self_output_port
):
28 def _build_meta(self
):
29 self
._tc
= self
._component
._create
_trace
_class
()
31 self
._sc
= self
._tc
.create_stream_class(supports_packets
=True)
32 self
._ec
= self
._sc
.create_event_class(name
='salut')
33 self
._my
_int
_ft
= self
._tc
.create_signed_integer_field_class(32)
34 payload_ft
= self
._tc
.create_structure_field_class()
35 payload_ft
+= [('my_int', self
._my
_int
_ft
)]
36 self
._ec
.payload_field_type
= payload_ft
37 self
._stream
= self
._t
.create_stream(self
._sc
)
38 self
._packet
= self
._stream
.create_packet()
40 def _create_event(self
, value
):
42 ev
.payload_field
['my_int'] = value
43 ev
.packet
= self
._packet
47 class GraphTestCase(unittest
.TestCase
):
49 self
._graph
= bt2
.Graph()
54 def test_create_empty(self
):
57 def test_add_component_user_cls(self
):
58 class MySink(bt2
._UserSinkComponent
):
59 def _user_consume(self
):
62 comp
= self
._graph
.add_component(MySink
, 'salut')
63 self
.assertEqual(comp
.name
, 'salut')
65 def test_add_component_gen_cls(self
):
66 class MySink(bt2
._UserSinkComponent
):
67 def _user_consume(self
):
70 comp
= self
._graph
.add_component(MySink
, 'salut')
72 comp2
= self
._graph
.add_component(comp
.cls
, 'salut2')
73 self
.assertEqual(comp2
.name
, 'salut2')
75 def test_add_component_params(self
):
78 class MySink(bt2
._UserSinkComponent
):
79 def __init__(self
, params
, obj
):
83 def _user_consume(self
):
86 params
= {'hello': 23, 'path': '/path/to/stuff'}
87 comp
= self
._graph
.add_component(MySink
, 'salut', params
)
88 self
.assertEqual(params
, comp_params
)
91 def test_add_component_obj_python_comp_cls(self
):
94 class MySink(bt2
._UserSinkComponent
):
95 def __init__(self
, params
, obj
):
99 def _user_consume(self
):
103 comp
= self
._graph
.add_component(MySink
, 'salut', obj
=obj
)
104 self
.assertIs(comp_obj
, obj
)
107 def test_add_component_obj_none_python_comp_cls(self
):
110 class MySink(bt2
._UserSinkComponent
):
111 def __init__(self
, params
, obj
):
115 def _user_consume(self
):
118 comp
= self
._graph
.add_component(MySink
, 'salut')
119 self
.assertIsNone(comp_obj
)
122 def test_add_component_obj_non_python_comp_cls(self
):
125 plugin
= bt2
.find_plugin('text', find_in_user_dir
=False, find_in_sys_dir
=False)
126 assert plugin
is not None
127 cc
= plugin
.source_component_classes
['dmesg']
128 assert cc
is not None
130 with self
.assertRaises(ValueError):
131 comp
= self
._graph
.add_component(cc
, 'salut', obj
=57)
133 def test_add_component_invalid_cls_type(self
):
134 with self
.assertRaises(TypeError):
135 self
._graph
.add_component(int, 'salut')
137 def test_add_component_invalid_logging_level_type(self
):
138 class MySink(bt2
._UserSinkComponent
):
139 def _user_consume(self
):
142 with self
.assertRaises(TypeError):
143 self
._graph
.add_component(MySink
, 'salut', logging_level
='yo')
145 def test_add_component_invalid_logging_level_value(self
):
146 class MySink(bt2
._UserSinkComponent
):
147 def _user_consume(self
):
150 with self
.assertRaises(ValueError):
151 self
._graph
.add_component(MySink
, 'salut', logging_level
=12345)
153 def test_add_component_logging_level(self
):
154 class MySink(bt2
._UserSinkComponent
):
155 def _user_consume(self
):
158 comp
= self
._graph
.add_component(
159 MySink
, 'salut', logging_level
=bt2
.LoggingLevel
.DEBUG
161 self
.assertEqual(comp
.logging_level
, bt2
.LoggingLevel
.DEBUG
)
163 def test_connect_ports(self
):
164 class MyIter(bt2
._UserMessageIterator
):
168 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
169 def __init__(self
, params
, obj
):
170 self
._add
_output
_port
('out')
172 class MySink(bt2
._UserSinkComponent
):
173 def __init__(self
, params
, obj
):
174 self
._add
_input
_port
('in')
176 def _user_consume(self
):
179 src
= self
._graph
.add_component(MySource
, 'src')
180 sink
= self
._graph
.add_component(MySink
, 'sink')
182 conn
= self
._graph
.connect_ports(
183 src
.output_ports
['out'], sink
.input_ports
['in']
185 self
.assertTrue(src
.output_ports
['out'].is_connected
)
186 self
.assertTrue(sink
.input_ports
['in'].is_connected
)
187 self
.assertEqual(src
.output_ports
['out'].connection
.addr
, conn
.addr
)
188 self
.assertEqual(sink
.input_ports
['in'].connection
.addr
, conn
.addr
)
190 def test_connect_ports_invalid_direction(self
):
191 class MyIter(bt2
._UserMessageIterator
):
195 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
196 def __init__(self
, params
, obj
):
197 self
._add
_output
_port
('out')
199 class MySink(bt2
._UserSinkComponent
):
200 def __init__(self
, params
, obj
):
201 self
._add
_input
_port
('in')
203 def _user_consume(self
):
206 src
= self
._graph
.add_component(MySource
, 'src')
207 sink
= self
._graph
.add_component(MySink
, 'sink')
209 with self
.assertRaises(TypeError):
210 conn
= self
._graph
.connect_ports(
211 sink
.input_ports
['in'], src
.output_ports
['out']
214 def test_add_interrupter(self
):
215 class MyIter(bt2
._UserMessageIterator
):
219 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
220 def __init__(self
, params
, obj
):
221 self
._add
_output
_port
('out')
223 class MySink(bt2
._UserSinkComponent
):
224 def __init__(self
, params
, obj
):
225 self
._add
_input
_port
('in')
227 def _user_consume(self
):
230 def _user_graph_is_configured(self
):
231 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
232 self
._input
_ports
['in']
235 # add two interrupters, set one of them
236 interrupter1
= bt2
.Interrupter()
237 interrupter2
= bt2
.Interrupter()
238 self
._graph
.add_interrupter(interrupter1
)
239 src
= self
._graph
.add_component(MySource
, 'src')
240 sink
= self
._graph
.add_component(MySink
, 'sink')
241 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
242 self
._graph
.add_interrupter(interrupter2
)
244 with self
.assertRaises(bt2
._Error
):
249 with self
.assertRaises(bt2
.TryAgain
):
254 with self
.assertRaises(bt2
._Error
):
257 # Test that Graph.run() raises bt2.Interrupted if the graph gets
258 # interrupted during execution.
259 def test_interrupt_while_running(self
):
260 class MyIter(_MyIter
):
262 return self
._create
_stream
_beginning
_message
(self
._stream
)
264 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
265 def __init__(self
, params
, obj
):
266 self
._add
_output
_port
('out')
268 class MySink(bt2
._UserSinkComponent
):
269 def __init__(self
, params
, obj
):
270 self
._add
_input
_port
('in')
272 def _user_consume(self
):
273 # Pretend that somebody asynchronously interrupted the graph.
276 return next(self
._msg
_iter
)
278 def _user_graph_is_configured(self
):
279 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
280 self
._input
_ports
['in']
284 up
= self
._graph
.add_component(MySource
, 'down')
285 down
= self
._graph
.add_component(MySink
, 'up')
286 self
._graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
288 with self
.assertRaises(bt2
.TryAgain
):
292 class MyIter(_MyIter
):
298 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
300 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
302 msg
= self
._create
_packet
_end
_message
(self
._packet
)
304 msg
= self
._create
_stream
_end
_message
(self
._stream
)
306 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
311 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
312 def __init__(self
, params
, obj
):
313 self
._add
_output
_port
('out')
315 class MySink(bt2
._UserSinkComponent
):
316 def __init__(self
, params
, obj
):
317 self
._input
_port
= self
._add
_input
_port
('in')
320 def _user_consume(comp_self
):
321 msg
= next(comp_self
._msg
_iter
)
323 if comp_self
._at
== 0:
324 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
325 elif comp_self
._at
== 1:
326 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
327 elif comp_self
._at
>= 2 and comp_self
._at
<= 6:
328 self
.assertIsInstance(msg
, bt2
._EventMessage
)
329 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
330 elif comp_self
._at
== 7:
331 self
.assertIsInstance(msg
, bt2
._PacketEndMessage
)
332 elif comp_self
._at
== 8:
333 self
.assertIsInstance(msg
, bt2
._StreamEndMessage
)
337 def _user_graph_is_configured(self
):
338 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
342 src
= self
._graph
.add_component(MySource
, 'src')
343 sink
= self
._graph
.add_component(MySink
, 'sink')
344 conn
= self
._graph
.connect_ports(
345 src
.output_ports
['out'], sink
.input_ports
['in']
349 def test_run_once(self
):
350 class MyIter(_MyIter
):
353 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
354 def __init__(self
, params
, obj
):
355 self
._add
_output
_port
('out')
357 class MySink(bt2
._UserSinkComponent
):
358 def __init__(self
, params
, obj
):
359 self
._input
_port
= self
._add
_input
_port
('in')
361 def _user_consume(comp_self
):
367 src
= self
._graph
.add_component(MySource
, 'src')
368 sink
= self
._graph
.add_component(MySink
, 'sink')
369 conn
= self
._graph
.connect_ports(
370 src
.output_ports
['out'], sink
.input_ports
['in']
373 with self
.assertRaises(bt2
.TryAgain
):
374 self
._graph
.run_once()
376 self
.assertEqual(run_count
, 1)
378 def test_run_once_stops(self
):
379 class MyIter(_MyIter
):
382 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
383 def __init__(self
, params
, obj
):
384 self
._add
_output
_port
('out')
386 class MySink(bt2
._UserSinkComponent
):
387 def __init__(self
, params
, obj
):
388 self
._input
_port
= self
._add
_input
_port
('in')
390 def _user_consume(comp_self
):
393 src
= self
._graph
.add_component(MySource
, 'src')
394 sink
= self
._graph
.add_component(MySink
, 'sink')
395 conn
= self
._graph
.connect_ports(
396 src
.output_ports
['out'], sink
.input_ports
['in']
399 with self
.assertRaises(bt2
.Stop
):
400 self
._graph
.run_once()
402 def test_run_again(self
):
403 class MyIter(_MyIter
):
409 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
411 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
413 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
418 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
419 def __init__(self
, params
, obj
):
420 self
._add
_output
_port
('out')
422 class MySink(bt2
._UserSinkComponent
):
423 def __init__(self
, params
, obj
):
424 self
._input
_port
= self
._add
_input
_port
('in')
427 def _user_consume(comp_self
):
428 msg
= next(comp_self
._msg
_iter
)
429 if comp_self
._at
== 0:
430 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
431 elif comp_self
._at
== 1:
432 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
433 elif comp_self
._at
== 2:
434 self
.assertIsInstance(msg
, bt2
._EventMessage
)
441 def _user_graph_is_configured(self
):
442 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
446 src
= self
._graph
.add_component(MySource
, 'src')
447 sink
= self
._graph
.add_component(MySink
, 'sink')
448 conn
= self
._graph
.connect_ports(
449 src
.output_ports
['out'], sink
.input_ports
['in']
452 with self
.assertRaises(bt2
.TryAgain
):
455 def test_run_error(self
):
456 raised_in_sink
= False
458 class MyIter(_MyIter
):
460 # If this gets called after the sink raised an exception, it is
462 nonlocal raised_in_sink
463 assert raised_in_sink
is False
466 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
468 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
469 elif self
._at
== 2 or self
._at
== 3:
470 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
476 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
477 def __init__(self
, params
, obj
):
478 self
._add
_output
_port
('out')
480 class MySink(bt2
._UserSinkComponent
):
481 def __init__(self
, params
, obj
):
482 self
._input
_port
= self
._add
_input
_port
('in')
485 def _user_consume(comp_self
):
486 msg
= next(comp_self
._msg
_iter
)
487 if comp_self
._at
== 0:
488 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
489 elif comp_self
._at
== 1:
490 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
491 elif comp_self
._at
== 2:
492 self
.assertIsInstance(msg
, bt2
._EventMessage
)
493 elif comp_self
._at
== 3:
494 nonlocal raised_in_sink
495 raised_in_sink
= True
496 raise RuntimeError('error!')
500 def _user_graph_is_configured(self
):
501 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
505 src
= self
._graph
.add_component(MySource
, 'src')
506 sink
= self
._graph
.add_component(MySink
, 'sink')
507 conn
= self
._graph
.connect_ports(
508 src
.output_ports
['out'], sink
.input_ports
['in']
511 with self
.assertRaises(bt2
._Error
):
514 def test_listeners(self
):
515 class MyIter(bt2
._UserMessageIterator
):
519 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
520 def __init__(self
, params
, obj
):
521 self
._add
_output
_port
('out')
522 self
._add
_output
_port
('zero')
524 class MySink(bt2
._UserSinkComponent
):
525 def __init__(self
, params
, obj
):
526 self
._add
_input
_port
('in')
528 def _user_consume(self
):
531 def _user_port_connected(self
, port
, other_port
):
532 self
._add
_input
_port
('taste')
534 def port_added_listener(component
, port
):
536 calls
.append((port_added_listener
, component
, port
))
538 def ports_connected_listener(
539 upstream_component
, upstream_port
, downstream_component
, downstream_port
544 ports_connected_listener
,
547 downstream_component
,
553 self
._graph
.add_port_added_listener(port_added_listener
)
554 self
._graph
.add_ports_connected_listener(ports_connected_listener
)
555 src
= self
._graph
.add_component(MySource
, 'src')
556 sink
= self
._graph
.add_component(MySink
, 'sink')
557 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
559 self
.assertEqual(len(calls
), 5)
561 self
.assertIs(calls
[0][0], port_added_listener
)
562 self
.assertEqual(calls
[0][1].name
, 'src')
563 self
.assertEqual(calls
[0][2].name
, 'out')
565 self
.assertIs(calls
[1][0], port_added_listener
)
566 self
.assertEqual(calls
[1][1].name
, 'src')
567 self
.assertEqual(calls
[1][2].name
, 'zero')
569 self
.assertIs(calls
[2][0], port_added_listener
)
570 self
.assertEqual(calls
[2][1].name
, 'sink')
571 self
.assertEqual(calls
[2][2].name
, 'in')
573 self
.assertIs(calls
[3][0], port_added_listener
)
574 self
.assertEqual(calls
[3][1].name
, 'sink')
575 self
.assertEqual(calls
[3][2].name
, 'taste')
577 self
.assertIs(calls
[4][0], ports_connected_listener
)
578 self
.assertEqual(calls
[4][1].name
, 'src')
579 self
.assertEqual(calls
[4][2].name
, 'out')
580 self
.assertEqual(calls
[4][3].name
, 'sink')
581 self
.assertEqual(calls
[4][4].name
, 'in')
583 def test_invalid_listeners(self
):
584 class MyIter(bt2
._UserMessageIterator
):
588 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
589 def __init__(self
, params
, obj
):
590 self
._add
_output
_port
('out')
591 self
._add
_output
_port
('zero')
593 class MySink(bt2
._UserSinkComponent
):
594 def __init__(self
, params
, obj
):
595 self
._add
_input
_port
('in')
597 def _user_consume(self
):
600 def _user_port_connected(self
, port
, other_port
):
601 self
._add
_input
_port
('taste')
603 with self
.assertRaises(TypeError):
604 self
._graph
.add_port_added_listener(1234)
605 with self
.assertRaises(TypeError):
606 self
._graph
.add_ports_connected_listener(1234)
608 def test_raise_in_component_init(self
):
609 class MySink(bt2
._UserSinkComponent
):
610 def __init__(self
, params
, obj
):
611 raise ValueError('oops!')
613 def _user_consume(self
):
618 with self
.assertRaises(bt2
._Error
):
619 graph
.add_component(MySink
, 'comp')
621 def test_raise_in_port_added_listener(self
):
622 class MySink(bt2
._UserSinkComponent
):
623 def __init__(self
, params
, obj
):
624 self
._add
_input
_port
('in')
626 def _user_consume(self
):
629 def port_added_listener(component
, port
):
630 raise ValueError('oh noes!')
633 graph
.add_port_added_listener(port_added_listener
)
635 with self
.assertRaises(bt2
._Error
):
636 graph
.add_component(MySink
, 'comp')
638 def test_raise_in_ports_connected_listener(self
):
639 class MyIter(bt2
._UserMessageIterator
):
643 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
644 def __init__(self
, params
, obj
):
645 self
._add
_output
_port
('out')
647 class MySink(bt2
._UserSinkComponent
):
648 def __init__(self
, params
, obj
):
649 self
._add
_input
_port
('in')
651 def _user_consume(self
):
654 def ports_connected_listener(
655 upstream_component
, upstream_port
, downstream_component
, downstream_port
657 raise ValueError('oh noes!')
660 graph
.add_ports_connected_listener(ports_connected_listener
)
661 up
= graph
.add_component(MySource
, 'down')
662 down
= graph
.add_component(MySink
, 'up')
664 with self
.assertRaises(bt2
._Error
):
665 graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
This page took 0.042605 seconds and 4 git commands to generate.