2 # Copyright (C) 2019 EfficiOS Inc.
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
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.
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.
22 from utils
import get_default_trace_class
25 class _TestIntegerFieldClassProps
:
26 def test_create_default(self
):
27 fc
= self
._create
_func
()
28 self
.assertEqual(fc
.field_value_range
, 64)
29 self
.assertEqual(fc
.preferred_display_base
, bt2
.IntegerDisplayBase
.DECIMAL
)
31 def test_create_range(self
):
32 fc
= self
._create
_func
(field_value_range
=35)
33 self
.assertEqual(fc
.field_value_range
, 35)
35 fc
= self
._create
_func
(36)
36 self
.assertEqual(fc
.field_value_range
, 36)
38 def test_create_invalid_range(self
):
39 with self
.assertRaises(TypeError):
40 self
._create
_func
('yes')
42 with self
.assertRaises(TypeError):
43 self
._create
_func
(field_value_range
='yes')
45 with self
.assertRaises(ValueError):
46 self
._create
_func
(field_value_range
=-2)
48 with self
.assertRaises(ValueError):
49 self
._create
_func
(field_value_range
=0)
51 def test_create_base(self
):
52 fc
= self
._create
_func
(preferred_display_base
=bt2
.IntegerDisplayBase
.HEXADECIMAL
)
53 self
.assertEqual(fc
.preferred_display_base
, bt2
.IntegerDisplayBase
.HEXADECIMAL
)
55 def test_create_invalid_base_type(self
):
56 with self
.assertRaises(TypeError):
57 self
._create
_func
(preferred_display_base
='yes')
59 def test_create_invalid_base_value(self
):
60 with self
.assertRaises(ValueError):
61 self
._create
_func
(preferred_display_base
=444)
63 def test_create_full(self
):
64 fc
= self
._create
_func
(24, preferred_display_base
=bt2
.IntegerDisplayBase
.OCTAL
)
65 self
.assertEqual(fc
.field_value_range
, 24)
66 self
.assertEqual(fc
.preferred_display_base
, bt2
.IntegerDisplayBase
.OCTAL
)
69 class IntegerFieldClassTestCase(_TestIntegerFieldClassProps
, unittest
.TestCase
):
71 self
._tc
= get_default_trace_class()
72 self
._create
_func
= self
._tc
.create_signed_integer_field_class
75 class RealFieldClassTestCase(unittest
.TestCase
):
77 self
._tc
= get_default_trace_class()
79 def test_create_default(self
):
80 fc
= self
._tc
.create_real_field_class()
81 self
.assertFalse(fc
.is_single_precision
)
83 def test_create_is_single_precision(self
):
84 fc
= self
._tc
.create_real_field_class(is_single_precision
=True)
85 self
.assertTrue(fc
.is_single_precision
)
87 def test_create_invalid_is_single_precision(self
):
88 with self
.assertRaises(TypeError):
89 self
._tc
.create_real_field_class(is_single_precision
='hohoho')
92 # Converts an _EnumerationFieldClassMapping to a list of ranges:
94 # [(lower0, upper0), (lower1, upper1), ...]
96 def enum_mapping_to_list(mapping
):
97 return sorted([(x
.lower
, x
.upper
) for x
in mapping
])
100 class EnumerationFieldClassTestCase(_TestIntegerFieldClassProps
):
102 self
._tc
= get_default_trace_class()
104 def test_create_from_invalid_type(self
):
105 with self
.assertRaises(TypeError):
106 self
._create
_func
('coucou')
108 def test_add_mapping_simple(self
):
109 self
._fc
.map_range('hello', 24)
110 mapping
= self
._fc
['hello']
111 self
.assertEqual(mapping
.label
, 'hello')
113 ranges
= enum_mapping_to_list(mapping
)
114 self
.assertEqual(ranges
, [(24, 24)])
116 def test_add_mapping_simple_kwargs(self
):
117 self
._fc
.map_range(label
='hello', lower
=17, upper
=23)
118 mapping
= self
._fc
['hello']
119 self
.assertEqual(mapping
.label
, 'hello')
121 ranges
= enum_mapping_to_list(mapping
)
122 self
.assertEqual(ranges
, [(17, 23)])
124 def test_add_mapping_range(self
):
125 self
._fc
.map_range('hello', 21, 199)
126 mapping
= self
._fc
['hello']
127 self
.assertEqual(mapping
.label
, 'hello')
129 ranges
= enum_mapping_to_list(mapping
)
130 self
.assertEqual(ranges
, [(21, 199)])
132 def test_add_mapping_invalid_name(self
):
133 with self
.assertRaises(TypeError):
134 self
._fc
.map_range(17, 21, 199)
137 enum_fc
= self
._tc
.create_signed_enumeration_field_class(field_value_range
=16)
138 enum_fc
.map_range('c', 4, 5)
139 enum_fc
.map_range('d', 6, 18)
140 enum_fc
.map_range('e', 20, 27)
141 self
._fc
.map_range('a', 0, 2)
142 self
._fc
.map_range('b', 3)
145 self
.assertEqual(self
._fc
['a'].label
, 'a')
146 self
.assertEqual(enum_mapping_to_list(self
._fc
['a']), [(0, 2)])
148 self
.assertEqual(self
._fc
['b'].label
, 'b')
149 self
.assertEqual(enum_mapping_to_list(self
._fc
['b']), [(3, 3)])
151 self
.assertEqual(self
._fc
['c'].label
, 'c')
152 self
.assertEqual(enum_mapping_to_list(self
._fc
['c']), [(4, 5)])
154 self
.assertEqual(self
._fc
['d'].label
, 'd')
155 self
.assertEqual(enum_mapping_to_list(self
._fc
['d']), [(6, 18)])
157 self
.assertEqual(self
._fc
['e'].label
, 'e')
158 self
.assertEqual(enum_mapping_to_list(self
._fc
['e']), [(20, 27)])
160 def test_bool_op(self
):
161 self
.assertFalse(self
._fc
)
162 self
._fc
.map_range('a', 0)
163 self
.assertTrue(self
._fc
)
166 self
._fc
.map_range('a', 0)
167 self
._fc
.map_range('b', 1)
168 self
._fc
.map_range('c', 2)
169 self
.assertEqual(len(self
._fc
), 3)
171 def test_getitem(self
):
172 self
._fc
.map_range('a', 0)
173 self
._fc
.map_range('b', 1, 3)
174 self
._fc
.map_range('a', 5)
175 self
._fc
.map_range('a', 17, 123)
176 self
._fc
.map_range('C', 5)
177 mapping
= self
._fc
['a']
179 self
.assertEqual(mapping
.label
, 'a')
180 ranges
= enum_mapping_to_list(mapping
)
181 self
.assertEqual(ranges
, [(0, 0), (5, 5), (17, 123)])
183 with self
.assertRaises(KeyError):
184 self
._fc
['doesnotexist']
186 def test_contains(self
):
187 self
._fc
.map_range('a', 0)
188 self
._fc
.map_range('a', 2, 23)
189 self
._fc
.map_range('b', 2)
190 self
._fc
.map_range('c', 5)
192 a_mapping
= self
._fc
['a']
193 b_mapping
= self
._fc
['b']
194 first_range
= next(iter(a_mapping
))
196 self
.assertIn(first_range
, a_mapping
)
197 self
.assertNotIn(first_range
, b_mapping
)
200 self
._fc
.map_range('a', 1, 5)
201 self
._fc
.map_range('b', 10, 17)
202 self
._fc
.map_range('c', 20, 1504)
204 self
._fc
.map_range('d', 22510, 99999)
206 # This exercises iteration.
207 labels
= sorted(self
._fc
)
209 self
.assertEqual(labels
, ['a', 'b', 'c', 'd'])
211 def test_find_by_value(self
):
212 self
._fc
.map_range('a', 0)
213 self
._fc
.map_range('b', 1, 3)
214 self
._fc
.map_range('c', 5, 19)
215 self
._fc
.map_range('d', 8, 15)
216 self
._fc
.map_range('e', 10, 21)
217 self
._fc
.map_range('f', 0)
218 self
._fc
.map_range('g', 14)
220 labels
= self
._fc
.labels_by_value(14)
222 expected_labels
= ['c', 'd', 'e', 'g']
224 self
.assertTrue(all(label
in labels
for label
in expected_labels
))
227 class UnsignedEnumerationFieldClassTestCase(EnumerationFieldClassTestCase
, unittest
.TestCase
):
230 self
._create
_func
= self
._tc
.create_unsigned_enumeration_field_class
231 self
._fc
= self
._tc
.create_unsigned_enumeration_field_class()
233 def test_add_mapping_invalid_signedness_lower(self
):
234 with self
.assertRaises(ValueError):
235 self
._fc
.map_range('hello', -21, 199)
237 def test_add_mapping_invalid_signedness_upper(self
):
238 with self
.assertRaises(ValueError):
239 self
._fc
.map_range('hello', 21, -199)
242 class SignedEnumerationFieldClassTestCase(EnumerationFieldClassTestCase
, unittest
.TestCase
):
245 self
._create
_func
= self
._tc
.create_signed_enumeration_field_class
246 self
._fc
= self
._tc
.create_signed_enumeration_field_class()
248 def test_add_mapping_simple_signed(self
):
249 self
._fc
.map_range('hello', -24)
250 mapping
= self
._fc
['hello']
251 self
.assertEqual(mapping
.label
, 'hello')
253 ranges
= enum_mapping_to_list(mapping
)
254 self
.assertEqual(ranges
, [(-24, -24)])
256 def test_add_mapping_range_signed(self
):
257 self
._fc
.map_range('hello', -21, 199)
258 mapping
= self
._fc
['hello']
259 self
.assertEqual(mapping
.label
, 'hello')
260 ranges
= enum_mapping_to_list(mapping
)
261 self
.assertEqual(ranges
, [(-21, 199)])
264 class StringFieldClassTestCase(unittest
.TestCase
):
266 tc
= get_default_trace_class()
267 self
._fc
= tc
.create_string_field_class()
269 def test_create_default(self
):
270 self
.assertIsNotNone(self
._fc
)
273 class _TestFieldContainer():
274 def test_append_element(self
):
275 int_field_class
= self
._tc
.create_signed_integer_field_class(32)
276 self
._append
_element
_method
(self
._fc
, 'int32', int_field_class
)
277 field_class
= self
._fc
['int32']
278 self
.assertEqual(field_class
.addr
, int_field_class
.addr
)
280 def test_append_elemenbt_kwargs(self
):
281 int_field_class
= self
._tc
.create_signed_integer_field_class(32)
282 self
._append
_element
_method
(self
._fc
, name
='int32', field_class
=int_field_class
)
283 field_class
= self
._fc
['int32']
284 self
.assertEqual(field_class
.addr
, int_field_class
.addr
)
286 def test_append_element_invalid_name(self
):
287 sub_fc
= self
._tc
.create_string_field_class()
289 with self
.assertRaises(TypeError):
290 self
._append
_element
_method
(self
._fc
, 23, sub_fc
)
292 def test_append_element_invalid_field_class(self
):
293 with self
.assertRaises(TypeError):
294 self
._append
_element
_method
(self
._fc
, 'yes', object())
297 struct_fc
= self
._tc
.create_structure_field_class()
298 c_field_class
= self
._tc
.create_string_field_class()
299 d_field_class
= self
._tc
.create_signed_enumeration_field_class(field_value_range
=32)
300 e_field_class
= self
._tc
.create_structure_field_class()
301 self
._append
_element
_method
(struct_fc
, 'c_string', c_field_class
)
302 self
._append
_element
_method
(struct_fc
, 'd_enum', d_field_class
)
303 self
._append
_element
_method
(struct_fc
, 'e_struct', e_field_class
)
304 a_field_class
= self
._tc
.create_real_field_class()
305 b_field_class
= self
._tc
.create_signed_integer_field_class(17)
306 self
._append
_element
_method
(self
._fc
, 'a_float', a_field_class
)
307 self
._append
_element
_method
(self
._fc
, 'b_int', b_field_class
)
308 self
._fc
+= struct_fc
309 self
.assertEqual(self
._fc
['a_float'].addr
, a_field_class
.addr
)
310 self
.assertEqual(self
._fc
['b_int'].addr
, b_field_class
.addr
)
311 self
.assertEqual(self
._fc
['c_string'].addr
, c_field_class
.addr
)
312 self
.assertEqual(self
._fc
['d_enum'].addr
, d_field_class
.addr
)
313 self
.assertEqual(self
._fc
['e_struct'].addr
, e_field_class
.addr
)
315 def test_bool_op(self
):
316 self
.assertFalse(self
._fc
)
317 self
._append
_element
_method
(self
._fc
, 'a', self
._tc
.create_string_field_class())
318 self
.assertTrue(self
._fc
)
321 fc
= self
._tc
.create_string_field_class()
322 self
._append
_element
_method
(self
._fc
, 'a', fc
)
323 self
._append
_element
_method
(self
._fc
, 'b', fc
)
324 self
._append
_element
_method
(self
._fc
, 'c', fc
)
325 self
.assertEqual(len(self
._fc
), 3)
327 def test_getitem(self
):
328 a_fc
= self
._tc
.create_signed_integer_field_class(32)
329 b_fc
= self
._tc
.create_string_field_class()
330 c_fc
= self
._tc
.create_real_field_class()
331 self
._append
_element
_method
(self
._fc
, 'a', a_fc
)
332 self
._append
_element
_method
(self
._fc
, 'b', b_fc
)
333 self
._append
_element
_method
(self
._fc
, 'c', c_fc
)
334 self
.assertEqual(self
._fc
['b'].addr
, b_fc
.addr
)
336 def test_getitem_invalid_key_type(self
):
337 with self
.assertRaises(TypeError):
340 def test_getitem_invalid_key(self
):
341 with self
.assertRaises(KeyError):
344 def test_contains(self
):
345 self
.assertFalse('a' in self
._fc
)
346 self
._append
_element
_method
(self
._fc
, 'a', self
._tc
.create_string_field_class())
347 self
.assertTrue('a' in self
._fc
)
350 a_fc
= self
._tc
.create_signed_integer_field_class(32)
351 b_fc
= self
._tc
.create_string_field_class()
352 c_fc
= self
._tc
.create_real_field_class()
360 self
._append
_element
_method
(self
._fc
, *field
)
362 for (name
, fc_field_class
), field
in zip(self
._fc
.items(), fields
):
363 self
.assertEqual(name
, field
[0])
364 self
.assertEqual(fc_field_class
.addr
, field
[1].addr
)
366 def test_at_index(self
):
367 a_fc
= self
._tc
.create_signed_integer_field_class(32)
368 b_fc
= self
._tc
.create_string_field_class()
369 c_fc
= self
._tc
.create_real_field_class()
370 self
._append
_element
_method
(self
._fc
, 'c', c_fc
)
371 self
._append
_element
_method
(self
._fc
, 'a', a_fc
)
372 self
._append
_element
_method
(self
._fc
, 'b', b_fc
)
373 self
.assertEqual(self
._at
_index
_method
(self
._fc
, 1).addr
, a_fc
.addr
)
375 def test_at_index_invalid(self
):
376 self
._append
_element
_method
(self
._fc
, 'c', self
._tc
.create_signed_integer_field_class(32))
378 with self
.assertRaises(TypeError):
379 self
._at
_index
_method
(self
._fc
, 'yes')
381 def test_at_index_out_of_bounds_after(self
):
382 self
._append
_element
_method
(self
._fc
, 'c', self
._tc
.create_signed_integer_field_class(32))
384 with self
.assertRaises(IndexError):
385 self
._at
_index
_method
(self
._fc
, len(self
._fc
))
388 class StructureFieldClassTestCase(_TestFieldContainer
, unittest
.TestCase
):
390 self
._append
_element
_method
= bt2
.field_class
._StructureFieldClass
.append_member
391 self
._at
_index
_method
= bt2
.field_class
._StructureFieldClass
.member_at_index
392 self
._tc
= get_default_trace_class()
393 self
._fc
= self
._tc
.create_structure_field_class()
395 def test_create_default(self
):
396 self
.assertIsNotNone(self
._fc
)
399 class VariantFieldClassTestCase(_TestFieldContainer
, unittest
.TestCase
):
401 self
._append
_element
_method
= bt2
.field_class
._VariantFieldClass
.append_option
402 self
._at
_index
_method
= bt2
.field_class
._VariantFieldClass
.option_at_index
403 self
._tc
= get_default_trace_class()
404 self
._fc
= self
._tc
.create_variant_field_class()
406 def test_create_default(self
):
407 fc
= self
._tc
.create_variant_field_class()
409 self
.assertIsNone(fc
.selector_field_path
)
411 def _create_field_class_for_field_path_test(self
):
412 # Create something equivalent to:
414 # struct outer_struct_fc {
416 # struct inner_struct_fc {
417 # enum { first = 1, second = 2..434 } selector;
420 # variant<selector> {
427 selector_fc
= self
._tc
.create_unsigned_enumeration_field_class(field_value_range
=42)
428 selector_fc
.map_range('first', 1)
429 selector_fc
.map_range('second', 2, 434)
431 fc
= self
._tc
.create_variant_field_class(selector_fc
)
432 fc
.append_option('a', self
._tc
.create_real_field_class())
433 fc
.append_option('b', self
._tc
.create_signed_integer_field_class(21))
434 fc
.append_option('c', self
._tc
.create_unsigned_integer_field_class(34))
436 foo_fc
= self
._tc
.create_real_field_class()
437 bar_fc
= self
._tc
.create_string_field_class()
438 baz_fc
= self
._tc
.create_string_field_class()
440 inner_struct_fc
= self
._tc
.create_structure_field_class()
441 inner_struct_fc
.append_member('selector', selector_fc
)
442 inner_struct_fc
.append_member('bar', bar_fc
)
443 inner_struct_fc
.append_member('baz', baz_fc
)
444 inner_struct_fc
.append_member('variant', fc
)
446 inner_struct_array_fc
= self
._tc
.create_static_array_field_class(inner_struct_fc
, 2)
448 outer_struct_fc
= self
._tc
.create_structure_field_class()
449 outer_struct_fc
.append_member('foo', foo_fc
)
450 outer_struct_fc
.append_member('inner_struct', inner_struct_array_fc
)
452 # The path to the selector field is resolved when the sequence is
453 # actually used, for example in a packet context.
454 self
._tc
.create_stream_class(packet_context_field_class
=outer_struct_fc
)
458 def test_selector_field_path_length(self
):
459 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
460 self
.assertEqual(len(fc
.selector_field_path
), 3)
462 def test_selector_field_path_iter(self
):
463 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
464 path_items
= list(fc
.selector_field_path
)
466 self
.assertEqual(len(path_items
), 3)
468 self
.assertIsInstance(path_items
[0], bt2
.field_path
._IndexFieldPathItem
)
469 self
.assertEqual(path_items
[0].index
, 1)
471 self
.assertIsInstance(path_items
[1], bt2
.field_path
._CurrentArrayElementFieldPathItem
)
473 self
.assertIsInstance(path_items
[2], bt2
.field_path
._IndexFieldPathItem
)
474 self
.assertEqual(path_items
[2].index
, 0)
476 def test_selector_field_path_root_scope(self
):
477 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
478 self
.assertEqual(fc
.selector_field_path
.root_scope
, bt2
.field_path
.Scope
.PACKET_CONTEXT
)
481 class StaticArrayFieldClassTestCase(unittest
.TestCase
):
483 self
._tc
= get_default_trace_class()
484 self
._elem
_fc
= self
._tc
.create_signed_integer_field_class(23)
486 def test_create_default(self
):
487 fc
= self
._tc
.create_static_array_field_class(self
._elem
_fc
, 45)
488 self
.assertEqual(fc
.element_field_class
.addr
, self
._elem
_fc
.addr
)
489 self
.assertEqual(fc
.length
, 45)
491 def test_create_invalid_elem_field_class(self
):
492 with self
.assertRaises(TypeError):
493 self
._tc
.create_static_array_field_class(object(), 45)
495 def test_create_invalid_length(self
):
496 with self
.assertRaises(ValueError):
497 self
._tc
.create_static_array_field_class(self
._tc
.create_string_field_class(), -17)
499 def test_create_invalid_length_type(self
):
500 with self
.assertRaises(TypeError):
501 self
._tc
.create_static_array_field_class(self
._tc
.create_string_field_class(), 'the length')
504 class DynamicArrayFieldClassTestCase(unittest
.TestCase
):
506 self
._tc
= get_default_trace_class()
507 self
._elem
_fc
= self
._tc
.create_signed_integer_field_class(23)
508 self
._len
_fc
= self
._tc
.create_unsigned_integer_field_class(12)
510 def test_create_default(self
):
511 fc
= self
._tc
.create_dynamic_array_field_class(self
._elem
_fc
)
512 self
.assertEqual(fc
.element_field_class
.addr
, self
._elem
_fc
.addr
)
513 self
.assertIsNone(fc
.length_field_path
, None)
515 def _create_field_class_for_field_path_test(self
):
516 # Create something a field class that is equivalent to:
518 # struct outer_struct_fc {
520 # struct inner_struct_fc {
524 # uint23_t dyn_array[len];
528 fc
= self
._tc
.create_dynamic_array_field_class(self
._elem
_fc
, self
._len
_fc
)
530 foo_fc
= self
._tc
.create_real_field_class()
531 bar_fc
= self
._tc
.create_string_field_class()
532 baz_fc
= self
._tc
.create_string_field_class()
534 inner_struct_fc
= self
._tc
.create_structure_field_class()
535 inner_struct_fc
.append_member('bar', bar_fc
)
536 inner_struct_fc
.append_member('baz', baz_fc
)
537 inner_struct_fc
.append_member('len', self
._len
_fc
)
538 inner_struct_fc
.append_member('dyn_array', fc
)
540 inner_struct_array_fc
= self
._tc
.create_static_array_field_class(inner_struct_fc
, 2)
542 outer_struct_fc
= self
._tc
.create_structure_field_class()
543 outer_struct_fc
.append_member('foo', foo_fc
)
544 outer_struct_fc
.append_member('inner_struct', inner_struct_array_fc
)
546 # The path to the length field is resolved when the sequence is
547 # actually used, for example in a packet context.
548 self
._tc
.create_stream_class(packet_context_field_class
=outer_struct_fc
)
552 def test_field_path_len(self
):
553 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
554 self
.assertEqual(len(fc
.length_field_path
), 3)
556 def test_field_path_iter(self
):
557 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
558 path_items
= list(fc
.length_field_path
)
560 self
.assertEqual(len(path_items
), 3)
562 self
.assertIsInstance(path_items
[0], bt2
.field_path
._IndexFieldPathItem
)
563 self
.assertEqual(path_items
[0].index
, 1)
565 self
.assertIsInstance(path_items
[1], bt2
.field_path
._CurrentArrayElementFieldPathItem
)
567 self
.assertIsInstance(path_items
[2], bt2
.field_path
._IndexFieldPathItem
)
568 self
.assertEqual(path_items
[2].index
, 2)
570 def test_field_path_root_scope(self
):
571 fc
= self
._create
_field
_class
_for
_field
_path
_test
()
572 self
.assertEqual(fc
.length_field_path
.root_scope
, bt2
.field_path
.Scope
.PACKET_CONTEXT
)
574 def test_create_invalid_field_class(self
):
575 with self
.assertRaises(TypeError):
576 self
._tc
.create_dynamic_array_field_class(object())
578 def test_create_invalid_length_type(self
):
579 with self
.assertRaises(TypeError):
580 self
._tc
.create_dynamic_array_field_class(self
._tc
.create_string_field_class(), 17)
583 if __name__
== "__main__":