"""Test that lldb recognizes enum structs emitted by Rust compiler """ import logging import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from RustEnumValue import RustEnumValue class TestRustEnumStructs(TestBase): def setUp(self): TestBase.setUp(self) src_dir = self.getSourceDir() yaml_path = os.path.join(src_dir, "main.yaml") obj_path = self.getBuildArtifact("main.o") self.yaml2obj(yaml_path, obj_path) self.dbg.CreateTarget(obj_path) def getFromGlobal(self, name): values = self.target().FindGlobalVariables(name, 1) self.assertEqual(values.GetSize(), 1) return RustEnumValue(values[0]) def test_clike_enums_are_represented_correctly(self): # these type of enums are not using DW_TAG_variant_part. all_values = [ self.target().FindFirstGlobalVariable("CLIKE_DEFAULT_A").GetValue(), self.target().FindFirstGlobalVariable("CLIKE_DEFAULT_B").GetValue(), self.target().FindFirstGlobalVariable("CLIKE_U8_A").GetValue(), self.target().FindFirstGlobalVariable("CLIKE_U8_C").GetValue(), self.target().FindFirstGlobalVariable("CLIKE_U32_A").GetValue(), self.target().FindFirstGlobalVariable("CLIKE_U32_B").GetValue(), ] self.assertEqual(all_values, ['A', 'B', 'VariantA', 'VariantC', 'VariantA', 'VariantB']) def test_enum_with_tuples_has_all_variants(self): self.assertEqual(self.getFromGlobal("ENUM_WITH_TUPLES_A").getAllVariantTypes(), ['main::EnumWithTuples::A:8', 'main::EnumWithTuples::B:8', 'main::EnumWithTuples::C:8', 'main::EnumWithTuples::D:8', 'main::EnumWithTuples::AA:8', 'main::EnumWithTuples::BB:8', 'main::EnumWithTuples::BC:8', 'main::EnumWithTuples::CC:8']) def test_enum_with_tuples_values_are_correct_a(self): # static ENUM_WITH_TUPLES_A: EnumWithTuples = EnumWithTuples::A(13); self.assertEqual( self.getFromGlobal("ENUM_WITH_TUPLES_A").getCurrentValue().GetChildAtIndex(0).GetData().GetUnsignedInt8( lldb.SBError(), 0), 13) def test_enum_with_tuples_values_are_correct_aa(self): # static ENUM_WITH_TUPLES_AA: EnumWithTuples = EnumWithTuples::AA(13, 37); value = self.getFromGlobal("ENUM_WITH_TUPLES_AA").getCurrentValue() self.assertEqual( (value.GetChildAtIndex(0).GetData().GetUnsignedInt8( lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt8( lldb.SBError(), 0)), (13, 37)) def test_enum_with_tuples_values_are_correct_b(self): # static ENUM_WITH_TUPLES_B: EnumWithTuples = EnumWithTuples::B(37); self.assertEqual( self.getFromGlobal("ENUM_WITH_TUPLES_B").getCurrentValue().GetChildAtIndex(0).GetData().GetUnsignedInt16( lldb.SBError(), 0), 37) def test_enum_with_tuples_values_are_correct_bb(self): # static ENUM_WITH_TUPLES_BB: EnumWithTuples = EnumWithTuples::BB(37, 5535); value = self.getFromGlobal("ENUM_WITH_TUPLES_BB").getCurrentValue() self.assertEqual( (value.GetChildAtIndex(0).GetData().GetUnsignedInt16(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt16(lldb.SBError(), 0)), (37, 5535)) def test_enum_with_tuples_values_are_correct_bc(self): # static ENUM_WITH_TUPLES_BC: EnumWithTuples = EnumWithTuples::BC(65000, 165000); value = self.getFromGlobal("ENUM_WITH_TUPLES_BC").getCurrentValue() self.assertEqual( (value.GetChildAtIndex(0).GetData().GetUnsignedInt16(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0)), (65000, 165000)) def test_enum_with_tuples_values_are_correct_c(self): # static ENUM_WITH_TUPLES_C: EnumWithTuples = EnumWithTuples::C(31337); self.assertEqual( self.getFromGlobal("ENUM_WITH_TUPLES_C").getCurrentValue().GetChildAtIndex(0).GetData().GetUnsignedInt32( lldb.SBError(), 0), 31337) def test_enum_with_tuples_values_are_correct_cc(self): # static ENUM_WITH_TUPLES_CC: EnumWithTuples = EnumWithTuples::CC(31337, 87236); value = self.getFromGlobal("ENUM_WITH_TUPLES_CC").getCurrentValue() self.assertEqual( (value.GetChildAtIndex(0).GetData().GetUnsignedInt32(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0)), (31337, 87236)) def test_enum_with_tuples_values_are_correct_d(self): # static ENUM_WITH_TUPLES_D: EnumWithTuples = EnumWithTuples::D(123456789012345678); self.assertEqual( self.getFromGlobal("ENUM_WITH_TUPLES_D").getCurrentValue().GetChildAtIndex(0).GetData().GetUnsignedInt64( lldb.SBError(), 0), 123456789012345678) def test_mixed_enum_variants(self): # static MIXED_ENUM_A: MixedEnum1 = MixedEnum1::A; self.assertEqual(self.getFromGlobal("MIXED_ENUM_A").getAllVariantTypes(), ['main::MixedEnum::A:64', 'main::MixedEnum::B:64', 'main::MixedEnum::C:64', 'main::MixedEnum::D:64', 'main::MixedEnum::E:64']) def test_mixed_enum_a(self): # static MIXED_ENUM_A: MixedEnum = MixedEnum::A; value = self.getFromGlobal("MIXED_ENUM_A").getCurrentValue() self.assertEqual(value.GetType().GetDisplayTypeName(), "main::MixedEnum::A") self.assertEqual(value.GetValue(), None) def test_mixed_enum_c(self): # static MIXED_ENUM_C: MixedEnum = MixedEnum::C(254, -254); value = self.getFromGlobal("MIXED_ENUM_C").getCurrentValue() self.assertEqual( (value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetSignedInt32(lldb.SBError(), 0)), (254, -254)) def test_mixed_enum_d_none(self): # static MIXED_ENUM_D_NONE: MixedEnum = MixedEnum::D(None); value = RustEnumValue(self.getFromGlobal("MIXED_ENUM_D_NONE").getCurrentValue().GetChildAtIndex(0)) self.assertEqual(value.getAllVariantTypes(), ["core::option::Option::None:32", "core::option::Option::Some:32"]) self.assertEqual(value.getCurrentValue().GetValue(), None) self.assertEqual(value.getCurrentValue().GetType().GetDisplayTypeName(), "core::option::Option::None") def test_mixed_enum_d_some(self): # static MIXED_ENUM_D_SOME: MixedEnum = MixedEnum::D(Some(Struct2 { # field: 123456, # inner: Struct1 { field: 123 }, # })); variant_with_option = RustEnumValue( self.getFromGlobal("MIXED_ENUM_D_SOME").getCurrentValue().GetChildAtIndex(0)) value_inside_option = variant_with_option.getCurrentValue().GetChildAtIndex(0) self.assertEqual( value_inside_option.GetChildMemberWithName("field").GetData().GetUnsignedInt32(lldb.SBError(), 0), 123456) self.assertEqual( value_inside_option.GetChildMemberWithName("inner").GetChildMemberWithName( "field").GetData().GetSignedInt32(lldb.SBError(), 0), 123) self.assertEqual(value_inside_option.GetType().GetDisplayTypeName(), "main::Struct2") def test_option_non_null_some_pointer(self): type = self.target().FindFirstType("core::option::Option>") # this type is "optimized" by rust compiler so the discriminant isn't present on Some variant of option data = [1337] pointer_size = self.target().GetAddressByteSize() byte_order = self.target().GetByteOrder() value = RustEnumValue(self.target().CreateValueFromData("adhoc_value", lldb.SBData.CreateDataFromUInt64Array(byte_order, pointer_size, data), type)) self.assertEqual(value.getFields(), ["$variant$0", "$variant$"]) self.assertEqual( value.getCurrentValue().GetChildAtIndex(0).GetChildMemberWithName("pointer").GetValueAsUnsigned(), 1337) def test_option_non_null_none(self): type = self.target().FindFirstType("core::option::Option>") # this type is "optimized" by rust compiler so the discriminant isn't present on Some variant of option # in this test case 0 is used to represent 'None' data = [0] pointer_size = self.target().GetAddressByteSize() byte_order = self.target().GetByteOrder() value = RustEnumValue(self.target().CreateValueFromData("adhoc_value", lldb.SBData.CreateDataFromUInt64Array(byte_order, pointer_size, data), type)) self.assertEqual(value.getFields(), ["$variant$0", "$variant$"]) self.assertEqual(value.getCurrentValue().GetValue(), None) self.assertEqual(value.getCurrentValue().GetType().GetDisplayTypeName(), "core::option::Option>::None >") def test_niche_layout_with_fields_2(self): # static NICHE_W_FIELDS_2_A: NicheLayoutWithFields2 = # NicheLayoutWithFields2::A(NonZeroU32::new(800).unwrap(), 900); value = self.getFromGlobal("NICHE_W_FIELDS_2_A").getCurrentValue() self.assertEqual( ( value.GetChildAtIndex(0).GetChildAtIndex(0).GetData().GetUnsignedInt32(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0) ), (800, 900) ) def test_niche_layout_with_fields_3_a(self): # static NICHE_W_FIELDS_3_A: NicheLayoutWithFields3 = NicheLayoutWithFields3::A(137, true); value = self.getFromGlobal("NICHE_W_FIELDS_3_A").getCurrentValue() self.assertEqual( ( value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0), value.GetChildAtIndex(1).GetData().GetUnsignedInt8(lldb.SBError(), 0), ), (137, 1) ) def test_niche_layout_with_fields_3_a(self): # static NICHE_W_FIELDS_3_C: NicheLayoutWithFields3 = NicheLayoutWithFields3::C(false); value = self.getFromGlobal("NICHE_W_FIELDS_3_C").getCurrentValue() self.assertEqual( value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0), 0 )