296 lines · python
1"""Test that lldb recognizes enum structs emitted by Rust compiler """2import logging3 4import lldb5from lldbsuite.test.decorators import *6from lldbsuite.test.lldbtest import *7from RustEnumValue import RustEnumValue8 9 10class TestRustEnumStructs(TestBase):11 def setUp(self):12 TestBase.setUp(self)13 src_dir = self.getSourceDir()14 yaml_path = os.path.join(src_dir, "main.yaml")15 obj_path = self.getBuildArtifact("main.o")16 self.yaml2obj(yaml_path, obj_path)17 self.dbg.CreateTarget(obj_path)18 19 def getFromGlobal(self, name):20 values = self.target().FindGlobalVariables(name, 1)21 self.assertEqual(values.GetSize(), 1)22 return RustEnumValue(values[0])23 24 def test_clike_enums_are_represented_correctly(self):25 # these type of enums are not using DW_TAG_variant_part.26 all_values = [27 self.target().FindFirstGlobalVariable("CLIKE_DEFAULT_A").GetValue(),28 self.target().FindFirstGlobalVariable("CLIKE_DEFAULT_B").GetValue(),29 self.target().FindFirstGlobalVariable("CLIKE_U8_A").GetValue(),30 self.target().FindFirstGlobalVariable("CLIKE_U8_C").GetValue(),31 self.target().FindFirstGlobalVariable("CLIKE_U32_A").GetValue(),32 self.target().FindFirstGlobalVariable("CLIKE_U32_B").GetValue(),33 ]34 self.assertEqual(35 all_values, ["A", "B", "VariantA", "VariantC", "VariantA", "VariantB"]36 )37 38 def test_enum_with_tuples_has_all_variants(self):39 self.assertEqual(40 self.getFromGlobal("ENUM_WITH_TUPLES_A").getAllVariantTypes(),41 [42 "main::EnumWithTuples::A:8",43 "main::EnumWithTuples::B:8",44 "main::EnumWithTuples::C:8",45 "main::EnumWithTuples::D:8",46 "main::EnumWithTuples::AA:8",47 "main::EnumWithTuples::BB:8",48 "main::EnumWithTuples::BC:8",49 "main::EnumWithTuples::CC:8",50 ],51 )52 53 def test_enum_with_tuples_values_are_correct_a(self):54 # static ENUM_WITH_TUPLES_A: EnumWithTuples = EnumWithTuples::A(13);55 self.assertEqual(56 self.getFromGlobal("ENUM_WITH_TUPLES_A")57 .getCurrentValue()58 .GetChildAtIndex(0)59 .GetData()60 .GetUnsignedInt8(lldb.SBError(), 0),61 13,62 )63 64 def test_enum_with_tuples_values_are_correct_aa(self):65 # static ENUM_WITH_TUPLES_AA: EnumWithTuples = EnumWithTuples::AA(13, 37);66 value = self.getFromGlobal("ENUM_WITH_TUPLES_AA").getCurrentValue()67 self.assertEqual(68 (69 value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0),70 value.GetChildAtIndex(1).GetData().GetUnsignedInt8(lldb.SBError(), 0),71 ),72 (13, 37),73 )74 75 def test_enum_with_tuples_values_are_correct_b(self):76 # static ENUM_WITH_TUPLES_B: EnumWithTuples = EnumWithTuples::B(37);77 self.assertEqual(78 self.getFromGlobal("ENUM_WITH_TUPLES_B")79 .getCurrentValue()80 .GetChildAtIndex(0)81 .GetData()82 .GetUnsignedInt16(lldb.SBError(), 0),83 37,84 )85 86 def test_enum_with_tuples_values_are_correct_bb(self):87 # static ENUM_WITH_TUPLES_BB: EnumWithTuples = EnumWithTuples::BB(37, 5535);88 value = self.getFromGlobal("ENUM_WITH_TUPLES_BB").getCurrentValue()89 self.assertEqual(90 (91 value.GetChildAtIndex(0).GetData().GetUnsignedInt16(lldb.SBError(), 0),92 value.GetChildAtIndex(1).GetData().GetUnsignedInt16(lldb.SBError(), 0),93 ),94 (37, 5535),95 )96 97 def test_enum_with_tuples_values_are_correct_bc(self):98 # static ENUM_WITH_TUPLES_BC: EnumWithTuples = EnumWithTuples::BC(65000, 165000);99 value = self.getFromGlobal("ENUM_WITH_TUPLES_BC").getCurrentValue()100 self.assertEqual(101 (102 value.GetChildAtIndex(0).GetData().GetUnsignedInt16(lldb.SBError(), 0),103 value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0),104 ),105 (65000, 165000),106 )107 108 def test_enum_with_tuples_values_are_correct_c(self):109 # static ENUM_WITH_TUPLES_C: EnumWithTuples = EnumWithTuples::C(31337);110 self.assertEqual(111 self.getFromGlobal("ENUM_WITH_TUPLES_C")112 .getCurrentValue()113 .GetChildAtIndex(0)114 .GetData()115 .GetUnsignedInt32(lldb.SBError(), 0),116 31337,117 )118 119 def test_enum_with_tuples_values_are_correct_cc(self):120 # static ENUM_WITH_TUPLES_CC: EnumWithTuples = EnumWithTuples::CC(31337, 87236);121 value = self.getFromGlobal("ENUM_WITH_TUPLES_CC").getCurrentValue()122 self.assertEqual(123 (124 value.GetChildAtIndex(0).GetData().GetUnsignedInt32(lldb.SBError(), 0),125 value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0),126 ),127 (31337, 87236),128 )129 130 def test_enum_with_tuples_values_are_correct_d(self):131 # static ENUM_WITH_TUPLES_D: EnumWithTuples = EnumWithTuples::D(123456789012345678);132 self.assertEqual(133 self.getFromGlobal("ENUM_WITH_TUPLES_D")134 .getCurrentValue()135 .GetChildAtIndex(0)136 .GetData()137 .GetUnsignedInt64(lldb.SBError(), 0),138 123456789012345678,139 )140 141 def test_mixed_enum_variants(self):142 # static MIXED_ENUM_A: MixedEnum1 = MixedEnum1::A;143 self.assertEqual(144 self.getFromGlobal("MIXED_ENUM_A").getAllVariantTypes(),145 [146 "main::MixedEnum::A:64",147 "main::MixedEnum::B:64",148 "main::MixedEnum::C:64",149 "main::MixedEnum::D:64",150 "main::MixedEnum::E:64",151 ],152 )153 154 def test_mixed_enum_a(self):155 # static MIXED_ENUM_A: MixedEnum = MixedEnum::A;156 value = self.getFromGlobal("MIXED_ENUM_A").getCurrentValue()157 self.assertEqual(value.GetType().GetDisplayTypeName(), "main::MixedEnum::A")158 self.assertEqual(value.GetValue(), None)159 160 def test_mixed_enum_c(self):161 # static MIXED_ENUM_C: MixedEnum = MixedEnum::C(254, -254);162 value = self.getFromGlobal("MIXED_ENUM_C").getCurrentValue()163 self.assertEqual(164 (165 value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0),166 value.GetChildAtIndex(1).GetData().GetSignedInt32(lldb.SBError(), 0),167 ),168 (254, -254),169 )170 171 def test_mixed_enum_d_none(self):172 # static MIXED_ENUM_D_NONE: MixedEnum = MixedEnum::D(None);173 value = RustEnumValue(174 self.getFromGlobal("MIXED_ENUM_D_NONE").getCurrentValue().GetChildAtIndex(0)175 )176 self.assertEqual(177 value.getAllVariantTypes(),178 [179 "core::option::Option<main::Struct2>::None<main::Struct2>:32",180 "core::option::Option<main::Struct2>::Some<main::Struct2>:32",181 ],182 )183 self.assertEqual(value.getCurrentValue().GetValue(), None)184 self.assertEqual(185 value.getCurrentValue().GetType().GetDisplayTypeName(),186 "core::option::Option<main::Struct2>::None<main::Struct2>",187 )188 189 def test_mixed_enum_d_some(self):190 # static MIXED_ENUM_D_SOME: MixedEnum = MixedEnum::D(Some(Struct2 {191 # field: 123456,192 # inner: Struct1 { field: 123 },193 # }));194 variant_with_option = RustEnumValue(195 self.getFromGlobal("MIXED_ENUM_D_SOME").getCurrentValue().GetChildAtIndex(0)196 )197 198 value_inside_option = variant_with_option.getCurrentValue().GetChildAtIndex(0)199 self.assertEqual(200 value_inside_option.GetChildMemberWithName("field")201 .GetData()202 .GetUnsignedInt32(lldb.SBError(), 0),203 123456,204 )205 206 self.assertEqual(207 value_inside_option.GetChildMemberWithName("inner")208 .GetChildMemberWithName("field")209 .GetData()210 .GetSignedInt32(lldb.SBError(), 0),211 123,212 )213 self.assertEqual(214 value_inside_option.GetType().GetDisplayTypeName(), "main::Struct2"215 )216 217 def test_option_non_null_some_pointer(self):218 type = self.target().FindFirstType(219 "core::option::Option<core::ptr::non_null::NonNull<u64>>"220 )221 # this type is "optimized" by rust compiler so the discriminant isn't present on Some variant of option222 data = [1337]223 pointer_size = self.target().GetAddressByteSize()224 byte_order = self.target().GetByteOrder()225 value = RustEnumValue(226 self.target().CreateValueFromData(227 "adhoc_value",228 lldb.SBData.CreateDataFromUInt64Array(byte_order, pointer_size, data),229 type,230 )231 )232 self.assertEqual(value.getFields(), ["$variant$0", "$variant$"])233 self.assertEqual(234 value.getCurrentValue()235 .GetChildAtIndex(0)236 .GetChildMemberWithName("pointer")237 .GetValueAsUnsigned(),238 1337,239 )240 241 def test_option_non_null_none(self):242 type = self.target().FindFirstType(243 "core::option::Option<core::ptr::non_null::NonNull<u64>>"244 )245 # this type is "optimized" by rust compiler so the discriminant isn't present on Some variant of option246 # in this test case 0 is used to represent 'None'247 data = [0]248 pointer_size = self.target().GetAddressByteSize()249 byte_order = self.target().GetByteOrder()250 value = RustEnumValue(251 self.target().CreateValueFromData(252 "adhoc_value",253 lldb.SBData.CreateDataFromUInt64Array(byte_order, pointer_size, data),254 type,255 )256 )257 self.assertEqual(value.getFields(), ["$variant$0", "$variant$"])258 self.assertEqual(value.getCurrentValue().GetValue(), None)259 self.assertEqual(260 value.getCurrentValue().GetType().GetDisplayTypeName(),261 "core::option::Option<core::ptr::non_null::NonNull<u64>>::None<core::ptr::non_null::NonNull<unsigned long> >",262 )263 264 def test_niche_layout_with_fields_2(self):265 # static NICHE_W_FIELDS_2_A: NicheLayoutWithFields2 =266 # NicheLayoutWithFields2::A(NonZeroU32::new(800).unwrap(), 900);267 value = self.getFromGlobal("NICHE_W_FIELDS_2_A").getCurrentValue()268 self.assertEqual(269 (270 value.GetChildAtIndex(0)271 .GetChildAtIndex(0)272 .GetData()273 .GetUnsignedInt32(lldb.SBError(), 0),274 value.GetChildAtIndex(1).GetData().GetUnsignedInt32(lldb.SBError(), 0),275 ),276 (800, 900),277 )278 279 def test_niche_layout_with_fields_3_a(self):280 # static NICHE_W_FIELDS_3_A: NicheLayoutWithFields3 = NicheLayoutWithFields3::A(137, true);281 value = self.getFromGlobal("NICHE_W_FIELDS_3_A").getCurrentValue()282 self.assertEqual(283 (284 value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0),285 value.GetChildAtIndex(1).GetData().GetUnsignedInt8(lldb.SBError(), 0),286 ),287 (137, 1),288 )289 290 def test_niche_layout_with_fields_3_c(self):291 # static NICHE_W_FIELDS_3_C: NicheLayoutWithFields3 = NicheLayoutWithFields3::C(false);292 value = self.getFromGlobal("NICHE_W_FIELDS_3_C").getCurrentValue()293 self.assertEqual(294 value.GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0), 0295 )296