bt2: Add remaining trace-ir `*Const` classes and adapt tests
[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
f0a42b33
FD
21from utils import get_default_trace_class, TestOutputPortMessageIterator
22from bt2 import value as bt2_value
23from bt2 import field_class as bt2_field_class
24
25
26def _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
40def _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, 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
b4f45851
SM
76
77
5783664e
PP
78class _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})
f0a42b33
FD
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)
5783664e
PP
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
98class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
99 @staticmethod
100 def _const_value_setter(field):
101 field = False
102
5783664e 103 def _create_default_field_class(self, **kwargs):
aae30e61 104 tc = get_default_trace_class()
5783664e
PP
105 return tc.create_bool_field_class(**kwargs)
106
f0a42b33
FD
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
5783664e
PP
112 def setUp(self):
113 self._fc = self._create_default_field_class()
f0a42b33 114 self._fc_const = self._create_default_const_field_class()
aae30e61
PP
115
116 def test_create_default(self):
117 self.assertIsNotNone(self._fc)
5783664e 118 self.assertEqual(len(self._fc.user_attributes), 0)
aae30e61
PP
119
120
5783664e 121class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
122 @staticmethod
123 def _const_value_setter(field):
124 field = []
125
5783664e
PP
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
f0a42b33
FD
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
ead8c3d4 138 def setUp(self):
5783664e 139 self._fc = self._create_default_field_class()
ead8c3d4
PP
140
141 def test_create_default(self):
142 self.assertIsNotNone(self._fc)
5783664e 143 self.assertEqual(len(self._fc.user_attributes), 0)
ead8c3d4
PP
144
145 def test_create_length_out_of_range(self):
146 with self.assertRaises(ValueError):
5783664e 147 self._create_field_class(65)
ead8c3d4
PP
148
149 def test_create_length_zero(self):
150 with self.assertRaises(ValueError):
5783664e 151 self._create_field_class(0)
ead8c3d4
PP
152
153 def test_create_length_invalid_type(self):
154 with self.assertRaises(TypeError):
5783664e 155 self._create_field_class('lel')
ead8c3d4
PP
156
157 def test_length_prop(self):
158 self.assertEqual(self._fc.length, 17)
159
160
d47b87ac
SM
161class _TestIntegerFieldClassProps:
162 def test_create_default(self):
5783664e 163 fc = self._create_default_field_class()
d47b87ac
SM
164 self.assertEqual(fc.field_value_range, 64)
165 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.DECIMAL)
5783664e 166 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 167
d47b87ac 168 def test_create_range(self):
5783664e 169 fc = self._create_field_class(field_value_range=35)
d47b87ac 170 self.assertEqual(fc.field_value_range, 35)
b4f45851 171
5783664e 172 fc = self._create_field_class(36)
d47b87ac 173 self.assertEqual(fc.field_value_range, 36)
b4f45851 174
d47b87ac
SM
175 def test_create_invalid_range(self):
176 with self.assertRaises(TypeError):
5783664e 177 self._create_field_class('yes')
b4f45851 178
d47b87ac 179 with self.assertRaises(TypeError):
5783664e 180 self._create_field_class(field_value_range='yes')
b4f45851 181
b4f45851 182 with self.assertRaises(ValueError):
5783664e 183 self._create_field_class(field_value_range=-2)
b4f45851 184
d47b87ac 185 with self.assertRaises(ValueError):
5783664e 186 self._create_field_class(field_value_range=0)
b4f45851 187
d47b87ac 188 def test_create_base(self):
5783664e 189 fc = self._create_field_class(
cfbd7cf3
FD
190 preferred_display_base=bt2.IntegerDisplayBase.HEXADECIMAL
191 )
d47b87ac 192 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.HEXADECIMAL)
b4f45851 193
d47b87ac 194 def test_create_invalid_base_type(self):
b4f45851 195 with self.assertRaises(TypeError):
5783664e 196 self._create_field_class(preferred_display_base='yes')
b4f45851 197
d47b87ac
SM
198 def test_create_invalid_base_value(self):
199 with self.assertRaises(ValueError):
5783664e 200 self._create_field_class(preferred_display_base=444)
b4f45851 201
d47b87ac 202 def test_create_full(self):
5783664e
PP
203 fc = self._create_field_class(
204 24, preferred_display_base=bt2.IntegerDisplayBase.OCTAL
205 )
d47b87ac
SM
206 self.assertEqual(fc.field_value_range, 24)
207 self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.OCTAL)
b4f45851
SM
208
209
5783664e
PP
210class SignedIntegerFieldClassTestCase(
211 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
212):
f0a42b33
FD
213 @staticmethod
214 def _const_value_setter(field):
215 field = -18
216
5783664e
PP
217 def _create_field_class(self, *args, **kwargs):
218 tc = get_default_trace_class()
219 return tc.create_signed_integer_field_class(*args, **kwargs)
b4f45851 220
f0a42b33
FD
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
5783664e
PP
226 _create_default_field_class = _create_field_class
227
228
229class UnsignedIntegerFieldClassTestCase(
230 _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
231):
f0a42b33
FD
232 @staticmethod
233 def _const_value_setter(field):
234 field = 18
235
5783664e
PP
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
f0a42b33
FD
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
5783664e 245 _create_default_field_class = _create_field_class
b4f45851 246
5783664e
PP
247
248class RealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
249 @staticmethod
250 def _const_value_setter(field):
251 field = -18
252
5783664e
PP
253 def _create_field_class(self, *args, **kwargs):
254 tc = get_default_trace_class()
255 return tc.create_real_field_class(*args, **kwargs)
256
f0a42b33
FD
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
5783664e 262 _create_default_field_class = _create_field_class
b4f45851 263
d47b87ac 264 def test_create_default(self):
5783664e 265 fc = self._create_field_class()
d47b87ac 266 self.assertFalse(fc.is_single_precision)
5783664e 267 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 268
d47b87ac 269 def test_create_is_single_precision(self):
5783664e 270 fc = self._create_field_class(is_single_precision=True)
d47b87ac
SM
271 self.assertTrue(fc.is_single_precision)
272
273 def test_create_invalid_is_single_precision(self):
b4f45851 274 with self.assertRaises(TypeError):
5783664e 275 self._create_field_class(is_single_precision='hohoho')
b4f45851 276
b4f45851 277
d47b87ac
SM
278# Converts an _EnumerationFieldClassMapping to a list of ranges:
279#
280# [(lower0, upper0), (lower1, upper1), ...]
281
cfbd7cf3 282
45c51519
PP
283def enum_mapping_to_set(mapping):
284 return {(x.lower, x.upper) for x in mapping.ranges}
b4f45851 285
b4f45851 286
45c51519 287class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
d47b87ac 288 def setUp(self):
45c51519 289 self._spec_set_up()
5783664e 290 self._fc = self._create_default_field_class()
f0a42b33 291 self._fc_const = self._create_default_const_field_class()
d47b87ac
SM
292
293 def test_create_from_invalid_type(self):
b4f45851 294 with self.assertRaises(TypeError):
5783664e 295 self._create_field_class('coucou')
b4f45851 296
d47b87ac 297 def test_add_mapping_simple(self):
45c51519 298 self._fc.add_mapping('hello', self._ranges1)
d47b87ac
SM
299 mapping = self._fc['hello']
300 self.assertEqual(mapping.label, 'hello')
45c51519 301 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 302
f0a42b33
FD
303 def test_const_add_mapping(self):
304 with self.assertRaises(AttributeError):
305 self._fc_const.add_mapping('hello', self._ranges1)
306
d47b87ac 307 def test_add_mapping_simple_kwargs(self):
45c51519 308 self._fc.add_mapping(label='hello', ranges=self._ranges1)
d47b87ac
SM
309 mapping = self._fc['hello']
310 self.assertEqual(mapping.label, 'hello')
45c51519 311 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 312
45c51519
PP
313 def test_add_mapping_invalid_name(self):
314 with self.assertRaises(TypeError):
315 self._fc.add_mapping(17, self._ranges1)
b4f45851 316
45c51519
PP
317 def test_add_mapping_invalid_range(self):
318 with self.assertRaises(TypeError):
319 self._fc.add_mapping('allo', 'meow')
d47b87ac 320
45c51519 321 def test_add_mapping_dup_label(self):
ce4923b0 322 with self.assertRaises(ValueError):
45c51519
PP
323 self._fc.add_mapping('a', self._ranges1)
324 self._fc.add_mapping('a', self._ranges2)
d47b87ac 325
45c51519 326 def test_add_mapping_invalid_ranges_signedness(self):
b4f45851 327 with self.assertRaises(TypeError):
45c51519 328 self._fc.add_mapping('allo', self._inval_ranges)
b4f45851 329
d47b87ac 330 def test_iadd(self):
45c51519 331 self._fc.add_mapping('c', self._ranges1)
b4f45851 332
cfbd7cf3 333 self._fc += [('d', self._ranges2), ('e', self._ranges3)]
b4f45851 334
45c51519 335 self.assertEqual(len(self._fc), 3)
d47b87ac 336 self.assertEqual(self._fc['c'].label, 'c')
45c51519 337 self.assertEqual(self._fc['c'].ranges, self._ranges1)
d47b87ac 338 self.assertEqual(self._fc['d'].label, 'd')
45c51519 339 self.assertEqual(self._fc['d'].ranges, self._ranges2)
d47b87ac 340 self.assertEqual(self._fc['e'].label, 'e')
45c51519 341 self.assertEqual(self._fc['e'].ranges, self._ranges3)
b4f45851 342
f0a42b33
FD
343 def test_const_iadd(self):
344 with self.assertRaises(TypeError):
345 self._fc_const += [('d', self._ranges2), ('e', self._ranges3)]
346
d47b87ac
SM
347 def test_bool_op(self):
348 self.assertFalse(self._fc)
45c51519 349 self._fc.add_mapping('a', self._ranges1)
d47b87ac 350 self.assertTrue(self._fc)
b4f45851 351
d47b87ac 352 def test_len(self):
45c51519
PP
353 self._fc.add_mapping('a', self._ranges1)
354 self._fc.add_mapping('b', self._ranges2)
355 self._fc.add_mapping('c', self._ranges3)
d47b87ac 356 self.assertEqual(len(self._fc), 3)
b4f45851 357
d47b87ac 358 def test_getitem(self):
45c51519
PP
359 self._fc.add_mapping('a', self._ranges1)
360 self._fc.add_mapping('b', self._ranges2)
361 self._fc.add_mapping('c', self._ranges3)
d47b87ac 362 mapping = self._fc['a']
d47b87ac 363 self.assertEqual(mapping.label, 'a')
45c51519 364 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 365
45c51519 366 def test_getitem_nonexistent(self):
d47b87ac
SM
367 with self.assertRaises(KeyError):
368 self._fc['doesnotexist']
b4f45851 369
d47b87ac 370 def test_iter(self):
45c51519
PP
371 self._fc.add_mapping('a', self._ranges1)
372 self._fc.add_mapping('b', self._ranges2)
373 self._fc.add_mapping('c', self._ranges3)
b4f45851 374
d47b87ac
SM
375 # This exercises iteration.
376 labels = sorted(self._fc)
b4f45851 377
45c51519 378 self.assertEqual(labels, ['a', 'b', 'c'])
b4f45851 379
d47b87ac 380 def test_find_by_value(self):
45c51519
PP
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
cfbd7cf3 390class UnsignedEnumerationFieldClassTestCase(
5783664e 391 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 392):
45c51519
PP
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
5783664e 399
f0a42b33
FD
400 @staticmethod
401 def _const_value_setter(field):
402 field = 0
403
5783664e
PP
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
f0a42b33
FD
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
5783664e 413 _create_default_field_class = _create_field_class
b4f45851 414
b4f45851 415
cfbd7cf3 416class SignedEnumerationFieldClassTestCase(
5783664e 417 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 418):
45c51519
PP
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
b4f45851 425
f0a42b33
FD
426 @staticmethod
427 def _const_value_setter(field):
428 field = 0
429
5783664e
PP
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
f0a42b33
FD
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
5783664e 439 _create_default_field_class = _create_field_class
b4f45851 440
5783664e
PP
441
442class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
443 @staticmethod
444 def _const_value_setter(field):
445 field = 'chaine'
446
5783664e 447 def _create_field_class(self, *args, **kwargs):
d47b87ac 448 tc = get_default_trace_class()
5783664e
PP
449 return tc.create_string_field_class(*args, **kwargs)
450
f0a42b33
FD
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
5783664e
PP
456 _create_default_field_class = _create_field_class
457
458 def setUp(self):
459 self._fc = self._create_default_field_class()
b4f45851
SM
460
461 def test_create_default(self):
d47b87ac 462 self.assertIsNotNone(self._fc)
5783664e 463 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 464
b4f45851 465
cfbd7cf3 466class _TestElementContainer:
45c51519
PP
467 def setUp(self):
468 self._tc = get_default_trace_class()
5783664e 469 self._fc = self._create_default_field_class()
f0a42b33 470 self._fc_const = self._create_default_const_field_class()
45c51519
PP
471
472 def test_create_default(self):
473 self.assertIsNotNone(self._fc)
5783664e 474 self.assertEqual(len(self._fc.user_attributes), 0)
45c51519 475
d47b87ac
SM
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)
45c51519 479 field_class = self._fc['int32'].field_class
d47b87ac 480 self.assertEqual(field_class.addr, int_field_class.addr)
b4f45851 481
45c51519 482 def test_append_element_kwargs(self):
d47b87ac
SM
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)
45c51519 485 field_class = self._fc['int32'].field_class
d47b87ac
SM
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()
b4f45851 490
b4f45851 491 with self.assertRaises(TypeError):
d47b87ac 492 self._append_element_method(self._fc, 23, sub_fc)
b4f45851 493
d47b87ac 494 def test_append_element_invalid_field_class(self):
b4f45851 495 with self.assertRaises(TypeError):
d47b87ac 496 self._append_element_method(self._fc, 'yes', object())
b4f45851 497
45c51519
PP
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
ce4923b0 502 with self.assertRaises(ValueError):
45c51519
PP
503 self._append_element_method(self._fc, 'yes', sub_fc1)
504 self._append_element_method(self._fc, 'yes', sub_fc2)
505
f0a42b33
FD
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
b4f45851 524 def test_iadd(self):
d47b87ac
SM
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)
45c51519 529 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
530 d_field_class = self._tc.create_signed_enumeration_field_class(
531 field_value_range=32
532 )
45c51519
PP
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')
b4f45851 549
f0a42b33
FD
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
b4f45851
SM
555 def test_bool_op(self):
556 self.assertFalse(self._fc)
d47b87ac 557 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
558 self.assertTrue(self._fc)
559
560 def test_len(self):
45c51519
PP
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())
b4f45851
SM
564 self.assertEqual(len(self._fc), 3)
565
566 def test_getitem(self):
d47b87ac
SM
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)
45c51519
PP
573 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
574 self.assertEqual(self._fc['b'].name, 'b')
b4f45851
SM
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)
d47b87ac 586 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
587 self.assertTrue('a' in self._fc)
588
589 def test_iter(self):
d47b87ac
SM
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()
cfbd7cf3 593 elements = (('a', a_fc), ('b', b_fc), ('c', c_fc))
b4f45851 594
45c51519
PP
595 for elem in elements:
596 self._append_element_method(self._fc, *elem)
b4f45851 597
45c51519
PP
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)
5783664e 602 self.assertEqual(len(element.user_attributes), 0)
b4f45851
SM
603
604 def test_at_index(self):
d47b87ac
SM
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)
45c51519
PP
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')
b4f45851
SM
614
615 def test_at_index_invalid(self):
cfbd7cf3
FD
616 self._append_element_method(
617 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
618 )
b4f45851
SM
619
620 with self.assertRaises(TypeError):
d47b87ac 621 self._at_index_method(self._fc, 'yes')
b4f45851
SM
622
623 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
624 self._append_element_method(
625 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
626 )
b4f45851
SM
627
628 with self.assertRaises(IndexError):
d47b87ac 629 self._at_index_method(self._fc, len(self._fc))
b4f45851 630
5783664e
PP
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})
f0a42b33
FD
639 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
640 self.assertIs(type(self._fc['c'].user_attributes), bt2_value.MapValue)
b4f45851 641
5783664e
PP
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
658class StructureFieldClassTestCase(
659 _TestFieldClass, _TestElementContainer, unittest.TestCase
660):
3fb99a22
PP
661 _append_element_method = staticmethod(bt2._StructureFieldClass.append_member)
662 _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index)
45c51519 663
f0a42b33
FD
664 @staticmethod
665 def _const_value_setter(field):
666 field.value = {}
667
5783664e
PP
668 def _create_field_class(self, *args, **kwargs):
669 tc = get_default_trace_class()
670 return tc.create_structure_field_class(*args, **kwargs)
45c51519 671
f0a42b33
FD
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
5783664e
PP
677 _create_default_field_class = _create_field_class
678
f0a42b33
FD
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
5783664e
PP
701
702class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
703 @staticmethod
704 def _const_value_setter(field):
705 field.has_field = True
706 field.value = 12
707
5783664e
PP
708 def _create_default_field_class(self, *args, **kwargs):
709 return self._tc.create_option_field_class(self._content_fc, **kwargs)
45c51519 710
f0a42b33
FD
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
cec0261d
PP
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):
5783664e 721 fc = self._create_default_field_class()
cec0261d
PP
722 self.assertEqual(fc.field_class.addr, self._content_fc.addr)
723 self.assertIsNone(fc.selector_field_path, None)
5783664e 724 self.assertEqual(len(fc.user_attributes), 0)
cec0261d 725
f0a42b33
FD
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
cec0261d 736 def _create_field_class_for_field_path_test(self):
5783664e 737 fc = self._create_default_field_class(selector_fc=self._tag_fc)
cec0261d
PP
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
cfbd7cf3 797class VariantFieldClassWithoutSelectorTestCase(
5783664e 798 _TestFieldClass, _TestElementContainer, unittest.TestCase
cfbd7cf3
FD
799):
800 _append_element_method = staticmethod(
3fb99a22 801 bt2._VariantFieldClassWithoutSelector.append_option
cfbd7cf3
FD
802 )
803 _at_index_method = staticmethod(
3fb99a22 804 bt2._VariantFieldClassWithoutSelector.option_at_index
cfbd7cf3 805 )
45c51519 806
f0a42b33
FD
807 @staticmethod
808 def _const_value_setter(variant_field):
809 variant_field.selected_option_index = 0
810 variant_field.value = 12
811
5783664e
PP
812 def _create_field_class(self, *args, **kwargs):
813 tc = get_default_trace_class()
814 return tc.create_variant_field_class(*args, **kwargs)
815
f0a42b33
FD
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
5783664e 824 _create_default_field_class = _create_field_class
45c51519
PP
825
826
827class _VariantFieldClassWithSelectorTestCase:
f0a42b33
FD
828 @staticmethod
829 def _const_value_setter(field):
830 field['variant'].selected_option_index = 0
831 field['variant'] = 12
832
5783664e
PP
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
f0a42b33
FD
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
b4f45851 855 def setUp(self):
d47b87ac 856 self._tc = get_default_trace_class()
45c51519 857 self._spec_set_up()
5783664e 858 self._fc = self._create_default_field_class()
d47b87ac
SM
859
860 def test_create_default(self):
861 self.assertIsNotNone(self._fc)
5783664e 862 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 863
45c51519
PP
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
f0a42b33
FD
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
45c51519
PP
877 def test_append_element_kwargs(self):
878 int_field_class = self._tc.create_signed_integer_field_class(32)
cfbd7cf3
FD
879 self._fc.append_option(
880 name='int32', field_class=int_field_class, ranges=self._ranges1
881 )
45c51519
PP
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)
d47b87ac 886
45c51519
PP
887 def test_append_element_invalid_name(self):
888 sub_fc = self._tc.create_string_field_class()
b4f45851 889
45c51519
PP
890 with self.assertRaises(TypeError):
891 self._fc.append_option(self._fc, 23, sub_fc)
b4f45851 892
45c51519
PP
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
ce4923b0 907 with self.assertRaises(ValueError):
45c51519
PP
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
5783664e
PP
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})
f0a42b33
FD
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)
5783664e
PP
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
45c51519 949 def test_iadd(self):
45c51519
PP
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()
cfbd7cf3
FD
953 d_field_class = self._tc.create_signed_enumeration_field_class(
954 field_value_range=32
955 )
45c51519
PP
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
f0a42b33
FD
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
45c51519
PP
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
f0a42b33
FD
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
45c51519
PP
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)
b4f45851 1037
45c51519
PP
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):
cfbd7cf3
FD
1056 self._fc.append_option(
1057 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1058 )
45c51519
PP
1059
1060 with self.assertRaises(TypeError):
1061 self._fc.option_at_index('yes')
1062
1063 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
1064 self._fc.append_option(
1065 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1066 )
45c51519
PP
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):
d47b87ac
SM
1072 # Create something equivalent to:
1073 #
1074 # struct outer_struct_fc {
1075 # real foo;
1076 # struct inner_struct_fc {
45c51519 1077 # [u]int64_t selector;
d47b87ac
SM
1078 # string bar;
1079 # string baz;
45c51519
PP
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
d47b87ac
SM
1084 # } variant;
1085 # } inner_struct[2];
1086 # };
45c51519 1087 self._fc.append_option('a', self._tc.create_real_field_class(), self._ranges1)
cfbd7cf3
FD
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 )
b4f45851 1094
d47b87ac
SM
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()
b4f45851 1098
d47b87ac 1099 inner_struct_fc = self._tc.create_structure_field_class()
45c51519 1100 inner_struct_fc.append_member('selector', self._selector_fc)
d47b87ac
SM
1101 inner_struct_fc.append_member('bar', bar_fc)
1102 inner_struct_fc.append_member('baz', baz_fc)
45c51519 1103 inner_struct_fc.append_member('variant', self._fc)
b4f45851 1104
cfbd7cf3
FD
1105 inner_struct_array_fc = self._tc.create_static_array_field_class(
1106 inner_struct_fc, 2
1107 )
b4f45851 1108
d47b87ac
SM
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)
b4f45851 1112
d47b87ac
SM
1113 # The path to the selector field is resolved when the sequence is
1114 # actually used, for example in a packet context.
cfbd7cf3
FD
1115 self._tc.create_stream_class(
1116 supports_packets=True, packet_context_field_class=outer_struct_fc
1117 )
b4f45851 1118
d47b87ac 1119 def test_selector_field_path_length(self):
45c51519
PP
1120 self._fill_default_fc_for_field_path_test()
1121 self.assertEqual(len(self._fc.selector_field_path), 3)
b4f45851 1122
d47b87ac 1123 def test_selector_field_path_iter(self):
45c51519
PP
1124 self._fill_default_fc_for_field_path_test()
1125 path_items = list(self._fc.selector_field_path)
b4f45851 1126
d47b87ac 1127 self.assertEqual(len(path_items), 3)
b4f45851 1128
3fb99a22 1129 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac 1130 self.assertEqual(path_items[0].index, 1)
b4f45851 1131
3fb99a22 1132 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
b4f45851 1133
3fb99a22 1134 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac 1135 self.assertEqual(path_items[2].index, 0)
b4f45851 1136
d47b87ac 1137 def test_selector_field_path_root_scope(self):
45c51519 1138 self._fill_default_fc_for_field_path_test()
cfbd7cf3 1139 self.assertEqual(
e7ceb9df 1140 self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
cfbd7cf3 1141 )
45c51519
PP
1142
1143
cfbd7cf3
FD
1144class VariantFieldClassWithUnsignedSelectorTestCase(
1145 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1146):
45c51519
PP
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
cfbd7cf3
FD
1155class VariantFieldClassWithSignedSelectorTestCase(
1156 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1157):
45c51519
PP
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()
b4f45851 1164
d47b87ac 1165
f0a42b33
FD
1166class _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
1180class 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
d47b87ac
SM
1192 def setUp(self):
1193 self._tc = get_default_trace_class()
1194 self._elem_fc = self._tc.create_signed_integer_field_class(23)
b4f45851
SM
1195
1196 def test_create_default(self):
d47b87ac
SM
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)
5783664e 1200 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1201
d47b87ac 1202 def test_create_invalid_elem_field_class(self):
b4f45851 1203 with self.assertRaises(TypeError):
d47b87ac 1204 self._tc.create_static_array_field_class(object(), 45)
b4f45851
SM
1205
1206 def test_create_invalid_length(self):
1207 with self.assertRaises(ValueError):
cfbd7cf3
FD
1208 self._tc.create_static_array_field_class(
1209 self._tc.create_string_field_class(), -17
1210 )
b4f45851
SM
1211
1212 def test_create_invalid_length_type(self):
1213 with self.assertRaises(TypeError):
cfbd7cf3
FD
1214 self._tc.create_static_array_field_class(
1215 self._tc.create_string_field_class(), 'the length'
1216 )
d47b87ac
SM
1217
1218
f0a42b33
FD
1219class 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
d47b87ac
SM
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)
b4f45851 1235
d47b87ac
SM
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)
5783664e 1240 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1241
d47b87ac
SM
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 # };
b4f45851 1254
d47b87ac 1255 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
b4f45851 1256
d47b87ac
SM
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()
b4f45851 1260
d47b87ac
SM
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)
b4f45851 1266
cfbd7cf3
FD
1267 inner_struct_array_fc = self._tc.create_static_array_field_class(
1268 inner_struct_fc, 2
1269 )
d47b87ac
SM
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.
cfbd7cf3
FD
1277 self._tc.create_stream_class(
1278 packet_context_field_class=outer_struct_fc, supports_packets=True
1279 )
d47b87ac
SM
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
3fb99a22 1293 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac
SM
1294 self.assertEqual(path_items[0].index, 1)
1295
3fb99a22 1296 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
d47b87ac 1297
3fb99a22 1298 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac
SM
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()
e7ceb9df
PP
1303 self.assertEqual(
1304 fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
1305 )
b4f45851
SM
1306
1307 def test_create_invalid_field_class(self):
1308 with self.assertRaises(TypeError):
d47b87ac 1309 self._tc.create_dynamic_array_field_class(object())
b4f45851
SM
1310
1311 def test_create_invalid_length_type(self):
1312 with self.assertRaises(TypeError):
cfbd7cf3
FD
1313 self._tc.create_dynamic_array_field_class(
1314 self._tc.create_string_field_class(), 17
1315 )
b4f45851 1316
b4f45851 1317
d47b87ac
SM
1318if __name__ == "__main__":
1319 unittest.main()
This page took 0.09454 seconds and 4 git commands to generate.