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 UserMessageIteratorTestCase(unittest
.TestCase
):
28 def _create_graph(src_comp_cls
):
29 class MySink(bt2
._UserSinkComponent
):
30 def __init__(self
, params
):
31 self
._add
_input
_port
('in')
36 def _graph_is_configured(self
):
37 self
._msg
_iter
= self
._input
_ports
['in'].create_message_iterator()
40 src_comp
= graph
.add_component(src_comp_cls
, 'src')
41 sink_comp
= graph
.add_component(MySink
, 'sink')
42 graph
.connect_ports(src_comp
.output_ports
['out'], sink_comp
.input_ports
['in'])
46 the_output_port_from_source
= None
47 the_output_port_from_iter
= None
49 class MyIter(bt2
._UserMessageIterator
):
50 def __init__(self
, self_port_output
):
52 nonlocal the_output_port_from_iter
54 the_output_port_from_iter
= self_port_output
56 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
57 def __init__(self
, params
):
58 nonlocal the_output_port_from_source
59 the_output_port_from_source
= self
._add
_output
_port
('out', 'user data')
62 graph
= self
._create
_graph
(MySource
)
64 self
.assertTrue(initialized
)
66 the_output_port_from_source
.addr
, the_output_port_from_iter
.addr
68 self
.assertEqual(the_output_port_from_iter
.user_data
, 'user data')
70 def test_finalize(self
):
71 class MyIter(bt2
._UserMessageIterator
):
76 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
77 def __init__(self
, params
):
78 self
._add
_output
_port
('out')
81 graph
= self
._create
_graph
(MySource
)
84 self
.assertTrue(finalized
)
86 def test_component(self
):
87 class MyIter(bt2
._UserMessageIterator
):
88 def __init__(self
, self_port_output
):
90 salut
= self
._component
._salut
92 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
93 def __init__(self
, params
):
94 self
._add
_output
_port
('out')
98 graph
= self
._create
_graph
(MySource
)
100 self
.assertEqual(salut
, 23)
103 class MyIter(bt2
._UserMessageIterator
):
104 def __init__(self
, self_port_output
):
108 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
109 def __init__(self
, params
):
110 self
._add
_output
_port
('out')
113 graph
= self
._create
_graph
(MySource
)
115 self
.assertIsNotNone(addr
)
116 self
.assertNotEqual(addr
, 0)
118 # Test that messages returned by _UserMessageIterator.__next__ remain valid
119 # and can be re-used.
120 def test_reuse_message(self
):
121 class MyIter(bt2
._UserMessageIterator
):
122 def __init__(self
, port
):
123 tc
, sc
, ec
= port
.user_data
125 stream
= trace
.create_stream(sc
)
126 packet
= stream
.create_packet()
128 # This message will be returned twice by __next__.
129 event_message
= self
._create
_event
_message
(ec
, packet
)
132 self
._create
_stream
_beginning
_message
(stream
),
133 self
._create
_packet
_beginning
_message
(packet
),
139 return self
._msgs
.pop(0)
141 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
142 def __init__(self
, params
):
143 tc
= self
._create
_trace
_class
()
144 sc
= tc
.create_stream_class(supports_packets
=True)
145 ec
= sc
.create_event_class()
146 self
._add
_output
_port
('out', (tc
, sc
, ec
))
149 src
= graph
.add_component(MySource
, 'src')
150 it
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
152 # Skip beginning messages.
154 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
156 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
161 self
.assertIsInstance(msg_ev1
, bt2
.message
._EventMessage
)
162 self
.assertIsInstance(msg_ev2
, bt2
.message
._EventMessage
)
163 self
.assertEqual(msg_ev1
.addr
, msg_ev2
.addr
)
166 def _setup_seek_beginning_test():
167 # Use a source, a filter and an output port iterator. This allows us
168 # to test calling `seek_beginning` on both a _OutputPortMessageIterator
169 # and a _UserComponentInputPortMessageIterator, on top of checking that
170 # _UserMessageIterator._seek_beginning is properly called.
172 class MySourceIter(bt2
._UserMessageIterator
):
173 def __init__(self
, port
):
174 tc
, sc
, ec
= port
.user_data
176 stream
= trace
.create_stream(sc
)
177 packet
= stream
.create_packet()
180 self
._create
_stream
_beginning
_message
(stream
),
181 self
._create
_packet
_beginning
_message
(packet
),
182 self
._create
_event
_message
(ec
, packet
),
183 self
._create
_event
_message
(ec
, packet
),
184 self
._create
_packet
_end
_message
(packet
),
185 self
._create
_stream
_end
_message
(stream
),
189 def _seek_beginning(self
):
193 if self
._at
< len(self
._msgs
):
194 msg
= self
._msgs
[self
._at
]
200 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MySourceIter
):
201 def __init__(self
, params
):
202 tc
= self
._create
_trace
_class
()
203 sc
= tc
.create_stream_class(supports_packets
=True)
204 ec
= sc
.create_event_class()
206 self
._add
_output
_port
('out', (tc
, sc
, ec
))
208 class MyFilterIter(bt2
._UserMessageIterator
):
209 def __init__(self
, port
):
210 input_port
= port
.user_data
211 self
._upstream
_iter
= input_port
.create_message_iterator()
214 return next(self
._upstream
_iter
)
216 def _seek_beginning(self
):
217 self
._upstream
_iter
.seek_beginning()
220 def _can_seek_beginning(self
):
221 return self
._upstream
_iter
.can_seek_beginning
223 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
224 def __init__(self
, params
):
225 input_port
= self
._add
_input
_port
('in')
226 self
._add
_output
_port
('out', input_port
)
229 src
= graph
.add_component(MySource
, 'src')
230 flt
= graph
.add_component(MyFilter
, 'flt')
231 graph
.connect_ports(src
.output_ports
['out'], flt
.input_ports
['in'])
232 it
= graph
.create_output_port_message_iterator(flt
.output_ports
['out'])
234 return it
, MySourceIter
236 def test_can_seek_beginning(self
):
237 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
239 def _can_seek_beginning(self
):
240 nonlocal can_seek_beginning
241 return can_seek_beginning
243 MySourceIter
._can
_seek
_beginning
= property(_can_seek_beginning
)
245 can_seek_beginning
= True
246 self
.assertTrue(it
.can_seek_beginning
)
248 can_seek_beginning
= False
249 self
.assertFalse(it
.can_seek_beginning
)
251 # Once can_seek_beginning returns an error, verify that it raises when
252 # _can_seek_beginning has/returns the wrong type.
254 # Remove the _can_seek_beginning method, we now rely on the presence of
255 # a _seek_beginning method to know whether the iterator can seek to
257 del MySourceIter
._can
_seek
_beginning
258 self
.assertTrue(it
.can_seek_beginning
)
260 del MySourceIter
._seek
_beginning
261 self
.assertFalse(it
.can_seek_beginning
)
263 def test_seek_beginning(self
):
264 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
267 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
269 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
274 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
276 # Verify that we can seek beginning after having reached the end.
278 # It currently does not work to seek an output port message iterator
279 # once it's ended, but we should eventually make it work and uncomment
280 # the following snippet.
288 # it.seek_beginning()
290 # self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
292 def test_seek_beginning_user_error(self
):
293 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
295 def _seek_beginning_error(self
):
296 raise ValueError('ouch')
298 MySourceIter
._seek
_beginning
= _seek_beginning_error
300 with self
.assertRaises(bt2
.Error
):
304 class OutputPortMessageIteratorTestCase(unittest
.TestCase
):
305 def test_component(self
):
306 class MyIter(bt2
._UserMessageIterator
):
307 def __init__(self
, self_port_output
):
315 msg
= self
._create
_stream
_beginning
_message
(test_obj
._stream
)
317 msg
= self
._create
_packet
_beginning
_message
(test_obj
._packet
)
319 msg
= self
._create
_packet
_end
_message
(test_obj
._packet
)
321 msg
= self
._create
_stream
_end
_message
(test_obj
._stream
)
323 msg
= self
._create
_event
_message
(
324 test_obj
._event
_class
, test_obj
._packet
326 msg
.event
.payload_field
['my_int'] = self
._at
* 3
331 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
332 def __init__(self
, params
):
333 self
._add
_output
_port
('out')
335 trace_class
= self
._create
_trace
_class
()
336 stream_class
= trace_class
.create_stream_class(supports_packets
=True)
338 # Create payload field class
339 my_int_ft
= trace_class
.create_signed_integer_field_class(32)
340 payload_ft
= trace_class
.create_structure_field_class()
341 payload_ft
+= [('my_int', my_int_ft
)]
343 event_class
= stream_class
.create_event_class(
344 name
='salut', payload_field_class
=payload_ft
347 trace
= trace_class()
348 stream
= trace
.create_stream(stream_class
)
349 packet
= stream
.create_packet()
351 test_obj
._event
_class
= event_class
352 test_obj
._stream
= stream
353 test_obj
._packet
= packet
357 src
= graph
.add_component(MySource
, 'src')
358 msg_iter
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
360 for at
, msg
in enumerate(msg_iter
):
362 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
364 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
366 self
.assertIsInstance(msg
, bt2
.message
._PacketEndMessage
)
368 self
.assertIsInstance(msg
, bt2
.message
._StreamEndMessage
)
370 self
.assertIsInstance(msg
, bt2
.message
._EventMessage
)
371 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
372 field
= msg
.event
.payload_field
['my_int']
373 self
.assertEqual(field
, at
* 3)
376 if __name__
== '__main__':