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
):
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_invalid_cls_type(self
):
95 with self
.assertRaises(TypeError):
96 self
._graph
.add_component(int, 'salut')
98 def test_add_component_invalid_logging_level_type(self
):
99 class MySink(bt2
._UserSinkComponent
):
100 def _user_consume(self
):
103 with self
.assertRaises(TypeError):
104 self
._graph
.add_component(MySink
, 'salut', logging_level
='yo')
106 def test_add_component_invalid_logging_level_value(self
):
107 class MySink(bt2
._UserSinkComponent
):
108 def _user_consume(self
):
111 with self
.assertRaises(ValueError):
112 self
._graph
.add_component(MySink
, 'salut', logging_level
=12345)
114 def test_add_component_logging_level(self
):
115 class MySink(bt2
._UserSinkComponent
):
116 def _user_consume(self
):
119 comp
= self
._graph
.add_component(
120 MySink
, 'salut', logging_level
=bt2
.LoggingLevel
.DEBUG
122 self
.assertEqual(comp
.logging_level
, bt2
.LoggingLevel
.DEBUG
)
124 def test_connect_ports(self
):
125 class MyIter(bt2
._UserMessageIterator
):
129 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
130 def __init__(self
, params
):
131 self
._add
_output
_port
('out')
133 class MySink(bt2
._UserSinkComponent
):
134 def __init__(self
, params
):
135 self
._add
_input
_port
('in')
137 def _user_consume(self
):
140 src
= self
._graph
.add_component(MySource
, 'src')
141 sink
= self
._graph
.add_component(MySink
, 'sink')
143 conn
= self
._graph
.connect_ports(
144 src
.output_ports
['out'], sink
.input_ports
['in']
146 self
.assertTrue(src
.output_ports
['out'].is_connected
)
147 self
.assertTrue(sink
.input_ports
['in'].is_connected
)
148 self
.assertEqual(src
.output_ports
['out'].connection
.addr
, conn
.addr
)
149 self
.assertEqual(sink
.input_ports
['in'].connection
.addr
, conn
.addr
)
151 def test_connect_ports_invalid_direction(self
):
152 class MyIter(bt2
._UserMessageIterator
):
156 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
157 def __init__(self
, params
):
158 self
._add
_output
_port
('out')
160 class MySink(bt2
._UserSinkComponent
):
161 def __init__(self
, params
):
162 self
._add
_input
_port
('in')
164 def _user_consume(self
):
167 src
= self
._graph
.add_component(MySource
, 'src')
168 sink
= self
._graph
.add_component(MySink
, 'sink')
170 with self
.assertRaises(TypeError):
171 conn
= self
._graph
.connect_ports(
172 sink
.input_ports
['in'], src
.output_ports
['out']
175 def test_add_interrupter(self
):
176 class MyIter(bt2
._UserMessageIterator
):
180 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
181 def __init__(self
, params
):
182 self
._add
_output
_port
('out')
184 class MySink(bt2
._UserSinkComponent
):
185 def __init__(self
, params
):
186 self
._add
_input
_port
('in')
188 def _user_consume(self
):
191 def _user_graph_is_configured(self
):
192 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
193 self
._input
_ports
['in']
196 # add two interrupters, set one of them
197 interrupter1
= bt2
.Interrupter()
198 interrupter2
= bt2
.Interrupter()
199 self
._graph
.add_interrupter(interrupter1
)
200 src
= self
._graph
.add_component(MySource
, 'src')
201 sink
= self
._graph
.add_component(MySink
, 'sink')
202 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
203 self
._graph
.add_interrupter(interrupter2
)
205 with self
.assertRaises(bt2
._Error
):
210 with self
.assertRaises(bt2
.TryAgain
):
215 with self
.assertRaises(bt2
._Error
):
218 # Test that Graph.run() raises bt2.Interrupted if the graph gets
219 # interrupted during execution.
220 def test_interrupt_while_running(self
):
221 class MyIter(_MyIter
):
223 return self
._create
_stream
_beginning
_message
(self
._stream
)
225 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
226 def __init__(self
, params
):
227 self
._add
_output
_port
('out')
229 class MySink(bt2
._UserSinkComponent
):
230 def __init__(self
, params
):
231 self
._add
_input
_port
('in')
233 def _user_consume(self
):
234 # Pretend that somebody asynchronously interrupted the graph.
237 return next(self
._msg
_iter
)
239 def _user_graph_is_configured(self
):
240 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
241 self
._input
_ports
['in']
245 up
= self
._graph
.add_component(MySource
, 'down')
246 down
= self
._graph
.add_component(MySink
, 'up')
247 self
._graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
249 with self
.assertRaises(bt2
.TryAgain
):
253 class MyIter(_MyIter
):
259 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
261 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
263 msg
= self
._create
_packet
_end
_message
(self
._packet
)
265 msg
= self
._create
_stream
_end
_message
(self
._stream
)
267 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
272 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
273 def __init__(self
, params
):
274 self
._add
_output
_port
('out')
276 class MySink(bt2
._UserSinkComponent
):
277 def __init__(self
, params
):
278 self
._input
_port
= self
._add
_input
_port
('in')
281 def _user_consume(comp_self
):
282 msg
= next(comp_self
._msg
_iter
)
284 if comp_self
._at
== 0:
285 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
286 elif comp_self
._at
== 1:
287 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
288 elif comp_self
._at
>= 2 and comp_self
._at
<= 6:
289 self
.assertIsInstance(msg
, bt2
._EventMessage
)
290 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
291 elif comp_self
._at
== 7:
292 self
.assertIsInstance(msg
, bt2
._PacketEndMessage
)
293 elif comp_self
._at
== 8:
294 self
.assertIsInstance(msg
, bt2
._StreamEndMessage
)
298 def _user_graph_is_configured(self
):
299 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
303 src
= self
._graph
.add_component(MySource
, 'src')
304 sink
= self
._graph
.add_component(MySink
, 'sink')
305 conn
= self
._graph
.connect_ports(
306 src
.output_ports
['out'], sink
.input_ports
['in']
310 def test_run_again(self
):
311 class MyIter(_MyIter
):
317 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
319 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
321 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
326 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
327 def __init__(self
, params
):
328 self
._add
_output
_port
('out')
330 class MySink(bt2
._UserSinkComponent
):
331 def __init__(self
, params
):
332 self
._input
_port
= self
._add
_input
_port
('in')
335 def _user_consume(comp_self
):
336 msg
= next(comp_self
._msg
_iter
)
337 if comp_self
._at
== 0:
338 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
339 elif comp_self
._at
== 1:
340 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
341 elif comp_self
._at
== 2:
342 self
.assertIsInstance(msg
, bt2
._EventMessage
)
349 def _user_graph_is_configured(self
):
350 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
354 src
= self
._graph
.add_component(MySource
, 'src')
355 sink
= self
._graph
.add_component(MySink
, 'sink')
356 conn
= self
._graph
.connect_ports(
357 src
.output_ports
['out'], sink
.input_ports
['in']
360 with self
.assertRaises(bt2
.TryAgain
):
363 def test_run_error(self
):
364 raised_in_sink
= False
366 class MyIter(_MyIter
):
368 # If this gets called after the sink raised an exception, it is
370 nonlocal raised_in_sink
371 assert raised_in_sink
is False
374 msg
= self
._create
_stream
_beginning
_message
(self
._stream
)
376 msg
= self
._create
_packet
_beginning
_message
(self
._packet
)
377 elif self
._at
== 2 or self
._at
== 3:
378 msg
= self
._create
_event
_message
(self
._ec
, self
._packet
)
384 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
385 def __init__(self
, params
):
386 self
._add
_output
_port
('out')
388 class MySink(bt2
._UserSinkComponent
):
389 def __init__(self
, params
):
390 self
._input
_port
= self
._add
_input
_port
('in')
393 def _user_consume(comp_self
):
394 msg
= next(comp_self
._msg
_iter
)
395 if comp_self
._at
== 0:
396 self
.assertIsInstance(msg
, bt2
._StreamBeginningMessage
)
397 elif comp_self
._at
== 1:
398 self
.assertIsInstance(msg
, bt2
._PacketBeginningMessage
)
399 elif comp_self
._at
== 2:
400 self
.assertIsInstance(msg
, bt2
._EventMessage
)
401 elif comp_self
._at
== 3:
402 nonlocal raised_in_sink
403 raised_in_sink
= True
404 raise RuntimeError('error!')
408 def _user_graph_is_configured(self
):
409 self
._msg
_iter
= self
._create
_input
_port
_message
_iterator
(
413 src
= self
._graph
.add_component(MySource
, 'src')
414 sink
= self
._graph
.add_component(MySink
, 'sink')
415 conn
= self
._graph
.connect_ports(
416 src
.output_ports
['out'], sink
.input_ports
['in']
419 with self
.assertRaises(bt2
._Error
):
422 def test_listeners(self
):
423 class MyIter(bt2
._UserMessageIterator
):
427 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
428 def __init__(self
, params
):
429 self
._add
_output
_port
('out')
430 self
._add
_output
_port
('zero')
432 class MySink(bt2
._UserSinkComponent
):
433 def __init__(self
, params
):
434 self
._add
_input
_port
('in')
436 def _user_consume(self
):
439 def _user_port_connected(self
, port
, other_port
):
440 self
._add
_input
_port
('taste')
442 def port_added_listener(component
, port
):
444 calls
.append((port_added_listener
, component
, port
))
446 def ports_connected_listener(
447 upstream_component
, upstream_port
, downstream_component
, downstream_port
452 ports_connected_listener
,
455 downstream_component
,
461 self
._graph
.add_port_added_listener(port_added_listener
)
462 self
._graph
.add_ports_connected_listener(ports_connected_listener
)
463 src
= self
._graph
.add_component(MySource
, 'src')
464 sink
= self
._graph
.add_component(MySink
, 'sink')
465 self
._graph
.connect_ports(src
.output_ports
['out'], sink
.input_ports
['in'])
467 self
.assertEqual(len(calls
), 5)
469 self
.assertIs(calls
[0][0], port_added_listener
)
470 self
.assertEqual(calls
[0][1].name
, 'src')
471 self
.assertEqual(calls
[0][2].name
, 'out')
473 self
.assertIs(calls
[1][0], port_added_listener
)
474 self
.assertEqual(calls
[1][1].name
, 'src')
475 self
.assertEqual(calls
[1][2].name
, 'zero')
477 self
.assertIs(calls
[2][0], port_added_listener
)
478 self
.assertEqual(calls
[2][1].name
, 'sink')
479 self
.assertEqual(calls
[2][2].name
, 'in')
481 self
.assertIs(calls
[3][0], port_added_listener
)
482 self
.assertEqual(calls
[3][1].name
, 'sink')
483 self
.assertEqual(calls
[3][2].name
, 'taste')
485 self
.assertIs(calls
[4][0], ports_connected_listener
)
486 self
.assertEqual(calls
[4][1].name
, 'src')
487 self
.assertEqual(calls
[4][2].name
, 'out')
488 self
.assertEqual(calls
[4][3].name
, 'sink')
489 self
.assertEqual(calls
[4][4].name
, 'in')
491 def test_invalid_listeners(self
):
492 class MyIter(bt2
._UserMessageIterator
):
496 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
497 def __init__(self
, params
):
498 self
._add
_output
_port
('out')
499 self
._add
_output
_port
('zero')
501 class MySink(bt2
._UserSinkComponent
):
502 def __init__(self
, params
):
503 self
._add
_input
_port
('in')
505 def _user_consume(self
):
508 def _user_port_connected(self
, port
, other_port
):
509 self
._add
_input
_port
('taste')
511 with self
.assertRaises(TypeError):
512 self
._graph
.add_port_added_listener(1234)
513 with self
.assertRaises(TypeError):
514 self
._graph
.add_ports_connected_listener(1234)
516 def test_raise_in_component_init(self
):
517 class MySink(bt2
._UserSinkComponent
):
518 def __init__(self
, params
):
519 raise ValueError('oops!')
521 def _user_consume(self
):
526 with self
.assertRaises(bt2
._Error
):
527 graph
.add_component(MySink
, 'comp')
529 def test_raise_in_port_added_listener(self
):
530 class MySink(bt2
._UserSinkComponent
):
531 def __init__(self
, params
):
532 self
._add
_input
_port
('in')
534 def _user_consume(self
):
537 def port_added_listener(component
, port
):
538 raise ValueError('oh noes!')
541 graph
.add_port_added_listener(port_added_listener
)
543 with self
.assertRaises(bt2
._Error
):
544 graph
.add_component(MySink
, 'comp')
546 def test_raise_in_ports_connected_listener(self
):
547 class MyIter(bt2
._UserMessageIterator
):
551 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
552 def __init__(self
, params
):
553 self
._add
_output
_port
('out')
555 class MySink(bt2
._UserSinkComponent
):
556 def __init__(self
, params
):
557 self
._add
_input
_port
('in')
559 def _user_consume(self
):
562 def ports_connected_listener(
563 upstream_component
, upstream_port
, downstream_component
, downstream_port
565 raise ValueError('oh noes!')
568 graph
.add_ports_connected_listener(ports_connected_listener
)
569 up
= graph
.add_component(MySource
, 'down')
570 down
= graph
.add_component(MySink
, 'up')
572 with self
.assertRaises(bt2
._Error
):
573 graph
.connect_ports(up
.output_ports
['out'], down
.input_ports
['in'])
This page took 0.05106 seconds and 4 git commands to generate.