3 # Copyright (C) 2019 EfficiOS Inc.
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; only version 2
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 class UserMessageIteratorTestCase(unittest
.TestCase
):
29 def _create_graph(src_comp_cls
):
30 class MySink(bt2
._UserSinkComponent
):
31 def __init__(self
, params
):
32 self
._add
_input
_port
('in')
37 def _graph_is_configured(self
):
38 self
._msg
_iter
= self
._input
_ports
['in'].create_message_iterator()
41 src_comp
= graph
.add_component(src_comp_cls
, 'src')
42 sink_comp
= graph
.add_component(MySink
, 'sink')
43 graph
.connect_ports(src_comp
.output_ports
['out'],
44 sink_comp
.input_ports
['in'])
48 the_output_port_from_source
= None
49 the_output_port_from_iter
= None
51 class MyIter(bt2
._UserMessageIterator
):
52 def __init__(self
, self_port_output
):
54 nonlocal the_output_port_from_iter
56 the_output_port_from_iter
= self_port_output
58 class MySource(bt2
._UserSourceComponent
,
59 message_iterator_class
=MyIter
):
60 def __init__(self
, params
):
61 nonlocal the_output_port_from_source
62 the_output_port_from_source
= self
._add
_output
_port
('out', 'user data')
65 graph
= self
._create
_graph
(MySource
)
67 self
.assertTrue(initialized
)
68 self
.assertEqual(the_output_port_from_source
.addr
, the_output_port_from_iter
.addr
)
69 self
.assertEqual(the_output_port_from_iter
.user_data
, 'user data')
71 def test_finalize(self
):
72 class MyIter(bt2
._UserMessageIterator
):
77 class MySource(bt2
._UserSourceComponent
,
78 message_iterator_class
=MyIter
):
79 def __init__(self
, params
):
80 self
._add
_output
_port
('out')
83 graph
= self
._create
_graph
(MySource
)
86 self
.assertTrue(finalized
)
88 def test_component(self
):
89 class MyIter(bt2
._UserMessageIterator
):
90 def __init__(self
, self_port_output
):
92 salut
= self
._component
._salut
94 class MySource(bt2
._UserSourceComponent
,
95 message_iterator_class
=MyIter
):
96 def __init__(self
, params
):
97 self
._add
_output
_port
('out')
101 graph
= self
._create
_graph
(MySource
)
103 self
.assertEqual(salut
, 23)
106 class MyIter(bt2
._UserMessageIterator
):
107 def __init__(self
, self_port_output
):
111 class MySource(bt2
._UserSourceComponent
,
112 message_iterator_class
=MyIter
):
113 def __init__(self
, params
):
114 self
._add
_output
_port
('out')
117 graph
= self
._create
_graph
(MySource
)
119 self
.assertIsNotNone(addr
)
120 self
.assertNotEqual(addr
, 0)
122 # Test that messages returned by _UserMessageIterator.__next__ remain valid
123 # and can be re-used.
124 def test_reuse_message(self
):
125 class MyIter(bt2
._UserMessageIterator
):
126 def __init__(self
, port
):
127 tc
, sc
, ec
= port
.user_data
129 stream
= trace
.create_stream(sc
)
130 packet
= stream
.create_packet()
132 # This message will be returned twice by __next__.
133 event_message
= self
._create
_event
_message
(ec
, packet
)
136 self
._create
_stream
_beginning
_message
(stream
),
137 self
._create
_packet
_beginning
_message
(packet
),
143 return self
._msgs
.pop(0)
145 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
146 def __init__(self
, params
):
147 tc
= self
._create
_trace
_class
()
148 sc
= tc
.create_stream_class(supports_packets
=True)
149 ec
= sc
.create_event_class()
150 self
._add
_output
_port
('out', (tc
, sc
, ec
))
153 src
= graph
.add_component(MySource
, 'src')
154 it
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
156 # Skip beginning messages.
158 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
160 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
165 self
.assertIsInstance(msg_ev1
, bt2
.message
._EventMessage
)
166 self
.assertIsInstance(msg_ev2
, bt2
.message
._EventMessage
)
167 self
.assertEqual(msg_ev1
.addr
, msg_ev2
.addr
)
170 def _setup_seek_beginning_test():
171 # Use a source, a filter and an output port iterator. This allows us
172 # to test calling `seek_beginning` on both a _OutputPortMessageIterator
173 # and a _UserComponentInputPortMessageIterator, on top of checking that
174 # _UserMessageIterator._seek_beginning is properly called.
176 class MySourceIter(bt2
._UserMessageIterator
):
177 def __init__(self
, port
):
178 tc
, sc
, ec
= port
.user_data
180 stream
= trace
.create_stream(sc
)
181 packet
= stream
.create_packet()
184 self
._create
_stream
_beginning
_message
(stream
),
185 self
._create
_packet
_beginning
_message
(packet
),
186 self
._create
_event
_message
(ec
, packet
),
187 self
._create
_event
_message
(ec
, packet
),
188 self
._create
_packet
_end
_message
(packet
),
189 self
._create
_stream
_end
_message
(stream
),
193 def _seek_beginning(self
):
197 if self
._at
< len(self
._msgs
):
198 msg
= self
._msgs
[self
._at
]
204 class MySource(bt2
._UserSourceComponent
,
205 message_iterator_class
=MySourceIter
):
206 def __init__(self
, params
):
207 tc
= self
._create
_trace
_class
()
208 sc
= tc
.create_stream_class(supports_packets
=True)
209 ec
= sc
.create_event_class()
211 self
._add
_output
_port
('out', (tc
, sc
, ec
))
213 class MyFilterIter(bt2
._UserMessageIterator
):
214 def __init__(self
, port
):
215 input_port
= port
.user_data
216 self
._upstream
_iter
= input_port
.create_message_iterator()
219 return next(self
._upstream
_iter
)
221 def _seek_beginning(self
):
222 self
._upstream
_iter
.seek_beginning()
225 def _can_seek_beginning(self
):
226 return self
._upstream
_iter
.can_seek_beginning
228 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
229 def __init__(self
, params
):
230 input_port
= self
._add
_input
_port
('in')
231 self
._add
_output
_port
('out', input_port
)
235 src
= graph
.add_component(MySource
, 'src')
236 flt
= graph
.add_component(MyFilter
, 'flt')
237 graph
.connect_ports(src
.output_ports
['out'], flt
.input_ports
['in'])
238 it
= graph
.create_output_port_message_iterator(flt
.output_ports
['out'])
240 return it
, MySourceIter
242 def test_can_seek_beginning(self
):
243 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
245 def _can_seek_beginning(self
):
246 nonlocal can_seek_beginning
247 return can_seek_beginning
249 MySourceIter
._can
_seek
_beginning
= property(_can_seek_beginning
)
251 can_seek_beginning
= True
252 self
.assertTrue(it
.can_seek_beginning
)
254 can_seek_beginning
= False
255 self
.assertFalse(it
.can_seek_beginning
)
257 # Once can_seek_beginning returns an error, verify that it raises when
258 # _can_seek_beginning has/returns the wrong type.
260 # Remove the _can_seek_beginning method, we now rely on the presence of
261 # a _seek_beginning method to know whether the iterator can seek to
263 del MySourceIter
._can
_seek
_beginning
264 self
.assertTrue(it
.can_seek_beginning
)
266 del MySourceIter
._seek
_beginning
267 self
.assertFalse(it
.can_seek_beginning
)
269 def test_seek_beginning(self
):
270 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
273 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
275 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
280 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
282 # Verify that we can seek beginning after having reached the end.
284 # It currently does not work to seek an output port message iterator
285 # once it's ended, but we should eventually make it work and uncomment
286 # the following snippet.
294 # it.seek_beginning()
296 # self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
298 def test_seek_beginning_user_error(self
):
299 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
301 def _seek_beginning_error(self
):
302 raise ValueError('ouch')
304 MySourceIter
._seek
_beginning
= _seek_beginning_error
306 with self
.assertRaises(bt2
.Error
):
311 class OutputPortMessageIteratorTestCase(unittest
.TestCase
):
312 def test_component(self
):
313 class MyIter(bt2
._UserMessageIterator
):
314 def __init__(self
, self_port_output
):
322 msg
= self
._create
_stream
_beginning
_message
(test_obj
._stream
)
324 msg
= self
._create
_packet
_beginning
_message
(test_obj
._packet
)
326 msg
= self
._create
_packet
_end
_message
(test_obj
._packet
)
328 msg
= self
._create
_stream
_end
_message
(test_obj
._stream
)
330 msg
= self
._create
_event
_message
(test_obj
._event
_class
, test_obj
._packet
)
331 msg
.event
.payload_field
['my_int'] = self
._at
* 3
336 class MySource(bt2
._UserSourceComponent
,
337 message_iterator_class
=MyIter
):
338 def __init__(self
, params
):
339 self
._add
_output
_port
('out')
341 trace_class
= self
._create
_trace
_class
()
342 stream_class
= trace_class
.create_stream_class(supports_packets
=True)
344 # Create payload field class
345 my_int_ft
= trace_class
.create_signed_integer_field_class(32)
346 payload_ft
= trace_class
.create_structure_field_class()
347 payload_ft
+= collections
.OrderedDict([
348 ('my_int', my_int_ft
),
351 event_class
= stream_class
.create_event_class(name
='salut', payload_field_class
=payload_ft
)
353 trace
= trace_class()
354 stream
= trace
.create_stream(stream_class
)
355 packet
= stream
.create_packet()
357 test_obj
._event
_class
= event_class
358 test_obj
._stream
= stream
359 test_obj
._packet
= packet
363 src
= graph
.add_component(MySource
, 'src')
364 msg_iter
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
366 for at
, msg
in enumerate(msg_iter
):
368 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
370 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
372 self
.assertIsInstance(msg
, bt2
.message
._PacketEndMessage
)
374 self
.assertIsInstance(msg
, bt2
.message
._StreamEndMessage
)
376 self
.assertIsInstance(msg
, bt2
.message
._EventMessage
)
377 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
378 field
= msg
.event
.payload_field
['my_int']
379 self
.assertEqual(field
, at
* 3)
381 if __name__
== '__main__':