lib: split real FC/field into single and double prec FC/field
[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):
8d8b141d 44 def __init__(self, config, self_port_output):
f0a42b33
FD
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):
59225a3e 64 def __init__(self, config, params, obj):
f0a42b33
FD
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):
d47b6b4e 101 field.value = False
f0a42b33 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):
d47b6b4e 124 field.value = []
f0a42b33 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):
d47b6b4e 215 field.value = -18
f0a42b33 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):
d47b6b4e 234 field.value = 18
f0a42b33 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 247
fe4df857 248class SingleRealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
249 @staticmethod
250 def _const_value_setter(field):
fe4df857 251 field.value = -18.0
f0a42b33 252
5783664e
PP
253 def _create_field_class(self, *args, **kwargs):
254 tc = get_default_trace_class()
fe4df857 255 return tc.create_single_precision_real_field_class(*args, **kwargs)
5783664e 256
f0a42b33
FD
257 def _create_default_const_field_class(self, *args, **kwargs):
258 tc = get_default_trace_class()
fe4df857 259 fc = tc.create_single_precision_real_field_class(*args, **kwargs)
f0a42b33
FD
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()
5783664e 266 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 267
d47b87ac 268
fe4df857
FD
269class DoubleRealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
270 @staticmethod
271 def _const_value_setter(field):
272 field.value = -18.0
273
274 def _create_field_class(self, *args, **kwargs):
275 tc = get_default_trace_class()
276 return tc.create_double_precision_real_field_class(*args, **kwargs)
277
278 def _create_default_const_field_class(self, *args, **kwargs):
279 tc = get_default_trace_class()
280 fc = tc.create_double_precision_real_field_class(*args, **kwargs)
281 return _create_const_field_class(tc, fc, self._const_value_setter)
282
283 _create_default_field_class = _create_field_class
284
285 def test_create_default(self):
286 fc = self._create_field_class()
287 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 288
b4f45851 289
d47b87ac
SM
290# Converts an _EnumerationFieldClassMapping to a list of ranges:
291#
292# [(lower0, upper0), (lower1, upper1), ...]
293
cfbd7cf3 294
45c51519
PP
295def enum_mapping_to_set(mapping):
296 return {(x.lower, x.upper) for x in mapping.ranges}
b4f45851 297
b4f45851 298
45c51519 299class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
d47b87ac 300 def setUp(self):
45c51519 301 self._spec_set_up()
5783664e 302 self._fc = self._create_default_field_class()
f0a42b33 303 self._fc_const = self._create_default_const_field_class()
d47b87ac
SM
304
305 def test_create_from_invalid_type(self):
b4f45851 306 with self.assertRaises(TypeError):
5783664e 307 self._create_field_class('coucou')
b4f45851 308
d47b87ac 309 def test_add_mapping_simple(self):
45c51519 310 self._fc.add_mapping('hello', self._ranges1)
d47b87ac
SM
311 mapping = self._fc['hello']
312 self.assertEqual(mapping.label, 'hello')
45c51519 313 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 314
f0a42b33
FD
315 def test_const_add_mapping(self):
316 with self.assertRaises(AttributeError):
317 self._fc_const.add_mapping('hello', self._ranges1)
318
d47b87ac 319 def test_add_mapping_simple_kwargs(self):
45c51519 320 self._fc.add_mapping(label='hello', ranges=self._ranges1)
d47b87ac
SM
321 mapping = self._fc['hello']
322 self.assertEqual(mapping.label, 'hello')
45c51519 323 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 324
45c51519
PP
325 def test_add_mapping_invalid_name(self):
326 with self.assertRaises(TypeError):
327 self._fc.add_mapping(17, self._ranges1)
b4f45851 328
45c51519
PP
329 def test_add_mapping_invalid_range(self):
330 with self.assertRaises(TypeError):
331 self._fc.add_mapping('allo', 'meow')
d47b87ac 332
45c51519 333 def test_add_mapping_dup_label(self):
ce4923b0 334 with self.assertRaises(ValueError):
45c51519
PP
335 self._fc.add_mapping('a', self._ranges1)
336 self._fc.add_mapping('a', self._ranges2)
d47b87ac 337
45c51519 338 def test_add_mapping_invalid_ranges_signedness(self):
b4f45851 339 with self.assertRaises(TypeError):
45c51519 340 self._fc.add_mapping('allo', self._inval_ranges)
b4f45851 341
d47b87ac 342 def test_iadd(self):
45c51519 343 self._fc.add_mapping('c', self._ranges1)
b4f45851 344
cfbd7cf3 345 self._fc += [('d', self._ranges2), ('e', self._ranges3)]
b4f45851 346
45c51519 347 self.assertEqual(len(self._fc), 3)
d47b87ac 348 self.assertEqual(self._fc['c'].label, 'c')
45c51519 349 self.assertEqual(self._fc['c'].ranges, self._ranges1)
d47b87ac 350 self.assertEqual(self._fc['d'].label, 'd')
45c51519 351 self.assertEqual(self._fc['d'].ranges, self._ranges2)
d47b87ac 352 self.assertEqual(self._fc['e'].label, 'e')
45c51519 353 self.assertEqual(self._fc['e'].ranges, self._ranges3)
b4f45851 354
f0a42b33
FD
355 def test_const_iadd(self):
356 with self.assertRaises(TypeError):
357 self._fc_const += [('d', self._ranges2), ('e', self._ranges3)]
358
d47b87ac
SM
359 def test_bool_op(self):
360 self.assertFalse(self._fc)
45c51519 361 self._fc.add_mapping('a', self._ranges1)
d47b87ac 362 self.assertTrue(self._fc)
b4f45851 363
d47b87ac 364 def test_len(self):
45c51519
PP
365 self._fc.add_mapping('a', self._ranges1)
366 self._fc.add_mapping('b', self._ranges2)
367 self._fc.add_mapping('c', self._ranges3)
d47b87ac 368 self.assertEqual(len(self._fc), 3)
b4f45851 369
d47b87ac 370 def test_getitem(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)
d47b87ac 374 mapping = self._fc['a']
d47b87ac 375 self.assertEqual(mapping.label, 'a')
45c51519 376 self.assertEqual(mapping.ranges, self._ranges1)
b4f45851 377
45c51519 378 def test_getitem_nonexistent(self):
d47b87ac
SM
379 with self.assertRaises(KeyError):
380 self._fc['doesnotexist']
b4f45851 381
d47b87ac 382 def test_iter(self):
45c51519
PP
383 self._fc.add_mapping('a', self._ranges1)
384 self._fc.add_mapping('b', self._ranges2)
385 self._fc.add_mapping('c', self._ranges3)
b4f45851 386
d47b87ac
SM
387 # This exercises iteration.
388 labels = sorted(self._fc)
b4f45851 389
45c51519 390 self.assertEqual(labels, ['a', 'b', 'c'])
b4f45851 391
d47b87ac 392 def test_find_by_value(self):
45c51519
PP
393 self._fc.add_mapping('a', self._ranges1)
394 self._fc.add_mapping('b', self._ranges2)
395 self._fc.add_mapping('c', self._ranges3)
396 mappings = self._fc.mappings_for_value(self._value_in_range_1_and_3)
397 labels = set([mapping.label for mapping in mappings])
398 expected_labels = set(['a', 'c'])
399 self.assertEqual(labels, expected_labels)
400
401
cfbd7cf3 402class UnsignedEnumerationFieldClassTestCase(
5783664e 403 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 404):
45c51519
PP
405 def _spec_set_up(self):
406 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
407 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
408 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 22), (48, 99)])
409 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, -5), (48, 1928)])
410 self._value_in_range_1_and_3 = 20
5783664e 411
f0a42b33
FD
412 @staticmethod
413 def _const_value_setter(field):
d47b6b4e 414 field.value = 0
f0a42b33 415
5783664e
PP
416 def _create_field_class(self, *args, **kwargs):
417 tc = get_default_trace_class()
418 return tc.create_unsigned_enumeration_field_class(*args, **kwargs)
419
f0a42b33
FD
420 def _create_default_const_field_class(self, *args, **kwargs):
421 tc = get_default_trace_class()
422 fc = tc.create_unsigned_enumeration_field_class(*args, **kwargs)
423 return _create_const_field_class(tc, fc, self._const_value_setter)
424
5783664e 425 _create_default_field_class = _create_field_class
b4f45851 426
b4f45851 427
cfbd7cf3 428class SignedEnumerationFieldClassTestCase(
5783664e 429 _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase
cfbd7cf3 430):
45c51519
PP
431 def _spec_set_up(self):
432 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
433 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
434 self._ranges3 = bt2.SignedIntegerRangeSet([(-100, -1), (8, 16), (48, 99)])
435 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
436 self._value_in_range_1_and_3 = -7
b4f45851 437
f0a42b33
FD
438 @staticmethod
439 def _const_value_setter(field):
d47b6b4e 440 field.value = 0
f0a42b33 441
5783664e
PP
442 def _create_field_class(self, *args, **kwargs):
443 tc = get_default_trace_class()
444 return tc.create_signed_enumeration_field_class(*args, **kwargs)
445
f0a42b33
FD
446 def _create_default_const_field_class(self, *args, **kwargs):
447 tc = get_default_trace_class()
448 fc = tc.create_signed_enumeration_field_class(*args, **kwargs)
449 return _create_const_field_class(tc, fc, self._const_value_setter)
450
5783664e 451 _create_default_field_class = _create_field_class
b4f45851 452
5783664e
PP
453
454class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
455 @staticmethod
456 def _const_value_setter(field):
d47b6b4e 457 field.value = 'chaine'
f0a42b33 458
5783664e 459 def _create_field_class(self, *args, **kwargs):
d47b87ac 460 tc = get_default_trace_class()
5783664e
PP
461 return tc.create_string_field_class(*args, **kwargs)
462
f0a42b33
FD
463 def _create_default_const_field_class(self, *args, **kwargs):
464 tc = get_default_trace_class()
465 fc = tc.create_string_field_class(*args, **kwargs)
466 return _create_const_field_class(tc, fc, self._const_value_setter)
467
5783664e
PP
468 _create_default_field_class = _create_field_class
469
470 def setUp(self):
471 self._fc = self._create_default_field_class()
b4f45851
SM
472
473 def test_create_default(self):
d47b87ac 474 self.assertIsNotNone(self._fc)
5783664e 475 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 476
b4f45851 477
cfbd7cf3 478class _TestElementContainer:
45c51519
PP
479 def setUp(self):
480 self._tc = get_default_trace_class()
5783664e 481 self._fc = self._create_default_field_class()
f0a42b33 482 self._fc_const = self._create_default_const_field_class()
45c51519
PP
483
484 def test_create_default(self):
485 self.assertIsNotNone(self._fc)
5783664e 486 self.assertEqual(len(self._fc.user_attributes), 0)
45c51519 487
d47b87ac
SM
488 def test_append_element(self):
489 int_field_class = self._tc.create_signed_integer_field_class(32)
490 self._append_element_method(self._fc, 'int32', int_field_class)
45c51519 491 field_class = self._fc['int32'].field_class
d47b87ac 492 self.assertEqual(field_class.addr, int_field_class.addr)
b4f45851 493
45c51519 494 def test_append_element_kwargs(self):
d47b87ac
SM
495 int_field_class = self._tc.create_signed_integer_field_class(32)
496 self._append_element_method(self._fc, name='int32', field_class=int_field_class)
45c51519 497 field_class = self._fc['int32'].field_class
d47b87ac
SM
498 self.assertEqual(field_class.addr, int_field_class.addr)
499
500 def test_append_element_invalid_name(self):
501 sub_fc = self._tc.create_string_field_class()
b4f45851 502
b4f45851 503 with self.assertRaises(TypeError):
d47b87ac 504 self._append_element_method(self._fc, 23, sub_fc)
b4f45851 505
d47b87ac 506 def test_append_element_invalid_field_class(self):
b4f45851 507 with self.assertRaises(TypeError):
d47b87ac 508 self._append_element_method(self._fc, 'yes', object())
b4f45851 509
45c51519
PP
510 def test_append_element_dup_name(self):
511 sub_fc1 = self._tc.create_string_field_class()
512 sub_fc2 = self._tc.create_string_field_class()
513
ce4923b0 514 with self.assertRaises(ValueError):
45c51519
PP
515 self._append_element_method(self._fc, 'yes', sub_fc1)
516 self._append_element_method(self._fc, 'yes', sub_fc2)
517
f0a42b33
FD
518 def test_attr_field_class(self):
519 int_field_class = self._tc.create_signed_integer_field_class(32)
520 self._append_element_method(self._fc, 'int32', int_field_class)
521 field_class = self._fc['int32'].field_class
522
523 self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClass)
524
525 def test_const_attr_field_class(self):
526 int_field_class = self._tc.create_signed_integer_field_class(32)
527 self._append_element_method(self._fc, 'int32', int_field_class)
528 field_class = self._fc['int32'].field_class
529 const_fc = _create_const_field_class(
530 self._tc, self._fc, self._const_value_setter
531 )
532 field_class = const_fc['int32'].field_class
533
534 self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClassConst)
535
b4f45851 536 def test_iadd(self):
fe4df857 537 a_field_class = self._tc.create_single_precision_real_field_class()
d47b87ac
SM
538 b_field_class = self._tc.create_signed_integer_field_class(17)
539 self._append_element_method(self._fc, 'a_float', a_field_class)
540 self._append_element_method(self._fc, 'b_int', b_field_class)
45c51519 541 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
542 d_field_class = self._tc.create_signed_enumeration_field_class(
543 field_value_range=32
544 )
45c51519
PP
545 e_field_class = self._tc.create_structure_field_class()
546 self._fc += [
547 ('c_string', c_field_class),
548 ('d_enum', d_field_class),
549 ('e_struct', e_field_class),
550 ]
551 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
552 self.assertEqual(self._fc['a_float'].name, 'a_float')
553 self.assertEqual(self._fc['b_int'].field_class.addr, b_field_class.addr)
554 self.assertEqual(self._fc['b_int'].name, 'b_int')
555 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
556 self.assertEqual(self._fc['c_string'].name, 'c_string')
557 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
558 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
559 self.assertEqual(self._fc['e_struct'].field_class.addr, e_field_class.addr)
560 self.assertEqual(self._fc['e_struct'].name, 'e_struct')
b4f45851 561
f0a42b33 562 def test_const_iadd(self):
fe4df857 563 a_field_class = self._tc.create_single_precision_real_field_class()
f0a42b33
FD
564 with self.assertRaises(TypeError):
565 self._fc_const += a_field_class
566
b4f45851
SM
567 def test_bool_op(self):
568 self.assertFalse(self._fc)
d47b87ac 569 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
570 self.assertTrue(self._fc)
571
572 def test_len(self):
45c51519
PP
573 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
574 self._append_element_method(self._fc, 'b', self._tc.create_string_field_class())
575 self._append_element_method(self._fc, 'c', self._tc.create_string_field_class())
b4f45851
SM
576 self.assertEqual(len(self._fc), 3)
577
578 def test_getitem(self):
d47b87ac
SM
579 a_fc = self._tc.create_signed_integer_field_class(32)
580 b_fc = self._tc.create_string_field_class()
fe4df857 581 c_fc = self._tc.create_single_precision_real_field_class()
d47b87ac
SM
582 self._append_element_method(self._fc, 'a', a_fc)
583 self._append_element_method(self._fc, 'b', b_fc)
584 self._append_element_method(self._fc, 'c', c_fc)
45c51519
PP
585 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
586 self.assertEqual(self._fc['b'].name, 'b')
b4f45851
SM
587
588 def test_getitem_invalid_key_type(self):
589 with self.assertRaises(TypeError):
590 self._fc[0]
591
592 def test_getitem_invalid_key(self):
593 with self.assertRaises(KeyError):
594 self._fc['no way']
595
596 def test_contains(self):
597 self.assertFalse('a' in self._fc)
d47b87ac 598 self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
b4f45851
SM
599 self.assertTrue('a' in self._fc)
600
601 def test_iter(self):
d47b87ac
SM
602 a_fc = self._tc.create_signed_integer_field_class(32)
603 b_fc = self._tc.create_string_field_class()
fe4df857 604 c_fc = self._tc.create_single_precision_real_field_class()
cfbd7cf3 605 elements = (('a', a_fc), ('b', b_fc), ('c', c_fc))
b4f45851 606
45c51519
PP
607 for elem in elements:
608 self._append_element_method(self._fc, *elem)
b4f45851 609
45c51519
PP
610 for (name, element), test_elem in zip(self._fc.items(), elements):
611 self.assertEqual(element.name, test_elem[0])
612 self.assertEqual(name, element.name)
613 self.assertEqual(element.field_class.addr, test_elem[1].addr)
5783664e 614 self.assertEqual(len(element.user_attributes), 0)
b4f45851
SM
615
616 def test_at_index(self):
d47b87ac
SM
617 a_fc = self._tc.create_signed_integer_field_class(32)
618 b_fc = self._tc.create_string_field_class()
fe4df857 619 c_fc = self._tc.create_single_precision_real_field_class()
d47b87ac
SM
620 self._append_element_method(self._fc, 'c', c_fc)
621 self._append_element_method(self._fc, 'a', a_fc)
622 self._append_element_method(self._fc, 'b', b_fc)
45c51519
PP
623 elem = self._at_index_method(self._fc, 1)
624 self.assertEqual(elem.field_class.addr, a_fc.addr)
625 self.assertEqual(elem.name, 'a')
b4f45851
SM
626
627 def test_at_index_invalid(self):
cfbd7cf3
FD
628 self._append_element_method(
629 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
630 )
b4f45851
SM
631
632 with self.assertRaises(TypeError):
d47b87ac 633 self._at_index_method(self._fc, 'yes')
b4f45851
SM
634
635 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
636 self._append_element_method(
637 self._fc, 'c', self._tc.create_signed_integer_field_class(32)
638 )
b4f45851
SM
639
640 with self.assertRaises(IndexError):
d47b87ac 641 self._at_index_method(self._fc, len(self._fc))
b4f45851 642
5783664e
PP
643 def test_user_attributes(self):
644 self._append_element_method(
645 self._fc,
646 'c',
647 self._tc.create_string_field_class(),
648 user_attributes={'salut': 23},
649 )
650 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
f0a42b33
FD
651 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
652 self.assertIs(type(self._fc['c'].user_attributes), bt2_value.MapValue)
b4f45851 653
5783664e
PP
654 def test_invalid_user_attributes(self):
655 with self.assertRaises(TypeError):
656 self._append_element_method(
657 self._fc,
658 'c',
659 self._tc.create_string_field_class(),
660 user_attributes=object(),
661 )
662
663 def test_invalid_user_attributes_value_type(self):
664 with self.assertRaises(TypeError):
665 self._append_element_method(
666 self._fc, 'c', self._tc.create_string_field_class(), user_attributes=23
667 )
668
669
670class StructureFieldClassTestCase(
671 _TestFieldClass, _TestElementContainer, unittest.TestCase
672):
3fb99a22
PP
673 _append_element_method = staticmethod(bt2._StructureFieldClass.append_member)
674 _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index)
45c51519 675
f0a42b33
FD
676 @staticmethod
677 def _const_value_setter(field):
678 field.value = {}
679
5783664e
PP
680 def _create_field_class(self, *args, **kwargs):
681 tc = get_default_trace_class()
682 return tc.create_structure_field_class(*args, **kwargs)
45c51519 683
f0a42b33
FD
684 def _create_default_const_field_class(self, *args, **kwargs):
685 tc = get_default_trace_class()
686 fc = tc.create_structure_field_class(*args, **kwargs)
687 return _create_const_field_class(tc, fc, self._const_value_setter)
688
5783664e
PP
689 _create_default_field_class = _create_field_class
690
f0a42b33
FD
691 def test_const_member_field_class(self):
692 def _real_value_setter(field):
693 field.value = {'real': 0}
694
695 tc = get_default_trace_class()
696 fc = tc.create_structure_field_class()
fe4df857 697 member_fc = self._tc.create_single_precision_real_field_class()
f0a42b33
FD
698 fc.append_member('real', member_fc)
699 const_fc = _create_const_field_class(tc, fc, _real_value_setter)
700
701 self.assertIs(
fe4df857
FD
702 type(const_fc['real'].field_class),
703 bt2_field_class._SinglePrecisionRealFieldClassConst,
f0a42b33
FD
704 )
705
706 def test_member_field_class(self):
707 tc = get_default_trace_class()
708 fc = tc.create_structure_field_class()
fe4df857 709 member_fc = self._tc.create_single_precision_real_field_class()
f0a42b33
FD
710 fc.append_member('real', member_fc)
711
fe4df857
FD
712 self.assertIs(
713 type(fc['real'].field_class), bt2_field_class._SinglePrecisionRealFieldClass
714 )
f0a42b33 715
5783664e
PP
716
717class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
718 @staticmethod
719 def _const_value_setter(field):
720 field.has_field = True
721 field.value = 12
722
5783664e
PP
723 def _create_default_field_class(self, *args, **kwargs):
724 return self._tc.create_option_field_class(self._content_fc, **kwargs)
45c51519 725
f0a42b33
FD
726 def _create_default_const_field_class(self, *args, **kwargs):
727 fc = self._tc.create_option_field_class(self._content_fc, **kwargs)
728 return _create_const_field_class(self._tc, fc, self._const_value_setter)
729
cec0261d
PP
730 def setUp(self):
731 self._tc = get_default_trace_class()
732 self._content_fc = self._tc.create_signed_integer_field_class(23)
733 self._tag_fc = self._tc.create_bool_field_class()
734
735 def test_create_default(self):
5783664e 736 fc = self._create_default_field_class()
cec0261d
PP
737 self.assertEqual(fc.field_class.addr, self._content_fc.addr)
738 self.assertIsNone(fc.selector_field_path, None)
5783664e 739 self.assertEqual(len(fc.user_attributes), 0)
cec0261d 740
f0a42b33
FD
741 def test_attr_field_class(self):
742 fc = self._create_default_field_class()
743 self.assertIs(type(fc.field_class), bt2_field_class._SignedIntegerFieldClass)
744
745 def test_const_attr_field_class(self):
746 fc = self._create_default_const_field_class()
747 self.assertIs(
748 type(fc.field_class), bt2_field_class._SignedIntegerFieldClassConst
749 )
750
cec0261d 751 def _create_field_class_for_field_path_test(self):
5783664e 752 fc = self._create_default_field_class(selector_fc=self._tag_fc)
cec0261d 753
fe4df857 754 foo_fc = self._tc.create_single_precision_real_field_class()
cec0261d
PP
755 bar_fc = self._tc.create_string_field_class()
756 baz_fc = self._tc.create_string_field_class()
757
758 inner_struct_fc = self._tc.create_structure_field_class()
759 inner_struct_fc.append_member('bar', bar_fc)
760 inner_struct_fc.append_member('baz', baz_fc)
761 inner_struct_fc.append_member('tag', self._tag_fc)
762 inner_struct_fc.append_member('opt', fc)
763
764 opt_struct_array_fc = self._tc.create_option_field_class(inner_struct_fc)
765
766 outer_struct_fc = self._tc.create_structure_field_class()
767 outer_struct_fc.append_member('foo', foo_fc)
768 outer_struct_fc.append_member('inner_opt', opt_struct_array_fc)
769
770 # The path to the selector field class is resolved when the
771 # option field class is actually used, for example in a packet
772 # context.
773 self._tc.create_stream_class(
774 packet_context_field_class=outer_struct_fc, supports_packets=True
775 )
776
777 return fc
778
779 def test_field_path_len(self):
780 fc = self._create_field_class_for_field_path_test()
781 self.assertEqual(len(fc.selector_field_path), 3)
782
783 def test_field_path_iter(self):
784 fc = self._create_field_class_for_field_path_test()
785 path_items = list(fc.selector_field_path)
786
787 self.assertEqual(len(path_items), 3)
788
789 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
790 self.assertEqual(path_items[0].index, 1)
791
792 self.assertIsInstance(path_items[1], bt2._CurrentOptionContentFieldPathItem)
793
794 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
795 self.assertEqual(path_items[2].index, 2)
796
797 def test_field_path_root_scope(self):
798 fc = self._create_field_class_for_field_path_test()
799 self.assertEqual(
800 fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
801 )
802
803 def test_create_invalid_field_class(self):
804 with self.assertRaises(TypeError):
805 self._tc.create_option_field_class(object())
806
807 def test_create_invalid_selector_type(self):
808 with self.assertRaises(TypeError):
809 self._tc.create_option_field_class(self._content_fc, 17)
810
811
cfbd7cf3 812class VariantFieldClassWithoutSelectorTestCase(
5783664e 813 _TestFieldClass, _TestElementContainer, unittest.TestCase
cfbd7cf3
FD
814):
815 _append_element_method = staticmethod(
3fb99a22 816 bt2._VariantFieldClassWithoutSelector.append_option
cfbd7cf3
FD
817 )
818 _at_index_method = staticmethod(
3fb99a22 819 bt2._VariantFieldClassWithoutSelector.option_at_index
cfbd7cf3 820 )
45c51519 821
f0a42b33
FD
822 @staticmethod
823 def _const_value_setter(variant_field):
824 variant_field.selected_option_index = 0
825 variant_field.value = 12
826
5783664e
PP
827 def _create_field_class(self, *args, **kwargs):
828 tc = get_default_trace_class()
829 return tc.create_variant_field_class(*args, **kwargs)
830
f0a42b33
FD
831 def _create_default_const_field_class(self, *args, **kwargs):
832 tc = get_default_trace_class()
833 fc = tc.create_variant_field_class(*args, **kwargs)
834 int_field_class = self._tc.create_signed_integer_field_class(32)
835 fc.append_option('int32', int_field_class)
836
837 return _create_const_field_class(tc, fc, self._const_value_setter)
838
5783664e 839 _create_default_field_class = _create_field_class
45c51519
PP
840
841
842class _VariantFieldClassWithSelectorTestCase:
f0a42b33
FD
843 @staticmethod
844 def _const_value_setter(field):
845 field['variant'].selected_option_index = 0
846 field['variant'] = 12
847
5783664e
PP
848 def _create_default_field_class(self, *args, **kwargs):
849 return self._tc.create_variant_field_class(
850 *args, selector_fc=self._selector_fc, **kwargs
851 )
852
f0a42b33
FD
853 def _create_default_const_field_class(self, *args, **kwargs):
854 # Create a struct to contain the variant and its selector else we can't
855 # create the non-const field necessary to get the the const field_class
856 struct_fc = self._tc.create_structure_field_class()
857 struct_fc.append_member('selecteux', self._selector_fc)
858 variant_fc = self._tc.create_variant_field_class(
859 *args, selector_fc=self._selector_fc
860 )
861 variant_fc.append_option(
862 'a', self._tc.create_signed_integer_field_class(32), self._ranges1
863 )
864 struct_fc.append_member('variant', variant_fc, **kwargs)
865
866 return _create_const_field_class(self._tc, struct_fc, self._const_value_setter)[
867 'variant'
868 ].field_class
869
b4f45851 870 def setUp(self):
d47b87ac 871 self._tc = get_default_trace_class()
45c51519 872 self._spec_set_up()
5783664e 873 self._fc = self._create_default_field_class()
d47b87ac
SM
874
875 def test_create_default(self):
876 self.assertIsNotNone(self._fc)
5783664e 877 self.assertEqual(len(self._fc.user_attributes), 0)
b4f45851 878
45c51519
PP
879 def test_append_element(self):
880 str_field_class = self._tc.create_string_field_class()
881 self._fc.append_option('str', str_field_class, self._ranges1)
882 opt = self._fc['str']
883 self.assertEqual(opt.field_class.addr, str_field_class.addr)
884 self.assertEqual(opt.name, 'str')
885 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
886
f0a42b33
FD
887 def test_const_append(self):
888 fc_const = self._create_default_const_field_class()
fd4e6235 889 str_field_class = self._tc.create_string_field_class()
f0a42b33
FD
890 with self.assertRaises(AttributeError):
891 fc_const.append_option('str', str_field_class, self._ranges1)
892
45c51519
PP
893 def test_append_element_kwargs(self):
894 int_field_class = self._tc.create_signed_integer_field_class(32)
cfbd7cf3
FD
895 self._fc.append_option(
896 name='int32', field_class=int_field_class, ranges=self._ranges1
897 )
45c51519
PP
898 opt = self._fc['int32']
899 self.assertEqual(opt.field_class.addr, int_field_class.addr)
900 self.assertEqual(opt.name, 'int32')
901 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
d47b87ac 902
45c51519
PP
903 def test_append_element_invalid_name(self):
904 sub_fc = self._tc.create_string_field_class()
b4f45851 905
45c51519
PP
906 with self.assertRaises(TypeError):
907 self._fc.append_option(self._fc, 23, sub_fc)
b4f45851 908
45c51519
PP
909 def test_append_element_invalid_field_class(self):
910 with self.assertRaises(TypeError):
911 self._fc.append_option(self._fc, 'yes', object())
912
913 def test_append_element_invalid_ranges(self):
914 sub_fc = self._tc.create_string_field_class()
915
916 with self.assertRaises(TypeError):
917 self._fc.append_option(self._fc, sub_fc, 'lel')
918
919 def test_append_element_dup_name(self):
920 sub_fc1 = self._tc.create_string_field_class()
921 sub_fc2 = self._tc.create_string_field_class()
922
ce4923b0 923 with self.assertRaises(ValueError):
45c51519
PP
924 self._fc.append_option('yes', sub_fc1, self._ranges1)
925 self._fc.append_option('yes', sub_fc2, self._ranges2)
926
927 def test_append_element_invalid_ranges_signedness(self):
928 sub_fc = self._tc.create_string_field_class()
929
930 with self.assertRaises(TypeError):
931 self._fc.append_option(self._fc, sub_fc, self._inval_ranges)
932
5783664e
PP
933 def test_user_attributes(self):
934 self._fc.append_option(
935 'c',
936 self._tc.create_string_field_class(),
937 self._ranges1,
938 user_attributes={'salut': 23},
939 )
940 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
f0a42b33
FD
941 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
942
943 def test_const_user_attributes(self):
944 fc_const = self._create_default_const_field_class()
945 self.assertIs(type(fc_const.user_attributes), bt2_value._MapValueConst)
5783664e
PP
946
947 def test_invalid_user_attributes(self):
948 with self.assertRaises(TypeError):
949 self._fc.append_option(
950 'c',
951 self._tc.create_string_field_class(),
952 self._ranges1,
953 user_attributes=object(),
954 )
955
956 def test_invalid_user_attributes_value_type(self):
957 with self.assertRaises(TypeError):
958 self._fc.append_option(
959 'c',
960 self._tc.create_string_field_class(),
961 self._ranges1,
962 user_attributes=23,
963 )
964
45c51519 965 def test_iadd(self):
fe4df857 966 a_field_class = self._tc.create_single_precision_real_field_class()
45c51519
PP
967 self._fc.append_option('a_float', a_field_class, self._ranges1)
968 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
969 d_field_class = self._tc.create_signed_enumeration_field_class(
970 field_value_range=32
971 )
45c51519
PP
972 self._fc += [
973 ('c_string', c_field_class, self._ranges2),
974 ('d_enum', d_field_class, self._ranges3),
975 ]
976 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
977 self.assertEqual(self._fc['a_float'].name, 'a_float')
978 self.assertEqual(self._fc['a_float'].ranges, self._ranges1)
979 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
980 self.assertEqual(self._fc['c_string'].name, 'c_string')
981 self.assertEqual(self._fc['c_string'].ranges, self._ranges2)
982 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
983 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
984 self.assertEqual(self._fc['d_enum'].ranges, self._ranges3)
985
f0a42b33
FD
986 def test_const_iadd(self):
987 fc_const = self._create_default_const_field_class()
fe4df857 988 a_field_class = self._tc.create_single_precision_real_field_class()
f0a42b33
FD
989 with self.assertRaises(TypeError):
990 fc_const += [('a_float', a_field_class, self._ranges1)]
991
45c51519
PP
992 def test_bool_op(self):
993 self.assertFalse(self._fc)
994 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
995 self.assertTrue(self._fc)
996
997 def test_len(self):
998 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
999 self._fc.append_option('b', self._tc.create_string_field_class(), self._ranges2)
1000 self._fc.append_option('c', self._tc.create_string_field_class(), self._ranges3)
1001 self.assertEqual(len(self._fc), 3)
1002
1003 def test_getitem(self):
1004 a_fc = self._tc.create_signed_integer_field_class(32)
1005 b_fc = self._tc.create_string_field_class()
fe4df857 1006 c_fc = self._tc.create_single_precision_real_field_class()
45c51519
PP
1007 self._fc.append_option('a', a_fc, self._ranges1)
1008 self._fc.append_option('b', b_fc, self._ranges2)
1009 self._fc.append_option('c', c_fc, self._ranges3)
1010 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
1011 self.assertEqual(self._fc['b'].name, 'b')
1012 self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr)
1013
f0a42b33
FD
1014 def test_option_field_class(self):
1015 a_fc = self._tc.create_signed_integer_field_class(32)
1016 self._fc.append_option('a', a_fc, self._ranges1)
1017 self.assertIs(
1018 type(self._fc['a'].field_class), bt2_field_class._SignedIntegerFieldClass
1019 )
1020
1021 def test_const_option_field_class(self):
1022 fc_const = self._create_default_const_field_class()
1023 self.assertIs(
1024 type(fc_const['a'].field_class),
1025 bt2_field_class._SignedIntegerFieldClassConst,
1026 )
1027
45c51519
PP
1028 def test_getitem_invalid_key_type(self):
1029 with self.assertRaises(TypeError):
1030 self._fc[0]
1031
1032 def test_getitem_invalid_key(self):
1033 with self.assertRaises(KeyError):
1034 self._fc['no way']
1035
1036 def test_contains(self):
1037 self.assertFalse('a' in self._fc)
1038 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
1039 self.assertTrue('a' in self._fc)
1040
1041 def test_iter(self):
1042 a_fc = self._tc.create_signed_integer_field_class(32)
1043 b_fc = self._tc.create_string_field_class()
fe4df857 1044 c_fc = self._tc.create_single_precision_real_field_class()
45c51519
PP
1045 opts = (
1046 ('a', a_fc, self._ranges1),
1047 ('b', b_fc, self._ranges2),
1048 ('c', c_fc, self._ranges3),
1049 )
1050
1051 for opt in opts:
1052 self._fc.append_option(*opt)
b4f45851 1053
45c51519
PP
1054 for (name, opt), test_opt in zip(self._fc.items(), opts):
1055 self.assertEqual(opt.name, test_opt[0])
1056 self.assertEqual(name, opt.name)
1057 self.assertEqual(opt.field_class.addr, test_opt[1].addr)
1058 self.assertEqual(opt.ranges.addr, test_opt[2].addr)
1059
1060 def test_at_index(self):
1061 a_fc = self._tc.create_signed_integer_field_class(32)
1062 b_fc = self._tc.create_string_field_class()
fe4df857 1063 c_fc = self._tc.create_single_precision_real_field_class()
45c51519
PP
1064 self._fc.append_option('c', c_fc, self._ranges1)
1065 self._fc.append_option('a', a_fc, self._ranges2)
1066 self._fc.append_option('b', b_fc, self._ranges3)
1067 self.assertEqual(self._fc.option_at_index(1).field_class.addr, a_fc.addr)
1068 self.assertEqual(self._fc.option_at_index(1).name, 'a')
1069 self.assertEqual(self._fc.option_at_index(1).ranges.addr, self._ranges2.addr)
1070
1071 def test_at_index_invalid(self):
cfbd7cf3
FD
1072 self._fc.append_option(
1073 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1074 )
45c51519
PP
1075
1076 with self.assertRaises(TypeError):
1077 self._fc.option_at_index('yes')
1078
1079 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
1080 self._fc.append_option(
1081 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1082 )
45c51519
PP
1083
1084 with self.assertRaises(IndexError):
1085 self._fc.option_at_index(len(self._fc))
1086
1087 def _fill_default_fc_for_field_path_test(self):
d47b87ac
SM
1088 # Create something equivalent to:
1089 #
1090 # struct outer_struct_fc {
1091 # real foo;
1092 # struct inner_struct_fc {
45c51519 1093 # [u]int64_t selector;
d47b87ac
SM
1094 # string bar;
1095 # string baz;
45c51519
PP
1096 # variant <selector> {
1097 # real a; // selected with self._ranges1
1098 # int21_t b; // selected with self._ranges2
1099 # uint34_t c; // selected with self._ranges3
d47b87ac
SM
1100 # } variant;
1101 # } inner_struct[2];
1102 # };
fe4df857
FD
1103 self._fc.append_option(
1104 'a', self._tc.create_single_precision_real_field_class(), self._ranges1
1105 )
cfbd7cf3
FD
1106 self._fc.append_option(
1107 'b', self._tc.create_signed_integer_field_class(21), self._ranges2
1108 )
1109 self._fc.append_option(
1110 'c', self._tc.create_unsigned_integer_field_class(34), self._ranges3
1111 )
b4f45851 1112
fe4df857 1113 foo_fc = self._tc.create_single_precision_real_field_class()
d47b87ac
SM
1114 bar_fc = self._tc.create_string_field_class()
1115 baz_fc = self._tc.create_string_field_class()
b4f45851 1116
d47b87ac 1117 inner_struct_fc = self._tc.create_structure_field_class()
45c51519 1118 inner_struct_fc.append_member('selector', self._selector_fc)
d47b87ac
SM
1119 inner_struct_fc.append_member('bar', bar_fc)
1120 inner_struct_fc.append_member('baz', baz_fc)
45c51519 1121 inner_struct_fc.append_member('variant', self._fc)
b4f45851 1122
cfbd7cf3
FD
1123 inner_struct_array_fc = self._tc.create_static_array_field_class(
1124 inner_struct_fc, 2
1125 )
b4f45851 1126
d47b87ac
SM
1127 outer_struct_fc = self._tc.create_structure_field_class()
1128 outer_struct_fc.append_member('foo', foo_fc)
1129 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
b4f45851 1130
d47b87ac
SM
1131 # The path to the selector field is resolved when the sequence is
1132 # actually used, for example in a packet context.
cfbd7cf3
FD
1133 self._tc.create_stream_class(
1134 supports_packets=True, packet_context_field_class=outer_struct_fc
1135 )
b4f45851 1136
d47b87ac 1137 def test_selector_field_path_length(self):
45c51519
PP
1138 self._fill_default_fc_for_field_path_test()
1139 self.assertEqual(len(self._fc.selector_field_path), 3)
b4f45851 1140
d47b87ac 1141 def test_selector_field_path_iter(self):
45c51519
PP
1142 self._fill_default_fc_for_field_path_test()
1143 path_items = list(self._fc.selector_field_path)
b4f45851 1144
d47b87ac 1145 self.assertEqual(len(path_items), 3)
b4f45851 1146
3fb99a22 1147 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac 1148 self.assertEqual(path_items[0].index, 1)
b4f45851 1149
3fb99a22 1150 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
b4f45851 1151
3fb99a22 1152 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac 1153 self.assertEqual(path_items[2].index, 0)
b4f45851 1154
d47b87ac 1155 def test_selector_field_path_root_scope(self):
45c51519 1156 self._fill_default_fc_for_field_path_test()
cfbd7cf3 1157 self.assertEqual(
e7ceb9df 1158 self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
cfbd7cf3 1159 )
45c51519
PP
1160
1161
cfbd7cf3
FD
1162class VariantFieldClassWithUnsignedSelectorTestCase(
1163 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1164):
45c51519
PP
1165 def _spec_set_up(self):
1166 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
1167 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
1168 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1169 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, 16), (48, 99)])
1170 self._selector_fc = self._tc.create_unsigned_integer_field_class()
1171
1172
cfbd7cf3
FD
1173class VariantFieldClassWithSignedSelectorTestCase(
1174 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1175):
45c51519
PP
1176 def _spec_set_up(self):
1177 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
1178 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
1179 self._ranges3 = bt2.SignedIntegerRangeSet([(8, 16), (48, 99)])
1180 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1181 self._selector_fc = self._tc.create_signed_integer_field_class()
b4f45851 1182
d47b87ac 1183
f0a42b33
FD
1184class _ArrayFieldClassTestCase:
1185 def test_attr_element_field_class(self):
1186 fc = self._create_array()
1187 self.assertIs(
1188 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClass
1189 )
1190
1191 def test_const_attr_element_field_class(self):
1192 fc = self._create_const_array()
1193 self.assertIs(
1194 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClassConst
1195 )
1196
1197
1198class StaticArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1199 @staticmethod
1200 def _const_value_setter(field):
d47b6b4e 1201 field.value = [9] * 45
f0a42b33
FD
1202
1203 def _create_array(self):
1204 return self._tc.create_static_array_field_class(self._elem_fc, 45)
1205
1206 def _create_const_array(self):
1207 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1208 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1209
d47b87ac
SM
1210 def setUp(self):
1211 self._tc = get_default_trace_class()
1212 self._elem_fc = self._tc.create_signed_integer_field_class(23)
b4f45851
SM
1213
1214 def test_create_default(self):
d47b87ac
SM
1215 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1216 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1217 self.assertEqual(fc.length, 45)
5783664e 1218 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1219
d47b87ac 1220 def test_create_invalid_elem_field_class(self):
b4f45851 1221 with self.assertRaises(TypeError):
d47b87ac 1222 self._tc.create_static_array_field_class(object(), 45)
b4f45851
SM
1223
1224 def test_create_invalid_length(self):
1225 with self.assertRaises(ValueError):
cfbd7cf3
FD
1226 self._tc.create_static_array_field_class(
1227 self._tc.create_string_field_class(), -17
1228 )
b4f45851
SM
1229
1230 def test_create_invalid_length_type(self):
1231 with self.assertRaises(TypeError):
cfbd7cf3
FD
1232 self._tc.create_static_array_field_class(
1233 self._tc.create_string_field_class(), 'the length'
1234 )
d47b87ac
SM
1235
1236
f0a42b33
FD
1237class DynamicArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1238 @staticmethod
1239 def _const_value_setter(field):
d47b6b4e 1240 field.value = []
f0a42b33
FD
1241
1242 def _create_array(self):
1243 return self._tc.create_dynamic_array_field_class(self._elem_fc)
1244
1245 def _create_const_array(self):
1246 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1247 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1248
d47b87ac
SM
1249 def setUp(self):
1250 self._tc = get_default_trace_class()
1251 self._elem_fc = self._tc.create_signed_integer_field_class(23)
1252 self._len_fc = self._tc.create_unsigned_integer_field_class(12)
b4f45851 1253
d47b87ac
SM
1254 def test_create_default(self):
1255 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1256 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1257 self.assertIsNone(fc.length_field_path, None)
5783664e 1258 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1259
d47b87ac
SM
1260 def _create_field_class_for_field_path_test(self):
1261 # Create something a field class that is equivalent to:
1262 #
1263 # struct outer_struct_fc {
1264 # real foo;
1265 # struct inner_struct_fc {
1266 # string bar;
1267 # string baz;
1268 # uint12_t len;
1269 # uint23_t dyn_array[len];
1270 # } inner_struct[2];
1271 # };
b4f45851 1272
d47b87ac 1273 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
b4f45851 1274
fe4df857 1275 foo_fc = self._tc.create_single_precision_real_field_class()
d47b87ac
SM
1276 bar_fc = self._tc.create_string_field_class()
1277 baz_fc = self._tc.create_string_field_class()
b4f45851 1278
d47b87ac
SM
1279 inner_struct_fc = self._tc.create_structure_field_class()
1280 inner_struct_fc.append_member('bar', bar_fc)
1281 inner_struct_fc.append_member('baz', baz_fc)
1282 inner_struct_fc.append_member('len', self._len_fc)
1283 inner_struct_fc.append_member('dyn_array', fc)
b4f45851 1284
cfbd7cf3
FD
1285 inner_struct_array_fc = self._tc.create_static_array_field_class(
1286 inner_struct_fc, 2
1287 )
d47b87ac
SM
1288
1289 outer_struct_fc = self._tc.create_structure_field_class()
1290 outer_struct_fc.append_member('foo', foo_fc)
1291 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
1292
1293 # The path to the length field is resolved when the sequence is
1294 # actually used, for example in a packet context.
cfbd7cf3
FD
1295 self._tc.create_stream_class(
1296 packet_context_field_class=outer_struct_fc, supports_packets=True
1297 )
d47b87ac
SM
1298
1299 return fc
1300
1301 def test_field_path_len(self):
1302 fc = self._create_field_class_for_field_path_test()
1303 self.assertEqual(len(fc.length_field_path), 3)
1304
1305 def test_field_path_iter(self):
1306 fc = self._create_field_class_for_field_path_test()
1307 path_items = list(fc.length_field_path)
1308
1309 self.assertEqual(len(path_items), 3)
1310
3fb99a22 1311 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac
SM
1312 self.assertEqual(path_items[0].index, 1)
1313
3fb99a22 1314 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
d47b87ac 1315
3fb99a22 1316 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac
SM
1317 self.assertEqual(path_items[2].index, 2)
1318
1319 def test_field_path_root_scope(self):
1320 fc = self._create_field_class_for_field_path_test()
e7ceb9df
PP
1321 self.assertEqual(
1322 fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
1323 )
b4f45851
SM
1324
1325 def test_create_invalid_field_class(self):
1326 with self.assertRaises(TypeError):
d47b87ac 1327 self._tc.create_dynamic_array_field_class(object())
b4f45851
SM
1328
1329 def test_create_invalid_length_type(self):
1330 with self.assertRaises(TypeError):
cfbd7cf3
FD
1331 self._tc.create_dynamic_array_field_class(
1332 self._tc.create_string_field_class(), 17
1333 )
b4f45851 1334
b4f45851 1335
d47b87ac
SM
1336if __name__ == "__main__":
1337 unittest.main()
This page took 0.096396 seconds and 4 git commands to generate.