lib: make packets and packet messages optional, disabled by default
[babeltrace.git] / tests / bindings / python / bt2 / test_message_iterator.py
CommitLineData
d2d857a8
MJ
1
2#
3# Copyright (C) 2019 EfficiOS Inc.
4#
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
8# of the License.
9#
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.
14#
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.
18#
19
c4239792 20from bt2 import value
548bb510 21import collections
811644b8
PP
22import unittest
23import copy
24import bt2
25
26
5602ef81 27class UserMessageIteratorTestCase(unittest.TestCase):
811644b8
PP
28 @staticmethod
29 def _create_graph(src_comp_cls):
30 class MySink(bt2._UserSinkComponent):
31 def __init__(self, params):
32 self._add_input_port('in')
33
34 def _consume(self):
5602ef81 35 next(self._msg_iter)
811644b8 36
c5f330cd
SM
37 def _graph_is_configured(self):
38 self._msg_iter = self._input_ports['in'].create_message_iterator()
811644b8
PP
39
40 graph = bt2.Graph()
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'])
45 return graph
46
47 def test_init(self):
c5f330cd
SM
48 the_output_port_from_source = None
49 the_output_port_from_iter = None
50
5602ef81 51 class MyIter(bt2._UserMessageIterator):
c5f330cd 52 def __init__(self, self_port_output):
811644b8 53 nonlocal initialized
c5f330cd 54 nonlocal the_output_port_from_iter
811644b8 55 initialized = True
c5f330cd 56 the_output_port_from_iter = self_port_output
811644b8
PP
57
58 class MySource(bt2._UserSourceComponent,
5602ef81 59 message_iterator_class=MyIter):
811644b8 60 def __init__(self, params):
c5f330cd 61 nonlocal the_output_port_from_source
2e00bc76 62 the_output_port_from_source = self._add_output_port('out', 'user data')
811644b8
PP
63
64 initialized = False
65 graph = self._create_graph(MySource)
c5f330cd 66 graph.run()
811644b8 67 self.assertTrue(initialized)
c5f330cd 68 self.assertEqual(the_output_port_from_source.addr, the_output_port_from_iter.addr)
2e00bc76 69 self.assertEqual(the_output_port_from_iter.user_data, 'user data')
811644b8
PP
70
71 def test_finalize(self):
5602ef81 72 class MyIter(bt2._UserMessageIterator):
811644b8
PP
73 def _finalize(self):
74 nonlocal finalized
75 finalized = True
76
77 class MySource(bt2._UserSourceComponent,
5602ef81 78 message_iterator_class=MyIter):
811644b8
PP
79 def __init__(self, params):
80 self._add_output_port('out')
81
82 finalized = False
83 graph = self._create_graph(MySource)
c5f330cd 84 graph.run()
811644b8
PP
85 del graph
86 self.assertTrue(finalized)
87
88 def test_component(self):
5602ef81 89 class MyIter(bt2._UserMessageIterator):
c5f330cd 90 def __init__(self, self_port_output):
811644b8
PP
91 nonlocal salut
92 salut = self._component._salut
93
94 class MySource(bt2._UserSourceComponent,
5602ef81 95 message_iterator_class=MyIter):
811644b8
PP
96 def __init__(self, params):
97 self._add_output_port('out')
98 self._salut = 23
99
100 salut = None
101 graph = self._create_graph(MySource)
c5f330cd 102 graph.run()
811644b8
PP
103 self.assertEqual(salut, 23)
104
105 def test_addr(self):
5602ef81 106 class MyIter(bt2._UserMessageIterator):
c5f330cd 107 def __init__(self, self_port_output):
811644b8
PP
108 nonlocal addr
109 addr = self.addr
110
111 class MySource(bt2._UserSourceComponent,
5602ef81 112 message_iterator_class=MyIter):
811644b8
PP
113 def __init__(self, params):
114 self._add_output_port('out')
115
116 addr = None
117 graph = self._create_graph(MySource)
c5f330cd 118 graph.run()
811644b8
PP
119 self.assertIsNotNone(addr)
120 self.assertNotEqual(addr, 0)
121
d79a8353
SM
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
128 trace = tc()
129 stream = trace.create_stream(sc)
130 packet = stream.create_packet()
131
132 # This message will be returned twice by __next__.
133 event_message = self._create_event_message(ec, packet)
134
135 self._msgs = [
136 self._create_stream_beginning_message(stream),
d79a8353
SM
137 self._create_packet_beginning_message(packet),
138 event_message,
139 event_message,
140 ]
141
142 def __next__(self):
143 return self._msgs.pop(0)
144
145 class MySource(bt2._UserSourceComponent, message_iterator_class=MyIter):
146 def __init__(self, params):
147 tc = self._create_trace_class()
26fc5aed 148 sc = tc.create_stream_class(supports_packets=True)
d79a8353
SM
149 ec = sc.create_event_class()
150 self._add_output_port('out', (tc, sc, ec))
151
152 graph = bt2.Graph()
153 src = graph.add_component(MySource, 'src')
154 it = graph.create_output_port_message_iterator(src.output_ports['out'])
155
156 # Skip beginning messages.
188edac1
SM
157 msg = next(it)
158 self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
159 msg = next(it)
160 self.assertIsInstance(msg, bt2.message._PacketBeginningMessage)
d79a8353
SM
161
162 msg_ev1 = next(it)
163 msg_ev2 = next(it)
164
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)
168
f00b8d40
SM
169 @staticmethod
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.
175
176 class MySourceIter(bt2._UserMessageIterator):
177 def __init__(self, port):
178 tc, sc, ec = port.user_data
179 trace = tc()
180 stream = trace.create_stream(sc)
181 packet = stream.create_packet()
182
183 self._msgs = [
184 self._create_stream_beginning_message(stream),
f00b8d40
SM
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),
f00b8d40
SM
189 self._create_stream_end_message(stream),
190 ]
191 self._at = 0
192
193 def _seek_beginning(self):
194 self._at = 0
195
196 def __next__(self):
197 if self._at < len(self._msgs):
198 msg = self._msgs[self._at]
199 self._at += 1
200 return msg
201 else:
202 raise StopIteration
203
204 class MySource(bt2._UserSourceComponent,
205 message_iterator_class=MySourceIter):
206 def __init__(self, params):
207 tc = self._create_trace_class()
26fc5aed 208 sc = tc.create_stream_class(supports_packets=True)
f00b8d40
SM
209 ec = sc.create_event_class()
210
211 self._add_output_port('out', (tc, sc, ec))
212
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()
217
218 def __next__(self):
219 return next(self._upstream_iter)
220
221 def _seek_beginning(self):
222 self._upstream_iter.seek_beginning()
223
224 @property
225 def _can_seek_beginning(self):
226 return self._upstream_iter.can_seek_beginning
227
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)
232
233
234 graph = bt2.Graph()
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'])
239
240 return it, MySourceIter
241
242 def test_can_seek_beginning(self):
243 it, MySourceIter = self._setup_seek_beginning_test()
244
245 def _can_seek_beginning(self):
246 nonlocal can_seek_beginning
247 return can_seek_beginning
248
249 MySourceIter._can_seek_beginning = property(_can_seek_beginning)
250
251 can_seek_beginning = True
252 self.assertTrue(it.can_seek_beginning)
253
254 can_seek_beginning = False
255 self.assertFalse(it.can_seek_beginning)
256
257 # Once can_seek_beginning returns an error, verify that it raises when
258 # _can_seek_beginning has/returns the wrong type.
259
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
262 # beginning or not.
263 del MySourceIter._can_seek_beginning
264 self.assertTrue(it.can_seek_beginning)
265
266 del MySourceIter._seek_beginning
267 self.assertFalse(it.can_seek_beginning)
268
269 def test_seek_beginning(self):
270 it, MySourceIter = self._setup_seek_beginning_test()
271
272 msg = next(it)
273 self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
274 msg = next(it)
188edac1 275 self.assertIsInstance(msg, bt2.message._PacketBeginningMessage)
f00b8d40
SM
276
277 it.seek_beginning()
278
279 msg = next(it)
280 self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
281
282 # Verify that we can seek beginning after having reached the end.
283 #
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.
287 #
288 # try:
289 # while True:
290 # next(it)
291 # except bt2.Stop:
292 # pass
293 #
294 # it.seek_beginning()
295 # msg = next(it)
296 # self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
297
298 def test_seek_beginning_user_error(self):
299 it, MySourceIter = self._setup_seek_beginning_test()
300
301 def _seek_beginning_error(self):
302 raise ValueError('ouch')
303
304 MySourceIter._seek_beginning = _seek_beginning_error
305
306 with self.assertRaises(bt2.Error):
307 it.seek_beginning()
308
309
811644b8 310
5602ef81 311class OutputPortMessageIteratorTestCase(unittest.TestCase):
548bb510 312 def test_component(self):
5602ef81 313 class MyIter(bt2._UserMessageIterator):
c5f330cd 314 def __init__(self, self_port_output):
548bb510
PP
315 self._at = 0
316
548bb510 317 def __next__(self):
c5f330cd 318 if self._at == 7:
548bb510
PP
319 raise bt2.Stop
320
c5f330cd
SM
321 if self._at == 0:
322 msg = self._create_stream_beginning_message(test_obj._stream)
323 elif self._at == 1:
324 msg = self._create_packet_beginning_message(test_obj._packet)
325 elif self._at == 5:
326 msg = self._create_packet_end_message(test_obj._packet)
327 elif self._at == 6:
328 msg = self._create_stream_end_message(test_obj._stream)
329 else:
330 msg = self._create_event_message(test_obj._event_class, test_obj._packet)
331 msg.event.payload_field['my_int'] = self._at * 3
332
548bb510 333 self._at += 1
5602ef81 334 return msg
548bb510
PP
335
336 class MySource(bt2._UserSourceComponent,
5602ef81 337 message_iterator_class=MyIter):
548bb510
PP
338 def __init__(self, params):
339 self._add_output_port('out')
340
c5f330cd 341 trace_class = self._create_trace_class()
26fc5aed 342 stream_class = trace_class.create_stream_class(supports_packets=True)
c5f330cd
SM
343
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),
349 ])
350
351 event_class = stream_class.create_event_class(name='salut', payload_field_class=payload_ft)
352
353 trace = trace_class()
354 stream = trace.create_stream(stream_class)
355 packet = stream.create_packet()
356
357 test_obj._event_class = event_class
358 test_obj._stream = stream
359 test_obj._packet = packet
360
361 test_obj = self
548bb510
PP
362 graph = bt2.Graph()
363 src = graph.add_component(MySource, 'src')
c5f330cd 364 msg_iter = graph.create_output_port_message_iterator(src.output_ports['out'])
548bb510 365
5602ef81 366 for at, msg in enumerate(msg_iter):
c5f330cd
SM
367 if at == 0:
368 self.assertIsInstance(msg, bt2.message._StreamBeginningMessage)
369 elif at == 1:
370 self.assertIsInstance(msg, bt2.message._PacketBeginningMessage)
371 elif at == 5:
372 self.assertIsInstance(msg, bt2.message._PacketEndMessage)
373 elif at == 6:
374 self.assertIsInstance(msg, bt2.message._StreamEndMessage)
375 else:
376 self.assertIsInstance(msg, bt2.message._EventMessage)
e8ac1aae 377 self.assertEqual(msg.event.cls.name, 'salut')
c5f330cd
SM
378 field = msg.event.payload_field['my_int']
379 self.assertEqual(field, at * 3)
f00b8d40
SM
380
381if __name__ == '__main__':
382 unittest.main()
This page took 0.049853 seconds and 4 git commands to generate.