Fix: cli: don't log error when using help command with a plugin name
[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
PP
247
248class RealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
f0a42b33
FD
249 @staticmethod
250 def _const_value_setter(field):
d47b6b4e 251 field.value = -18
f0a42b33 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):
d47b6b4e 402 field.value = 0
f0a42b33 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):
d47b6b4e 428 field.value = 0
f0a42b33 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):
d47b6b4e 445 field.value = 'chaine'
f0a42b33 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()
fd4e6235 874 str_field_class = self._tc.create_string_field_class()
f0a42b33
FD
875 with self.assertRaises(AttributeError):
876 fc_const.append_option('str', str_field_class, self._ranges1)
877
45c51519
PP
878 def test_append_element_kwargs(self):
879 int_field_class = self._tc.create_signed_integer_field_class(32)
cfbd7cf3
FD
880 self._fc.append_option(
881 name='int32', field_class=int_field_class, ranges=self._ranges1
882 )
45c51519
PP
883 opt = self._fc['int32']
884 self.assertEqual(opt.field_class.addr, int_field_class.addr)
885 self.assertEqual(opt.name, 'int32')
886 self.assertEqual(opt.ranges.addr, self._ranges1.addr)
d47b87ac 887
45c51519
PP
888 def test_append_element_invalid_name(self):
889 sub_fc = self._tc.create_string_field_class()
b4f45851 890
45c51519
PP
891 with self.assertRaises(TypeError):
892 self._fc.append_option(self._fc, 23, sub_fc)
b4f45851 893
45c51519
PP
894 def test_append_element_invalid_field_class(self):
895 with self.assertRaises(TypeError):
896 self._fc.append_option(self._fc, 'yes', object())
897
898 def test_append_element_invalid_ranges(self):
899 sub_fc = self._tc.create_string_field_class()
900
901 with self.assertRaises(TypeError):
902 self._fc.append_option(self._fc, sub_fc, 'lel')
903
904 def test_append_element_dup_name(self):
905 sub_fc1 = self._tc.create_string_field_class()
906 sub_fc2 = self._tc.create_string_field_class()
907
ce4923b0 908 with self.assertRaises(ValueError):
45c51519
PP
909 self._fc.append_option('yes', sub_fc1, self._ranges1)
910 self._fc.append_option('yes', sub_fc2, self._ranges2)
911
912 def test_append_element_invalid_ranges_signedness(self):
913 sub_fc = self._tc.create_string_field_class()
914
915 with self.assertRaises(TypeError):
916 self._fc.append_option(self._fc, sub_fc, self._inval_ranges)
917
5783664e
PP
918 def test_user_attributes(self):
919 self._fc.append_option(
920 'c',
921 self._tc.create_string_field_class(),
922 self._ranges1,
923 user_attributes={'salut': 23},
924 )
925 self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
f0a42b33
FD
926 self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
927
928 def test_const_user_attributes(self):
929 fc_const = self._create_default_const_field_class()
930 self.assertIs(type(fc_const.user_attributes), bt2_value._MapValueConst)
5783664e
PP
931
932 def test_invalid_user_attributes(self):
933 with self.assertRaises(TypeError):
934 self._fc.append_option(
935 'c',
936 self._tc.create_string_field_class(),
937 self._ranges1,
938 user_attributes=object(),
939 )
940
941 def test_invalid_user_attributes_value_type(self):
942 with self.assertRaises(TypeError):
943 self._fc.append_option(
944 'c',
945 self._tc.create_string_field_class(),
946 self._ranges1,
947 user_attributes=23,
948 )
949
45c51519 950 def test_iadd(self):
45c51519
PP
951 a_field_class = self._tc.create_real_field_class()
952 self._fc.append_option('a_float', a_field_class, self._ranges1)
953 c_field_class = self._tc.create_string_field_class()
cfbd7cf3
FD
954 d_field_class = self._tc.create_signed_enumeration_field_class(
955 field_value_range=32
956 )
45c51519
PP
957 self._fc += [
958 ('c_string', c_field_class, self._ranges2),
959 ('d_enum', d_field_class, self._ranges3),
960 ]
961 self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr)
962 self.assertEqual(self._fc['a_float'].name, 'a_float')
963 self.assertEqual(self._fc['a_float'].ranges, self._ranges1)
964 self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr)
965 self.assertEqual(self._fc['c_string'].name, 'c_string')
966 self.assertEqual(self._fc['c_string'].ranges, self._ranges2)
967 self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr)
968 self.assertEqual(self._fc['d_enum'].name, 'd_enum')
969 self.assertEqual(self._fc['d_enum'].ranges, self._ranges3)
970
f0a42b33
FD
971 def test_const_iadd(self):
972 fc_const = self._create_default_const_field_class()
973 a_field_class = self._tc.create_real_field_class()
974 with self.assertRaises(TypeError):
975 fc_const += [('a_float', a_field_class, self._ranges1)]
976
45c51519
PP
977 def test_bool_op(self):
978 self.assertFalse(self._fc)
979 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
980 self.assertTrue(self._fc)
981
982 def test_len(self):
983 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
984 self._fc.append_option('b', self._tc.create_string_field_class(), self._ranges2)
985 self._fc.append_option('c', self._tc.create_string_field_class(), self._ranges3)
986 self.assertEqual(len(self._fc), 3)
987
988 def test_getitem(self):
989 a_fc = self._tc.create_signed_integer_field_class(32)
990 b_fc = self._tc.create_string_field_class()
991 c_fc = self._tc.create_real_field_class()
992 self._fc.append_option('a', a_fc, self._ranges1)
993 self._fc.append_option('b', b_fc, self._ranges2)
994 self._fc.append_option('c', c_fc, self._ranges3)
995 self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr)
996 self.assertEqual(self._fc['b'].name, 'b')
997 self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr)
998
f0a42b33
FD
999 def test_option_field_class(self):
1000 a_fc = self._tc.create_signed_integer_field_class(32)
1001 self._fc.append_option('a', a_fc, self._ranges1)
1002 self.assertIs(
1003 type(self._fc['a'].field_class), bt2_field_class._SignedIntegerFieldClass
1004 )
1005
1006 def test_const_option_field_class(self):
1007 fc_const = self._create_default_const_field_class()
1008 self.assertIs(
1009 type(fc_const['a'].field_class),
1010 bt2_field_class._SignedIntegerFieldClassConst,
1011 )
1012
45c51519
PP
1013 def test_getitem_invalid_key_type(self):
1014 with self.assertRaises(TypeError):
1015 self._fc[0]
1016
1017 def test_getitem_invalid_key(self):
1018 with self.assertRaises(KeyError):
1019 self._fc['no way']
1020
1021 def test_contains(self):
1022 self.assertFalse('a' in self._fc)
1023 self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
1024 self.assertTrue('a' in self._fc)
1025
1026 def test_iter(self):
1027 a_fc = self._tc.create_signed_integer_field_class(32)
1028 b_fc = self._tc.create_string_field_class()
1029 c_fc = self._tc.create_real_field_class()
1030 opts = (
1031 ('a', a_fc, self._ranges1),
1032 ('b', b_fc, self._ranges2),
1033 ('c', c_fc, self._ranges3),
1034 )
1035
1036 for opt in opts:
1037 self._fc.append_option(*opt)
b4f45851 1038
45c51519
PP
1039 for (name, opt), test_opt in zip(self._fc.items(), opts):
1040 self.assertEqual(opt.name, test_opt[0])
1041 self.assertEqual(name, opt.name)
1042 self.assertEqual(opt.field_class.addr, test_opt[1].addr)
1043 self.assertEqual(opt.ranges.addr, test_opt[2].addr)
1044
1045 def test_at_index(self):
1046 a_fc = self._tc.create_signed_integer_field_class(32)
1047 b_fc = self._tc.create_string_field_class()
1048 c_fc = self._tc.create_real_field_class()
1049 self._fc.append_option('c', c_fc, self._ranges1)
1050 self._fc.append_option('a', a_fc, self._ranges2)
1051 self._fc.append_option('b', b_fc, self._ranges3)
1052 self.assertEqual(self._fc.option_at_index(1).field_class.addr, a_fc.addr)
1053 self.assertEqual(self._fc.option_at_index(1).name, 'a')
1054 self.assertEqual(self._fc.option_at_index(1).ranges.addr, self._ranges2.addr)
1055
1056 def test_at_index_invalid(self):
cfbd7cf3
FD
1057 self._fc.append_option(
1058 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1059 )
45c51519
PP
1060
1061 with self.assertRaises(TypeError):
1062 self._fc.option_at_index('yes')
1063
1064 def test_at_index_out_of_bounds_after(self):
cfbd7cf3
FD
1065 self._fc.append_option(
1066 'c', self._tc.create_signed_integer_field_class(32), self._ranges3
1067 )
45c51519
PP
1068
1069 with self.assertRaises(IndexError):
1070 self._fc.option_at_index(len(self._fc))
1071
1072 def _fill_default_fc_for_field_path_test(self):
d47b87ac
SM
1073 # Create something equivalent to:
1074 #
1075 # struct outer_struct_fc {
1076 # real foo;
1077 # struct inner_struct_fc {
45c51519 1078 # [u]int64_t selector;
d47b87ac
SM
1079 # string bar;
1080 # string baz;
45c51519
PP
1081 # variant <selector> {
1082 # real a; // selected with self._ranges1
1083 # int21_t b; // selected with self._ranges2
1084 # uint34_t c; // selected with self._ranges3
d47b87ac
SM
1085 # } variant;
1086 # } inner_struct[2];
1087 # };
45c51519 1088 self._fc.append_option('a', self._tc.create_real_field_class(), self._ranges1)
cfbd7cf3
FD
1089 self._fc.append_option(
1090 'b', self._tc.create_signed_integer_field_class(21), self._ranges2
1091 )
1092 self._fc.append_option(
1093 'c', self._tc.create_unsigned_integer_field_class(34), self._ranges3
1094 )
b4f45851 1095
d47b87ac
SM
1096 foo_fc = self._tc.create_real_field_class()
1097 bar_fc = self._tc.create_string_field_class()
1098 baz_fc = self._tc.create_string_field_class()
b4f45851 1099
d47b87ac 1100 inner_struct_fc = self._tc.create_structure_field_class()
45c51519 1101 inner_struct_fc.append_member('selector', self._selector_fc)
d47b87ac
SM
1102 inner_struct_fc.append_member('bar', bar_fc)
1103 inner_struct_fc.append_member('baz', baz_fc)
45c51519 1104 inner_struct_fc.append_member('variant', self._fc)
b4f45851 1105
cfbd7cf3
FD
1106 inner_struct_array_fc = self._tc.create_static_array_field_class(
1107 inner_struct_fc, 2
1108 )
b4f45851 1109
d47b87ac
SM
1110 outer_struct_fc = self._tc.create_structure_field_class()
1111 outer_struct_fc.append_member('foo', foo_fc)
1112 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
b4f45851 1113
d47b87ac
SM
1114 # The path to the selector field is resolved when the sequence is
1115 # actually used, for example in a packet context.
cfbd7cf3
FD
1116 self._tc.create_stream_class(
1117 supports_packets=True, packet_context_field_class=outer_struct_fc
1118 )
b4f45851 1119
d47b87ac 1120 def test_selector_field_path_length(self):
45c51519
PP
1121 self._fill_default_fc_for_field_path_test()
1122 self.assertEqual(len(self._fc.selector_field_path), 3)
b4f45851 1123
d47b87ac 1124 def test_selector_field_path_iter(self):
45c51519
PP
1125 self._fill_default_fc_for_field_path_test()
1126 path_items = list(self._fc.selector_field_path)
b4f45851 1127
d47b87ac 1128 self.assertEqual(len(path_items), 3)
b4f45851 1129
3fb99a22 1130 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac 1131 self.assertEqual(path_items[0].index, 1)
b4f45851 1132
3fb99a22 1133 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
b4f45851 1134
3fb99a22 1135 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac 1136 self.assertEqual(path_items[2].index, 0)
b4f45851 1137
d47b87ac 1138 def test_selector_field_path_root_scope(self):
45c51519 1139 self._fill_default_fc_for_field_path_test()
cfbd7cf3 1140 self.assertEqual(
e7ceb9df 1141 self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
cfbd7cf3 1142 )
45c51519
PP
1143
1144
cfbd7cf3
FD
1145class VariantFieldClassWithUnsignedSelectorTestCase(
1146 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1147):
45c51519
PP
1148 def _spec_set_up(self):
1149 self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)])
1150 self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)])
1151 self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1152 self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, 16), (48, 99)])
1153 self._selector_fc = self._tc.create_unsigned_integer_field_class()
1154
1155
cfbd7cf3
FD
1156class VariantFieldClassWithSignedSelectorTestCase(
1157 _VariantFieldClassWithSelectorTestCase, unittest.TestCase
1158):
45c51519
PP
1159 def _spec_set_up(self):
1160 self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)])
1161 self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)])
1162 self._ranges3 = bt2.SignedIntegerRangeSet([(8, 16), (48, 99)])
1163 self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
1164 self._selector_fc = self._tc.create_signed_integer_field_class()
b4f45851 1165
d47b87ac 1166
f0a42b33
FD
1167class _ArrayFieldClassTestCase:
1168 def test_attr_element_field_class(self):
1169 fc = self._create_array()
1170 self.assertIs(
1171 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClass
1172 )
1173
1174 def test_const_attr_element_field_class(self):
1175 fc = self._create_const_array()
1176 self.assertIs(
1177 type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClassConst
1178 )
1179
1180
1181class StaticArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1182 @staticmethod
1183 def _const_value_setter(field):
d47b6b4e 1184 field.value = [9] * 45
f0a42b33
FD
1185
1186 def _create_array(self):
1187 return self._tc.create_static_array_field_class(self._elem_fc, 45)
1188
1189 def _create_const_array(self):
1190 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1191 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1192
d47b87ac
SM
1193 def setUp(self):
1194 self._tc = get_default_trace_class()
1195 self._elem_fc = self._tc.create_signed_integer_field_class(23)
b4f45851
SM
1196
1197 def test_create_default(self):
d47b87ac
SM
1198 fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
1199 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1200 self.assertEqual(fc.length, 45)
5783664e 1201 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1202
d47b87ac 1203 def test_create_invalid_elem_field_class(self):
b4f45851 1204 with self.assertRaises(TypeError):
d47b87ac 1205 self._tc.create_static_array_field_class(object(), 45)
b4f45851
SM
1206
1207 def test_create_invalid_length(self):
1208 with self.assertRaises(ValueError):
cfbd7cf3
FD
1209 self._tc.create_static_array_field_class(
1210 self._tc.create_string_field_class(), -17
1211 )
b4f45851
SM
1212
1213 def test_create_invalid_length_type(self):
1214 with self.assertRaises(TypeError):
cfbd7cf3
FD
1215 self._tc.create_static_array_field_class(
1216 self._tc.create_string_field_class(), 'the length'
1217 )
d47b87ac
SM
1218
1219
f0a42b33
FD
1220class DynamicArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
1221 @staticmethod
1222 def _const_value_setter(field):
d47b6b4e 1223 field.value = []
f0a42b33
FD
1224
1225 def _create_array(self):
1226 return self._tc.create_dynamic_array_field_class(self._elem_fc)
1227
1228 def _create_const_array(self):
1229 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1230 return _create_const_field_class(self._tc, fc, self._const_value_setter)
1231
d47b87ac
SM
1232 def setUp(self):
1233 self._tc = get_default_trace_class()
1234 self._elem_fc = self._tc.create_signed_integer_field_class(23)
1235 self._len_fc = self._tc.create_unsigned_integer_field_class(12)
b4f45851 1236
d47b87ac
SM
1237 def test_create_default(self):
1238 fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
1239 self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr)
1240 self.assertIsNone(fc.length_field_path, None)
5783664e 1241 self.assertEqual(len(fc.user_attributes), 0)
b4f45851 1242
d47b87ac
SM
1243 def _create_field_class_for_field_path_test(self):
1244 # Create something a field class that is equivalent to:
1245 #
1246 # struct outer_struct_fc {
1247 # real foo;
1248 # struct inner_struct_fc {
1249 # string bar;
1250 # string baz;
1251 # uint12_t len;
1252 # uint23_t dyn_array[len];
1253 # } inner_struct[2];
1254 # };
b4f45851 1255
d47b87ac 1256 fc = self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc)
b4f45851 1257
d47b87ac
SM
1258 foo_fc = self._tc.create_real_field_class()
1259 bar_fc = self._tc.create_string_field_class()
1260 baz_fc = self._tc.create_string_field_class()
b4f45851 1261
d47b87ac
SM
1262 inner_struct_fc = self._tc.create_structure_field_class()
1263 inner_struct_fc.append_member('bar', bar_fc)
1264 inner_struct_fc.append_member('baz', baz_fc)
1265 inner_struct_fc.append_member('len', self._len_fc)
1266 inner_struct_fc.append_member('dyn_array', fc)
b4f45851 1267
cfbd7cf3
FD
1268 inner_struct_array_fc = self._tc.create_static_array_field_class(
1269 inner_struct_fc, 2
1270 )
d47b87ac
SM
1271
1272 outer_struct_fc = self._tc.create_structure_field_class()
1273 outer_struct_fc.append_member('foo', foo_fc)
1274 outer_struct_fc.append_member('inner_struct', inner_struct_array_fc)
1275
1276 # The path to the length field is resolved when the sequence is
1277 # actually used, for example in a packet context.
cfbd7cf3
FD
1278 self._tc.create_stream_class(
1279 packet_context_field_class=outer_struct_fc, supports_packets=True
1280 )
d47b87ac
SM
1281
1282 return fc
1283
1284 def test_field_path_len(self):
1285 fc = self._create_field_class_for_field_path_test()
1286 self.assertEqual(len(fc.length_field_path), 3)
1287
1288 def test_field_path_iter(self):
1289 fc = self._create_field_class_for_field_path_test()
1290 path_items = list(fc.length_field_path)
1291
1292 self.assertEqual(len(path_items), 3)
1293
3fb99a22 1294 self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
d47b87ac
SM
1295 self.assertEqual(path_items[0].index, 1)
1296
3fb99a22 1297 self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem)
d47b87ac 1298
3fb99a22 1299 self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
d47b87ac
SM
1300 self.assertEqual(path_items[2].index, 2)
1301
1302 def test_field_path_root_scope(self):
1303 fc = self._create_field_class_for_field_path_test()
e7ceb9df
PP
1304 self.assertEqual(
1305 fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
1306 )
b4f45851
SM
1307
1308 def test_create_invalid_field_class(self):
1309 with self.assertRaises(TypeError):
d47b87ac 1310 self._tc.create_dynamic_array_field_class(object())
b4f45851
SM
1311
1312 def test_create_invalid_length_type(self):
1313 with self.assertRaises(TypeError):
cfbd7cf3
FD
1314 self._tc.create_dynamic_array_field_class(
1315 self._tc.create_string_field_class(), 17
1316 )
b4f45851 1317
b4f45851 1318
d47b87ac
SM
1319if __name__ == "__main__":
1320 unittest.main()
This page took 0.139359 seconds and 4 git commands to generate.