bt2: add user attributes property support
[babeltrace.git] / tests / bindings / python / bt2 / test_field_class.py
CommitLineData
d2d857a8
MJ
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
b4f45851 19import unittest
b4f45851 20import bt2
d47b87ac 21from utils import get_default_trace_class
b4f45851
SM
22
23
5783664e
PP
24class _TestFieldClass:
25 def test_create_user_attributes(self):
26 fc = self._create_default_field_class(user_attributes={'salut': 23})
27 self.assertEqual(fc.user_attributes, {'salut': 23})
28
29 def test_create_invalid_user_attributes(self):
30 with self.assertRaises(TypeError):
31 self._create_default_field_class(user_attributes=object())
32
33 def test_create_invalid_user_attributes_value_type(self):
34 with self.assertRaises(TypeError):
35 self._create_default_field_class(user_attributes=23)
36
37
38class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase):
39 def _create_default_field_class(self, **kwargs):
aae30e61 40 tc = get_default_trace_class()
5783664e
PP
41 return tc.create_bool_field_class(**kwargs)
42
43 def setUp(self):
44 self._fc = self._create_default_field_class()
aae30e61
PP
45
46 def test_create_default(self):
47 self.assertIsNotNone(self._fc)
5783664e 48 self.assertEqual(len(self._fc.user_attributes), 0)
aae30e61
PP
49
50
5783664e
PP
51class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase):
52 def _create_field_class(self, *args, **kwargs):
53 tc = get_default_trace_class()
54 return tc.create_bit_array_field_class(*args, **kwargs)
55
56 def _create_default_field_class(self, **kwargs):
57 return self._create_field_class(17, **kwargs)
58
ead8c3d4 59 def setUp(self):
5783664e 60 self._fc = self._create_default_field_class()
ead8c3d4
PP
61
62 def test_create_default(self):
63 self.assertIsNotNone(self._fc)
5783664e 64 self.assertEqual(len(self._fc.user_attributes), 0)
ead8c3d4
PP
65
66 def test_create_length_out_of_range(self):
67 with self.assertRaises(ValueError):
5783664e 68 self._create_field_class(65)
ead8c3d4
PP
69
70 def test_create_length_zero(self):
71 with self.assertRaises(ValueError):
5783664e 72 self._create_field_class(0)
ead8c3d4
PP
73
74 def test_create_length_invalid_type(self):
75 with self.assertRaises(TypeError):
5783664e 76 self._create_field_class('lel')
ead8c3d4
PP
77
78 def test_length_prop(self):
79 self.assertEqual(self._fc.length, 17)
80
81
d47b87ac
SM
82class _TestIntegerFieldClassProps:
83 def test_create_default(self):
5783664e 84 fc = self._create_default_field_class()
d47b87ac
SM
85 self.assertEqual(fc.field_value_range, 64)
86 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.DECIMAL)
5783664e 87 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 88
d47b87ac 89 def test_create_range(self):
5783664e 90 fc = self._create_field_class(field_value_range=35)
d47b87ac 91 self.assertEqual(fc.field_value_range, 35)
b4f45851 92
5783664e 93 fc = self._create_field_class(36)
d47b87ac 94 self.assertEqual(fc.field_value_range, 36)
b4f45851 95
d47b87ac
SM
96 def test_create_invalid_range(self):
97 with self.assertRaises(TypeError):
5783664e 98 self._create_field_class('yes')
b4f45851 99
d47b87ac 100 with self.assertRaises(TypeError):
5783664e 101 self._create_field_class(field_value_range='yes')
b4f45851 102
b4f45851 103 with self.assertRaises(ValueError):
5783664e 104 self._create_field_class(field_value_range=-2)
b4f45851 105
d47b87ac 106 with self.assertRaises(ValueError):
5783664e 107 self._create_field_class(field_value_range=0)
b4f45851 108
d47b87ac 109 def test_create_base(self):
5783664e 110 fc = self._create_field_class(
cfbd7cf3
FD
111 preferred_display_base=bt2.IntegerDisplayBase.HEXADECIMAL
112 )
d47b87ac 113 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.HEXADECIMAL)
b4f45851 114
d47b87ac 115 def test_create_invalid_base_type(self):
b4f45851 116 with self.assertRaises(TypeError):
5783664e 117 self._create_field_class(preferred_display_base='yes')
b4f45851 118
d47b87ac
SM
119 def test_create_invalid_base_value(self):
120 with self.assertRaises(ValueError):
5783664e 121 self._create_field_class(preferred_display_base=444)
b4f45851 122
d47b87ac 123 def test_create_full(self):
5783664e
PP
124 fc = self._create_field_class(
125 24, preferred_display_base=bt2.IntegerDisplayBase.OCTAL
126 )
d47b87ac
SM
127 self.assertEqual(fc.field_value_range, 24)
128 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.OCTAL)
b4f45851
SM
129
130
5783664e
PP
131class SignedIntegerFieldClassTestCase(
132 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
133):
134 def _create_field_class(self, *args, **kwargs):
135 tc = get_default_trace_class()
136 return tc.create_signed_integer_field_class(*args, **kwargs)
b4f45851 137
5783664e
PP
138 _create_default_field_class = _create_field_class
139
140
141class UnsignedIntegerFieldClassTestCase(
142 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
143):
144 def _create_field_class(self, *args, **kwargs):
145 tc = get_default_trace_class()
146 return tc.create_unsigned_integer_field_class(*args, **kwargs)
147
148 _create_default_field_class = _create_field_class
b4f45851 149
5783664e
PP
150
151class RealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
152 def _create_field_class(self, *args, **kwargs):
153 tc = get_default_trace_class()
154 return tc.create_real_field_class(*args, **kwargs)
155
156 _create_default_field_class = _create_field_class
b4f45851 157
d47b87ac 158 def test_create_default(self):
5783664e 159 fc = self._create_field_class()
d47b87ac 160 self.assertFalse(fc.is_single_precision)
5783664e 161 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 162
d47b87ac 163 def test_create_is_single_precision(self):
5783664e 164 fc = self._create_field_class(is_single_precision=True)
d47b87ac
SM
165 self.assertTrue(fc.is_single_precision)
166
167 def test_create_invalid_is_single_precision(self):
b4f45851 168 with self.assertRaises(TypeError):
5783664e 169 self._create_field_class(is_single_precision='hohoho')
b4f45851 170
b4f45851 171
d47b87ac
SM
172# Converts an _EnumerationFieldClassMapping to a list of ranges:
173#
174# [(lower0, upper0), (lower1, upper1), ...]
175
cfbd7cf3 176
45c51519
PP
177def enum_mapping_to_set(mapping):
178 return {(x.lower, x.upper) for x in mapping.ranges}
b4f45851 179
b4f45851 180
45c51519 181class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
d47b87ac 182 def setUp(self):
45c51519 183 self._spec_set_up()
5783664e 184 self._fc = self._create_default_field_class()
d47b87ac
SM
185
186 def test_create_from_invalid_type(self):
b4f45851 187 with self.assertRaises(TypeError):
5783664e 188 self._create_field_class('coucou')
b4f45851 189
d47b87ac 190 def test_add_mapping_simple(self):
45c51519 191 self._fc.add_mapping('hello', self._ranges1)
d47b87ac
SM
192 mapping = self._fc['hello']
193 self.assertEqual(mapping.label, 'hello')
45c51519 194 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 195
d47b87ac 196 def test_add_mapping_simple_kwargs(self):
45c51519 197 self._fc.add_mapping(label='hello', ranges=self._ranges1)
d47b87ac
SM
198 mapping = self._fc['hello']
199 self.assertEqual(mapping.label, 'hello')
45c51519 200 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 201
45c51519
PP
202 def test_add_mapping_invalid_name(self):
203 with self.assertRaises(TypeError):
204 self._fc.add_mapping(17, self._ranges1)
b4f45851 205
45c51519
PP
206 def test_add_mapping_invalid_range(self):
207 with self.assertRaises(TypeError):
208 self._fc.add_mapping('allo', 'meow')
d47b87ac 209
45c51519 210 def test_add_mapping_dup_label(self):
ce4923b0 211 with self.assertRaises(ValueError):
45c51519
PP
212 self._fc.add_mapping('a', self._ranges1)
213 self._fc.add_mapping('a', self._ranges2)
d47b87ac 214
45c51519 215 def test_add_mapping_invalid_ranges_signedness(self):
b4f45851 216 with self.assertRaises(TypeError):
45c51519 217 self._fc.add_mapping('allo', self._inval_ranges)
b4f45851 218
d47b87ac 219 def test_iadd(self):
45c51519 220 self._fc.add_mapping('c', self._ranges1)
b4f45851 221
cfbd7cf3 222 self._fc += [('d', self._ranges2), ('e', self._ranges3)]
b4f45851 223
45c51519 224 self.assertEqual(len(self._fc), 3)
d47b87ac 225 self.assertEqual(self._fc['c'].label, 'c')
45c51519 226 self.assertEqual(self._fc['c'].ranges, self._ranges1)
d47b87ac 227 self.assertEqual(self._fc['d'].label, 'd')
45c51519 228 self.assertEqual(self._fc['d'].ranges, self._ranges2)
d47b87ac 229 self.assertEqual(self._fc['e'].label, 'e')
45c51519 230 self.assertEqual(self._fc['e'].ranges, self._ranges3)
b4f45851 231
d47b87ac
SM
232 def test_bool_op(self):
233 self.assertFalse(self._fc)
45c51519 234 self._fc.add_mapping('a', self._ranges1)
d47b87ac 235 self.assertTrue(self._fc)
b4f45851 236
d47b87ac 237 def test_len(self):
45c51519
PP
238 self._fc.add_mapping('a', self._ranges1)
239 self._fc.add_mapping('b', self._ranges2)
240 self._fc.add_mapping('c', self._ranges3)
d47b87ac 241 self.assertEqual(len(self._fc), 3)
b4f45851 242
d47b87ac 243 def test_getitem(self):
45c51519
PP
244 self._fc.add_mapping('a', self._ranges1)
245 self._fc.add_mapping('b', self._ranges2)
246 self._fc.add_mapping('c', self._ranges3)
d47b87ac 247 mapping = self._fc['a']
d47b87ac 248 self.assertEqual(mapping.label, 'a')
45c51519 249 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 250
45c51519 251 def test_getitem_nonexistent(self):
d47b87ac
SM
252 with self.assertRaises(KeyError):
253 self._fc['doesnotexist']
b4f45851 254
d47b87ac 255 def test_iter(self):
45c51519
PP
256 self._fc.add_mapping('a', self._ranges1)
257 self._fc.add_mapping('b', self._ranges2)
258 self._fc.add_mapping('c', self._ranges3)
b4f45851 259
d47b87ac
SM
260 # This exercises iteration.
261 labels = sorted(self._fc)
b4f45851 262
45c51519 263 self.assertEqual(labels, ['a', 'b', 'c'])
b4f45851 264
d47b87ac 265 def test_find_by_value(self):
45c51519
PP
266 self._fc.add_mapping('a', self._ranges1)
267 self._fc.add_mapping('b', self._ranges2)
268 self._fc.add_mapping('c', self._ranges3)
269 mappings = self._fc.mappings_for_value(self._value_in_range_1_and_3)
270 labels = set([mapping.label for mapping in mappings])
271 expected_labels = set(['a', 'c'])
272 self.assertEqual(labels, expected_labels)
273
274
cfbd7cf3 275class UnsignedEnumerationFieldClassTestCase(
5783664e 276 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 277):
45c51519
PP
278 def _spec_set_up(self):
279 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
280 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
281 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 22), (48, 99)])
282 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, -5), (48, 1928)])
283 self._value_in_range_1_and_3 = 20
5783664e
PP
284
285 def _create_field_class(self, *args, **kwargs):
286 tc = get_default_trace_class()
287 return tc.create_unsigned_enumeration_field_class(*args, **kwargs)
288
289 _create_default_field_class = _create_field_class
b4f45851 290
b4f45851 291
cfbd7cf3 292class SignedEnumerationFieldClassTestCase(
5783664e 293 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 294):
45c51519
PP
295 def _spec_set_up(self):
296 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
297 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
298 self._ranges3 = bt2.SignedIntegerRangeSet([(-100, -1), (8, 16), (48, 99)])
299 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
300 self._value_in_range_1_and_3 = -7
b4f45851 301
5783664e
PP
302 def _create_field_class(self, *args, **kwargs):
303 tc = get_default_trace_class()
304 return tc.create_signed_enumeration_field_class(*args, **kwargs)
305
306 _create_default_field_class = _create_field_class
b4f45851 307
5783664e
PP
308
309class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase):
310 def _create_field_class(self, *args, **kwargs):
d47b87ac 311 tc = get_default_trace_class()
5783664e
PP
312 return tc.create_string_field_class(*args, **kwargs)
313
314 _create_default_field_class = _create_field_class
315
316 def setUp(self):
317 self._fc = self._create_default_field_class()
b4f45851
SM
318
319 def test_create_default(self):
d47b87ac 320 self.assertIsNotNone(self._fc)
5783664e 321 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 322
b4f45851 323
cfbd7cf3 324class _TestElementContainer:
45c51519
PP
325 def setUp(self):
326 self._tc = get_default_trace_class()
5783664e 327 self._fc = self._create_default_field_class()
45c51519
PP
328
329 def test_create_default(self):
330 self.assertIsNotNone(self._fc)
5783664e 331 self.assertEqual(len(self._fc.user_attributes), 0)
45c51519 332
d47b87ac
SM
333 def test_append_element(self):
334 int_field_class = self._tc.create_signed_integer_field_class(32)
335 self._append_element_method(self._fc, 'int32', int_field_class)
45c51519 336 field_class = self._fc['int32'].field_class
d47b87ac 337 self.assertEqual(field_class.addr, int_field_class.addr)
b4f45851 338
45c51519 339 def test_append_element_kwargs(self):
d47b87ac
SM
340 int_field_class = self._tc.create_signed_integer_field_class(32)
341 self._append_element_method(self._fc, name='int32', field_class=int_field_class)
45c51519 342 field_class = self._fc['int32'].field_class
d47b87ac
SM
343 self.assertEqual(field_class.addr, int_field_class.addr)
344
345 def test_append_element_invalid_name(self):
346 sub_fc = self._tc.create_string_field_class()
b4f45851 347
b4f45851 348 with self.assertRaises(TypeError):
d47b87ac 349 self._append_element_method(self._fc, 23, sub_fc)
b4f45851 350
d47b87ac 351 def test_append_element_invalid_field_class(self):
b4f45851 352 with self.assertRaises(TypeError):
d47b87ac 353 self._append_element_method(self._fc, 'yes', object())
b4f45851 354
45c51519
PP
355 def test_append_element_dup_name(self):
356 sub_fc1 = self._tc.create_string_field_class()
357 sub_fc2 = self._tc.create_string_field_class()
358
ce4923b0 359 with self.assertRaises(ValueError):
45c51519
PP
360 self._append_element_method(self._fc, 'yes', sub_fc1)
361 self._append_element_method(self._fc, 'yes', sub_fc2)
362
b4f45851 363 def test_iadd(self):
5783664e 364 other_fc = self._create_default_field_class()
d47b87ac
SM
365 a_field_class = self._tc.create_real_field_class()
366 b_field_class = self._tc.create_signed_integer_field_class(17)
367 self._append_element_method(self._fc, 'a_float', a_field_class)
368 self._append_element_method(self._fc, 'b_int', b_field_class)
45c51519 369 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
370 d_field_class = self._tc.create_signed_enumeration_field_class(
371 field_value_range=32
372 )
45c51519
PP
373 e_field_class = self._tc.create_structure_field_class()
374 self._fc += [
375 ('c_string', c_field_class),
376 ('d_enum', d_field_class),
377 ('e_struct', e_field_class),
378 ]
379 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
380 self.assertEqual(self._fc['a_float'].name, 'a_float')
381 self.assertEqual(self._fc['b_int'].field_class.addr, b_field_class.addr)
382 self.assertEqual(self._fc['b_int'].name, 'b_int')
383 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
384 self.assertEqual(self._fc['c_string'].name, 'c_string')
385 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
386 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
387 self.assertEqual(self._fc['e_struct'].field_class.addr, e_field_class.addr)
388 self.assertEqual(self._fc['e_struct'].name, 'e_struct')
b4f45851
SM
389
390 def test_bool_op(self):
391 self.assertFalse(self._fc)
d47b87ac 392 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
393 self.assertTrue(self._fc)
394
395 def test_len(self):
45c51519
PP
396 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
397 self._append_element_method(self._fc, 'b', self._tc.create_string_field_class())
398 self._append_element_method(self._fc, 'c', self._tc.create_string_field_class())
b4f45851
SM
399 self.assertEqual(len(self._fc), 3)
400
401 def test_getitem(self):
d47b87ac
SM
402 a_fc = self._tc.create_signed_integer_field_class(32)
403 b_fc = self._tc.create_string_field_class()
404 c_fc = self._tc.create_real_field_class()
405 self._append_element_method(self._fc, 'a', a_fc)
406 self._append_element_method(self._fc, 'b', b_fc)
407 self._append_element_method(self._fc, 'c', c_fc)
45c51519
PP
408 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
409 self.assertEqual(self._fc['b'].name, 'b')
b4f45851
SM
410
411 def test_getitem_invalid_key_type(self):
412 with self.assertRaises(TypeError):
413 self._fc[0]
414
415 def test_getitem_invalid_key(self):
416 with self.assertRaises(KeyError):
417 self._fc['no way']
418
419 def test_contains(self):
420 self.assertFalse('a' in self._fc)
d47b87ac 421 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
422 self.assertTrue('a' in self._fc)
423
424 def test_iter(self):
d47b87ac
SM
425 a_fc = self._tc.create_signed_integer_field_class(32)
426 b_fc = self._tc.create_string_field_class()
427 c_fc = self._tc.create_real_field_class()
cfbd7cf3 428 elements = (('a', a_fc), ('b', b_fc), ('c', c_fc))
b4f45851 429
45c51519
PP
430 for elem in elements:
431 self._append_element_method(self._fc, *elem)
b4f45851 432
45c51519
PP
433 for (name, element), test_elem in zip(self._fc.items(), elements):
434 self.assertEqual(element.name, test_elem[0])
435 self.assertEqual(name, element.name)
436 self.assertEqual(element.field_class.addr, test_elem[1].addr)
5783664e 437 self.assertEqual(len(element.user_attributes), 0)
b4f45851
SM
438
439 def test_at_index(self):
d47b87ac
SM
440 a_fc = self._tc.create_signed_integer_field_class(32)
441 b_fc = self._tc.create_string_field_class()
442 c_fc = self._tc.create_real_field_class()
443 self._append_element_method(self._fc, 'c', c_fc)
444 self._append_element_method(self._fc, 'a', a_fc)
445 self._append_element_method(self._fc, 'b', b_fc)
45c51519
PP
446 elem = self._at_index_method(self._fc, 1)
447 self.assertEqual(elem.field_class.addr, a_fc.addr)
448 self.assertEqual(elem.name, 'a')
b4f45851
SM
449
450 def test_at_index_invalid(self):
cfbd7cf3
FD
451 self._append_element_method(
452 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
453 )
b4f45851
SM
454
455 with self.assertRaises(TypeError):
d47b87ac 456 self._at_index_method(self._fc, 'yes')
b4f45851
SM
457
458 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
459 self._append_element_method(
460 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
461 )
b4f45851
SM
462
463 with self.assertRaises(IndexError):
d47b87ac 464 self._at_index_method(self._fc, len(self._fc))
b4f45851 465
5783664e
PP
466 def test_user_attributes(self):
467 self._append_element_method(
468 self._fc,
469 'c',
470 self._tc.create_string_field_class(),
471 user_attributes={'salut': 23},
472 )
473 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
b4f45851 474
5783664e
PP
475 def test_invalid_user_attributes(self):
476 with self.assertRaises(TypeError):
477 self._append_element_method(
478 self._fc,
479 'c',
480 self._tc.create_string_field_class(),
481 user_attributes=object(),
482 )
483
484 def test_invalid_user_attributes_value_type(self):
485 with self.assertRaises(TypeError):
486 self._append_element_method(
487 self._fc, 'c', self._tc.create_string_field_class(), user_attributes=23
488 )
489
490
491class StructureFieldClassTestCase(
492 _TestFieldClass, _TestElementContainer, unittest.TestCase
493):
3fb99a22
PP
494 _append_element_method = staticmethod(bt2._StructureFieldClass.append_member)
495 _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index)
45c51519 496
5783664e
PP
497 def _create_field_class(self, *args, **kwargs):
498 tc = get_default_trace_class()
499 return tc.create_structure_field_class(*args, **kwargs)
45c51519 500
5783664e
PP
501 _create_default_field_class = _create_field_class
502
503
504class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
505 def _create_default_field_class(self, *args, **kwargs):
506 return self._tc.create_option_field_class(self._content_fc, **kwargs)
45c51519 507
cec0261d
PP
508 def setUp(self):
509 self._tc = get_default_trace_class()
510 self._content_fc = self._tc.create_signed_integer_field_class(23)
511 self._tag_fc = self._tc.create_bool_field_class()
512
513 def test_create_default(self):
5783664e 514 fc = self._create_default_field_class()
cec0261d
PP
515 self.assertEqual(fc.field_class.addr, self._content_fc.addr)
516 self.assertIsNone(fc.selector_field_path, None)
5783664e 517 self.assertEqual(len(fc.user_attributes), 0)
cec0261d
PP
518
519 def _create_field_class_for_field_path_test(self):
5783664e 520 fc = self._create_default_field_class(selector_fc=self._tag_fc)
cec0261d
PP
521
522 foo_fc = self._tc.create_real_field_class()
523 bar_fc = self._tc.create_string_field_class()
524 baz_fc = self._tc.create_string_field_class()
525
526 inner_struct_fc = self._tc.create_structure_field_class()
527 inner_struct_fc.append_member('bar', bar_fc)
528 inner_struct_fc.append_member('baz', baz_fc)
529 inner_struct_fc.append_member('tag', self._tag_fc)
530 inner_struct_fc.append_member('opt', fc)
531
532 opt_struct_array_fc = self._tc.create_option_field_class(inner_struct_fc)
533
534 outer_struct_fc = self._tc.create_structure_field_class()
535 outer_struct_fc.append_member('foo', foo_fc)
536 outer_struct_fc.append_member('inner_opt', opt_struct_array_fc)
537
538 # The path to the selector field class is resolved when the
539 # option field class is actually used, for example in a packet
540 # context.
541 self._tc.create_stream_class(
542 packet_context_field_class=outer_struct_fc, supports_packets=True
543 )
544
545 return fc
546
547 def test_field_path_len(self):
548 fc = self._create_field_class_for_field_path_test()
549 self.assertEqual(len(fc.selector_field_path), 3)
550
551 def test_field_path_iter(self):
552 fc = self._create_field_class_for_field_path_test()
553 path_items = list(fc.selector_field_path)
554
555 self.assertEqual(len(path_items), 3)
556
557 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
558 self.assertEqual(path_items[0].index, 1)
559
560 self.assertIsInstance(path_items[1], bt2._CurrentOptionContentFieldPathItem)
561
562 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
563 self.assertEqual(path_items[2].index, 2)
564
565 def test_field_path_root_scope(self):
566 fc = self._create_field_class_for_field_path_test()
567 self.assertEqual(
568 fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
569 )
570
571 def test_create_invalid_field_class(self):
572 with self.assertRaises(TypeError):
573 self._tc.create_option_field_class(object())
574
575 def test_create_invalid_selector_type(self):
576 with self.assertRaises(TypeError):
577 self._tc.create_option_field_class(self._content_fc, 17)
578
579
cfbd7cf3 580class VariantFieldClassWithoutSelectorTestCase(
5783664e 581 _TestFieldClass, _TestElementContainer, unittest.TestCase
cfbd7cf3
FD
582):
583 _append_element_method = staticmethod(
3fb99a22 584 bt2._VariantFieldClassWithoutSelector.append_option
cfbd7cf3
FD
585 )
586 _at_index_method = staticmethod(
3fb99a22 587 bt2._VariantFieldClassWithoutSelector.option_at_index
cfbd7cf3 588 )
45c51519 589
5783664e
PP
590 def _create_field_class(self, *args, **kwargs):
591 tc = get_default_trace_class()
592 return tc.create_variant_field_class(*args, **kwargs)
593
594 _create_default_field_class = _create_field_class
45c51519
PP
595
596
597class _VariantFieldClassWithSelectorTestCase:
5783664e
PP
598 def _create_default_field_class(self, *args, **kwargs):
599 return self._tc.create_variant_field_class(
600 *args, selector_fc=self._selector_fc, **kwargs
601 )
602
b4f45851 603 def setUp(self):
d47b87ac 604 self._tc = get_default_trace_class()
45c51519 605 self._spec_set_up()
5783664e 606 self._fc = self._create_default_field_class()
d47b87ac
SM
607
608 def test_create_default(self):
609 self.assertIsNotNone(self._fc)
5783664e 610 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 611
45c51519
PP
612 def test_append_element(self):
613 str_field_class = self._tc.create_string_field_class()
614 self._fc.append_option('str', str_field_class, self._ranges1)
615 opt = self._fc['str']
616 self.assertEqual(opt.field_class.addr, str_field_class.addr)
617 self.assertEqual(opt.name, 'str')
618 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
619
620 def test_append_element_kwargs(self):
621 int_field_class = self._tc.create_signed_integer_field_class(32)
cfbd7cf3
FD
622 self._fc.append_option(
623 name='int32', field_class=int_field_class, ranges=self._ranges1
624 )
45c51519
PP
625 opt = self._fc['int32']
626 self.assertEqual(opt.field_class.addr, int_field_class.addr)
627 self.assertEqual(opt.name, 'int32')
628 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
d47b87ac 629
45c51519
PP
630 def test_append_element_invalid_name(self):
631 sub_fc = self._tc.create_string_field_class()
b4f45851 632
45c51519
PP
633 with self.assertRaises(TypeError):
634 self._fc.append_option(self._fc, 23, sub_fc)
b4f45851 635
45c51519
PP
636 def test_append_element_invalid_field_class(self):
637 with self.assertRaises(TypeError):
638 self._fc.append_option(self._fc, 'yes', object())
639
640 def test_append_element_invalid_ranges(self):
641 sub_fc = self._tc.create_string_field_class()
642
643 with self.assertRaises(TypeError):
644 self._fc.append_option(self._fc, sub_fc, 'lel')
645
646 def test_append_element_dup_name(self):
647 sub_fc1 = self._tc.create_string_field_class()
648 sub_fc2 = self._tc.create_string_field_class()
649
ce4923b0 650 with self.assertRaises(ValueError):
45c51519
PP
651 self._fc.append_option('yes', sub_fc1, self._ranges1)
652 self._fc.append_option('yes', sub_fc2, self._ranges2)
653
654 def test_append_element_invalid_ranges_signedness(self):
655 sub_fc = self._tc.create_string_field_class()
656
657 with self.assertRaises(TypeError):
658 self._fc.append_option(self._fc, sub_fc, self._inval_ranges)
659
5783664e
PP
660 def test_user_attributes(self):
661 self._fc.append_option(
662 'c',
663 self._tc.create_string_field_class(),
664 self._ranges1,
665 user_attributes={'salut': 23},
666 )
667 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
668
669 def test_invalid_user_attributes(self):
670 with self.assertRaises(TypeError):
671 self._fc.append_option(
672 'c',
673 self._tc.create_string_field_class(),
674 self._ranges1,
675 user_attributes=object(),
676 )
677
678 def test_invalid_user_attributes_value_type(self):
679 with self.assertRaises(TypeError):
680 self._fc.append_option(
681 'c',
682 self._tc.create_string_field_class(),
683 self._ranges1,
684 user_attributes=23,
685 )
686
45c51519 687 def test_iadd(self):
5783664e 688 other_fc = self._create_default_field_class()
45c51519
PP
689 a_field_class = self._tc.create_real_field_class()
690 self._fc.append_option('a_float', a_field_class, self._ranges1)
691 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
692 d_field_class = self._tc.create_signed_enumeration_field_class(
693 field_value_range=32
694 )
45c51519
PP
695 self._fc += [
696 ('c_string', c_field_class, self._ranges2),
697 ('d_enum', d_field_class, self._ranges3),
698 ]
699 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
700 self.assertEqual(self._fc['a_float'].name, 'a_float')
701 self.assertEqual(self._fc['a_float'].ranges, self._ranges1)
702 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
703 self.assertEqual(self._fc['c_string'].name, 'c_string')
704 self.assertEqual(self._fc['c_string'].ranges, self._ranges2)
705 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
706 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
707 self.assertEqual(self._fc['d_enum'].ranges, self._ranges3)
708
709 def test_bool_op(self):
710 self.assertFalse(self._fc)
711 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
712 self.assertTrue(self._fc)
713
714 def test_len(self):
715 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
716 self._fc.append_option('b', self._tc.create_string_field_class(), self._ranges2)
717 self._fc.append_option('c', self._tc.create_string_field_class(), self._ranges3)
718 self.assertEqual(len(self._fc), 3)
719
720 def test_getitem(self):
721 a_fc = self._tc.create_signed_integer_field_class(32)
722 b_fc = self._tc.create_string_field_class()
723 c_fc = self._tc.create_real_field_class()
724 self._fc.append_option('a', a_fc, self._ranges1)
725 self._fc.append_option('b', b_fc, self._ranges2)
726 self._fc.append_option('c', c_fc, self._ranges3)
727 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
728 self.assertEqual(self._fc['b'].name, 'b')
729 self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr)
730
731 def test_getitem_invalid_key_type(self):
732 with self.assertRaises(TypeError):
733 self._fc[0]
734
735 def test_getitem_invalid_key(self):
736 with self.assertRaises(KeyError):
737 self._fc['no way']
738
739 def test_contains(self):
740 self.assertFalse('a' in self._fc)
741 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
742 self.assertTrue('a' in self._fc)
743
744 def test_iter(self):
745 a_fc = self._tc.create_signed_integer_field_class(32)
746 b_fc = self._tc.create_string_field_class()
747 c_fc = self._tc.create_real_field_class()
748 opts = (
749 ('a', a_fc, self._ranges1),
750 ('b', b_fc, self._ranges2),
751 ('c', c_fc, self._ranges3),
752 )
753
754 for opt in opts:
755 self._fc.append_option(*opt)
b4f45851 756
45c51519
PP
757 for (name, opt), test_opt in zip(self._fc.items(), opts):
758 self.assertEqual(opt.name, test_opt[0])
759 self.assertEqual(name, opt.name)
760 self.assertEqual(opt.field_class.addr, test_opt[1].addr)
761 self.assertEqual(opt.ranges.addr, test_opt[2].addr)
762
763 def test_at_index(self):
764 a_fc = self._tc.create_signed_integer_field_class(32)
765 b_fc = self._tc.create_string_field_class()
766 c_fc = self._tc.create_real_field_class()
767 self._fc.append_option('c', c_fc, self._ranges1)
768 self._fc.append_option('a', a_fc, self._ranges2)
769 self._fc.append_option('b', b_fc, self._ranges3)
770 self.assertEqual(self._fc.option_at_index(1).field_class.addr, a_fc.addr)
771 self.assertEqual(self._fc.option_at_index(1).name, 'a')
772 self.assertEqual(self._fc.option_at_index(1).ranges.addr, self._ranges2.addr)
773
774 def test_at_index_invalid(self):
cfbd7cf3
FD
775 self._fc.append_option(
776 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
777 )
45c51519
PP
778
779 with self.assertRaises(TypeError):
780 self._fc.option_at_index('yes')
781
782 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
783 self._fc.append_option(
784 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
785 )
45c51519
PP
786
787 with self.assertRaises(IndexError):
788 self._fc.option_at_index(len(self._fc))
789
790 def _fill_default_fc_for_field_path_test(self):
d47b87ac
SM
791 # Create something equivalent to:
792 #
793 # struct outer_struct_fc {
794 # real foo;
795 # struct inner_struct_fc {
45c51519 796 # [u]int64_t selector;
d47b87ac
SM
797 # string bar;
798 # string baz;
45c51519
PP
799 # variant <selector> {
800 # real a; // selected with self._ranges1
801 # int21_t b; // selected with self._ranges2
802 # uint34_t c; // selected with self._ranges3
d47b87ac
SM
803 # } variant;
804 # } inner_struct[2];
805 # };
45c51519 806 self._fc.append_option('a', self._tc.create_real_field_class(), self._ranges1)
cfbd7cf3
FD
807 self._fc.append_option(
808 'b', self._tc.create_signed_integer_field_class(21), self._ranges2
809 )
810 self._fc.append_option(
811 'c', self._tc.create_unsigned_integer_field_class(34), self._ranges3
812 )
b4f45851 813
d47b87ac
SM
814 foo_fc = self._tc.create_real_field_class()
815 bar_fc = self._tc.create_string_field_class()
816 baz_fc = self._tc.create_string_field_class()
b4f45851 817
d47b87ac 818 inner_struct_fc = self._tc.create_structure_field_class()
45c51519 819 inner_struct_fc.append_member('selector', self._selector_fc)
d47b87ac
SM
820 inner_struct_fc.append_member('bar', bar_fc)
821 inner_struct_fc.append_member('baz', baz_fc)
45c51519 822 inner_struct_fc.append_member('variant', self._fc)
b4f45851 823
cfbd7cf3
FD
824 inner_struct_array_fc = self._tc.create_static_array_field_class(
825 inner_struct_fc, 2
826 )
b4f45851 827
d47b87ac
SM
828 outer_struct_fc = self._tc.create_structure_field_class()
829 outer_struct_fc.append_member('foo', foo_fc)
830 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
b4f45851 831
d47b87ac
SM
832 # The path to the selector field is resolved when the sequence is
833 # actually used, for example in a packet context.
cfbd7cf3
FD
834 self._tc.create_stream_class(
835 supports_packets=True, packet_context_field_class=outer_struct_fc
836 )
b4f45851 837
d47b87ac 838 def test_selector_field_path_length(self):
45c51519
PP
839 self._fill_default_fc_for_field_path_test()
840 self.assertEqual(len(self._fc.selector_field_path), 3)
b4f45851 841
d47b87ac 842 def test_selector_field_path_iter(self):
45c51519
PP
843 self._fill_default_fc_for_field_path_test()
844 path_items = list(self._fc.selector_field_path)
b4f45851 845
d47b87ac 846 self.assertEqual(len(path_items), 3)
b4f45851 847
3fb99a22 848 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac 849 self.assertEqual(path_items[0].index, 1)
b4f45851 850
3fb99a22 851 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
b4f45851 852
3fb99a22 853 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac 854 self.assertEqual(path_items[2].index, 0)
b4f45851 855
d47b87ac 856 def test_selector_field_path_root_scope(self):
45c51519 857 self._fill_default_fc_for_field_path_test()
cfbd7cf3 858 self.assertEqual(
e7ceb9df 859 self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
cfbd7cf3 860 )
45c51519
PP
861
862
cfbd7cf3
FD
863class VariantFieldClassWithUnsignedSelectorTestCase(
864 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
865):
45c51519
PP
866 def _spec_set_up(self):
867 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
868 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
869 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
870 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, 16), (48, 99)])
871 self._selector_fc = self._tc.create_unsigned_integer_field_class()
872
873
cfbd7cf3
FD
874class VariantFieldClassWithSignedSelectorTestCase(
875 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
876):
45c51519
PP
877 def _spec_set_up(self):
878 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
879 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
880 self._ranges3 = bt2.SignedIntegerRangeSet([(8, 16), (48, 99)])
881 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
882 self._selector_fc = self._tc.create_signed_integer_field_class()
b4f45851 883
d47b87ac
SM
884
885class StaticArrayFieldClassTestCase(unittest.TestCase):
886 def setUp(self):
887 self._tc = get_default_trace_class()
888 self._elem_fc = self._tc.create_signed_integer_field_class(23)
b4f45851
SM
889
890 def test_create_default(self):
d47b87ac
SM
891 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
892 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
893 self.assertEqual(fc.length, 45)
5783664e 894 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 895
d47b87ac 896 def test_create_invalid_elem_field_class(self):
b4f45851 897 with self.assertRaises(TypeError):
d47b87ac 898 self._tc.create_static_array_field_class(object(), 45)
b4f45851
SM
899
900 def test_create_invalid_length(self):
901 with self.assertRaises(ValueError):
cfbd7cf3
FD
902 self._tc.create_static_array_field_class(
903 self._tc.create_string_field_class(), -17
904 )
b4f45851
SM
905
906 def test_create_invalid_length_type(self):
907 with self.assertRaises(TypeError):
cfbd7cf3
FD
908 self._tc.create_static_array_field_class(
909 self._tc.create_string_field_class(), 'the length'
910 )
d47b87ac
SM
911
912
913class DynamicArrayFieldClassTestCase(unittest.TestCase):
914 def setUp(self):
915 self._tc = get_default_trace_class()
916 self._elem_fc = self._tc.create_signed_integer_field_class(23)
917 self._len_fc = self._tc.create_unsigned_integer_field_class(12)
b4f45851 918
d47b87ac
SM
919 def test_create_default(self):
920 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
921 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
922 self.assertIsNone(fc.length_field_path, None)
5783664e 923 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 924
d47b87ac
SM
925 def _create_field_class_for_field_path_test(self):
926 # Create something a field class that is equivalent to:
927 #
928 # struct outer_struct_fc {
929 # real foo;
930 # struct inner_struct_fc {
931 # string bar;
932 # string baz;
933 # uint12_t len;
934 # uint23_t dyn_array[len];
935 # } inner_struct[2];
936 # };
b4f45851 937
d47b87ac 938 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
b4f45851 939
d47b87ac
SM
940 foo_fc = self._tc.create_real_field_class()
941 bar_fc = self._tc.create_string_field_class()
942 baz_fc = self._tc.create_string_field_class()
b4f45851 943
d47b87ac
SM
944 inner_struct_fc = self._tc.create_structure_field_class()
945 inner_struct_fc.append_member('bar', bar_fc)
946 inner_struct_fc.append_member('baz', baz_fc)
947 inner_struct_fc.append_member('len', self._len_fc)
948 inner_struct_fc.append_member('dyn_array', fc)
b4f45851 949
cfbd7cf3
FD
950 inner_struct_array_fc = self._tc.create_static_array_field_class(
951 inner_struct_fc, 2
952 )
d47b87ac
SM
953
954 outer_struct_fc = self._tc.create_structure_field_class()
955 outer_struct_fc.append_member('foo', foo_fc)
956 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
957
958 # The path to the length field is resolved when the sequence is
959 # actually used, for example in a packet context.
cfbd7cf3
FD
960 self._tc.create_stream_class(
961 packet_context_field_class=outer_struct_fc, supports_packets=True
962 )
d47b87ac
SM
963
964 return fc
965
966 def test_field_path_len(self):
967 fc = self._create_field_class_for_field_path_test()
968 self.assertEqual(len(fc.length_field_path), 3)
969
970 def test_field_path_iter(self):
971 fc = self._create_field_class_for_field_path_test()
972 path_items = list(fc.length_field_path)
973
974 self.assertEqual(len(path_items), 3)
975
3fb99a22 976 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac
SM
977 self.assertEqual(path_items[0].index, 1)
978
3fb99a22 979 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
d47b87ac 980
3fb99a22 981 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac
SM
982 self.assertEqual(path_items[2].index, 2)
983
984 def test_field_path_root_scope(self):
985 fc = self._create_field_class_for_field_path_test()
e7ceb9df
PP
986 self.assertEqual(
987 fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
988 )
b4f45851
SM
989
990 def test_create_invalid_field_class(self):
991 with self.assertRaises(TypeError):
d47b87ac 992 self._tc.create_dynamic_array_field_class(object())
b4f45851
SM
993
994 def test_create_invalid_length_type(self):
995 with self.assertRaises(TypeError):
cfbd7cf3
FD
996 self._tc.create_dynamic_array_field_class(
997 self._tc.create_string_field_class(), 17
998 )
b4f45851 999
b4f45851 1000
d47b87ac
SM
1001if __name__ == "__main__":
1002 unittest.main()
This page took 0.082624 seconds and 4 git commands to generate.