4ca01d866b98fa4a2c797b2f3f19563ec9e23a9f
[babeltrace.git] / tests / bindings / python / bt2 / test_field_class.py
1 import bt2.field
2 import unittest
3 import bt2
4 from utils import get_default_trace_class
5
6
7 class _TestIntegerFieldClassProps:
8 def test_create_default(self):
9 fc = self._create_func()
10 self.assertEqual(fc.field_value_range, 64)
11 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.DECIMAL)
12
13 def test_create_range(self):
14 fc = self._create_func(field_value_range=35)
15 self.assertEqual(fc.field_value_range, 35)
16
17 fc = self._create_func(36)
18 self.assertEqual(fc.field_value_range, 36)
19
20 def test_create_invalid_range(self):
21 with self.assertRaises(TypeError):
22 self._create_func('yes')
23
24 with self.assertRaises(TypeError):
25 self._create_func(field_value_range='yes')
26
27 with self.assertRaises(ValueError):
28 self._create_func(field_value_range=-2)
29
30 with self.assertRaises(ValueError):
31 self._create_func(field_value_range=0)
32
33 def test_create_base(self):
34 fc = self._create_func(preferred_display_base=bt2.IntegerDisplayBase.HEXADECIMAL)
35 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.HEXADECIMAL)
36
37 def test_create_invalid_base_type(self):
38 with self.assertRaises(TypeError):
39 self._create_func(preferred_display_base='yes')
40
41 def test_create_invalid_base_value(self):
42 with self.assertRaises(ValueError):
43 self._create_func(preferred_display_base=444)
44
45 def test_create_full(self):
46 fc = self._create_func(24, preferred_display_base=bt2.IntegerDisplayBase.OCTAL)
47 self.assertEqual(fc.field_value_range, 24)
48 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.OCTAL)
49
50
51 class IntegerFieldClassTestCase(_TestIntegerFieldClassProps, unittest.TestCase):
52 def setUp(self):
53 self._tc = get_default_trace_class()
54 self._create_func = self._tc.create_signed_integer_field_class
55
56
57 class RealFieldClassTestCase(unittest.TestCase):
58 def setUp(self):
59 self._tc = get_default_trace_class()
60
61 def test_create_default(self):
62 fc = self._tc.create_real_field_class()
63 self.assertFalse(fc.is_single_precision)
64
65 def test_create_is_single_precision(self):
66 fc = self._tc.create_real_field_class(is_single_precision=True)
67 self.assertTrue(fc.is_single_precision)
68
69 def test_create_invalid_is_single_precision(self):
70 with self.assertRaises(TypeError):
71 self._tc.create_real_field_class(is_single_precision='hohoho')
72
73
74 # Converts an _EnumerationFieldClassMapping to a list of ranges:
75 #
76 # [(lower0, upper0), (lower1, upper1), ...]
77
78 def enum_mapping_to_list(mapping):
79 return sorted([(x.lower, x.upper) for x in mapping])
80
81
82 class EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
83 def setUp(self):
84 self._tc = get_default_trace_class()
85
86 def test_create_from_invalid_type(self):
87 with self.assertRaises(TypeError):
88 self._create_func('coucou')
89
90 def test_add_mapping_simple(self):
91 self._fc.map_range('hello', 24)
92 mapping = self._fc['hello']
93 self.assertEqual(mapping.label, 'hello')
94
95 ranges = enum_mapping_to_list(mapping)
96 self.assertEqual(ranges, [(24, 24)])
97
98 def test_add_mapping_simple_kwargs(self):
99 self._fc.map_range(label='hello', lower=17, upper=23)
100 mapping = self._fc['hello']
101 self.assertEqual(mapping.label, 'hello')
102
103 ranges = enum_mapping_to_list(mapping)
104 self.assertEqual(ranges, [(17, 23)])
105
106 def test_add_mapping_range(self):
107 self._fc.map_range('hello', 21, 199)
108 mapping = self._fc['hello']
109 self.assertEqual(mapping.label, 'hello')
110
111 ranges = enum_mapping_to_list(mapping)
112 self.assertEqual(ranges, [(21, 199)])
113
114 def test_add_mapping_invalid_name(self):
115 with self.assertRaises(TypeError):
116 self._fc.map_range(17, 21, 199)
117
118 def test_iadd(self):
119 enum_fc = self._tc.create_signed_enumeration_field_class(field_value_range=16)
120 enum_fc.map_range('c', 4, 5)
121 enum_fc.map_range('d', 6, 18)
122 enum_fc.map_range('e', 20, 27)
123 self._fc.map_range('a', 0, 2)
124 self._fc.map_range('b', 3)
125 self._fc += enum_fc
126
127 self.assertEqual(self._fc['a'].label, 'a')
128 self.assertEqual(enum_mapping_to_list(self._fc['a']), [(0, 2)])
129
130 self.assertEqual(self._fc['b'].label, 'b')
131 self.assertEqual(enum_mapping_to_list(self._fc['b']), [(3, 3)])
132
133 self.assertEqual(self._fc['c'].label, 'c')
134 self.assertEqual(enum_mapping_to_list(self._fc['c']), [(4, 5)])
135
136 self.assertEqual(self._fc['d'].label, 'd')
137 self.assertEqual(enum_mapping_to_list(self._fc['d']), [(6, 18)])
138
139 self.assertEqual(self._fc['e'].label, 'e')
140 self.assertEqual(enum_mapping_to_list(self._fc['e']), [(20, 27)])
141
142 def test_bool_op(self):
143 self.assertFalse(self._fc)
144 self._fc.map_range('a', 0)
145 self.assertTrue(self._fc)
146
147 def test_len(self):
148 self._fc.map_range('a', 0)
149 self._fc.map_range('b', 1)
150 self._fc.map_range('c', 2)
151 self.assertEqual(len(self._fc), 3)
152
153 def test_getitem(self):
154 self._fc.map_range('a', 0)
155 self._fc.map_range('b', 1, 3)
156 self._fc.map_range('a', 5)
157 self._fc.map_range('a', 17, 123)
158 self._fc.map_range('C', 5)
159 mapping = self._fc['a']
160
161 self.assertEqual(mapping.label, 'a')
162 ranges = enum_mapping_to_list(mapping)
163 self.assertEqual(ranges, [(0, 0), (5, 5), (17, 123)])
164
165 with self.assertRaises(KeyError):
166 self._fc['doesnotexist']
167
168 def test_contains(self):
169 self._fc.map_range('a', 0)
170 self._fc.map_range('a', 2, 23)
171 self._fc.map_range('b', 2)
172 self._fc.map_range('c', 5)
173
174 a_mapping = self._fc['a']
175 b_mapping = self._fc['b']
176 first_range = next(iter(a_mapping))
177
178 self.assertIn(first_range, a_mapping)
179 self.assertNotIn(first_range, b_mapping)
180
181 def test_iter(self):
182 self._fc.map_range('a', 1, 5)
183 self._fc.map_range('b', 10, 17)
184 self._fc.map_range('c', 20, 1504)
185
186 self._fc.map_range('d', 22510, 99999)
187
188 # This exercises iteration.
189 labels = sorted(self._fc)
190
191 self.assertEqual(labels, ['a', 'b', 'c', 'd'])
192
193 def test_find_by_value(self):
194 self._fc.map_range('a', 0)
195 self._fc.map_range('b', 1, 3)
196 self._fc.map_range('c', 5, 19)
197 self._fc.map_range('d', 8, 15)
198 self._fc.map_range('e', 10, 21)
199 self._fc.map_range('f', 0)
200 self._fc.map_range('g', 14)
201
202 labels = self._fc.labels_by_value(14)
203
204 expected_labels = ['c', 'd', 'e', 'g']
205
206 self.assertTrue(all(label in labels for label in expected_labels))
207
208
209 class UnsignedEnumerationFieldClassTestCase(EnumerationFieldClassTestCase, unittest.TestCase):
210 def setUp(self):
211 super().setUp()
212 self._create_func = self._tc.create_unsigned_enumeration_field_class
213 self._fc = self._tc.create_unsigned_enumeration_field_class()
214
215 def test_add_mapping_invalid_signedness_lower(self):
216 with self.assertRaises(ValueError):
217 self._fc.map_range('hello', -21, 199)
218
219 def test_add_mapping_invalid_signedness_upper(self):
220 with self.assertRaises(ValueError):
221 self._fc.map_range('hello', 21, -199)
222
223
224 class SignedEnumerationFieldClassTestCase(EnumerationFieldClassTestCase, unittest.TestCase):
225 def setUp(self):
226 super().setUp()
227 self._create_func = self._tc.create_signed_enumeration_field_class
228 self._fc = self._tc.create_signed_enumeration_field_class()
229
230 def test_add_mapping_simple_signed(self):
231 self._fc.map_range('hello', -24)
232 mapping = self._fc['hello']
233 self.assertEqual(mapping.label, 'hello')
234
235 ranges = enum_mapping_to_list(mapping)
236 self.assertEqual(ranges, [(-24, -24)])
237
238 def test_add_mapping_range_signed(self):
239 self._fc.map_range('hello', -21, 199)
240 mapping = self._fc['hello']
241 self.assertEqual(mapping.label, 'hello')
242 ranges = enum_mapping_to_list(mapping)
243 self.assertEqual(ranges, [(-21, 199)])
244
245
246 class StringFieldClassTestCase(unittest.TestCase):
247 def setUp(self):
248 tc = get_default_trace_class()
249 self._fc = tc.create_string_field_class()
250
251 def test_create_default(self):
252 self.assertIsNotNone(self._fc)
253
254
255 class _TestFieldContainer():
256 def test_append_element(self):
257 int_field_class = self._tc.create_signed_integer_field_class(32)
258 self._append_element_method(self._fc, 'int32', int_field_class)
259 field_class = self._fc['int32']
260 self.assertEqual(field_class.addr, int_field_class.addr)
261
262 def test_append_elemenbt_kwargs(self):
263 int_field_class = self._tc.create_signed_integer_field_class(32)
264 self._append_element_method(self._fc, name='int32', field_class=int_field_class)
265 field_class = self._fc['int32']
266 self.assertEqual(field_class.addr, int_field_class.addr)
267
268 def test_append_element_invalid_name(self):
269 sub_fc = self._tc.create_string_field_class()
270
271 with self.assertRaises(TypeError):
272 self._append_element_method(self._fc, 23, sub_fc)
273
274 def test_append_element_invalid_field_class(self):
275 with self.assertRaises(TypeError):
276 self._append_element_method(self._fc, 'yes', object())
277
278 def test_iadd(self):
279 struct_fc = self._tc.create_structure_field_class()
280 c_field_class = self._tc.create_string_field_class()
281 d_field_class = self._tc.create_signed_enumeration_field_class(field_value_range=32)
282 e_field_class = self._tc.create_structure_field_class()
283 self._append_element_method(struct_fc, 'c_string', c_field_class)
284 self._append_element_method(struct_fc, 'd_enum', d_field_class)
285 self._append_element_method(struct_fc, 'e_struct', e_field_class)
286 a_field_class = self._tc.create_real_field_class()
287 b_field_class = self._tc.create_signed_integer_field_class(17)
288 self._append_element_method(self._fc, 'a_float', a_field_class)
289 self._append_element_method(self._fc, 'b_int', b_field_class)
290 self._fc += struct_fc
291 self.assertEqual(self._fc['a_float'].addr, a_field_class.addr)
292 self.assertEqual(self._fc['b_int'].addr, b_field_class.addr)
293 self.assertEqual(self._fc['c_string'].addr, c_field_class.addr)
294 self.assertEqual(self._fc['d_enum'].addr, d_field_class.addr)
295 self.assertEqual(self._fc['e_struct'].addr, e_field_class.addr)
296
297 def test_bool_op(self):
298 self.assertFalse(self._fc)
299 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
300 self.assertTrue(self._fc)
301
302 def test_len(self):
303 fc = self._tc.create_string_field_class()
304 self._append_element_method(self._fc, 'a', fc)
305 self._append_element_method(self._fc, 'b', fc)
306 self._append_element_method(self._fc, 'c', fc)
307 self.assertEqual(len(self._fc), 3)
308
309 def test_getitem(self):
310 a_fc = self._tc.create_signed_integer_field_class(32)
311 b_fc = self._tc.create_string_field_class()
312 c_fc = self._tc.create_real_field_class()
313 self._append_element_method(self._fc, 'a', a_fc)
314 self._append_element_method(self._fc, 'b', b_fc)
315 self._append_element_method(self._fc, 'c', c_fc)
316 self.assertEqual(self._fc['b'].addr, b_fc.addr)
317
318 def test_getitem_invalid_key_type(self):
319 with self.assertRaises(TypeError):
320 self._fc[0]
321
322 def test_getitem_invalid_key(self):
323 with self.assertRaises(KeyError):
324 self._fc['no way']
325
326 def test_contains(self):
327 self.assertFalse('a' in self._fc)
328 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
329 self.assertTrue('a' in self._fc)
330
331 def test_iter(self):
332 a_fc = self._tc.create_signed_integer_field_class(32)
333 b_fc = self._tc.create_string_field_class()
334 c_fc = self._tc.create_real_field_class()
335 fields = (
336 ('a', a_fc),
337 ('b', b_fc),
338 ('c', c_fc),
339 )
340
341 for field in fields:
342 self._append_element_method(self._fc, *field)
343
344 for (name, fc_field_class), field in zip(self._fc.items(), fields):
345 self.assertEqual(name, field[0])
346 self.assertEqual(fc_field_class.addr, field[1].addr)
347
348 def test_at_index(self):
349 a_fc = self._tc.create_signed_integer_field_class(32)
350 b_fc = self._tc.create_string_field_class()
351 c_fc = self._tc.create_real_field_class()
352 self._append_element_method(self._fc, 'c', c_fc)
353 self._append_element_method(self._fc, 'a', a_fc)
354 self._append_element_method(self._fc, 'b', b_fc)
355 self.assertEqual(self._at_index_method(self._fc, 1).addr, a_fc.addr)
356
357 def test_at_index_invalid(self):
358 self._append_element_method(self._fc, 'c', self._tc.create_signed_integer_field_class(32))
359
360 with self.assertRaises(TypeError):
361 self._at_index_method(self._fc, 'yes')
362
363 def test_at_index_out_of_bounds_after(self):
364 self._append_element_method(self._fc, 'c', self._tc.create_signed_integer_field_class(32))
365
366 with self.assertRaises(IndexError):
367 self._at_index_method(self._fc, len(self._fc))
368
369
370 class StructureFieldClassTestCase(_TestFieldContainer, unittest.TestCase):
371 def setUp(self):
372 self._append_element_method = bt2.field_class._StructureFieldClass.append_member
373 self._at_index_method = bt2.field_class._StructureFieldClass.member_at_index
374 self._tc = get_default_trace_class()
375 self._fc = self._tc.create_structure_field_class()
376
377 def test_create_default(self):
378 self.assertIsNotNone(self._fc)
379
380
381 class VariantFieldClassTestCase(_TestFieldContainer, unittest.TestCase):
382 def setUp(self):
383 self._append_element_method = bt2.field_class._VariantFieldClass.append_option
384 self._at_index_method = bt2.field_class._VariantFieldClass.option_at_index
385 self._tc = get_default_trace_class()
386 self._fc = self._tc.create_variant_field_class()
387
388 def test_create_default(self):
389 fc = self._tc.create_variant_field_class()
390
391 self.assertIsNone(fc.selector_field_path)
392
393 def _create_field_class_for_field_path_test(self):
394 # Create something equivalent to:
395 #
396 # struct outer_struct_fc {
397 # real foo;
398 # struct inner_struct_fc {
399 # enum { first = 1, second = 2..434 } selector;
400 # string bar;
401 # string baz;
402 # variant<selector> {
403 # real a;
404 # int21_t b;
405 # uint34_t c;
406 # } variant;
407 # } inner_struct[2];
408 # };
409 selector_fc = self._tc.create_unsigned_enumeration_field_class(field_value_range=42)
410 selector_fc.map_range('first', 1)
411 selector_fc.map_range('second', 2, 434)
412
413 fc = self._tc.create_variant_field_class(selector_fc)
414 fc.append_option('a', self._tc.create_real_field_class())
415 fc.append_option('b', self._tc.create_signed_integer_field_class(21))
416 fc.append_option('c', self._tc.create_unsigned_integer_field_class(34))
417
418 foo_fc = self._tc.create_real_field_class()
419 bar_fc = self._tc.create_string_field_class()
420 baz_fc = self._tc.create_string_field_class()
421
422 inner_struct_fc = self._tc.create_structure_field_class()
423 inner_struct_fc.append_member('selector', selector_fc)
424 inner_struct_fc.append_member('bar', bar_fc)
425 inner_struct_fc.append_member('baz', baz_fc)
426 inner_struct_fc.append_member('variant', fc)
427
428 inner_struct_array_fc = self._tc.create_static_array_field_class(inner_struct_fc, 2)
429
430 outer_struct_fc = self._tc.create_structure_field_class()
431 outer_struct_fc.append_member('foo', foo_fc)
432 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
433
434 # The path to the selector field is resolved when the sequence is
435 # actually used, for example in a packet context.
436 self._tc.create_stream_class(packet_context_field_class=outer_struct_fc)
437
438 return fc
439
440 def test_selector_field_path_length(self):
441 fc = self._create_field_class_for_field_path_test()
442 self.assertEqual(len(fc.selector_field_path), 3)
443
444 def test_selector_field_path_iter(self):
445 fc = self._create_field_class_for_field_path_test()
446 path_items = list(fc.selector_field_path)
447
448 self.assertEqual(len(path_items), 3)
449
450 self.assertIsInstance(path_items[0], bt2.field_path._IndexFieldPathItem)
451 self.assertEqual(path_items[0].index, 1)
452
453 self.assertIsInstance(path_items[1], bt2.field_path._CurrentArrayElementFieldPathItem)
454
455 self.assertIsInstance(path_items[2], bt2.field_path._IndexFieldPathItem)
456 self.assertEqual(path_items[2].index, 0)
457
458 def test_selector_field_path_root_scope(self):
459 fc = self._create_field_class_for_field_path_test()
460 self.assertEqual(fc.selector_field_path.root_scope, bt2.field_path.Scope.PACKET_CONTEXT)
461
462
463 class StaticArrayFieldClassTestCase(unittest.TestCase):
464 def setUp(self):
465 self._tc = get_default_trace_class()
466 self._elem_fc = self._tc.create_signed_integer_field_class(23)
467
468 def test_create_default(self):
469 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
470 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
471 self.assertEqual(fc.length, 45)
472
473 def test_create_invalid_elem_field_class(self):
474 with self.assertRaises(TypeError):
475 self._tc.create_static_array_field_class(object(), 45)
476
477 def test_create_invalid_length(self):
478 with self.assertRaises(ValueError):
479 self._tc.create_static_array_field_class(self._tc.create_string_field_class(), -17)
480
481 def test_create_invalid_length_type(self):
482 with self.assertRaises(TypeError):
483 self._tc.create_static_array_field_class(self._tc.create_string_field_class(), 'the length')
484
485
486 class DynamicArrayFieldClassTestCase(unittest.TestCase):
487 def setUp(self):
488 self._tc = get_default_trace_class()
489 self._elem_fc = self._tc.create_signed_integer_field_class(23)
490 self._len_fc = self._tc.create_unsigned_integer_field_class(12)
491
492 def test_create_default(self):
493 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
494 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
495 self.assertIsNone(fc.length_field_path, None)
496
497 def _create_field_class_for_field_path_test(self):
498 # Create something a field class that is equivalent to:
499 #
500 # struct outer_struct_fc {
501 # real foo;
502 # struct inner_struct_fc {
503 # string bar;
504 # string baz;
505 # uint12_t len;
506 # uint23_t dyn_array[len];
507 # } inner_struct[2];
508 # };
509
510 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
511
512 foo_fc = self._tc.create_real_field_class()
513 bar_fc = self._tc.create_string_field_class()
514 baz_fc = self._tc.create_string_field_class()
515
516 inner_struct_fc = self._tc.create_structure_field_class()
517 inner_struct_fc.append_member('bar', bar_fc)
518 inner_struct_fc.append_member('baz', baz_fc)
519 inner_struct_fc.append_member('len', self._len_fc)
520 inner_struct_fc.append_member('dyn_array', fc)
521
522 inner_struct_array_fc = self._tc.create_static_array_field_class(inner_struct_fc, 2)
523
524 outer_struct_fc = self._tc.create_structure_field_class()
525 outer_struct_fc.append_member('foo', foo_fc)
526 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
527
528 # The path to the length field is resolved when the sequence is
529 # actually used, for example in a packet context.
530 self._tc.create_stream_class(packet_context_field_class=outer_struct_fc)
531
532 return fc
533
534 def test_field_path_len(self):
535 fc = self._create_field_class_for_field_path_test()
536 self.assertEqual(len(fc.length_field_path), 3)
537
538 def test_field_path_iter(self):
539 fc = self._create_field_class_for_field_path_test()
540 path_items = list(fc.length_field_path)
541
542 self.assertEqual(len(path_items), 3)
543
544 self.assertIsInstance(path_items[0], bt2.field_path._IndexFieldPathItem)
545 self.assertEqual(path_items[0].index, 1)
546
547 self.assertIsInstance(path_items[1], bt2.field_path._CurrentArrayElementFieldPathItem)
548
549 self.assertIsInstance(path_items[2], bt2.field_path._IndexFieldPathItem)
550 self.assertEqual(path_items[2].index, 2)
551
552 def test_field_path_root_scope(self):
553 fc = self._create_field_class_for_field_path_test()
554 self.assertEqual(fc.length_field_path.root_scope, bt2.field_path.Scope.PACKET_CONTEXT)
555
556 def test_create_invalid_field_class(self):
557 with self.assertRaises(TypeError):
558 self._tc.create_dynamic_array_field_class(object())
559
560 def test_create_invalid_length_type(self):
561 with self.assertRaises(TypeError):
562 self._tc.create_dynamic_array_field_class(self._tc.create_string_field_class(), 17)
563
564
565 if __name__ == "__main__":
566 unittest.main()
This page took 0.043922 seconds and 3 git commands to generate.