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
_stream
_activity
_beginning
_message
(stream
),
138 self
._create
_packet
_beginning
_message
(packet
),
144 return self
._msgs
.pop(0)
146 class MySource(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
147 def __init__(self
, params
):
148 tc
= self
._create
_trace
_class
()
149 sc
= tc
.create_stream_class()
150 ec
= sc
.create_event_class()
151 self
._add
_output
_port
('out', (tc
, sc
, ec
))
154 src
= graph
.add_component(MySource
, 'src')
155 it
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
157 # Skip beginning messages.
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
_stream
_activity
_beginning
_message
(stream
),
186 self
._create
_packet
_beginning
_message
(packet
),
187 self
._create
_event
_message
(ec
, packet
),
188 self
._create
_event
_message
(ec
, packet
),
189 self
._create
_packet
_end
_message
(packet
),
190 self
._create
_stream
_activity
_end
_message
(stream
),
191 self
._create
_stream
_end
_message
(stream
),
195 def _seek_beginning(self
):
199 if self
._at
< len(self
._msgs
):
200 msg
= self
._msgs
[self
._at
]
206 class MySource(bt2
._UserSourceComponent
,
207 message_iterator_class
=MySourceIter
):
208 def __init__(self
, params
):
209 tc
= self
._create
_trace
_class
()
210 sc
= tc
.create_stream_class()
211 ec
= sc
.create_event_class()
213 self
._add
_output
_port
('out', (tc
, sc
, ec
))
215 class MyFilterIter(bt2
._UserMessageIterator
):
216 def __init__(self
, port
):
217 input_port
= port
.user_data
218 self
._upstream
_iter
= input_port
.create_message_iterator()
221 return next(self
._upstream
_iter
)
223 def _seek_beginning(self
):
224 self
._upstream
_iter
.seek_beginning()
227 def _can_seek_beginning(self
):
228 return self
._upstream
_iter
.can_seek_beginning
230 class MyFilter(bt2
._UserFilterComponent
, message_iterator_class
=MyFilterIter
):
231 def __init__(self
, params
):
232 input_port
= self
._add
_input
_port
('in')
233 self
._add
_output
_port
('out', input_port
)
237 src
= graph
.add_component(MySource
, 'src')
238 flt
= graph
.add_component(MyFilter
, 'flt')
239 graph
.connect_ports(src
.output_ports
['out'], flt
.input_ports
['in'])
240 it
= graph
.create_output_port_message_iterator(flt
.output_ports
['out'])
242 return it
, MySourceIter
244 def test_can_seek_beginning(self
):
245 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
247 def _can_seek_beginning(self
):
248 nonlocal can_seek_beginning
249 return can_seek_beginning
251 MySourceIter
._can
_seek
_beginning
= property(_can_seek_beginning
)
253 can_seek_beginning
= True
254 self
.assertTrue(it
.can_seek_beginning
)
256 can_seek_beginning
= False
257 self
.assertFalse(it
.can_seek_beginning
)
259 # Once can_seek_beginning returns an error, verify that it raises when
260 # _can_seek_beginning has/returns the wrong type.
262 # Remove the _can_seek_beginning method, we now rely on the presence of
263 # a _seek_beginning method to know whether the iterator can seek to
265 del MySourceIter
._can
_seek
_beginning
266 self
.assertTrue(it
.can_seek_beginning
)
268 del MySourceIter
._seek
_beginning
269 self
.assertFalse(it
.can_seek_beginning
)
271 def test_seek_beginning(self
):
272 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
275 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
277 self
.assertIsInstance(msg
, bt2
.message
._StreamActivityBeginningMessage
)
282 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
284 # Verify that we can seek beginning after having reached the end.
286 # It currently does not work to seek an output port message iterator
287 # once it's ended, but we should eventually make it work and uncomment
288 # the following snippet.
296 # it.seek_beginning()
298 # self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
300 def test_seek_beginning_user_error(self
):
301 it
, MySourceIter
= self
._setup
_seek
_beginning
_test
()
303 def _seek_beginning_error(self
):
304 raise ValueError('ouch')
306 MySourceIter
._seek
_beginning
= _seek_beginning_error
308 with self
.assertRaises(bt2
.Error
):
313 class OutputPortMessageIteratorTestCase(unittest
.TestCase
):
314 def test_component(self
):
315 class MyIter(bt2
._UserMessageIterator
):
316 def __init__(self
, self_port_output
):
324 msg
= self
._create
_stream
_beginning
_message
(test_obj
._stream
)
326 msg
= self
._create
_packet
_beginning
_message
(test_obj
._packet
)
328 msg
= self
._create
_packet
_end
_message
(test_obj
._packet
)
330 msg
= self
._create
_stream
_end
_message
(test_obj
._stream
)
332 msg
= self
._create
_event
_message
(test_obj
._event
_class
, test_obj
._packet
)
333 msg
.event
.payload_field
['my_int'] = self
._at
* 3
338 class MySource(bt2
._UserSourceComponent
,
339 message_iterator_class
=MyIter
):
340 def __init__(self
, params
):
341 self
._add
_output
_port
('out')
343 trace_class
= self
._create
_trace
_class
()
344 stream_class
= trace_class
.create_stream_class()
346 # Create payload field class
347 my_int_ft
= trace_class
.create_signed_integer_field_class(32)
348 payload_ft
= trace_class
.create_structure_field_class()
349 payload_ft
+= collections
.OrderedDict([
350 ('my_int', my_int_ft
),
353 event_class
= stream_class
.create_event_class(name
='salut', payload_field_class
=payload_ft
)
355 trace
= trace_class()
356 stream
= trace
.create_stream(stream_class
)
357 packet
= stream
.create_packet()
359 test_obj
._event
_class
= event_class
360 test_obj
._stream
= stream
361 test_obj
._packet
= packet
365 src
= graph
.add_component(MySource
, 'src')
366 msg_iter
= graph
.create_output_port_message_iterator(src
.output_ports
['out'])
368 for at
, msg
in enumerate(msg_iter
):
370 self
.assertIsInstance(msg
, bt2
.message
._StreamBeginningMessage
)
372 self
.assertIsInstance(msg
, bt2
.message
._PacketBeginningMessage
)
374 self
.assertIsInstance(msg
, bt2
.message
._PacketEndMessage
)
376 self
.assertIsInstance(msg
, bt2
.message
._StreamEndMessage
)
378 self
.assertIsInstance(msg
, bt2
.message
._EventMessage
)
379 self
.assertEqual(msg
.event
.cls
.name
, 'salut')
380 field
= msg
.event
.payload_field
['my_int']
381 self
.assertEqual(field
, at
* 3)
383 if __name__
== '__main__':