3a383fddd7ff911c92035562754b3e98f7005013
[babeltrace.git] / tests / bindings / python / bt2 / test_field_class.py
1 #
2 # Copyright (C) 2019 EfficiOS Inc.
3 #
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
7 # of the License.
8 #
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.
13 #
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.
17 #
18
19 import unittest
20 import bt2
21 from utils import get_default_trace_class, TestOutputPortMessageIterator
22 from bt2 import value as bt2_value
23 from bt2 import field_class as bt2_field_class
24
25
26 def _create_stream(tc, ctx_field_classes):
27 packet_context_fc = tc.create_structure_field_class()
28 for name, fc in ctx_field_classes:
29 packet_context_fc.append_member(name, fc)
30
31 trace = tc()
32 stream_class = tc.create_stream_class(
33 packet_context_field_class=packet_context_fc, supports_packets=True
34 )
35
36 stream = trace.create_stream(stream_class)
37 return stream
38
39
40 def _create_const_field_class(tc, field_class, value_setter_fn):
41 field_name = 'const field'
42
43 class MyIter(bt2._UserMessageIterator):
44 def __init__(self, self_port_output):
45 nonlocal field_class
46 nonlocal value_setter_fn
47 stream = _create_stream(tc, [(field_name, field_class)])
48 packet = stream.create_packet()
49
50 value_setter_fn(packet.context_field[field_name])
51
52 self._msgs = [
53 self._create_stream_beginning_message(stream),
54 self._create_packet_beginning_message(packet),
55 ]
56
57 def __next__(self):
58 if len(self._msgs) == 0:
59 raise StopIteration
60
61 return self._msgs.pop(0)
62
63 class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
64 def __init__(self, config, params, obj):
65 self._add_output_port('out', params)
66
67 graph = bt2.Graph()
68 src_comp = graph.add_component(MySrc, 'my_source', None)
69 msg_iter = TestOutputPortMessageIterator(graph, src_comp.output_ports['out'])
70
71 # Ignore first message, stream beginning
72 _ = next(msg_iter)
73 packet_beg_msg = next(msg_iter)
74
75 return packet_beg_msg.packet.context_field[field_name].cls
76
77
78 class _TestFieldClass:
79 def test_create_user_attributes(self):
80 fc = self._create_default_field_class(user_attributes={'salut': 23})
81 self.assertEqual(fc.user_attributes, {'salut': 23})
82 self.assertIs(type(fc.user_attributes), bt2_value.MapValue)
83
84 def test_const_create_user_attributes(self):
85 fc = self._create_default_const_field_class(user_attributes={'salut': 23})
86 self.assertEqual(fc.user_attributes, {'salut': 23})
87 self.assertIs(type(fc.user_attributes), bt2_value._MapValueConst)
88
89 def test_create_invalid_user_attributes(self):
90 with self.assertRaises(TypeError):
91 self._create_default_field_class(user_attributes=object())
92
93 def test_create_invalid_user_attributes_value_type(self):
94 with self.assertRaises(TypeError):
95 self._create_default_field_class(user_attributes=23)
96
97
98 class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase):
99 @staticmethod
100 def _const_value_setter(field):
101 field = False
102
103 def _create_default_field_class(self, **kwargs):
104 tc = get_default_trace_class()
105 return tc.create_bool_field_class(**kwargs)
106
107 def _create_default_const_field_class(self, *args, **kwargs):
108 tc = get_default_trace_class()
109 fc = tc.create_bool_field_class(*args, **kwargs)
110 return _create_const_field_class(tc, fc, self._const_value_setter)
111
112 def setUp(self):
113 self._fc = self._create_default_field_class()
114 self._fc_const = self._create_default_const_field_class()
115
116 def test_create_default(self):
117 self.assertIsNotNone(self._fc)
118 self.assertEqual(len(self._fc.user_attributes), 0)
119
120
121 class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase):
122 @staticmethod
123 def _const_value_setter(field):
124 field = []
125
126 def _create_field_class(self, *args, **kwargs):
127 tc = get_default_trace_class()
128 return tc.create_bit_array_field_class(*args, **kwargs)
129
130 def _create_default_field_class(self, **kwargs):
131 return self._create_field_class(17, **kwargs)
132
133 def _create_default_const_field_class(self, *args, **kwargs):
134 tc = get_default_trace_class()
135 fc = tc.create_bit_array_field_class(17, **kwargs)
136 return _create_const_field_class(tc, fc, self._const_value_setter)
137
138 def setUp(self):
139 self._fc = self._create_default_field_class()
140
141 def test_create_default(self):
142 self.assertIsNotNone(self._fc)
143 self.assertEqual(len(self._fc.user_attributes), 0)
144
145 def test_create_length_out_of_range(self):
146 with self.assertRaises(ValueError):
147 self._create_field_class(65)
148
149 def test_create_length_zero(self):
150 with self.assertRaises(ValueError):
151 self._create_field_class(0)
152
153 def test_create_length_invalid_type(self):
154 with self.assertRaises(TypeError):
155 self._create_field_class('lel')
156
157 def test_length_prop(self):
158 self.assertEqual(self._fc.length, 17)
159
160
161 class _TestIntegerFieldClassProps:
162 def test_create_default(self):
163 fc = self._create_default_field_class()
164 self.assertEqual(fc.field_value_range, 64)
165 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.DECIMAL)
166 self.assertEqual(len(fc.user_attributes), 0)
167
168 def test_create_range(self):
169 fc = self._create_field_class(field_value_range=35)
170 self.assertEqual(fc.field_value_range, 35)
171
172 fc = self._create_field_class(36)
173 self.assertEqual(fc.field_value_range, 36)
174
175 def test_create_invalid_range(self):
176 with self.assertRaises(TypeError):
177 self._create_field_class('yes')
178
179 with self.assertRaises(TypeError):
180 self._create_field_class(field_value_range='yes')
181
182 with self.assertRaises(ValueError):
183 self._create_field_class(field_value_range=-2)
184
185 with self.assertRaises(ValueError):
186 self._create_field_class(field_value_range=0)
187
188 def test_create_base(self):
189 fc = self._create_field_class(
190 preferred_display_base=bt2.IntegerDisplayBase.HEXADECIMAL
191 )
192 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.HEXADECIMAL)
193
194 def test_create_invalid_base_type(self):
195 with self.assertRaises(TypeError):
196 self._create_field_class(preferred_display_base='yes')
197
198 def test_create_invalid_base_value(self):
199 with self.assertRaises(ValueError):
200 self._create_field_class(preferred_display_base=444)
201
202 def test_create_full(self):
203 fc = self._create_field_class(
204 24, preferred_display_base=bt2.IntegerDisplayBase.OCTAL
205 )
206 self.assertEqual(fc.field_value_range, 24)
207 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.OCTAL)
208
209
210 class SignedIntegerFieldClassTestCase(
211 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
212 ):
213 @staticmethod
214 def _const_value_setter(field):
215 field = -18
216
217 def _create_field_class(self, *args, **kwargs):
218 tc = get_default_trace_class()
219 return tc.create_signed_integer_field_class(*args, **kwargs)
220
221 def _create_default_const_field_class(self, *args, **kwargs):
222 tc = get_default_trace_class()
223 fc = tc.create_signed_integer_field_class(*args, **kwargs)
224 return _create_const_field_class(tc, fc, self._const_value_setter)
225
226 _create_default_field_class = _create_field_class
227
228
229 class UnsignedIntegerFieldClassTestCase(
230 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
231 ):
232 @staticmethod
233 def _const_value_setter(field):
234 field = 18
235
236 def _create_field_class(self, *args, **kwargs):
237 tc = get_default_trace_class()
238 return tc.create_unsigned_integer_field_class(*args, **kwargs)
239
240 def _create_default_const_field_class(self, *args, **kwargs):
241 tc = get_default_trace_class()
242 fc = tc.create_signed_integer_field_class(*args, **kwargs)
243 return _create_const_field_class(tc, fc, self._const_value_setter)
244
245 _create_default_field_class = _create_field_class
246
247
248 class RealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
249 @staticmethod
250 def _const_value_setter(field):
251 field = -18
252
253 def _create_field_class(self, *args, **kwargs):
254 tc = get_default_trace_class()
255 return tc.create_real_field_class(*args, **kwargs)
256
257 def _create_default_const_field_class(self, *args, **kwargs):
258 tc = get_default_trace_class()
259 fc = tc.create_real_field_class(*args, **kwargs)
260 return _create_const_field_class(tc, fc, self._const_value_setter)
261
262 _create_default_field_class = _create_field_class
263
264 def test_create_default(self):
265 fc = self._create_field_class()
266 self.assertFalse(fc.is_single_precision)
267 self.assertEqual(len(fc.user_attributes), 0)
268
269 def test_create_is_single_precision(self):
270 fc = self._create_field_class(is_single_precision=True)
271 self.assertTrue(fc.is_single_precision)
272
273 def test_create_invalid_is_single_precision(self):
274 with self.assertRaises(TypeError):
275 self._create_field_class(is_single_precision='hohoho')
276
277
278 # Converts an _EnumerationFieldClassMapping to a list of ranges:
279 #
280 # [(lower0, upper0), (lower1, upper1), ...]
281
282
283 def enum_mapping_to_set(mapping):
284 return {(x.lower, x.upper) for x in mapping.ranges}
285
286
287 class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
288 def setUp(self):
289 self._spec_set_up()
290 self._fc = self._create_default_field_class()
291 self._fc_const = self._create_default_const_field_class()
292
293 def test_create_from_invalid_type(self):
294 with self.assertRaises(TypeError):
295 self._create_field_class('coucou')
296
297 def test_add_mapping_simple(self):
298 self._fc.add_mapping('hello', self._ranges1)
299 mapping = self._fc['hello']
300 self.assertEqual(mapping.label, 'hello')
301 self.assertEqual(mapping.ranges, self._ranges1)
302
303 def test_const_add_mapping(self):
304 with self.assertRaises(AttributeError):
305 self._fc_const.add_mapping('hello', self._ranges1)
306
307 def test_add_mapping_simple_kwargs(self):
308 self._fc.add_mapping(label='hello', ranges=self._ranges1)
309 mapping = self._fc['hello']
310 self.assertEqual(mapping.label, 'hello')
311 self.assertEqual(mapping.ranges, self._ranges1)
312
313 def test_add_mapping_invalid_name(self):
314 with self.assertRaises(TypeError):
315 self._fc.add_mapping(17, self._ranges1)
316
317 def test_add_mapping_invalid_range(self):
318 with self.assertRaises(TypeError):
319 self._fc.add_mapping('allo', 'meow')
320
321 def test_add_mapping_dup_label(self):
322 with self.assertRaises(ValueError):
323 self._fc.add_mapping('a', self._ranges1)
324 self._fc.add_mapping('a', self._ranges2)
325
326 def test_add_mapping_invalid_ranges_signedness(self):
327 with self.assertRaises(TypeError):
328 self._fc.add_mapping('allo', self._inval_ranges)
329
330 def test_iadd(self):
331 self._fc.add_mapping('c', self._ranges1)
332
333 self._fc += [('d', self._ranges2), ('e', self._ranges3)]
334
335 self.assertEqual(len(self._fc), 3)
336 self.assertEqual(self._fc['c'].label, 'c')
337 self.assertEqual(self._fc['c'].ranges, self._ranges1)
338 self.assertEqual(self._fc['d'].label, 'd')
339 self.assertEqual(self._fc['d'].ranges, self._ranges2)
340 self.assertEqual(self._fc['e'].label, 'e')
341 self.assertEqual(self._fc['e'].ranges, self._ranges3)
342
343 def test_const_iadd(self):
344 with self.assertRaises(TypeError):
345 self._fc_const += [('d', self._ranges2), ('e', self._ranges3)]
346
347 def test_bool_op(self):
348 self.assertFalse(self._fc)
349 self._fc.add_mapping('a', self._ranges1)
350 self.assertTrue(self._fc)
351
352 def test_len(self):
353 self._fc.add_mapping('a', self._ranges1)
354 self._fc.add_mapping('b', self._ranges2)
355 self._fc.add_mapping('c', self._ranges3)
356 self.assertEqual(len(self._fc), 3)
357
358 def test_getitem(self):
359 self._fc.add_mapping('a', self._ranges1)
360 self._fc.add_mapping('b', self._ranges2)
361 self._fc.add_mapping('c', self._ranges3)
362 mapping = self._fc['a']
363 self.assertEqual(mapping.label, 'a')
364 self.assertEqual(mapping.ranges, self._ranges1)
365
366 def test_getitem_nonexistent(self):
367 with self.assertRaises(KeyError):
368 self._fc['doesnotexist']
369
370 def test_iter(self):
371 self._fc.add_mapping('a', self._ranges1)
372 self._fc.add_mapping('b', self._ranges2)
373 self._fc.add_mapping('c', self._ranges3)
374
375 # This exercises iteration.
376 labels = sorted(self._fc)
377
378 self.assertEqual(labels, ['a', 'b', 'c'])
379
380 def test_find_by_value(self):
381 self._fc.add_mapping('a', self._ranges1)
382 self._fc.add_mapping('b', self._ranges2)
383 self._fc.add_mapping('c', self._ranges3)
384 mappings = self._fc.mappings_for_value(self._value_in_range_1_and_3)
385 labels = set([mapping.label for mapping in mappings])
386 expected_labels = set(['a', 'c'])
387 self.assertEqual(labels, expected_labels)
388
389
390 class UnsignedEnumerationFieldClassTestCase(
391 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
392 ):
393 def _spec_set_up(self):
394 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
395 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
396 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 22), (48, 99)])
397 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, -5), (48, 1928)])
398 self._value_in_range_1_and_3 = 20
399
400 @staticmethod
401 def _const_value_setter(field):
402 field = 0
403
404 def _create_field_class(self, *args, **kwargs):
405 tc = get_default_trace_class()
406 return tc.create_unsigned_enumeration_field_class(*args, **kwargs)
407
408 def _create_default_const_field_class(self, *args, **kwargs):
409 tc = get_default_trace_class()
410 fc = tc.create_unsigned_enumeration_field_class(*args, **kwargs)
411 return _create_const_field_class(tc, fc, self._const_value_setter)
412
413 _create_default_field_class = _create_field_class
414
415
416 class SignedEnumerationFieldClassTestCase(
417 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
418 ):
419 def _spec_set_up(self):
420 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
421 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
422 self._ranges3 = bt2.SignedIntegerRangeSet([(-100, -1), (8, 16), (48, 99)])
423 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
424 self._value_in_range_1_and_3 = -7
425
426 @staticmethod
427 def _const_value_setter(field):
428 field = 0
429
430 def _create_field_class(self, *args, **kwargs):
431 tc = get_default_trace_class()
432 return tc.create_signed_enumeration_field_class(*args, **kwargs)
433
434 def _create_default_const_field_class(self, *args, **kwargs):
435 tc = get_default_trace_class()
436 fc = tc.create_signed_enumeration_field_class(*args, **kwargs)
437 return _create_const_field_class(tc, fc, self._const_value_setter)
438
439 _create_default_field_class = _create_field_class
440
441
442 class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase):
443 @staticmethod
444 def _const_value_setter(field):
445 field = 'chaine'
446
447 def _create_field_class(self, *args, **kwargs):
448 tc = get_default_trace_class()
449 return tc.create_string_field_class(*args, **kwargs)
450
451 def _create_default_const_field_class(self, *args, **kwargs):
452 tc = get_default_trace_class()
453 fc = tc.create_string_field_class(*args, **kwargs)
454 return _create_const_field_class(tc, fc, self._const_value_setter)
455
456 _create_default_field_class = _create_field_class
457
458 def setUp(self):
459 self._fc = self._create_default_field_class()
460
461 def test_create_default(self):
462 self.assertIsNotNone(self._fc)
463 self.assertEqual(len(self._fc.user_attributes), 0)
464
465
466 class _TestElementContainer:
467 def setUp(self):
468 self._tc = get_default_trace_class()
469 self._fc = self._create_default_field_class()
470 self._fc_const = self._create_default_const_field_class()
471
472 def test_create_default(self):
473 self.assertIsNotNone(self._fc)
474 self.assertEqual(len(self._fc.user_attributes), 0)
475
476 def test_append_element(self):
477 int_field_class = self._tc.create_signed_integer_field_class(32)
478 self._append_element_method(self._fc, 'int32', int_field_class)
479 field_class = self._fc['int32'].field_class
480 self.assertEqual(field_class.addr, int_field_class.addr)
481
482 def test_append_element_kwargs(self):
483 int_field_class = self._tc.create_signed_integer_field_class(32)
484 self._append_element_method(self._fc, name='int32', field_class=int_field_class)
485 field_class = self._fc['int32'].field_class
486 self.assertEqual(field_class.addr, int_field_class.addr)
487
488 def test_append_element_invalid_name(self):
489 sub_fc = self._tc.create_string_field_class()
490
491 with self.assertRaises(TypeError):
492 self._append_element_method(self._fc, 23, sub_fc)
493
494 def test_append_element_invalid_field_class(self):
495 with self.assertRaises(TypeError):
496 self._append_element_method(self._fc, 'yes', object())
497
498 def test_append_element_dup_name(self):
499 sub_fc1 = self._tc.create_string_field_class()
500 sub_fc2 = self._tc.create_string_field_class()
501
502 with self.assertRaises(ValueError):
503 self._append_element_method(self._fc, 'yes', sub_fc1)
504 self._append_element_method(self._fc, 'yes', sub_fc2)
505
506 def test_attr_field_class(self):
507 int_field_class = self._tc.create_signed_integer_field_class(32)
508 self._append_element_method(self._fc, 'int32', int_field_class)
509 field_class = self._fc['int32'].field_class
510
511 self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClass)
512
513 def test_const_attr_field_class(self):
514 int_field_class = self._tc.create_signed_integer_field_class(32)
515 self._append_element_method(self._fc, 'int32', int_field_class)
516 field_class = self._fc['int32'].field_class
517 const_fc = _create_const_field_class(
518 self._tc, self._fc, self._const_value_setter
519 )
520 field_class = const_fc['int32'].field_class
521
522 self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClassConst)
523
524 def test_iadd(self):
525 a_field_class = self._tc.create_real_field_class()
526 b_field_class = self._tc.create_signed_integer_field_class(17)
527 self._append_element_method(self._fc, 'a_float', a_field_class)
528 self._append_element_method(self._fc, 'b_int', b_field_class)
529 c_field_class = self._tc.create_string_field_class()
530 d_field_class = self._tc.create_signed_enumeration_field_class(
531 field_value_range=32
532 )
533 e_field_class = self._tc.create_structure_field_class()
534 self._fc += [
535 ('c_string', c_field_class),
536 ('d_enum', d_field_class),
537 ('e_struct', e_field_class),
538 ]
539 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
540 self.assertEqual(self._fc['a_float'].name, 'a_float')
541 self.assertEqual(self._fc['b_int'].field_class.addr, b_field_class.addr)
542 self.assertEqual(self._fc['b_int'].name, 'b_int')
543 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
544 self.assertEqual(self._fc['c_string'].name, 'c_string')
545 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
546 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
547 self.assertEqual(self._fc['e_struct'].field_class.addr, e_field_class.addr)
548 self.assertEqual(self._fc['e_struct'].name, 'e_struct')
549
550 def test_const_iadd(self):
551 a_field_class = self._tc.create_real_field_class()
552 with self.assertRaises(TypeError):
553 self._fc_const += a_field_class
554
555 def test_bool_op(self):
556 self.assertFalse(self._fc)
557 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
558 self.assertTrue(self._fc)
559
560 def test_len(self):
561 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
562 self._append_element_method(self._fc, 'b', self._tc.create_string_field_class())
563 self._append_element_method(self._fc, 'c', self._tc.create_string_field_class())
564 self.assertEqual(len(self._fc), 3)
565
566 def test_getitem(self):
567 a_fc = self._tc.create_signed_integer_field_class(32)
568 b_fc = self._tc.create_string_field_class()
569 c_fc = self._tc.create_real_field_class()
570 self._append_element_method(self._fc, 'a', a_fc)
571 self._append_element_method(self._fc, 'b', b_fc)
572 self._append_element_method(self._fc, 'c', c_fc)
573 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
574 self.assertEqual(self._fc['b'].name, 'b')
575
576 def test_getitem_invalid_key_type(self):
577 with self.assertRaises(TypeError):
578 self._fc[0]
579
580 def test_getitem_invalid_key(self):
581 with self.assertRaises(KeyError):
582 self._fc['no way']
583
584 def test_contains(self):
585 self.assertFalse('a' in self._fc)
586 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
587 self.assertTrue('a' in self._fc)
588
589 def test_iter(self):
590 a_fc = self._tc.create_signed_integer_field_class(32)
591 b_fc = self._tc.create_string_field_class()
592 c_fc = self._tc.create_real_field_class()
593 elements = (('a', a_fc), ('b', b_fc), ('c', c_fc))
594
595 for elem in elements:
596 self._append_element_method(self._fc, *elem)
597
598 for (name, element), test_elem in zip(self._fc.items(), elements):
599 self.assertEqual(element.name, test_elem[0])
600 self.assertEqual(name, element.name)
601 self.assertEqual(element.field_class.addr, test_elem[1].addr)
602 self.assertEqual(len(element.user_attributes), 0)
603
604 def test_at_index(self):
605 a_fc = self._tc.create_signed_integer_field_class(32)
606 b_fc = self._tc.create_string_field_class()
607 c_fc = self._tc.create_real_field_class()
608 self._append_element_method(self._fc, 'c', c_fc)
609 self._append_element_method(self._fc, 'a', a_fc)
610 self._append_element_method(self._fc, 'b', b_fc)
611 elem = self._at_index_method(self._fc, 1)
612 self.assertEqual(elem.field_class.addr, a_fc.addr)
613 self.assertEqual(elem.name, 'a')
614
615 def test_at_index_invalid(self):
616 self._append_element_method(
617 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
618 )
619
620 with self.assertRaises(TypeError):
621 self._at_index_method(self._fc, 'yes')
622
623 def test_at_index_out_of_bounds_after(self):
624 self._append_element_method(
625 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
626 )
627
628 with self.assertRaises(IndexError):
629 self._at_index_method(self._fc, len(self._fc))
630
631 def test_user_attributes(self):
632 self._append_element_method(
633 self._fc,
634 'c',
635 self._tc.create_string_field_class(),
636 user_attributes={'salut': 23},
637 )
638 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
639 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
640 self.assertIs(type(self._fc['c'].user_attributes), bt2_value.MapValue)
641
642 def test_invalid_user_attributes(self):
643 with self.assertRaises(TypeError):
644 self._append_element_method(
645 self._fc,
646 'c',
647 self._tc.create_string_field_class(),
648 user_attributes=object(),
649 )
650
651 def test_invalid_user_attributes_value_type(self):
652 with self.assertRaises(TypeError):
653 self._append_element_method(
654 self._fc, 'c', self._tc.create_string_field_class(), user_attributes=23
655 )
656
657
658 class StructureFieldClassTestCase(
659 _TestFieldClass, _TestElementContainer, unittest.TestCase
660 ):
661 _append_element_method = staticmethod(bt2._StructureFieldClass.append_member)
662 _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index)
663
664 @staticmethod
665 def _const_value_setter(field):
666 field.value = {}
667
668 def _create_field_class(self, *args, **kwargs):
669 tc = get_default_trace_class()
670 return tc.create_structure_field_class(*args, **kwargs)
671
672 def _create_default_const_field_class(self, *args, **kwargs):
673 tc = get_default_trace_class()
674 fc = tc.create_structure_field_class(*args, **kwargs)
675 return _create_const_field_class(tc, fc, self._const_value_setter)
676
677 _create_default_field_class = _create_field_class
678
679 def test_const_member_field_class(self):
680 def _real_value_setter(field):
681 field.value = {'real': 0}
682
683 tc = get_default_trace_class()
684 fc = tc.create_structure_field_class()
685 member_fc = self._tc.create_real_field_class()
686 fc.append_member('real', member_fc)
687 const_fc = _create_const_field_class(tc, fc, _real_value_setter)
688
689 self.assertIs(
690 type(const_fc['real'].field_class), bt2_field_class._RealFieldClassConst
691 )
692
693 def test_member_field_class(self):
694 tc = get_default_trace_class()
695 fc = tc.create_structure_field_class()
696 member_fc = self._tc.create_real_field_class()
697 fc.append_member('real', member_fc)
698
699 self.assertIs(type(fc['real'].field_class), bt2_field_class._RealFieldClass)
700
701
702 class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
703 @staticmethod
704 def _const_value_setter(field):
705 field.has_field = True
706 field.value = 12
707
708 def _create_default_field_class(self, *args, **kwargs):
709 return self._tc.create_option_field_class(self._content_fc, **kwargs)
710
711 def _create_default_const_field_class(self, *args, **kwargs):
712 fc = self._tc.create_option_field_class(self._content_fc, **kwargs)
713 return _create_const_field_class(self._tc, fc, self._const_value_setter)
714
715 def setUp(self):
716 self._tc = get_default_trace_class()
717 self._content_fc = self._tc.create_signed_integer_field_class(23)
718 self._tag_fc = self._tc.create_bool_field_class()
719
720 def test_create_default(self):
721 fc = self._create_default_field_class()
722 self.assertEqual(fc.field_class.addr, self._content_fc.addr)
723 self.assertIsNone(fc.selector_field_path, None)
724 self.assertEqual(len(fc.user_attributes), 0)
725
726 def test_attr_field_class(self):
727 fc = self._create_default_field_class()
728 self.assertIs(type(fc.field_class), bt2_field_class._SignedIntegerFieldClass)
729
730 def test_const_attr_field_class(self):
731 fc = self._create_default_const_field_class()
732 self.assertIs(
733 type(fc.field_class), bt2_field_class._SignedIntegerFieldClassConst
734 )
735
736 def _create_field_class_for_field_path_test(self):
737 fc = self._create_default_field_class(selector_fc=self._tag_fc)
738
739 foo_fc = self._tc.create_real_field_class()
740 bar_fc = self._tc.create_string_field_class()
741 baz_fc = self._tc.create_string_field_class()
742
743 inner_struct_fc = self._tc.create_structure_field_class()
744 inner_struct_fc.append_member('bar', bar_fc)
745 inner_struct_fc.append_member('baz', baz_fc)
746 inner_struct_fc.append_member('tag', self._tag_fc)
747 inner_struct_fc.append_member('opt', fc)
748
749 opt_struct_array_fc = self._tc.create_option_field_class(inner_struct_fc)
750
751 outer_struct_fc = self._tc.create_structure_field_class()
752 outer_struct_fc.append_member('foo', foo_fc)
753 outer_struct_fc.append_member('inner_opt', opt_struct_array_fc)
754
755 # The path to the selector field class is resolved when the
756 # option field class is actually used, for example in a packet
757 # context.
758 self._tc.create_stream_class(
759 packet_context_field_class=outer_struct_fc, supports_packets=True
760 )
761
762 return fc
763
764 def test_field_path_len(self):
765 fc = self._create_field_class_for_field_path_test()
766 self.assertEqual(len(fc.selector_field_path), 3)
767
768 def test_field_path_iter(self):
769 fc = self._create_field_class_for_field_path_test()
770 path_items = list(fc.selector_field_path)
771
772 self.assertEqual(len(path_items), 3)
773
774 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
775 self.assertEqual(path_items[0].index, 1)
776
777 self.assertIsInstance(path_items[1], bt2._CurrentOptionContentFieldPathItem)
778
779 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
780 self.assertEqual(path_items[2].index, 2)
781
782 def test_field_path_root_scope(self):
783 fc = self._create_field_class_for_field_path_test()
784 self.assertEqual(
785 fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
786 )
787
788 def test_create_invalid_field_class(self):
789 with self.assertRaises(TypeError):
790 self._tc.create_option_field_class(object())
791
792 def test_create_invalid_selector_type(self):
793 with self.assertRaises(TypeError):
794 self._tc.create_option_field_class(self._content_fc, 17)
795
796
797 class VariantFieldClassWithoutSelectorTestCase(
798 _TestFieldClass, _TestElementContainer, unittest.TestCase
799 ):
800 _append_element_method = staticmethod(
801 bt2._VariantFieldClassWithoutSelector.append_option
802 )
803 _at_index_method = staticmethod(
804 bt2._VariantFieldClassWithoutSelector.option_at_index
805 )
806
807 @staticmethod
808 def _const_value_setter(variant_field):
809 variant_field.selected_option_index = 0
810 variant_field.value = 12
811
812 def _create_field_class(self, *args, **kwargs):
813 tc = get_default_trace_class()
814 return tc.create_variant_field_class(*args, **kwargs)
815
816 def _create_default_const_field_class(self, *args, **kwargs):
817 tc = get_default_trace_class()
818 fc = tc.create_variant_field_class(*args, **kwargs)
819 int_field_class = self._tc.create_signed_integer_field_class(32)
820 fc.append_option('int32', int_field_class)
821
822 return _create_const_field_class(tc, fc, self._const_value_setter)
823
824 _create_default_field_class = _create_field_class
825
826
827 class _VariantFieldClassWithSelectorTestCase:
828 @staticmethod
829 def _const_value_setter(field):
830 field['variant'].selected_option_index = 0
831 field['variant'] = 12
832
833 def _create_default_field_class(self, *args, **kwargs):
834 return self._tc.create_variant_field_class(
835 *args, selector_fc=self._selector_fc, **kwargs
836 )
837
838 def _create_default_const_field_class(self, *args, **kwargs):
839 # Create a struct to contain the variant and its selector else we can't
840 # create the non-const field necessary to get the the const field_class
841 struct_fc = self._tc.create_structure_field_class()
842 struct_fc.append_member('selecteux', self._selector_fc)
843 variant_fc = self._tc.create_variant_field_class(
844 *args, selector_fc=self._selector_fc
845 )
846 variant_fc.append_option(
847 'a', self._tc.create_signed_integer_field_class(32), self._ranges1
848 )
849 struct_fc.append_member('variant', variant_fc, **kwargs)
850
851 return _create_const_field_class(self._tc, struct_fc, self._const_value_setter)[
852 'variant'
853 ].field_class
854
855 def setUp(self):
856 self._tc = get_default_trace_class()
857 self._spec_set_up()
858 self._fc = self._create_default_field_class()
859
860 def test_create_default(self):
861 self.assertIsNotNone(self._fc)
862 self.assertEqual(len(self._fc.user_attributes), 0)
863
864 def test_append_element(self):
865 str_field_class = self._tc.create_string_field_class()
866 self._fc.append_option('str', str_field_class, self._ranges1)
867 opt = self._fc['str']
868 self.assertEqual(opt.field_class.addr, str_field_class.addr)
869 self.assertEqual(opt.name, 'str')
870 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
871
872 def test_const_append(self):
873 fc_const = self._create_default_const_field_class()
874 with self.assertRaises(AttributeError):
875 fc_const.append_option('str', str_field_class, self._ranges1)
876
877 def test_append_element_kwargs(self):
878 int_field_class = self._tc.create_signed_integer_field_class(32)
879 self._fc.append_option(
880 name='int32', field_class=int_field_class, ranges=self._ranges1
881 )
882 opt = self._fc['int32']
883 self.assertEqual(opt.field_class.addr, int_field_class.addr)
884 self.assertEqual(opt.name, 'int32')
885 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
886
887 def test_append_element_invalid_name(self):
888 sub_fc = self._tc.create_string_field_class()
889
890 with self.assertRaises(TypeError):
891 self._fc.append_option(self._fc, 23, sub_fc)
892
893 def test_append_element_invalid_field_class(self):
894 with self.assertRaises(TypeError):
895 self._fc.append_option(self._fc, 'yes', object())
896
897 def test_append_element_invalid_ranges(self):
898 sub_fc = self._tc.create_string_field_class()
899
900 with self.assertRaises(TypeError):
901 self._fc.append_option(self._fc, sub_fc, 'lel')
902
903 def test_append_element_dup_name(self):
904 sub_fc1 = self._tc.create_string_field_class()
905 sub_fc2 = self._tc.create_string_field_class()
906
907 with self.assertRaises(ValueError):
908 self._fc.append_option('yes', sub_fc1, self._ranges1)
909 self._fc.append_option('yes', sub_fc2, self._ranges2)
910
911 def test_append_element_invalid_ranges_signedness(self):
912 sub_fc = self._tc.create_string_field_class()
913
914 with self.assertRaises(TypeError):
915 self._fc.append_option(self._fc, sub_fc, self._inval_ranges)
916
917 def test_user_attributes(self):
918 self._fc.append_option(
919 'c',
920 self._tc.create_string_field_class(),
921 self._ranges1,
922 user_attributes={'salut': 23},
923 )
924 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
925 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
926
927 def test_const_user_attributes(self):
928 fc_const = self._create_default_const_field_class()
929 self.assertIs(type(fc_const.user_attributes), bt2_value._MapValueConst)
930
931 def test_invalid_user_attributes(self):
932 with self.assertRaises(TypeError):
933 self._fc.append_option(
934 'c',
935 self._tc.create_string_field_class(),
936 self._ranges1,
937 user_attributes=object(),
938 )
939
940 def test_invalid_user_attributes_value_type(self):
941 with self.assertRaises(TypeError):
942 self._fc.append_option(
943 'c',
944 self._tc.create_string_field_class(),
945 self._ranges1,
946 user_attributes=23,
947 )
948
949 def test_iadd(self):
950 a_field_class = self._tc.create_real_field_class()
951 self._fc.append_option('a_float', a_field_class, self._ranges1)
952 c_field_class = self._tc.create_string_field_class()
953 d_field_class = self._tc.create_signed_enumeration_field_class(
954 field_value_range=32
955 )
956 self._fc += [
957 ('c_string', c_field_class, self._ranges2),
958 ('d_enum', d_field_class, self._ranges3),
959 ]
960 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
961 self.assertEqual(self._fc['a_float'].name, 'a_float')
962 self.assertEqual(self._fc['a_float'].ranges, self._ranges1)
963 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
964 self.assertEqual(self._fc['c_string'].name, 'c_string')
965 self.assertEqual(self._fc['c_string'].ranges, self._ranges2)
966 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
967 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
968 self.assertEqual(self._fc['d_enum'].ranges, self._ranges3)
969
970 def test_const_iadd(self):
971 fc_const = self._create_default_const_field_class()
972 a_field_class = self._tc.create_real_field_class()
973 with self.assertRaises(TypeError):
974 fc_const += [('a_float', a_field_class, self._ranges1)]
975
976 def test_bool_op(self):
977 self.assertFalse(self._fc)
978 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
979 self.assertTrue(self._fc)
980
981 def test_len(self):
982 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
983 self._fc.append_option('b', self._tc.create_string_field_class(), self._ranges2)
984 self._fc.append_option('c', self._tc.create_string_field_class(), self._ranges3)
985 self.assertEqual(len(self._fc), 3)
986
987 def test_getitem(self):
988 a_fc = self._tc.create_signed_integer_field_class(32)
989 b_fc = self._tc.create_string_field_class()
990 c_fc = self._tc.create_real_field_class()
991 self._fc.append_option('a', a_fc, self._ranges1)
992 self._fc.append_option('b', b_fc, self._ranges2)
993 self._fc.append_option('c', c_fc, self._ranges3)
994 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
995 self.assertEqual(self._fc['b'].name, 'b')
996 self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr)
997
998 def test_option_field_class(self):
999 a_fc = self._tc.create_signed_integer_field_class(32)
1000 self._fc.append_option('a', a_fc, self._ranges1)
1001 self.assertIs(
1002 type(self._fc['a'].field_class), bt2_field_class._SignedIntegerFieldClass
1003 )
1004
1005 def test_const_option_field_class(self):
1006 fc_const = self._create_default_const_field_class()
1007 self.assertIs(
1008 type(fc_const['a'].field_class),
1009 bt2_field_class._SignedIntegerFieldClassConst,
1010 )
1011
1012 def test_getitem_invalid_key_type(self):
1013 with self.assertRaises(TypeError):
1014 self._fc[0]
1015
1016 def test_getitem_invalid_key(self):
1017 with self.assertRaises(KeyError):
1018 self._fc['no way']
1019
1020 def test_contains(self):
1021 self.assertFalse('a' in self._fc)
1022 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
1023 self.assertTrue('a' in self._fc)
1024
1025 def test_iter(self):
1026 a_fc = self._tc.create_signed_integer_field_class(32)
1027 b_fc = self._tc.create_string_field_class()
1028 c_fc = self._tc.create_real_field_class()
1029 opts = (
1030 ('a', a_fc, self._ranges1),
1031 ('b', b_fc, self._ranges2),
1032 ('c', c_fc, self._ranges3),
1033 )
1034
1035 for opt in opts:
1036 self._fc.append_option(*opt)
1037
1038 for (name, opt), test_opt in zip(self._fc.items(), opts):
1039 self.assertEqual(opt.name, test_opt[0])
1040 self.assertEqual(name, opt.name)
1041 self.assertEqual(opt.field_class.addr, test_opt[1].addr)
1042 self.assertEqual(opt.ranges.addr, test_opt[2].addr)
1043
1044 def test_at_index(self):
1045 a_fc = self._tc.create_signed_integer_field_class(32)
1046 b_fc = self._tc.create_string_field_class()
1047 c_fc = self._tc.create_real_field_class()
1048 self._fc.append_option('c', c_fc, self._ranges1)
1049 self._fc.append_option('a', a_fc, self._ranges2)
1050 self._fc.append_option('b', b_fc, self._ranges3)
1051 self.assertEqual(self._fc.option_at_index(1).field_class.addr, a_fc.addr)
1052 self.assertEqual(self._fc.option_at_index(1).name, 'a')
1053 self.assertEqual(self._fc.option_at_index(1).ranges.addr, self._ranges2.addr)
1054
1055 def test_at_index_invalid(self):
1056 self._fc.append_option(
1057 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1058 )
1059
1060 with self.assertRaises(TypeError):
1061 self._fc.option_at_index('yes')
1062
1063 def test_at_index_out_of_bounds_after(self):
1064 self._fc.append_option(
1065 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1066 )
1067
1068 with self.assertRaises(IndexError):
1069 self._fc.option_at_index(len(self._fc))
1070
1071 def _fill_default_fc_for_field_path_test(self):
1072 # Create something equivalent to:
1073 #
1074 # struct outer_struct_fc {
1075 # real foo;
1076 # struct inner_struct_fc {
1077 # [u]int64_t selector;
1078 # string bar;
1079 # string baz;
1080 # variant <selector> {
1081 # real a; // selected with self._ranges1
1082 # int21_t b; // selected with self._ranges2
1083 # uint34_t c; // selected with self._ranges3
1084 # } variant;
1085 # } inner_struct[2];
1086 # };
1087 self._fc.append_option('a', self._tc.create_real_field_class(), self._ranges1)
1088 self._fc.append_option(
1089 'b', self._tc.create_signed_integer_field_class(21), self._ranges2
1090 )
1091 self._fc.append_option(
1092 'c', self._tc.create_unsigned_integer_field_class(34), self._ranges3
1093 )
1094
1095 foo_fc = self._tc.create_real_field_class()
1096 bar_fc = self._tc.create_string_field_class()
1097 baz_fc = self._tc.create_string_field_class()
1098
1099 inner_struct_fc = self._tc.create_structure_field_class()
1100 inner_struct_fc.append_member('selector', self._selector_fc)
1101 inner_struct_fc.append_member('bar', bar_fc)
1102 inner_struct_fc.append_member('baz', baz_fc)
1103 inner_struct_fc.append_member('variant', self._fc)
1104
1105 inner_struct_array_fc = self._tc.create_static_array_field_class(
1106 inner_struct_fc, 2
1107 )
1108
1109 outer_struct_fc = self._tc.create_structure_field_class()
1110 outer_struct_fc.append_member('foo', foo_fc)
1111 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
1112
1113 # The path to the selector field is resolved when the sequence is
1114 # actually used, for example in a packet context.
1115 self._tc.create_stream_class(
1116 supports_packets=True, packet_context_field_class=outer_struct_fc
1117 )
1118
1119 def test_selector_field_path_length(self):
1120 self._fill_default_fc_for_field_path_test()
1121 self.assertEqual(len(self._fc.selector_field_path), 3)
1122
1123 def test_selector_field_path_iter(self):
1124 self._fill_default_fc_for_field_path_test()
1125 path_items = list(self._fc.selector_field_path)
1126
1127 self.assertEqual(len(path_items), 3)
1128
1129 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
1130 self.assertEqual(path_items[0].index, 1)
1131
1132 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
1133
1134 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
1135 self.assertEqual(path_items[2].index, 0)
1136
1137 def test_selector_field_path_root_scope(self):
1138 self._fill_default_fc_for_field_path_test()
1139 self.assertEqual(
1140 self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
1141 )
1142
1143
1144 class VariantFieldClassWithUnsignedSelectorTestCase(
1145 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1146 ):
1147 def _spec_set_up(self):
1148 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
1149 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
1150 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1151 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, 16), (48, 99)])
1152 self._selector_fc = self._tc.create_unsigned_integer_field_class()
1153
1154
1155 class VariantFieldClassWithSignedSelectorTestCase(
1156 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1157 ):
1158 def _spec_set_up(self):
1159 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
1160 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
1161 self._ranges3 = bt2.SignedIntegerRangeSet([(8, 16), (48, 99)])
1162 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1163 self._selector_fc = self._tc.create_signed_integer_field_class()
1164
1165
1166 class _ArrayFieldClassTestCase:
1167 def test_attr_element_field_class(self):
1168 fc = self._create_array()
1169 self.assertIs(
1170 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClass
1171 )
1172
1173 def test_const_attr_element_field_class(self):
1174 fc = self._create_const_array()
1175 self.assertIs(
1176 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClassConst
1177 )
1178
1179
1180 class StaticArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1181 @staticmethod
1182 def _const_value_setter(field):
1183 field = []
1184
1185 def _create_array(self):
1186 return self._tc.create_static_array_field_class(self._elem_fc, 45)
1187
1188 def _create_const_array(self):
1189 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1190 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1191
1192 def setUp(self):
1193 self._tc = get_default_trace_class()
1194 self._elem_fc = self._tc.create_signed_integer_field_class(23)
1195
1196 def test_create_default(self):
1197 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1198 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1199 self.assertEqual(fc.length, 45)
1200 self.assertEqual(len(fc.user_attributes), 0)
1201
1202 def test_create_invalid_elem_field_class(self):
1203 with self.assertRaises(TypeError):
1204 self._tc.create_static_array_field_class(object(), 45)
1205
1206 def test_create_invalid_length(self):
1207 with self.assertRaises(ValueError):
1208 self._tc.create_static_array_field_class(
1209 self._tc.create_string_field_class(), -17
1210 )
1211
1212 def test_create_invalid_length_type(self):
1213 with self.assertRaises(TypeError):
1214 self._tc.create_static_array_field_class(
1215 self._tc.create_string_field_class(), 'the length'
1216 )
1217
1218
1219 class DynamicArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1220 @staticmethod
1221 def _const_value_setter(field):
1222 field = []
1223
1224 def _create_array(self):
1225 return self._tc.create_dynamic_array_field_class(self._elem_fc)
1226
1227 def _create_const_array(self):
1228 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1229 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1230
1231 def setUp(self):
1232 self._tc = get_default_trace_class()
1233 self._elem_fc = self._tc.create_signed_integer_field_class(23)
1234 self._len_fc = self._tc.create_unsigned_integer_field_class(12)
1235
1236 def test_create_default(self):
1237 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1238 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1239 self.assertIsNone(fc.length_field_path, None)
1240 self.assertEqual(len(fc.user_attributes), 0)
1241
1242 def _create_field_class_for_field_path_test(self):
1243 # Create something a field class that is equivalent to:
1244 #
1245 # struct outer_struct_fc {
1246 # real foo;
1247 # struct inner_struct_fc {
1248 # string bar;
1249 # string baz;
1250 # uint12_t len;
1251 # uint23_t dyn_array[len];
1252 # } inner_struct[2];
1253 # };
1254
1255 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
1256
1257 foo_fc = self._tc.create_real_field_class()
1258 bar_fc = self._tc.create_string_field_class()
1259 baz_fc = self._tc.create_string_field_class()
1260
1261 inner_struct_fc = self._tc.create_structure_field_class()
1262 inner_struct_fc.append_member('bar', bar_fc)
1263 inner_struct_fc.append_member('baz', baz_fc)
1264 inner_struct_fc.append_member('len', self._len_fc)
1265 inner_struct_fc.append_member('dyn_array', fc)
1266
1267 inner_struct_array_fc = self._tc.create_static_array_field_class(
1268 inner_struct_fc, 2
1269 )
1270
1271 outer_struct_fc = self._tc.create_structure_field_class()
1272 outer_struct_fc.append_member('foo', foo_fc)
1273 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
1274
1275 # The path to the length field is resolved when the sequence is
1276 # actually used, for example in a packet context.
1277 self._tc.create_stream_class(
1278 packet_context_field_class=outer_struct_fc, supports_packets=True
1279 )
1280
1281 return fc
1282
1283 def test_field_path_len(self):
1284 fc = self._create_field_class_for_field_path_test()
1285 self.assertEqual(len(fc.length_field_path), 3)
1286
1287 def test_field_path_iter(self):
1288 fc = self._create_field_class_for_field_path_test()
1289 path_items = list(fc.length_field_path)
1290
1291 self.assertEqual(len(path_items), 3)
1292
1293 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
1294 self.assertEqual(path_items[0].index, 1)
1295
1296 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
1297
1298 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
1299 self.assertEqual(path_items[2].index, 2)
1300
1301 def test_field_path_root_scope(self):
1302 fc = self._create_field_class_for_field_path_test()
1303 self.assertEqual(
1304 fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
1305 )
1306
1307 def test_create_invalid_field_class(self):
1308 with self.assertRaises(TypeError):
1309 self._tc.create_dynamic_array_field_class(object())
1310
1311 def test_create_invalid_length_type(self):
1312 with self.assertRaises(TypeError):
1313 self._tc.create_dynamic_array_field_class(
1314 self._tc.create_string_field_class(), 17
1315 )
1316
1317
1318 if __name__ == "__main__":
1319 unittest.main()
This page took 0.109504 seconds and 3 git commands to generate.