from bt2.field import _SignedEnumerationField
from bt2.field import _StringField
from bt2.field import _StructureField
+from bt2.field import _OptionField
from bt2.field import _VariantField
from bt2.field import _ArrayField
from bt2.field import _StaticArrayField
from bt2.field_class import _SignedEnumerationFieldClass
from bt2.field_class import _StringFieldClass
from bt2.field_class import _StructureFieldClass
+from bt2.field_class import _OptionFieldClass
from bt2.field_class import _VariantFieldClass
from bt2.field_class import _VariantFieldClassWithoutSelector
from bt2.field_class import _VariantFieldClassWithSelector
from bt2.field_path import FieldPathScope
from bt2.field_path import _IndexFieldPathItem
from bt2.field_path import _CurrentArrayElementFieldPathItem
+from bt2.field_path import _CurrentOptionContentFieldPathItem
from bt2.graph import Graph
from bt2.integer_range_set import SignedIntegerRange
from bt2.integer_range_set import UnsignedIntegerRange
return field
-# Get the "effective" field of `field`. If `field` is a variant, return the
-# currently selected field. If `field` is of any other type, return `field`
+# Get the "effective" field of `field`. If `field` is a variant, return
+# the currently selected field. If `field` is an option, return the
+# content field. If `field` is of any other type, return `field`
# directly.
def _get_leaf_field(field):
- if not isinstance(field, _VariantField):
- return field
+ if isinstance(field, _VariantField):
+ return _get_leaf_field(field.selected_option)
- return _get_leaf_field(field.selected_option)
+ if isinstance(field, _OptionField):
+ return _get_leaf_field(field.field)
+
+ return field
class _Field(object._UniqueObject):
)
+class _OptionField(_Field):
+ _NAME = 'Option'
+
+ @property
+ def field(self):
+ field_ptr = native_bt.field_option_borrow_field_const(self._ptr)
+
+ if field_ptr is None:
+ return
+
+ return _create_field_from_ptr(
+ field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
+ )
+
+ @property
+ def has_field(self):
+ return self.field is not None
+
+ @has_field.setter
+ def has_field(self, value):
+ utils._check_bool(value)
+ native_bt.field_option_set_has_field(self._ptr, value)
+
+ def _spec_eq(self, other):
+ return _get_leaf_field(self) == other
+
+ def __bool__(self):
+ return self.has_field
+
+ def __str__(self):
+ return str(self.field)
+
+ def _repr(self):
+ return repr(self.field)
+
+ def _set_value(self, value):
+ self.has_field = True
+ field = self.field
+ assert field is not None
+ field.value = value
+
+ value = property(fset=_set_value)
+
+
class _VariantField(_ContainerField, _Field):
_NAME = 'Variant'
native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureField,
native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayField,
native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayField,
+ native_bt.FIELD_CLASS_TYPE_OPTION: _OptionField,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantField,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantField,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantField,
return self._create_member_from_ptr(member_ptr)
+class _OptionFieldClass(_FieldClass):
+ @property
+ def field_class(self):
+ elem_fc_ptr = native_bt.field_class_option_borrow_field_class_const(self._ptr)
+ return _create_field_class_from_ptr_and_get_ref(elem_fc_ptr)
+
+ @property
+ def selector_field_path(self):
+ ptr = native_bt.field_class_option_borrow_selector_field_path_const(self._ptr)
+ if ptr is None:
+ return
+
+ return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
+
+
class _VariantFieldClassOption:
def __init__(self, name, field_class):
self._name = name
native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldClass,
native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldClass,
native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayFieldClass,
+ native_bt.FIELD_CLASS_TYPE_OPTION: _OptionFieldClass,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldClassWithoutSelector,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantFieldClassWithUnsignedSelector,
native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantFieldClassWithSignedSelector,
pass
+class _CurrentOptionContentFieldPathItem(_FieldPathItem):
+ pass
+
+
class _FieldPath(object._SharedObject, collections.abc.Iterable):
_get_ref = staticmethod(native_bt.field_path_get_ref)
_put_ref = staticmethod(native_bt.field_path_put_ref)
yield _IndexFieldPathItem(idx)
elif item_type == native_bt.FIELD_PATH_ITEM_TYPE_CURRENT_ARRAY_ELEMENT:
yield _CurrentArrayElementFieldPathItem()
+ elif item_type == native_bt.FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT:
+ yield _CurrentOptionContentFieldPathItem()
else:
assert False
self._check_field_class_create_status(ptr, 'dynamic array')
return bt2_field_class._DynamicArrayFieldClass._create_from_ptr(ptr)
+ def create_option_field_class(self, content_fc, selector_fc=None):
+ utils._check_type(content_fc, bt2_field_class._FieldClass)
+
+ selector_fc_ptr = None
+
+ if selector_fc is not None:
+ utils._check_type(selector_fc, bt2_field_class._BoolFieldClass)
+ selector_fc_ptr = selector_fc._ptr
+
+ ptr = native_bt.field_class_option_create(
+ self._ptr, content_fc._ptr, selector_fc_ptr
+ )
+ self._check_field_class_create_status(ptr, 'option')
+ return bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
+
def create_variant_field_class(self, selector_fc=None):
selector_fc_ptr = None
case BT_FIELD_CLASS_TYPE_OPTION:
{
struct bt_field_class_option *opt_fc = (void *) fc;
-
struct bt_field_path_item item = {
.type = BT_FIELD_PATH_ITEM_TYPE_CURRENT_OPTION_CONTENT,
.index = UINT64_C(-1),
self.assertTrue(expected_string_found)
+class OptionFieldTestCase(unittest.TestCase):
+ def _create_fc(self, tc):
+ fc = tc.create_option_field_class(tc.create_string_field_class())
+ top_fc = tc.create_structure_field_class()
+ top_fc.append_member('opt_field', fc)
+ return top_fc
+
+ def setUp(self):
+ self._tc = get_default_trace_class()
+ fld = _create_field(self._tc, self._create_fc(self._tc))
+ self._def = fld['opt_field']
+
+ def test_value_prop(self):
+ self._def.value = 'hiboux'
+ self.assertEqual(self._def.field, 'hiboux')
+ self.assertTrue(self._def.has_field)
+
+ def test_has_field_prop_true(self):
+ self._def.has_field = True
+ self.assertTrue(self._def.has_field)
+
+ def test_has_field_prop_true(self):
+ self._def.has_field = False
+ self.assertFalse(self._def.has_field)
+
+ def test_bool_op_true(self):
+ self._def.value = 'allo'
+ self.assertTrue(self._def)
+
+ def test_bool_op_true(self):
+ self._def.has_field = False
+ self.assertFalse(self._def)
+
+ def test_field_prop_existing(self):
+ self._def.value = 'meow'
+ field = self._def.field
+ self.assertEqual(field, 'meow')
+
+ def test_field_prop_none(self):
+ self._def.has_field = False
+ field = self._def.field
+ self.assertIsNone(field)
+
+ def test_field_prop_existing_then_none(self):
+ self._def.value = 'meow'
+ field = self._def.field
+ self.assertEqual(field, 'meow')
+ self._def.has_field = False
+ field = self._def.field
+ self.assertIsNone(field)
+
+ def test_eq(self):
+ field = _create_field(self._tc, self._create_fc(self._tc))
+ field = field['opt_field']
+ field.value = 'walk'
+ self._def.value = 'walk'
+ self.assertEqual(self._def, field)
+
+ def test_eq_invalid_type(self):
+ self._def.value = 'gerry'
+ self.assertNotEqual(self._def, 23)
+
+ def test_str_op(self):
+ self._def.value = 'marcel'
+ self.assertEqual(str(self._def), str(self._def.field))
+
+ def test_repr_op(self):
+ self._def.value = 'mireille'
+ self.assertEqual(repr(self._def), repr(self._def.field))
+
+
class VariantFieldTestCase(unittest.TestCase):
def _create_fc(self, tc):
ft0 = tc.create_signed_integer_field_class(32)
return self._tc.create_structure_field_class()
+class OptionFieldClassTestCase(unittest.TestCase):
+ def setUp(self):
+ self._tc = get_default_trace_class()
+ self._content_fc = self._tc.create_signed_integer_field_class(23)
+ self._tag_fc = self._tc.create_bool_field_class()
+
+ def test_create_default(self):
+ fc = self._tc.create_option_field_class(self._content_fc)
+ self.assertEqual(fc.field_class.addr, self._content_fc.addr)
+ self.assertIsNone(fc.selector_field_path, None)
+
+ def _create_field_class_for_field_path_test(self):
+ fc = self._tc.create_option_field_class(self._content_fc, self._tag_fc)
+
+ foo_fc = self._tc.create_real_field_class()
+ bar_fc = self._tc.create_string_field_class()
+ baz_fc = self._tc.create_string_field_class()
+
+ inner_struct_fc = self._tc.create_structure_field_class()
+ inner_struct_fc.append_member('bar', bar_fc)
+ inner_struct_fc.append_member('baz', baz_fc)
+ inner_struct_fc.append_member('tag', self._tag_fc)
+ inner_struct_fc.append_member('opt', fc)
+
+ opt_struct_array_fc = self._tc.create_option_field_class(inner_struct_fc)
+
+ outer_struct_fc = self._tc.create_structure_field_class()
+ outer_struct_fc.append_member('foo', foo_fc)
+ outer_struct_fc.append_member('inner_opt', opt_struct_array_fc)
+
+ # The path to the selector field class is resolved when the
+ # option field class is actually used, for example in a packet
+ # context.
+ self._tc.create_stream_class(
+ packet_context_field_class=outer_struct_fc, supports_packets=True
+ )
+
+ return fc
+
+ def test_field_path_len(self):
+ fc = self._create_field_class_for_field_path_test()
+ self.assertEqual(len(fc.selector_field_path), 3)
+
+ def test_field_path_iter(self):
+ fc = self._create_field_class_for_field_path_test()
+ path_items = list(fc.selector_field_path)
+
+ self.assertEqual(len(path_items), 3)
+
+ self.assertIsInstance(path_items[0], bt2._IndexFieldPathItem)
+ self.assertEqual(path_items[0].index, 1)
+
+ self.assertIsInstance(path_items[1], bt2._CurrentOptionContentFieldPathItem)
+
+ self.assertIsInstance(path_items[2], bt2._IndexFieldPathItem)
+ self.assertEqual(path_items[2].index, 2)
+
+ def test_field_path_root_scope(self):
+ fc = self._create_field_class_for_field_path_test()
+ self.assertEqual(
+ fc.selector_field_path.root_scope, bt2.FieldPathScope.PACKET_CONTEXT
+ )
+
+ def test_create_invalid_field_class(self):
+ with self.assertRaises(TypeError):
+ self._tc.create_option_field_class(object())
+
+ def test_create_invalid_selector_type(self):
+ with self.assertRaises(TypeError):
+ self._tc.create_option_field_class(self._content_fc, 17)
+
+
class VariantFieldClassWithoutSelectorTestCase(
_TestElementContainer, unittest.TestCase
):
def test_has__StructureField(self):
self._assert_in_bt2('_StructureField')
+ def test_has__OptionField(self):
+ self._assert_in_bt2('_VariantField')
+
def test_has__VariantField(self):
self._assert_in_bt2('_VariantField')
def test_has__StructureFieldClass(self):
self._assert_in_bt2('_StructureFieldClass')
+ def test_has__OptionFieldClass(self):
+ self._assert_in_bt2('_OptionFieldClass')
+
def test_has__VariantFieldClass(self):
self._assert_in_bt2('_VariantFieldClass')
def test_has__CurrentArrayElementFieldPathItem(self):
self._assert_in_bt2('_CurrentArrayElementFieldPathItem')
+ def test_has__CurrentOptionContentFieldPathItem(self):
+ self._assert_in_bt2('_CurrentOptionContentFieldPathItem')
+
def test_has_ComponentDescriptor(self):
self._assert_in_bt2('ComponentDescriptor')