Commit | Line | Data |
---|---|---|
0235b0db | 1 | # SPDX-License-Identifier: GPL-2.0-only |
d2d857a8 MJ |
2 | # |
3 | # Copyright (C) 2019 EfficiOS Inc. | |
4 | # | |
d2d857a8 | 5 | |
b4f45851 | 6 | import unittest |
b4f45851 | 7 | import bt2 |
f0a42b33 FD |
8 | from utils import get_default_trace_class, TestOutputPortMessageIterator |
9 | from bt2 import value as bt2_value | |
10 | from bt2 import field_class as bt2_field_class | |
11 | ||
12 | ||
13 | def _create_stream(tc, ctx_field_classes): | |
14 | packet_context_fc = tc.create_structure_field_class() | |
15 | for name, fc in ctx_field_classes: | |
16 | packet_context_fc.append_member(name, fc) | |
17 | ||
18 | trace = tc() | |
19 | stream_class = tc.create_stream_class( | |
20 | packet_context_field_class=packet_context_fc, supports_packets=True | |
21 | ) | |
22 | ||
23 | stream = trace.create_stream(stream_class) | |
24 | return stream | |
25 | ||
26 | ||
27 | def _create_const_field_class(tc, field_class, value_setter_fn): | |
28 | field_name = 'const field' | |
29 | ||
30 | class MyIter(bt2._UserMessageIterator): | |
8d8b141d | 31 | def __init__(self, config, self_port_output): |
f0a42b33 FD |
32 | nonlocal field_class |
33 | nonlocal value_setter_fn | |
34 | stream = _create_stream(tc, [(field_name, field_class)]) | |
35 | packet = stream.create_packet() | |
36 | ||
37 | value_setter_fn(packet.context_field[field_name]) | |
38 | ||
39 | self._msgs = [ | |
40 | self._create_stream_beginning_message(stream), | |
41 | self._create_packet_beginning_message(packet), | |
42 | ] | |
43 | ||
44 | def __next__(self): | |
45 | if len(self._msgs) == 0: | |
46 | raise StopIteration | |
47 | ||
48 | return self._msgs.pop(0) | |
49 | ||
50 | class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter): | |
59225a3e | 51 | def __init__(self, config, params, obj): |
f0a42b33 FD |
52 | self._add_output_port('out', params) |
53 | ||
54 | graph = bt2.Graph() | |
55 | src_comp = graph.add_component(MySrc, 'my_source', None) | |
56 | msg_iter = TestOutputPortMessageIterator(graph, src_comp.output_ports['out']) | |
57 | ||
58 | # Ignore first message, stream beginning | |
59 | _ = next(msg_iter) | |
60 | packet_beg_msg = next(msg_iter) | |
61 | ||
62 | return packet_beg_msg.packet.context_field[field_name].cls | |
b4f45851 SM |
63 | |
64 | ||
5783664e PP |
65 | class _TestFieldClass: |
66 | def test_create_user_attributes(self): | |
67 | fc = self._create_default_field_class(user_attributes={'salut': 23}) | |
68 | self.assertEqual(fc.user_attributes, {'salut': 23}) | |
f0a42b33 FD |
69 | self.assertIs(type(fc.user_attributes), bt2_value.MapValue) |
70 | ||
71 | def test_const_create_user_attributes(self): | |
72 | fc = self._create_default_const_field_class(user_attributes={'salut': 23}) | |
73 | self.assertEqual(fc.user_attributes, {'salut': 23}) | |
74 | self.assertIs(type(fc.user_attributes), bt2_value._MapValueConst) | |
5783664e PP |
75 | |
76 | def test_create_invalid_user_attributes(self): | |
77 | with self.assertRaises(TypeError): | |
78 | self._create_default_field_class(user_attributes=object()) | |
79 | ||
80 | def test_create_invalid_user_attributes_value_type(self): | |
81 | with self.assertRaises(TypeError): | |
82 | self._create_default_field_class(user_attributes=23) | |
83 | ||
84 | ||
85 | class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase): | |
f0a42b33 FD |
86 | @staticmethod |
87 | def _const_value_setter(field): | |
d47b6b4e | 88 | field.value = False |
f0a42b33 | 89 | |
5783664e | 90 | def _create_default_field_class(self, **kwargs): |
aae30e61 | 91 | tc = get_default_trace_class() |
5783664e PP |
92 | return tc.create_bool_field_class(**kwargs) |
93 | ||
f0a42b33 FD |
94 | def _create_default_const_field_class(self, *args, **kwargs): |
95 | tc = get_default_trace_class() | |
96 | fc = tc.create_bool_field_class(*args, **kwargs) | |
97 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
98 | ||
5783664e PP |
99 | def setUp(self): |
100 | self._fc = self._create_default_field_class() | |
f0a42b33 | 101 | self._fc_const = self._create_default_const_field_class() |
aae30e61 PP |
102 | |
103 | def test_create_default(self): | |
104 | self.assertIsNotNone(self._fc) | |
5783664e | 105 | self.assertEqual(len(self._fc.user_attributes), 0) |
aae30e61 PP |
106 | |
107 | ||
5783664e | 108 | class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase): |
f0a42b33 FD |
109 | @staticmethod |
110 | def _const_value_setter(field): | |
d47b6b4e | 111 | field.value = [] |
f0a42b33 | 112 | |
5783664e PP |
113 | def _create_field_class(self, *args, **kwargs): |
114 | tc = get_default_trace_class() | |
115 | return tc.create_bit_array_field_class(*args, **kwargs) | |
116 | ||
117 | def _create_default_field_class(self, **kwargs): | |
118 | return self._create_field_class(17, **kwargs) | |
119 | ||
f0a42b33 FD |
120 | def _create_default_const_field_class(self, *args, **kwargs): |
121 | tc = get_default_trace_class() | |
122 | fc = tc.create_bit_array_field_class(17, **kwargs) | |
123 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
124 | ||
ead8c3d4 | 125 | def setUp(self): |
5783664e | 126 | self._fc = self._create_default_field_class() |
ead8c3d4 PP |
127 | |
128 | def test_create_default(self): | |
129 | self.assertIsNotNone(self._fc) | |
5783664e | 130 | self.assertEqual(len(self._fc.user_attributes), 0) |
ead8c3d4 PP |
131 | |
132 | def test_create_length_out_of_range(self): | |
133 | with self.assertRaises(ValueError): | |
5783664e | 134 | self._create_field_class(65) |
ead8c3d4 PP |
135 | |
136 | def test_create_length_zero(self): | |
137 | with self.assertRaises(ValueError): | |
5783664e | 138 | self._create_field_class(0) |
ead8c3d4 PP |
139 | |
140 | def test_create_length_invalid_type(self): | |
141 | with self.assertRaises(TypeError): | |
5783664e | 142 | self._create_field_class('lel') |
ead8c3d4 PP |
143 | |
144 | def test_length_prop(self): | |
145 | self.assertEqual(self._fc.length, 17) | |
146 | ||
147 | ||
d47b87ac SM |
148 | class _TestIntegerFieldClassProps: |
149 | def test_create_default(self): | |
5783664e | 150 | fc = self._create_default_field_class() |
d47b87ac SM |
151 | self.assertEqual(fc.field_value_range, 64) |
152 | self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.DECIMAL) | |
5783664e | 153 | self.assertEqual(len(fc.user_attributes), 0) |
b4f45851 | 154 | |
d47b87ac | 155 | def test_create_range(self): |
5783664e | 156 | fc = self._create_field_class(field_value_range=35) |
d47b87ac | 157 | self.assertEqual(fc.field_value_range, 35) |
b4f45851 | 158 | |
5783664e | 159 | fc = self._create_field_class(36) |
d47b87ac | 160 | self.assertEqual(fc.field_value_range, 36) |
b4f45851 | 161 | |
d47b87ac SM |
162 | def test_create_invalid_range(self): |
163 | with self.assertRaises(TypeError): | |
5783664e | 164 | self._create_field_class('yes') |
b4f45851 | 165 | |
d47b87ac | 166 | with self.assertRaises(TypeError): |
5783664e | 167 | self._create_field_class(field_value_range='yes') |
b4f45851 | 168 | |
b4f45851 | 169 | with self.assertRaises(ValueError): |
5783664e | 170 | self._create_field_class(field_value_range=-2) |
b4f45851 | 171 | |
d47b87ac | 172 | with self.assertRaises(ValueError): |
5783664e | 173 | self._create_field_class(field_value_range=0) |
b4f45851 | 174 | |
d47b87ac | 175 | def test_create_base(self): |
5783664e | 176 | fc = self._create_field_class( |
cfbd7cf3 FD |
177 | preferred_display_base=bt2.IntegerDisplayBase.HEXADECIMAL |
178 | ) | |
d47b87ac | 179 | self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.HEXADECIMAL) |
b4f45851 | 180 | |
d47b87ac | 181 | def test_create_invalid_base_type(self): |
b4f45851 | 182 | with self.assertRaises(TypeError): |
5783664e | 183 | self._create_field_class(preferred_display_base='yes') |
b4f45851 | 184 | |
d47b87ac SM |
185 | def test_create_invalid_base_value(self): |
186 | with self.assertRaises(ValueError): | |
5783664e | 187 | self._create_field_class(preferred_display_base=444) |
b4f45851 | 188 | |
d47b87ac | 189 | def test_create_full(self): |
5783664e PP |
190 | fc = self._create_field_class( |
191 | 24, preferred_display_base=bt2.IntegerDisplayBase.OCTAL | |
192 | ) | |
d47b87ac SM |
193 | self.assertEqual(fc.field_value_range, 24) |
194 | self.assertEqual(fc.preferred_display_base, bt2.IntegerDisplayBase.OCTAL) | |
b4f45851 SM |
195 | |
196 | ||
5783664e PP |
197 | class SignedIntegerFieldClassTestCase( |
198 | _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase | |
199 | ): | |
f0a42b33 FD |
200 | @staticmethod |
201 | def _const_value_setter(field): | |
d47b6b4e | 202 | field.value = -18 |
f0a42b33 | 203 | |
5783664e PP |
204 | def _create_field_class(self, *args, **kwargs): |
205 | tc = get_default_trace_class() | |
206 | return tc.create_signed_integer_field_class(*args, **kwargs) | |
b4f45851 | 207 | |
f0a42b33 FD |
208 | def _create_default_const_field_class(self, *args, **kwargs): |
209 | tc = get_default_trace_class() | |
210 | fc = tc.create_signed_integer_field_class(*args, **kwargs) | |
211 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
212 | ||
5783664e PP |
213 | _create_default_field_class = _create_field_class |
214 | ||
215 | ||
216 | class UnsignedIntegerFieldClassTestCase( | |
217 | _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase | |
218 | ): | |
f0a42b33 FD |
219 | @staticmethod |
220 | def _const_value_setter(field): | |
d47b6b4e | 221 | field.value = 18 |
f0a42b33 | 222 | |
5783664e PP |
223 | def _create_field_class(self, *args, **kwargs): |
224 | tc = get_default_trace_class() | |
225 | return tc.create_unsigned_integer_field_class(*args, **kwargs) | |
226 | ||
f0a42b33 FD |
227 | def _create_default_const_field_class(self, *args, **kwargs): |
228 | tc = get_default_trace_class() | |
229 | fc = tc.create_signed_integer_field_class(*args, **kwargs) | |
230 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
231 | ||
5783664e | 232 | _create_default_field_class = _create_field_class |
b4f45851 | 233 | |
5783664e | 234 | |
fe4df857 | 235 | class SingleRealFieldClassTestCase(_TestFieldClass, unittest.TestCase): |
f0a42b33 FD |
236 | @staticmethod |
237 | def _const_value_setter(field): | |
fe4df857 | 238 | field.value = -18.0 |
f0a42b33 | 239 | |
5783664e PP |
240 | def _create_field_class(self, *args, **kwargs): |
241 | tc = get_default_trace_class() | |
fe4df857 | 242 | return tc.create_single_precision_real_field_class(*args, **kwargs) |
5783664e | 243 | |
f0a42b33 FD |
244 | def _create_default_const_field_class(self, *args, **kwargs): |
245 | tc = get_default_trace_class() | |
fe4df857 | 246 | fc = tc.create_single_precision_real_field_class(*args, **kwargs) |
f0a42b33 FD |
247 | return _create_const_field_class(tc, fc, self._const_value_setter) |
248 | ||
5783664e | 249 | _create_default_field_class = _create_field_class |
b4f45851 | 250 | |
d47b87ac | 251 | def test_create_default(self): |
5783664e | 252 | fc = self._create_field_class() |
5783664e | 253 | self.assertEqual(len(fc.user_attributes), 0) |
b4f45851 | 254 | |
d47b87ac | 255 | |
fe4df857 FD |
256 | class DoubleRealFieldClassTestCase(_TestFieldClass, unittest.TestCase): |
257 | @staticmethod | |
258 | def _const_value_setter(field): | |
259 | field.value = -18.0 | |
260 | ||
261 | def _create_field_class(self, *args, **kwargs): | |
262 | tc = get_default_trace_class() | |
263 | return tc.create_double_precision_real_field_class(*args, **kwargs) | |
264 | ||
265 | def _create_default_const_field_class(self, *args, **kwargs): | |
266 | tc = get_default_trace_class() | |
267 | fc = tc.create_double_precision_real_field_class(*args, **kwargs) | |
268 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
269 | ||
270 | _create_default_field_class = _create_field_class | |
271 | ||
272 | def test_create_default(self): | |
273 | fc = self._create_field_class() | |
274 | self.assertEqual(len(fc.user_attributes), 0) | |
b4f45851 | 275 | |
b4f45851 | 276 | |
d47b87ac SM |
277 | # Converts an _EnumerationFieldClassMapping to a list of ranges: |
278 | # | |
279 | # [(lower0, upper0), (lower1, upper1), ...] | |
280 | ||
cfbd7cf3 | 281 | |
45c51519 PP |
282 | def enum_mapping_to_set(mapping): |
283 | return {(x.lower, x.upper) for x in mapping.ranges} | |
b4f45851 | 284 | |
b4f45851 | 285 | |
45c51519 | 286 | class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps): |
d47b87ac | 287 | def setUp(self): |
45c51519 | 288 | self._spec_set_up() |
5783664e | 289 | self._fc = self._create_default_field_class() |
f0a42b33 | 290 | self._fc_const = self._create_default_const_field_class() |
d47b87ac SM |
291 | |
292 | def test_create_from_invalid_type(self): | |
b4f45851 | 293 | with self.assertRaises(TypeError): |
5783664e | 294 | self._create_field_class('coucou') |
b4f45851 | 295 | |
d47b87ac | 296 | def test_add_mapping_simple(self): |
45c51519 | 297 | self._fc.add_mapping('hello', self._ranges1) |
d47b87ac SM |
298 | mapping = self._fc['hello'] |
299 | self.assertEqual(mapping.label, 'hello') | |
45c51519 | 300 | self.assertEqual(mapping.ranges, self._ranges1) |
b4f45851 | 301 | |
f0a42b33 FD |
302 | def test_const_add_mapping(self): |
303 | with self.assertRaises(AttributeError): | |
304 | self._fc_const.add_mapping('hello', self._ranges1) | |
305 | ||
d47b87ac | 306 | def test_add_mapping_simple_kwargs(self): |
45c51519 | 307 | self._fc.add_mapping(label='hello', ranges=self._ranges1) |
d47b87ac SM |
308 | mapping = self._fc['hello'] |
309 | self.assertEqual(mapping.label, 'hello') | |
45c51519 | 310 | self.assertEqual(mapping.ranges, self._ranges1) |
b4f45851 | 311 | |
45c51519 PP |
312 | def test_add_mapping_invalid_name(self): |
313 | with self.assertRaises(TypeError): | |
314 | self._fc.add_mapping(17, self._ranges1) | |
b4f45851 | 315 | |
45c51519 PP |
316 | def test_add_mapping_invalid_range(self): |
317 | with self.assertRaises(TypeError): | |
318 | self._fc.add_mapping('allo', 'meow') | |
d47b87ac | 319 | |
45c51519 | 320 | def test_add_mapping_dup_label(self): |
ce4923b0 | 321 | with self.assertRaises(ValueError): |
45c51519 PP |
322 | self._fc.add_mapping('a', self._ranges1) |
323 | self._fc.add_mapping('a', self._ranges2) | |
d47b87ac | 324 | |
45c51519 | 325 | def test_add_mapping_invalid_ranges_signedness(self): |
b4f45851 | 326 | with self.assertRaises(TypeError): |
45c51519 | 327 | self._fc.add_mapping('allo', self._inval_ranges) |
b4f45851 | 328 | |
d47b87ac | 329 | def test_iadd(self): |
45c51519 | 330 | self._fc.add_mapping('c', self._ranges1) |
b4f45851 | 331 | |
cfbd7cf3 | 332 | self._fc += [('d', self._ranges2), ('e', self._ranges3)] |
b4f45851 | 333 | |
45c51519 | 334 | self.assertEqual(len(self._fc), 3) |
d47b87ac | 335 | self.assertEqual(self._fc['c'].label, 'c') |
45c51519 | 336 | self.assertEqual(self._fc['c'].ranges, self._ranges1) |
d47b87ac | 337 | self.assertEqual(self._fc['d'].label, 'd') |
45c51519 | 338 | self.assertEqual(self._fc['d'].ranges, self._ranges2) |
d47b87ac | 339 | self.assertEqual(self._fc['e'].label, 'e') |
45c51519 | 340 | self.assertEqual(self._fc['e'].ranges, self._ranges3) |
b4f45851 | 341 | |
f0a42b33 FD |
342 | def test_const_iadd(self): |
343 | with self.assertRaises(TypeError): | |
344 | self._fc_const += [('d', self._ranges2), ('e', self._ranges3)] | |
345 | ||
d47b87ac SM |
346 | def test_bool_op(self): |
347 | self.assertFalse(self._fc) | |
45c51519 | 348 | self._fc.add_mapping('a', self._ranges1) |
d47b87ac | 349 | self.assertTrue(self._fc) |
b4f45851 | 350 | |
d47b87ac | 351 | def test_len(self): |
45c51519 PP |
352 | self._fc.add_mapping('a', self._ranges1) |
353 | self._fc.add_mapping('b', self._ranges2) | |
354 | self._fc.add_mapping('c', self._ranges3) | |
d47b87ac | 355 | self.assertEqual(len(self._fc), 3) |
b4f45851 | 356 | |
d47b87ac | 357 | def test_getitem(self): |
45c51519 PP |
358 | self._fc.add_mapping('a', self._ranges1) |
359 | self._fc.add_mapping('b', self._ranges2) | |
360 | self._fc.add_mapping('c', self._ranges3) | |
d47b87ac | 361 | mapping = self._fc['a'] |
d47b87ac | 362 | self.assertEqual(mapping.label, 'a') |
45c51519 | 363 | self.assertEqual(mapping.ranges, self._ranges1) |
fc866000 FD |
364 | self.assertIs(type(mapping), self._MAPPING_CLASS) |
365 | self.assertIs(type(mapping.ranges), self._CONST_RANGE_SET_CLASS) | |
b4f45851 | 366 | |
45c51519 | 367 | def test_getitem_nonexistent(self): |
d47b87ac SM |
368 | with self.assertRaises(KeyError): |
369 | self._fc['doesnotexist'] | |
b4f45851 | 370 | |
d47b87ac | 371 | def test_iter(self): |
45c51519 PP |
372 | self._fc.add_mapping('a', self._ranges1) |
373 | self._fc.add_mapping('b', self._ranges2) | |
374 | self._fc.add_mapping('c', self._ranges3) | |
b4f45851 | 375 | |
d47b87ac SM |
376 | # This exercises iteration. |
377 | labels = sorted(self._fc) | |
b4f45851 | 378 | |
45c51519 | 379 | self.assertEqual(labels, ['a', 'b', 'c']) |
b4f45851 | 380 | |
d47b87ac | 381 | def test_find_by_value(self): |
45c51519 PP |
382 | self._fc.add_mapping('a', self._ranges1) |
383 | self._fc.add_mapping('b', self._ranges2) | |
384 | self._fc.add_mapping('c', self._ranges3) | |
385 | mappings = self._fc.mappings_for_value(self._value_in_range_1_and_3) | |
386 | labels = set([mapping.label for mapping in mappings]) | |
387 | expected_labels = set(['a', 'c']) | |
388 | self.assertEqual(labels, expected_labels) | |
389 | ||
390 | ||
cfbd7cf3 | 391 | class UnsignedEnumerationFieldClassTestCase( |
5783664e | 392 | _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase |
cfbd7cf3 | 393 | ): |
fc866000 FD |
394 | _MAPPING_CLASS = bt2_field_class._UnsignedEnumerationFieldClassMappingConst |
395 | _RANGE_SET_CLASS = bt2.UnsignedIntegerRangeSet | |
396 | _CONST_RANGE_SET_CLASS = bt2._UnsignedIntegerRangeSetConst | |
397 | ||
45c51519 PP |
398 | def _spec_set_up(self): |
399 | self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)]) | |
400 | self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)]) | |
401 | self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 22), (48, 99)]) | |
402 | self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, -5), (48, 1928)]) | |
403 | self._value_in_range_1_and_3 = 20 | |
5783664e | 404 | |
f0a42b33 FD |
405 | @staticmethod |
406 | def _const_value_setter(field): | |
d47b6b4e | 407 | field.value = 0 |
f0a42b33 | 408 | |
5783664e PP |
409 | def _create_field_class(self, *args, **kwargs): |
410 | tc = get_default_trace_class() | |
411 | return tc.create_unsigned_enumeration_field_class(*args, **kwargs) | |
412 | ||
f0a42b33 FD |
413 | def _create_default_const_field_class(self, *args, **kwargs): |
414 | tc = get_default_trace_class() | |
415 | fc = tc.create_unsigned_enumeration_field_class(*args, **kwargs) | |
416 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
417 | ||
5783664e | 418 | _create_default_field_class = _create_field_class |
b4f45851 | 419 | |
b4f45851 | 420 | |
cfbd7cf3 | 421 | class SignedEnumerationFieldClassTestCase( |
5783664e | 422 | _EnumerationFieldClassTestCase, _TestFieldClass, unittest.TestCase |
cfbd7cf3 | 423 | ): |
fc866000 FD |
424 | _MAPPING_CLASS = bt2_field_class._SignedEnumerationFieldClassMappingConst |
425 | _RANGE_SET_CLASS = bt2.SignedIntegerRangeSet | |
426 | _CONST_RANGE_SET_CLASS = bt2._SignedIntegerRangeSetConst | |
427 | ||
45c51519 PP |
428 | def _spec_set_up(self): |
429 | self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)]) | |
430 | self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)]) | |
431 | self._ranges3 = bt2.SignedIntegerRangeSet([(-100, -1), (8, 16), (48, 99)]) | |
432 | self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)]) | |
433 | self._value_in_range_1_and_3 = -7 | |
b4f45851 | 434 | |
f0a42b33 FD |
435 | @staticmethod |
436 | def _const_value_setter(field): | |
d47b6b4e | 437 | field.value = 0 |
f0a42b33 | 438 | |
5783664e PP |
439 | def _create_field_class(self, *args, **kwargs): |
440 | tc = get_default_trace_class() | |
441 | return tc.create_signed_enumeration_field_class(*args, **kwargs) | |
442 | ||
f0a42b33 FD |
443 | def _create_default_const_field_class(self, *args, **kwargs): |
444 | tc = get_default_trace_class() | |
445 | fc = tc.create_signed_enumeration_field_class(*args, **kwargs) | |
446 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
447 | ||
5783664e | 448 | _create_default_field_class = _create_field_class |
b4f45851 | 449 | |
5783664e PP |
450 | |
451 | class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase): | |
f0a42b33 FD |
452 | @staticmethod |
453 | def _const_value_setter(field): | |
d47b6b4e | 454 | field.value = 'chaine' |
f0a42b33 | 455 | |
5783664e | 456 | def _create_field_class(self, *args, **kwargs): |
d47b87ac | 457 | tc = get_default_trace_class() |
5783664e PP |
458 | return tc.create_string_field_class(*args, **kwargs) |
459 | ||
f0a42b33 FD |
460 | def _create_default_const_field_class(self, *args, **kwargs): |
461 | tc = get_default_trace_class() | |
462 | fc = tc.create_string_field_class(*args, **kwargs) | |
463 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
464 | ||
5783664e PP |
465 | _create_default_field_class = _create_field_class |
466 | ||
467 | def setUp(self): | |
468 | self._fc = self._create_default_field_class() | |
b4f45851 SM |
469 | |
470 | def test_create_default(self): | |
d47b87ac | 471 | self.assertIsNotNone(self._fc) |
5783664e | 472 | self.assertEqual(len(self._fc.user_attributes), 0) |
b4f45851 | 473 | |
b4f45851 | 474 | |
cfbd7cf3 | 475 | class _TestElementContainer: |
45c51519 PP |
476 | def setUp(self): |
477 | self._tc = get_default_trace_class() | |
5783664e | 478 | self._fc = self._create_default_field_class() |
f0a42b33 | 479 | self._fc_const = self._create_default_const_field_class() |
45c51519 PP |
480 | |
481 | def test_create_default(self): | |
482 | self.assertIsNotNone(self._fc) | |
5783664e | 483 | self.assertEqual(len(self._fc.user_attributes), 0) |
45c51519 | 484 | |
d47b87ac SM |
485 | def test_append_element(self): |
486 | int_field_class = self._tc.create_signed_integer_field_class(32) | |
487 | self._append_element_method(self._fc, 'int32', int_field_class) | |
45c51519 | 488 | field_class = self._fc['int32'].field_class |
d47b87ac | 489 | self.assertEqual(field_class.addr, int_field_class.addr) |
b4f45851 | 490 | |
45c51519 | 491 | def test_append_element_kwargs(self): |
d47b87ac SM |
492 | int_field_class = self._tc.create_signed_integer_field_class(32) |
493 | self._append_element_method(self._fc, name='int32', field_class=int_field_class) | |
45c51519 | 494 | field_class = self._fc['int32'].field_class |
d47b87ac SM |
495 | self.assertEqual(field_class.addr, int_field_class.addr) |
496 | ||
497 | def test_append_element_invalid_name(self): | |
498 | sub_fc = self._tc.create_string_field_class() | |
b4f45851 | 499 | |
b4f45851 | 500 | with self.assertRaises(TypeError): |
d47b87ac | 501 | self._append_element_method(self._fc, 23, sub_fc) |
b4f45851 | 502 | |
d47b87ac | 503 | def test_append_element_invalid_field_class(self): |
b4f45851 | 504 | with self.assertRaises(TypeError): |
d47b87ac | 505 | self._append_element_method(self._fc, 'yes', object()) |
b4f45851 | 506 | |
45c51519 PP |
507 | def test_append_element_dup_name(self): |
508 | sub_fc1 = self._tc.create_string_field_class() | |
509 | sub_fc2 = self._tc.create_string_field_class() | |
510 | ||
ce4923b0 | 511 | with self.assertRaises(ValueError): |
45c51519 PP |
512 | self._append_element_method(self._fc, 'yes', sub_fc1) |
513 | self._append_element_method(self._fc, 'yes', sub_fc2) | |
514 | ||
f0a42b33 FD |
515 | def test_attr_field_class(self): |
516 | int_field_class = self._tc.create_signed_integer_field_class(32) | |
517 | self._append_element_method(self._fc, 'int32', int_field_class) | |
518 | field_class = self._fc['int32'].field_class | |
519 | ||
520 | self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClass) | |
521 | ||
522 | def test_const_attr_field_class(self): | |
523 | int_field_class = self._tc.create_signed_integer_field_class(32) | |
524 | self._append_element_method(self._fc, 'int32', int_field_class) | |
525 | field_class = self._fc['int32'].field_class | |
526 | const_fc = _create_const_field_class( | |
527 | self._tc, self._fc, self._const_value_setter | |
528 | ) | |
529 | field_class = const_fc['int32'].field_class | |
530 | ||
531 | self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClassConst) | |
532 | ||
b4f45851 | 533 | def test_iadd(self): |
fe4df857 | 534 | a_field_class = self._tc.create_single_precision_real_field_class() |
d47b87ac SM |
535 | b_field_class = self._tc.create_signed_integer_field_class(17) |
536 | self._append_element_method(self._fc, 'a_float', a_field_class) | |
537 | self._append_element_method(self._fc, 'b_int', b_field_class) | |
45c51519 | 538 | c_field_class = self._tc.create_string_field_class() |
cfbd7cf3 FD |
539 | d_field_class = self._tc.create_signed_enumeration_field_class( |
540 | field_value_range=32 | |
541 | ) | |
45c51519 PP |
542 | e_field_class = self._tc.create_structure_field_class() |
543 | self._fc += [ | |
544 | ('c_string', c_field_class), | |
545 | ('d_enum', d_field_class), | |
546 | ('e_struct', e_field_class), | |
547 | ] | |
548 | self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr) | |
549 | self.assertEqual(self._fc['a_float'].name, 'a_float') | |
550 | self.assertEqual(self._fc['b_int'].field_class.addr, b_field_class.addr) | |
551 | self.assertEqual(self._fc['b_int'].name, 'b_int') | |
552 | self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr) | |
553 | self.assertEqual(self._fc['c_string'].name, 'c_string') | |
554 | self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr) | |
555 | self.assertEqual(self._fc['d_enum'].name, 'd_enum') | |
556 | self.assertEqual(self._fc['e_struct'].field_class.addr, e_field_class.addr) | |
557 | self.assertEqual(self._fc['e_struct'].name, 'e_struct') | |
b4f45851 | 558 | |
f0a42b33 | 559 | def test_const_iadd(self): |
fe4df857 | 560 | a_field_class = self._tc.create_single_precision_real_field_class() |
f0a42b33 FD |
561 | with self.assertRaises(TypeError): |
562 | self._fc_const += a_field_class | |
563 | ||
b4f45851 SM |
564 | def test_bool_op(self): |
565 | self.assertFalse(self._fc) | |
d47b87ac | 566 | self._append_element_method(self._fc, 'a', self._tc.create_string_field_class()) |
b4f45851 SM |
567 | self.assertTrue(self._fc) |
568 | ||
569 | def test_len(self): | |
45c51519 PP |
570 | self._append_element_method(self._fc, 'a', self._tc.create_string_field_class()) |
571 | self._append_element_method(self._fc, 'b', self._tc.create_string_field_class()) | |
572 | self._append_element_method(self._fc, 'c', self._tc.create_string_field_class()) | |
b4f45851 SM |
573 | self.assertEqual(len(self._fc), 3) |
574 | ||
575 | def test_getitem(self): | |
d47b87ac SM |
576 | a_fc = self._tc.create_signed_integer_field_class(32) |
577 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 578 | c_fc = self._tc.create_single_precision_real_field_class() |
d47b87ac SM |
579 | self._append_element_method(self._fc, 'a', a_fc) |
580 | self._append_element_method(self._fc, 'b', b_fc) | |
581 | self._append_element_method(self._fc, 'c', c_fc) | |
45c51519 PP |
582 | self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr) |
583 | self.assertEqual(self._fc['b'].name, 'b') | |
b4f45851 SM |
584 | |
585 | def test_getitem_invalid_key_type(self): | |
586 | with self.assertRaises(TypeError): | |
587 | self._fc[0] | |
588 | ||
589 | def test_getitem_invalid_key(self): | |
590 | with self.assertRaises(KeyError): | |
591 | self._fc['no way'] | |
592 | ||
593 | def test_contains(self): | |
594 | self.assertFalse('a' in self._fc) | |
d47b87ac | 595 | self._append_element_method(self._fc, 'a', self._tc.create_string_field_class()) |
b4f45851 SM |
596 | self.assertTrue('a' in self._fc) |
597 | ||
598 | def test_iter(self): | |
d47b87ac SM |
599 | a_fc = self._tc.create_signed_integer_field_class(32) |
600 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 601 | c_fc = self._tc.create_single_precision_real_field_class() |
cfbd7cf3 | 602 | elements = (('a', a_fc), ('b', b_fc), ('c', c_fc)) |
b4f45851 | 603 | |
45c51519 PP |
604 | for elem in elements: |
605 | self._append_element_method(self._fc, *elem) | |
b4f45851 | 606 | |
45c51519 PP |
607 | for (name, element), test_elem in zip(self._fc.items(), elements): |
608 | self.assertEqual(element.name, test_elem[0]) | |
609 | self.assertEqual(name, element.name) | |
610 | self.assertEqual(element.field_class.addr, test_elem[1].addr) | |
5783664e | 611 | self.assertEqual(len(element.user_attributes), 0) |
b4f45851 SM |
612 | |
613 | def test_at_index(self): | |
d47b87ac SM |
614 | a_fc = self._tc.create_signed_integer_field_class(32) |
615 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 616 | c_fc = self._tc.create_single_precision_real_field_class() |
d47b87ac SM |
617 | self._append_element_method(self._fc, 'c', c_fc) |
618 | self._append_element_method(self._fc, 'a', a_fc) | |
619 | self._append_element_method(self._fc, 'b', b_fc) | |
45c51519 PP |
620 | elem = self._at_index_method(self._fc, 1) |
621 | self.assertEqual(elem.field_class.addr, a_fc.addr) | |
622 | self.assertEqual(elem.name, 'a') | |
b4f45851 SM |
623 | |
624 | def test_at_index_invalid(self): | |
cfbd7cf3 FD |
625 | self._append_element_method( |
626 | self._fc, 'c', self._tc.create_signed_integer_field_class(32) | |
627 | ) | |
b4f45851 SM |
628 | |
629 | with self.assertRaises(TypeError): | |
d47b87ac | 630 | self._at_index_method(self._fc, 'yes') |
b4f45851 SM |
631 | |
632 | def test_at_index_out_of_bounds_after(self): | |
cfbd7cf3 FD |
633 | self._append_element_method( |
634 | self._fc, 'c', self._tc.create_signed_integer_field_class(32) | |
635 | ) | |
b4f45851 SM |
636 | |
637 | with self.assertRaises(IndexError): | |
d47b87ac | 638 | self._at_index_method(self._fc, len(self._fc)) |
b4f45851 | 639 | |
5783664e PP |
640 | def test_user_attributes(self): |
641 | self._append_element_method( | |
642 | self._fc, | |
643 | 'c', | |
644 | self._tc.create_string_field_class(), | |
645 | user_attributes={'salut': 23}, | |
646 | ) | |
647 | self.assertEqual(self._fc['c'].user_attributes, {'salut': 23}) | |
f0a42b33 FD |
648 | self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue) |
649 | self.assertIs(type(self._fc['c'].user_attributes), bt2_value.MapValue) | |
b4f45851 | 650 | |
5783664e PP |
651 | def test_invalid_user_attributes(self): |
652 | with self.assertRaises(TypeError): | |
653 | self._append_element_method( | |
654 | self._fc, | |
655 | 'c', | |
656 | self._tc.create_string_field_class(), | |
657 | user_attributes=object(), | |
658 | ) | |
659 | ||
660 | def test_invalid_user_attributes_value_type(self): | |
661 | with self.assertRaises(TypeError): | |
662 | self._append_element_method( | |
663 | self._fc, 'c', self._tc.create_string_field_class(), user_attributes=23 | |
664 | ) | |
665 | ||
666 | ||
667 | class StructureFieldClassTestCase( | |
668 | _TestFieldClass, _TestElementContainer, unittest.TestCase | |
669 | ): | |
3fb99a22 PP |
670 | _append_element_method = staticmethod(bt2._StructureFieldClass.append_member) |
671 | _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index) | |
45c51519 | 672 | |
f0a42b33 FD |
673 | @staticmethod |
674 | def _const_value_setter(field): | |
675 | field.value = {} | |
676 | ||
5783664e PP |
677 | def _create_field_class(self, *args, **kwargs): |
678 | tc = get_default_trace_class() | |
679 | return tc.create_structure_field_class(*args, **kwargs) | |
45c51519 | 680 | |
f0a42b33 FD |
681 | def _create_default_const_field_class(self, *args, **kwargs): |
682 | tc = get_default_trace_class() | |
683 | fc = tc.create_structure_field_class(*args, **kwargs) | |
684 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
685 | ||
5783664e PP |
686 | _create_default_field_class = _create_field_class |
687 | ||
f0a42b33 FD |
688 | def test_const_member_field_class(self): |
689 | def _real_value_setter(field): | |
690 | field.value = {'real': 0} | |
691 | ||
692 | tc = get_default_trace_class() | |
693 | fc = tc.create_structure_field_class() | |
fe4df857 | 694 | member_fc = self._tc.create_single_precision_real_field_class() |
f0a42b33 FD |
695 | fc.append_member('real', member_fc) |
696 | const_fc = _create_const_field_class(tc, fc, _real_value_setter) | |
697 | ||
698 | self.assertIs( | |
fe4df857 FD |
699 | type(const_fc['real'].field_class), |
700 | bt2_field_class._SinglePrecisionRealFieldClassConst, | |
f0a42b33 FD |
701 | ) |
702 | ||
703 | def test_member_field_class(self): | |
704 | tc = get_default_trace_class() | |
705 | fc = tc.create_structure_field_class() | |
fe4df857 | 706 | member_fc = self._tc.create_single_precision_real_field_class() |
f0a42b33 FD |
707 | fc.append_member('real', member_fc) |
708 | ||
fe4df857 FD |
709 | self.assertIs( |
710 | type(fc['real'].field_class), bt2_field_class._SinglePrecisionRealFieldClass | |
711 | ) | |
f0a42b33 | 712 | |
5783664e | 713 | |
0aa006b7 | 714 | class OptionWithoutSelectorFieldClassTestCase(_TestFieldClass, unittest.TestCase): |
f0a42b33 FD |
715 | @staticmethod |
716 | def _const_value_setter(field): | |
717 | field.has_field = True | |
718 | field.value = 12 | |
719 | ||
5783664e | 720 | def _create_default_field_class(self, *args, **kwargs): |
0aa006b7 PP |
721 | return self._tc.create_option_without_selector_field_class( |
722 | self._content_fc, *args, **kwargs | |
723 | ) | |
45c51519 | 724 | |
f0a42b33 | 725 | def _create_default_const_field_class(self, *args, **kwargs): |
0aa006b7 PP |
726 | fc = self._tc.create_option_without_selector_field_class( |
727 | self._content_fc, *args, **kwargs | |
728 | ) | |
f0a42b33 FD |
729 | return _create_const_field_class(self._tc, fc, self._const_value_setter) |
730 | ||
cec0261d PP |
731 | def setUp(self): |
732 | self._tc = get_default_trace_class() | |
733 | self._content_fc = self._tc.create_signed_integer_field_class(23) | |
cec0261d PP |
734 | |
735 | def test_create_default(self): | |
5783664e | 736 | fc = self._create_default_field_class() |
cec0261d | 737 | self.assertEqual(fc.field_class.addr, self._content_fc.addr) |
5783664e | 738 | self.assertEqual(len(fc.user_attributes), 0) |
cec0261d | 739 | |
0aa006b7 PP |
740 | def test_create_invalid_field_class(self): |
741 | with self.assertRaises(TypeError): | |
742 | self._tc.create_option_without_selector_field_class(object()) | |
743 | ||
f0a42b33 FD |
744 | def test_attr_field_class(self): |
745 | fc = self._create_default_field_class() | |
746 | self.assertIs(type(fc.field_class), bt2_field_class._SignedIntegerFieldClass) | |
747 | ||
748 | def test_const_attr_field_class(self): | |
749 | fc = self._create_default_const_field_class() | |
750 | self.assertIs( | |
751 | type(fc.field_class), bt2_field_class._SignedIntegerFieldClassConst | |
752 | ) | |
753 | ||
0aa006b7 PP |
754 | |
755 | class _OptionWithSelectorFieldClassTestCase(_TestFieldClass): | |
756 | @staticmethod | |
757 | def _const_value_setter(field): | |
758 | field['opt'].has_field = True | |
759 | field['opt'].value = 12 | |
760 | ||
761 | def _create_default_const_field_class(self, *args, **kwargs): | |
762 | # Create a struct to contain the option and its selector else we can't | |
763 | # create the non-const field necessary to get the the const field_class | |
764 | struct_fc = self._tc.create_structure_field_class() | |
765 | struct_fc.append_member('selecteux', self._tag_fc) | |
766 | opt_fc = self._create_default_field_class(*args, **kwargs) | |
767 | struct_fc.append_member('opt', opt_fc) | |
768 | ||
769 | return _create_const_field_class(self._tc, struct_fc, self._const_value_setter)[ | |
770 | 'opt' | |
771 | ].field_class | |
772 | ||
773 | def setUp(self): | |
774 | self._tc = get_default_trace_class() | |
775 | self._content_fc = self._tc.create_signed_integer_field_class(23) | |
776 | self._tag_fc = self._create_tag_fc() | |
777 | ||
cec0261d | 778 | def _create_field_class_for_field_path_test(self): |
0aa006b7 | 779 | fc = self._create_default_field_class() |
cec0261d | 780 | |
fe4df857 | 781 | foo_fc = self._tc.create_single_precision_real_field_class() |
cec0261d PP |
782 | bar_fc = self._tc.create_string_field_class() |
783 | baz_fc = self._tc.create_string_field_class() | |
784 | ||
785 | inner_struct_fc = self._tc.create_structure_field_class() | |
786 | inner_struct_fc.append_member('bar', bar_fc) | |
787 | inner_struct_fc.append_member('baz', baz_fc) | |
788 | inner_struct_fc.append_member('tag', self._tag_fc) | |
789 | inner_struct_fc.append_member('opt', fc) | |
790 | ||
0aa006b7 PP |
791 | opt_struct_array_fc = self._tc.create_option_without_selector_field_class( |
792 | inner_struct_fc | |
793 | ) | |
cec0261d PP |
794 | |
795 | outer_struct_fc = self._tc.create_structure_field_class() | |
796 | outer_struct_fc.append_member('foo', foo_fc) | |
797 | outer_struct_fc.append_member('inner_opt', opt_struct_array_fc) | |
798 | ||
799 | # The path to the selector field class is resolved when the | |
800 | # option field class is actually used, for example in a packet | |
801 | # context. | |
802 | self._tc.create_stream_class( | |
803 | packet_context_field_class=outer_struct_fc, supports_packets=True | |
804 | ) | |
805 | ||
806 | return fc | |
807 | ||
808 | def test_field_path_len(self): | |
809 | fc = self._create_field_class_for_field_path_test() | |
810 | self.assertEqual(len(fc.selector_field_path), 3) | |
811 | ||
812 | def test_field_path_iter(self): | |
813 | fc = self._create_field_class_for_field_path_test() | |
814 | path_items = list(fc.selector_field_path) | |
815 | ||
816 | self.assertEqual(len(path_items), 3) | |
817 | ||
818 | self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem) | |
819 | self.assertEqual(path_items[0].index, 1) | |
820 | ||
821 | self.assertIsInstance(path_items[1], bt2._CurrentOptionContentFieldPathItem) | |
822 | ||
823 | self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem) | |
824 | self.assertEqual(path_items[2].index, 2) | |
825 | ||
826 | def test_field_path_root_scope(self): | |
827 | fc = self._create_field_class_for_field_path_test() | |
828 | self.assertEqual( | |
829 | fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT | |
830 | ) | |
831 | ||
0aa006b7 PP |
832 | |
833 | class OptionWithBoolSelectorFieldClassTestCase( | |
834 | _OptionWithSelectorFieldClassTestCase, unittest.TestCase | |
835 | ): | |
836 | def _create_default_field_class(self, *args, **kwargs): | |
837 | return self._tc.create_option_with_bool_selector_field_class( | |
838 | self._content_fc, self._tag_fc, *args, **kwargs | |
839 | ) | |
840 | ||
841 | def _create_tag_fc(self): | |
842 | return self._tc.create_bool_field_class() | |
843 | ||
844 | def test_create_default(self): | |
845 | fc = self._create_default_field_class() | |
846 | self.assertEqual(fc.field_class.addr, self._content_fc.addr) | |
847 | self.assertFalse(fc.selector_is_reversed) | |
848 | self.assertEqual(len(fc.user_attributes), 0) | |
849 | ||
850 | def test_create_selector_is_reversed_wrong_type(self): | |
cec0261d | 851 | with self.assertRaises(TypeError): |
0aa006b7 | 852 | self._create_default_field_class(selector_is_reversed=23) |
cec0261d PP |
853 | |
854 | def test_create_invalid_selector_type(self): | |
855 | with self.assertRaises(TypeError): | |
0aa006b7 PP |
856 | self._tc.create_option_with_bool_selector_field_class(self._content_fc, 17) |
857 | ||
858 | def test_attr_selector_is_reversed(self): | |
859 | fc = self._create_default_field_class(selector_is_reversed=True) | |
860 | self.assertTrue(fc.selector_is_reversed) | |
861 | ||
862 | def test_const_attr_selector_is_reversed(self): | |
863 | fc = self._create_default_const_field_class(selector_is_reversed=True) | |
864 | self.assertTrue(fc.selector_is_reversed) | |
865 | ||
866 | ||
867 | class _OptionWithIntegerSelectorFieldClassTestCase( | |
868 | _OptionWithSelectorFieldClassTestCase | |
869 | ): | |
870 | def _create_default_field_class(self, *args, **kwargs): | |
871 | return self._tc.create_option_with_integer_selector_field_class( | |
872 | self._content_fc, self._tag_fc, self._ranges, *args, **kwargs | |
873 | ) | |
874 | ||
875 | def test_create_default(self): | |
876 | fc = self._create_default_field_class() | |
877 | self.assertEqual(fc.field_class.addr, self._content_fc.addr) | |
878 | self.assertEqual(fc.ranges, self._ranges) | |
879 | self.assertEqual(len(fc.user_attributes), 0) | |
880 | ||
881 | def test_create_ranges_wrong_type(self): | |
882 | with self.assertRaises(TypeError): | |
883 | self._tc.create_option_with_integer_selector_field_class( | |
884 | self._content_fc, self._tag_fc, 23 | |
885 | ) | |
886 | ||
887 | def test_create_ranges_empty(self): | |
888 | with self.assertRaises(ValueError): | |
889 | self._tc.create_option_with_integer_selector_field_class( | |
890 | self._content_fc, self._tag_fc, type(self._ranges)() | |
891 | ) | |
892 | ||
893 | def test_create_invalid_selector_type(self): | |
894 | with self.assertRaises(TypeError): | |
895 | self._tc.create_option_with_bool_selector_field_class(self._content_fc, 17) | |
896 | ||
897 | def test_attr_ranges(self): | |
898 | fc = self._create_default_field_class() | |
899 | print(type(fc.ranges), type(self._ranges)) | |
900 | self.assertEqual(fc.ranges, self._ranges) | |
901 | ||
902 | def test_const_attr_ranges(self): | |
903 | fc = self._create_default_const_field_class() | |
904 | self.assertEqual(fc.ranges, self._ranges) | |
905 | ||
906 | ||
907 | class OptionWithUnsignedIntegerSelectorFieldClassTestCase( | |
908 | _OptionWithIntegerSelectorFieldClassTestCase, unittest.TestCase | |
909 | ): | |
910 | def setUp(self): | |
911 | self._ranges = bt2.UnsignedIntegerRangeSet([(1, 3), (18, 44)]) | |
912 | super().setUp() | |
913 | ||
914 | def _create_tag_fc(self): | |
915 | return self._tc.create_unsigned_integer_field_class() | |
cec0261d PP |
916 | |
917 | ||
cfbd7cf3 | 918 | class VariantFieldClassWithoutSelectorTestCase( |
5783664e | 919 | _TestFieldClass, _TestElementContainer, unittest.TestCase |
cfbd7cf3 FD |
920 | ): |
921 | _append_element_method = staticmethod( | |
3fb99a22 | 922 | bt2._VariantFieldClassWithoutSelector.append_option |
cfbd7cf3 FD |
923 | ) |
924 | _at_index_method = staticmethod( | |
3fb99a22 | 925 | bt2._VariantFieldClassWithoutSelector.option_at_index |
cfbd7cf3 | 926 | ) |
45c51519 | 927 | |
f0a42b33 FD |
928 | @staticmethod |
929 | def _const_value_setter(variant_field): | |
930 | variant_field.selected_option_index = 0 | |
931 | variant_field.value = 12 | |
932 | ||
5783664e PP |
933 | def _create_field_class(self, *args, **kwargs): |
934 | tc = get_default_trace_class() | |
935 | return tc.create_variant_field_class(*args, **kwargs) | |
936 | ||
f0a42b33 FD |
937 | def _create_default_const_field_class(self, *args, **kwargs): |
938 | tc = get_default_trace_class() | |
939 | fc = tc.create_variant_field_class(*args, **kwargs) | |
940 | int_field_class = self._tc.create_signed_integer_field_class(32) | |
941 | fc.append_option('int32', int_field_class) | |
942 | ||
943 | return _create_const_field_class(tc, fc, self._const_value_setter) | |
944 | ||
5783664e | 945 | _create_default_field_class = _create_field_class |
45c51519 PP |
946 | |
947 | ||
fabfe034 | 948 | class _VariantFieldClassWithIntegerSelectorTestCase: |
f0a42b33 FD |
949 | @staticmethod |
950 | def _const_value_setter(field): | |
951 | field['variant'].selected_option_index = 0 | |
952 | field['variant'] = 12 | |
953 | ||
5783664e PP |
954 | def _create_default_field_class(self, *args, **kwargs): |
955 | return self._tc.create_variant_field_class( | |
956 | *args, selector_fc=self._selector_fc, **kwargs | |
957 | ) | |
958 | ||
f0a42b33 FD |
959 | def _create_default_const_field_class(self, *args, **kwargs): |
960 | # Create a struct to contain the variant and its selector else we can't | |
961 | # create the non-const field necessary to get the the const field_class | |
962 | struct_fc = self._tc.create_structure_field_class() | |
963 | struct_fc.append_member('selecteux', self._selector_fc) | |
964 | variant_fc = self._tc.create_variant_field_class( | |
965 | *args, selector_fc=self._selector_fc | |
966 | ) | |
967 | variant_fc.append_option( | |
968 | 'a', self._tc.create_signed_integer_field_class(32), self._ranges1 | |
969 | ) | |
970 | struct_fc.append_member('variant', variant_fc, **kwargs) | |
971 | ||
972 | return _create_const_field_class(self._tc, struct_fc, self._const_value_setter)[ | |
973 | 'variant' | |
974 | ].field_class | |
975 | ||
b4f45851 | 976 | def setUp(self): |
d47b87ac | 977 | self._tc = get_default_trace_class() |
45c51519 | 978 | self._spec_set_up() |
5783664e | 979 | self._fc = self._create_default_field_class() |
d47b87ac SM |
980 | |
981 | def test_create_default(self): | |
982 | self.assertIsNotNone(self._fc) | |
5783664e | 983 | self.assertEqual(len(self._fc.user_attributes), 0) |
b4f45851 | 984 | |
45c51519 PP |
985 | def test_append_element(self): |
986 | str_field_class = self._tc.create_string_field_class() | |
987 | self._fc.append_option('str', str_field_class, self._ranges1) | |
988 | opt = self._fc['str'] | |
989 | self.assertEqual(opt.field_class.addr, str_field_class.addr) | |
990 | self.assertEqual(opt.name, 'str') | |
991 | self.assertEqual(opt.ranges.addr, self._ranges1.addr) | |
992 | ||
f0a42b33 FD |
993 | def test_const_append(self): |
994 | fc_const = self._create_default_const_field_class() | |
fd4e6235 | 995 | str_field_class = self._tc.create_string_field_class() |
f0a42b33 FD |
996 | with self.assertRaises(AttributeError): |
997 | fc_const.append_option('str', str_field_class, self._ranges1) | |
998 | ||
45c51519 PP |
999 | def test_append_element_kwargs(self): |
1000 | int_field_class = self._tc.create_signed_integer_field_class(32) | |
cfbd7cf3 FD |
1001 | self._fc.append_option( |
1002 | name='int32', field_class=int_field_class, ranges=self._ranges1 | |
1003 | ) | |
45c51519 PP |
1004 | opt = self._fc['int32'] |
1005 | self.assertEqual(opt.field_class.addr, int_field_class.addr) | |
1006 | self.assertEqual(opt.name, 'int32') | |
1007 | self.assertEqual(opt.ranges.addr, self._ranges1.addr) | |
d47b87ac | 1008 | |
45c51519 PP |
1009 | def test_append_element_invalid_name(self): |
1010 | sub_fc = self._tc.create_string_field_class() | |
b4f45851 | 1011 | |
45c51519 PP |
1012 | with self.assertRaises(TypeError): |
1013 | self._fc.append_option(self._fc, 23, sub_fc) | |
b4f45851 | 1014 | |
45c51519 PP |
1015 | def test_append_element_invalid_field_class(self): |
1016 | with self.assertRaises(TypeError): | |
1017 | self._fc.append_option(self._fc, 'yes', object()) | |
1018 | ||
1019 | def test_append_element_invalid_ranges(self): | |
1020 | sub_fc = self._tc.create_string_field_class() | |
1021 | ||
1022 | with self.assertRaises(TypeError): | |
1023 | self._fc.append_option(self._fc, sub_fc, 'lel') | |
1024 | ||
1025 | def test_append_element_dup_name(self): | |
1026 | sub_fc1 = self._tc.create_string_field_class() | |
1027 | sub_fc2 = self._tc.create_string_field_class() | |
1028 | ||
ce4923b0 | 1029 | with self.assertRaises(ValueError): |
45c51519 PP |
1030 | self._fc.append_option('yes', sub_fc1, self._ranges1) |
1031 | self._fc.append_option('yes', sub_fc2, self._ranges2) | |
1032 | ||
1033 | def test_append_element_invalid_ranges_signedness(self): | |
1034 | sub_fc = self._tc.create_string_field_class() | |
1035 | ||
1036 | with self.assertRaises(TypeError): | |
1037 | self._fc.append_option(self._fc, sub_fc, self._inval_ranges) | |
1038 | ||
5783664e PP |
1039 | def test_user_attributes(self): |
1040 | self._fc.append_option( | |
1041 | 'c', | |
1042 | self._tc.create_string_field_class(), | |
1043 | self._ranges1, | |
1044 | user_attributes={'salut': 23}, | |
1045 | ) | |
1046 | self.assertEqual(self._fc['c'].user_attributes, {'salut': 23}) | |
f0a42b33 FD |
1047 | self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue) |
1048 | ||
1049 | def test_const_user_attributes(self): | |
1050 | fc_const = self._create_default_const_field_class() | |
1051 | self.assertIs(type(fc_const.user_attributes), bt2_value._MapValueConst) | |
5783664e PP |
1052 | |
1053 | def test_invalid_user_attributes(self): | |
1054 | with self.assertRaises(TypeError): | |
1055 | self._fc.append_option( | |
1056 | 'c', | |
1057 | self._tc.create_string_field_class(), | |
1058 | self._ranges1, | |
1059 | user_attributes=object(), | |
1060 | ) | |
1061 | ||
1062 | def test_invalid_user_attributes_value_type(self): | |
1063 | with self.assertRaises(TypeError): | |
1064 | self._fc.append_option( | |
1065 | 'c', | |
1066 | self._tc.create_string_field_class(), | |
1067 | self._ranges1, | |
1068 | user_attributes=23, | |
1069 | ) | |
1070 | ||
45c51519 | 1071 | def test_iadd(self): |
fe4df857 | 1072 | a_field_class = self._tc.create_single_precision_real_field_class() |
45c51519 PP |
1073 | self._fc.append_option('a_float', a_field_class, self._ranges1) |
1074 | c_field_class = self._tc.create_string_field_class() | |
cfbd7cf3 FD |
1075 | d_field_class = self._tc.create_signed_enumeration_field_class( |
1076 | field_value_range=32 | |
1077 | ) | |
45c51519 PP |
1078 | self._fc += [ |
1079 | ('c_string', c_field_class, self._ranges2), | |
1080 | ('d_enum', d_field_class, self._ranges3), | |
1081 | ] | |
1082 | self.assertEqual(self._fc['a_float'].field_class.addr, a_field_class.addr) | |
1083 | self.assertEqual(self._fc['a_float'].name, 'a_float') | |
1084 | self.assertEqual(self._fc['a_float'].ranges, self._ranges1) | |
1085 | self.assertEqual(self._fc['c_string'].field_class.addr, c_field_class.addr) | |
1086 | self.assertEqual(self._fc['c_string'].name, 'c_string') | |
1087 | self.assertEqual(self._fc['c_string'].ranges, self._ranges2) | |
1088 | self.assertEqual(self._fc['d_enum'].field_class.addr, d_field_class.addr) | |
1089 | self.assertEqual(self._fc['d_enum'].name, 'd_enum') | |
1090 | self.assertEqual(self._fc['d_enum'].ranges, self._ranges3) | |
1091 | ||
f0a42b33 FD |
1092 | def test_const_iadd(self): |
1093 | fc_const = self._create_default_const_field_class() | |
fe4df857 | 1094 | a_field_class = self._tc.create_single_precision_real_field_class() |
f0a42b33 FD |
1095 | with self.assertRaises(TypeError): |
1096 | fc_const += [('a_float', a_field_class, self._ranges1)] | |
1097 | ||
45c51519 PP |
1098 | def test_bool_op(self): |
1099 | self.assertFalse(self._fc) | |
1100 | self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1) | |
1101 | self.assertTrue(self._fc) | |
1102 | ||
1103 | def test_len(self): | |
1104 | self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1) | |
1105 | self._fc.append_option('b', self._tc.create_string_field_class(), self._ranges2) | |
1106 | self._fc.append_option('c', self._tc.create_string_field_class(), self._ranges3) | |
1107 | self.assertEqual(len(self._fc), 3) | |
1108 | ||
1109 | def test_getitem(self): | |
1110 | a_fc = self._tc.create_signed_integer_field_class(32) | |
1111 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 1112 | c_fc = self._tc.create_single_precision_real_field_class() |
45c51519 PP |
1113 | self._fc.append_option('a', a_fc, self._ranges1) |
1114 | self._fc.append_option('b', b_fc, self._ranges2) | |
1115 | self._fc.append_option('c', c_fc, self._ranges3) | |
1116 | self.assertEqual(self._fc['b'].field_class.addr, b_fc.addr) | |
1117 | self.assertEqual(self._fc['b'].name, 'b') | |
1118 | self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr) | |
1119 | ||
f0a42b33 FD |
1120 | def test_option_field_class(self): |
1121 | a_fc = self._tc.create_signed_integer_field_class(32) | |
1122 | self._fc.append_option('a', a_fc, self._ranges1) | |
1123 | self.assertIs( | |
1124 | type(self._fc['a'].field_class), bt2_field_class._SignedIntegerFieldClass | |
1125 | ) | |
1126 | ||
1127 | def test_const_option_field_class(self): | |
1128 | fc_const = self._create_default_const_field_class() | |
1129 | self.assertIs( | |
1130 | type(fc_const['a'].field_class), | |
1131 | bt2_field_class._SignedIntegerFieldClassConst, | |
1132 | ) | |
1133 | ||
45c51519 PP |
1134 | def test_getitem_invalid_key_type(self): |
1135 | with self.assertRaises(TypeError): | |
1136 | self._fc[0] | |
1137 | ||
1138 | def test_getitem_invalid_key(self): | |
1139 | with self.assertRaises(KeyError): | |
1140 | self._fc['no way'] | |
1141 | ||
1142 | def test_contains(self): | |
1143 | self.assertFalse('a' in self._fc) | |
1144 | self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1) | |
1145 | self.assertTrue('a' in self._fc) | |
1146 | ||
1147 | def test_iter(self): | |
1148 | a_fc = self._tc.create_signed_integer_field_class(32) | |
1149 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 1150 | c_fc = self._tc.create_single_precision_real_field_class() |
45c51519 PP |
1151 | opts = ( |
1152 | ('a', a_fc, self._ranges1), | |
1153 | ('b', b_fc, self._ranges2), | |
1154 | ('c', c_fc, self._ranges3), | |
1155 | ) | |
1156 | ||
1157 | for opt in opts: | |
1158 | self._fc.append_option(*opt) | |
b4f45851 | 1159 | |
45c51519 PP |
1160 | for (name, opt), test_opt in zip(self._fc.items(), opts): |
1161 | self.assertEqual(opt.name, test_opt[0]) | |
1162 | self.assertEqual(name, opt.name) | |
1163 | self.assertEqual(opt.field_class.addr, test_opt[1].addr) | |
1164 | self.assertEqual(opt.ranges.addr, test_opt[2].addr) | |
1165 | ||
1166 | def test_at_index(self): | |
1167 | a_fc = self._tc.create_signed_integer_field_class(32) | |
1168 | b_fc = self._tc.create_string_field_class() | |
fe4df857 | 1169 | c_fc = self._tc.create_single_precision_real_field_class() |
45c51519 PP |
1170 | self._fc.append_option('c', c_fc, self._ranges1) |
1171 | self._fc.append_option('a', a_fc, self._ranges2) | |
1172 | self._fc.append_option('b', b_fc, self._ranges3) | |
1173 | self.assertEqual(self._fc.option_at_index(1).field_class.addr, a_fc.addr) | |
1174 | self.assertEqual(self._fc.option_at_index(1).name, 'a') | |
1175 | self.assertEqual(self._fc.option_at_index(1).ranges.addr, self._ranges2.addr) | |
1176 | ||
1177 | def test_at_index_invalid(self): | |
cfbd7cf3 FD |
1178 | self._fc.append_option( |
1179 | 'c', self._tc.create_signed_integer_field_class(32), self._ranges3 | |
1180 | ) | |
45c51519 PP |
1181 | |
1182 | with self.assertRaises(TypeError): | |
1183 | self._fc.option_at_index('yes') | |
1184 | ||
1185 | def test_at_index_out_of_bounds_after(self): | |
cfbd7cf3 FD |
1186 | self._fc.append_option( |
1187 | 'c', self._tc.create_signed_integer_field_class(32), self._ranges3 | |
1188 | ) | |
45c51519 PP |
1189 | |
1190 | with self.assertRaises(IndexError): | |
1191 | self._fc.option_at_index(len(self._fc)) | |
1192 | ||
1193 | def _fill_default_fc_for_field_path_test(self): | |
d47b87ac SM |
1194 | # Create something equivalent to: |
1195 | # | |
1196 | # struct outer_struct_fc { | |
1197 | # real foo; | |
1198 | # struct inner_struct_fc { | |
45c51519 | 1199 | # [u]int64_t selector; |
d47b87ac SM |
1200 | # string bar; |
1201 | # string baz; | |
45c51519 PP |
1202 | # variant <selector> { |
1203 | # real a; // selected with self._ranges1 | |
1204 | # int21_t b; // selected with self._ranges2 | |
1205 | # uint34_t c; // selected with self._ranges3 | |
d47b87ac SM |
1206 | # } variant; |
1207 | # } inner_struct[2]; | |
1208 | # }; | |
fe4df857 FD |
1209 | self._fc.append_option( |
1210 | 'a', self._tc.create_single_precision_real_field_class(), self._ranges1 | |
1211 | ) | |
cfbd7cf3 FD |
1212 | self._fc.append_option( |
1213 | 'b', self._tc.create_signed_integer_field_class(21), self._ranges2 | |
1214 | ) | |
1215 | self._fc.append_option( | |
1216 | 'c', self._tc.create_unsigned_integer_field_class(34), self._ranges3 | |
1217 | ) | |
b4f45851 | 1218 | |
fe4df857 | 1219 | foo_fc = self._tc.create_single_precision_real_field_class() |
d47b87ac SM |
1220 | bar_fc = self._tc.create_string_field_class() |
1221 | baz_fc = self._tc.create_string_field_class() | |
b4f45851 | 1222 | |
d47b87ac | 1223 | inner_struct_fc = self._tc.create_structure_field_class() |
45c51519 | 1224 | inner_struct_fc.append_member('selector', self._selector_fc) |
d47b87ac SM |
1225 | inner_struct_fc.append_member('bar', bar_fc) |
1226 | inner_struct_fc.append_member('baz', baz_fc) | |
45c51519 | 1227 | inner_struct_fc.append_member('variant', self._fc) |
b4f45851 | 1228 | |
cfbd7cf3 FD |
1229 | inner_struct_array_fc = self._tc.create_static_array_field_class( |
1230 | inner_struct_fc, 2 | |
1231 | ) | |
b4f45851 | 1232 | |
d47b87ac SM |
1233 | outer_struct_fc = self._tc.create_structure_field_class() |
1234 | outer_struct_fc.append_member('foo', foo_fc) | |
1235 | outer_struct_fc.append_member('inner_struct', inner_struct_array_fc) | |
b4f45851 | 1236 | |
d47b87ac SM |
1237 | # The path to the selector field is resolved when the sequence is |
1238 | # actually used, for example in a packet context. | |
cfbd7cf3 FD |
1239 | self._tc.create_stream_class( |
1240 | supports_packets=True, packet_context_field_class=outer_struct_fc | |
1241 | ) | |
b4f45851 | 1242 | |
d47b87ac | 1243 | def test_selector_field_path_length(self): |
45c51519 PP |
1244 | self._fill_default_fc_for_field_path_test() |
1245 | self.assertEqual(len(self._fc.selector_field_path), 3) | |
b4f45851 | 1246 | |
d47b87ac | 1247 | def test_selector_field_path_iter(self): |
45c51519 PP |
1248 | self._fill_default_fc_for_field_path_test() |
1249 | path_items = list(self._fc.selector_field_path) | |
b4f45851 | 1250 | |
d47b87ac | 1251 | self.assertEqual(len(path_items), 3) |
b4f45851 | 1252 | |
3fb99a22 | 1253 | self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem) |
d47b87ac | 1254 | self.assertEqual(path_items[0].index, 1) |
b4f45851 | 1255 | |
3fb99a22 | 1256 | self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem) |
b4f45851 | 1257 | |
3fb99a22 | 1258 | self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem) |
d47b87ac | 1259 | self.assertEqual(path_items[2].index, 0) |
b4f45851 | 1260 | |
d47b87ac | 1261 | def test_selector_field_path_root_scope(self): |
45c51519 | 1262 | self._fill_default_fc_for_field_path_test() |
cfbd7cf3 | 1263 | self.assertEqual( |
e7ceb9df | 1264 | self._fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT |
cfbd7cf3 | 1265 | ) |
45c51519 PP |
1266 | |
1267 | ||
cfbd7cf3 | 1268 | class VariantFieldClassWithUnsignedSelectorTestCase( |
fabfe034 | 1269 | _VariantFieldClassWithIntegerSelectorTestCase, unittest.TestCase |
cfbd7cf3 | 1270 | ): |
45c51519 PP |
1271 | def _spec_set_up(self): |
1272 | self._ranges1 = bt2.UnsignedIntegerRangeSet([(1, 4), (18, 47)]) | |
1273 | self._ranges2 = bt2.UnsignedIntegerRangeSet([(5, 5)]) | |
1274 | self._ranges3 = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)]) | |
1275 | self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, 16), (48, 99)]) | |
1276 | self._selector_fc = self._tc.create_unsigned_integer_field_class() | |
1277 | ||
1278 | ||
cfbd7cf3 | 1279 | class VariantFieldClassWithSignedSelectorTestCase( |
fabfe034 | 1280 | _VariantFieldClassWithIntegerSelectorTestCase, unittest.TestCase |
cfbd7cf3 | 1281 | ): |
45c51519 PP |
1282 | def _spec_set_up(self): |
1283 | self._ranges1 = bt2.SignedIntegerRangeSet([(-10, -4), (18, 47)]) | |
1284 | self._ranges2 = bt2.SignedIntegerRangeSet([(-3, -3)]) | |
1285 | self._ranges3 = bt2.SignedIntegerRangeSet([(8, 16), (48, 99)]) | |
1286 | self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)]) | |
1287 | self._selector_fc = self._tc.create_signed_integer_field_class() | |
b4f45851 | 1288 | |
d47b87ac | 1289 | |
f0a42b33 FD |
1290 | class _ArrayFieldClassTestCase: |
1291 | def test_attr_element_field_class(self): | |
1292 | fc = self._create_array() | |
1293 | self.assertIs( | |
1294 | type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClass | |
1295 | ) | |
1296 | ||
81b8fa44 PP |
1297 | |
1298 | class _ArrayFieldClassConstTestCase: | |
f0a42b33 FD |
1299 | def test_const_attr_element_field_class(self): |
1300 | fc = self._create_const_array() | |
1301 | self.assertIs( | |
1302 | type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClassConst | |
1303 | ) | |
1304 | ||
1305 | ||
81b8fa44 PP |
1306 | class StaticArrayFieldClassTestCase( |
1307 | _ArrayFieldClassTestCase, _ArrayFieldClassConstTestCase, unittest.TestCase | |
1308 | ): | |
f0a42b33 FD |
1309 | @staticmethod |
1310 | def _const_value_setter(field): | |
d47b6b4e | 1311 | field.value = [9] * 45 |
f0a42b33 FD |
1312 | |
1313 | def _create_array(self): | |
1314 | return self._tc.create_static_array_field_class(self._elem_fc, 45) | |
1315 | ||
1316 | def _create_const_array(self): | |
1317 | fc = self._tc.create_static_array_field_class(self._elem_fc, 45) | |
1318 | return _create_const_field_class(self._tc, fc, self._const_value_setter) | |
1319 | ||
d47b87ac SM |
1320 | def setUp(self): |
1321 | self._tc = get_default_trace_class() | |
1322 | self._elem_fc = self._tc.create_signed_integer_field_class(23) | |
b4f45851 SM |
1323 | |
1324 | def test_create_default(self): | |
d47b87ac SM |
1325 | fc = self._tc.create_static_array_field_class(self._elem_fc, 45) |
1326 | self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr) | |
1327 | self.assertEqual(fc.length, 45) | |
5783664e | 1328 | self.assertEqual(len(fc.user_attributes), 0) |
b4f45851 | 1329 | |
d47b87ac | 1330 | def test_create_invalid_elem_field_class(self): |
b4f45851 | 1331 | with self.assertRaises(TypeError): |
d47b87ac | 1332 | self._tc.create_static_array_field_class(object(), 45) |
b4f45851 SM |
1333 | |
1334 | def test_create_invalid_length(self): | |
1335 | with self.assertRaises(ValueError): | |
cfbd7cf3 FD |
1336 | self._tc.create_static_array_field_class( |
1337 | self._tc.create_string_field_class(), -17 | |
1338 | ) | |
b4f45851 SM |
1339 | |
1340 | def test_create_invalid_length_type(self): | |
1341 | with self.assertRaises(TypeError): | |
cfbd7cf3 FD |
1342 | self._tc.create_static_array_field_class( |
1343 | self._tc.create_string_field_class(), 'the length' | |
1344 | ) | |
d47b87ac SM |
1345 | |
1346 | ||
81b8fa44 PP |
1347 | class DynamicArrayFieldClassTestCase( |
1348 | _ArrayFieldClassTestCase, _ArrayFieldClassConstTestCase, unittest.TestCase | |
1349 | ): | |
f0a42b33 FD |
1350 | @staticmethod |
1351 | def _const_value_setter(field): | |
d47b6b4e | 1352 | field.value = [] |
f0a42b33 FD |
1353 | |
1354 | def _create_array(self): | |
1355 | return self._tc.create_dynamic_array_field_class(self._elem_fc) | |
1356 | ||
1357 | def _create_const_array(self): | |
1358 | fc = self._tc.create_dynamic_array_field_class(self._elem_fc) | |
1359 | return _create_const_field_class(self._tc, fc, self._const_value_setter) | |
1360 | ||
d47b87ac SM |
1361 | def setUp(self): |
1362 | self._tc = get_default_trace_class() | |
1363 | self._elem_fc = self._tc.create_signed_integer_field_class(23) | |
b4f45851 | 1364 | |
d47b87ac SM |
1365 | def test_create_default(self): |
1366 | fc = self._tc.create_dynamic_array_field_class(self._elem_fc) | |
1367 | self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr) | |
81b8fa44 PP |
1368 | self.assertEqual(len(fc.user_attributes), 0) |
1369 | ||
1370 | def test_create_invalid_field_class(self): | |
1371 | with self.assertRaises(TypeError): | |
1372 | self._tc.create_dynamic_array_field_class(object()) | |
1373 | ||
1374 | ||
1375 | class DynamicArrayWithLengthFieldFieldClassTestCase( | |
1376 | _ArrayFieldClassTestCase, unittest.TestCase | |
1377 | ): | |
1378 | @staticmethod | |
1379 | def _const_value_setter(field): | |
1380 | field.value = [] | |
1381 | ||
1382 | def _create_array(self): | |
1383 | return self._tc.create_dynamic_array_field_class(self._elem_fc, self._len_fc) | |
1384 | ||
1385 | def setUp(self): | |
1386 | self._tc = get_default_trace_class() | |
1387 | self._elem_fc = self._tc.create_signed_integer_field_class(23) | |
1388 | self._len_fc = self._tc.create_unsigned_integer_field_class(12) | |
1389 | ||
1390 | def test_create_default(self): | |
1391 | fc = self._create_array() | |
1392 | self.assertEqual(fc.element_field_class.addr, self._elem_fc.addr) | |
d47b87ac | 1393 | self.assertIsNone(fc.length_field_path, None) |
5783664e | 1394 | self.assertEqual(len(fc.user_attributes), 0) |
b4f45851 | 1395 | |
d47b87ac SM |
1396 | def _create_field_class_for_field_path_test(self): |
1397 | # Create something a field class that is equivalent to: | |
1398 | # | |
1399 | # struct outer_struct_fc { | |
1400 | # real foo; | |
1401 | # struct inner_struct_fc { | |
1402 | # string bar; | |
1403 | # string baz; | |
1404 | # uint12_t len; | |
1405 | # uint23_t dyn_array[len]; | |
1406 | # } inner_struct[2]; | |
1407 | # }; | |
b4f45851 | 1408 | |
81b8fa44 | 1409 | fc = self._create_array() |
b4f45851 | 1410 | |
fe4df857 | 1411 | foo_fc = self._tc.create_single_precision_real_field_class() |
d47b87ac SM |
1412 | bar_fc = self._tc.create_string_field_class() |
1413 | baz_fc = self._tc.create_string_field_class() | |
b4f45851 | 1414 | |
d47b87ac SM |
1415 | inner_struct_fc = self._tc.create_structure_field_class() |
1416 | inner_struct_fc.append_member('bar', bar_fc) | |
1417 | inner_struct_fc.append_member('baz', baz_fc) | |
1418 | inner_struct_fc.append_member('len', self._len_fc) | |
1419 | inner_struct_fc.append_member('dyn_array', fc) | |
b4f45851 | 1420 | |
cfbd7cf3 FD |
1421 | inner_struct_array_fc = self._tc.create_static_array_field_class( |
1422 | inner_struct_fc, 2 | |
1423 | ) | |
d47b87ac SM |
1424 | |
1425 | outer_struct_fc = self._tc.create_structure_field_class() | |
1426 | outer_struct_fc.append_member('foo', foo_fc) | |
1427 | outer_struct_fc.append_member('inner_struct', inner_struct_array_fc) | |
1428 | ||
1429 | # The path to the length field is resolved when the sequence is | |
1430 | # actually used, for example in a packet context. | |
cfbd7cf3 FD |
1431 | self._tc.create_stream_class( |
1432 | packet_context_field_class=outer_struct_fc, supports_packets=True | |
1433 | ) | |
d47b87ac SM |
1434 | |
1435 | return fc | |
1436 | ||
1437 | def test_field_path_len(self): | |
1438 | fc = self._create_field_class_for_field_path_test() | |
1439 | self.assertEqual(len(fc.length_field_path), 3) | |
1440 | ||
1441 | def test_field_path_iter(self): | |
1442 | fc = self._create_field_class_for_field_path_test() | |
1443 | path_items = list(fc.length_field_path) | |
1444 | ||
1445 | self.assertEqual(len(path_items), 3) | |
1446 | ||
3fb99a22 | 1447 | self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem) |
d47b87ac SM |
1448 | self.assertEqual(path_items[0].index, 1) |
1449 | ||
3fb99a22 | 1450 | self.assertIsInstance(path_items[1], bt2._CurrentArrayElementFieldPathItem) |
d47b87ac | 1451 | |
3fb99a22 | 1452 | self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem) |
d47b87ac SM |
1453 | self.assertEqual(path_items[2].index, 2) |
1454 | ||
1455 | def test_field_path_root_scope(self): | |
1456 | fc = self._create_field_class_for_field_path_test() | |
e7ceb9df PP |
1457 | self.assertEqual( |
1458 | fc.length_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT | |
1459 | ) | |
b4f45851 | 1460 | |
b4f45851 SM |
1461 | def test_create_invalid_length_type(self): |
1462 | with self.assertRaises(TypeError): | |
cfbd7cf3 FD |
1463 | self._tc.create_dynamic_array_field_class( |
1464 | self._tc.create_string_field_class(), 17 | |
1465 | ) | |
b4f45851 | 1466 | |
b4f45851 | 1467 | |
d47b87ac SM |
1468 | if __name__ == "__main__": |
1469 | unittest.main() |