559 lines · python
1"""Test Python APIs for working with formatters"""2 3import lldb4from lldbsuite.test.decorators import *5from lldbsuite.test.lldbtest import *6from lldbsuite.test import lldbutil7 8 9class SBFormattersAPITestCase(TestBase):10 NO_DEBUG_INFO_TESTCASE = True11 12 def setUp(self):13 # Call super's setUp().14 TestBase.setUp(self)15 self.line = line_number("main.cpp", "// Set break point at this line.")16 17 def test_formatters_api(self):18 """Test Python APIs for working with formatters"""19 self.build()20 self.setTearDownCleanup()21 22 """Test Python APIs for working with formatters"""23 self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)24 25 lldbutil.run_break_set_by_file_and_line(26 self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True27 )28 29 self.runCmd("run", RUN_SUCCEEDED)30 31 # The stop reason of the thread should be breakpoint.32 self.expect(33 "thread list",34 STOPPED_DUE_TO_BREAKPOINT,35 substrs=["stopped", "stop reason = breakpoint"],36 )37 38 # This is the function to remove the custom formats in order to have a39 # clean slate for the next test case.40 def cleanup():41 self.runCmd("type format clear", check=False)42 self.runCmd("type summary clear", check=False)43 self.runCmd("type filter clear", check=False)44 self.runCmd("type synthetic clear", check=False)45 self.runCmd("type category delete foobar", check=False)46 self.runCmd("type category delete JASSynth", check=False)47 self.runCmd("type category delete newbar", check=False)48 49 # Execute the cleanup function during test case tear down.50 self.addTearDownHook(cleanup)51 52 format = lldb.SBTypeFormat(lldb.eFormatHex)53 category = self.dbg.GetDefaultCategory()54 category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"), format)55 56 self.expect("frame variable foo.A", substrs=["0x00000001"])57 self.expect("frame variable foo.E", matching=False, substrs=["b8cca70a"])58 59 category.AddTypeFormat(lldb.SBTypeNameSpecifier("long"), format)60 self.expect("frame variable foo.A", substrs=["0x00000001"])61 self.expect("frame variable foo.E", substrs=["b8cca70a"])62 63 format.SetFormat(lldb.eFormatOctal)64 category.AddTypeFormat(lldb.SBTypeNameSpecifier("int"), format)65 self.expect("frame variable foo.A", substrs=[" 01"])66 self.expect("frame variable foo.E", substrs=["b8cca70a"])67 68 category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("int"))69 category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("long"))70 self.expect("frame variable foo.A", matching=False, substrs=[" 01"])71 self.expect("frame variable foo.E", matching=False, substrs=["b8cca70a"])72 73 summary = lldb.SBTypeSummary.CreateWithSummaryString(74 "the hello world you'll never see"75 )76 summary.SetSummaryString("hello world")77 new_category = self.dbg.GetCategory("foobar")78 self.assertFalse(79 new_category.IsValid(), "getting a non-existing category worked"80 )81 new_category = self.dbg.CreateCategory("foobar")82 new_category.SetEnabled(True)83 new_category.AddTypeSummary(84 lldb.SBTypeNameSpecifier(85 "^.*t$",86 True, # is_regexp87 ),88 summary,89 )90 91 self.expect("frame variable foo.A", substrs=["hello world"])92 self.expect("frame variable foo.E", matching=False, substrs=["hello world"])93 self.expect("frame variable foo.B", substrs=["hello world"])94 self.expect("frame variable foo.F", substrs=["hello world"])95 new_category.SetEnabled(False)96 self.expect("frame variable foo.A", matching=False, substrs=["hello world"])97 self.expect("frame variable foo.E", matching=False, substrs=["hello world"])98 self.expect("frame variable foo.B", matching=False, substrs=["hello world"])99 self.expect("frame variable foo.F", matching=False, substrs=["hello world"])100 self.dbg.DeleteCategory(new_category.GetName())101 self.expect("frame variable foo.A", matching=False, substrs=["hello world"])102 self.expect("frame variable foo.E", matching=False, substrs=["hello world"])103 self.expect("frame variable foo.B", matching=False, substrs=["hello world"])104 self.expect("frame variable foo.F", matching=False, substrs=["hello world"])105 106 filter = lldb.SBTypeFilter(0)107 filter.AppendExpressionPath("A")108 filter.AppendExpressionPath("D")109 self.assertEqual(110 filter.GetNumberOfExpressionPaths(),111 2,112 "filter with two items does not have two items",113 )114 115 category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)116 self.expect("frame variable foo", substrs=["A = 1", "D = 6.28"])117 self.expect(118 "frame variable foo",119 matching=False,120 substrs=["B = ", "C = ", "E = ", "F = "],121 )122 123 category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct", True))124 self.expect("frame variable foo", substrs=["A = 1", "D = 6.28"])125 self.expect(126 "frame variable foo",127 matching=False,128 substrs=["B = ", "C = ", "E = ", "F = "],129 )130 131 category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct", False))132 self.expect("frame variable foo", substrs=["A = 1", "D = 6.28"])133 self.expect(134 "frame variable foo",135 matching=True,136 substrs=["B = ", "C = ", "E = ", "F = "],137 )138 139 self.runCmd("command script import --allow-reload ./synth.py")140 141 self.expect("frame variable foo", matching=False, substrs=["X = 1"])142 143 self.dbg.GetCategory("JASSynth").SetEnabled(True)144 self.expect("frame variable foo", matching=True, substrs=["X = 1"])145 146 self.dbg.GetCategory("CCCSynth2").SetEnabled(True)147 self.expect(148 "frame variable ccc",149 matching=True,150 substrs=[151 "CCC object with leading synthetic value (int) b = 222",152 "a = 111",153 "b = 222",154 "c = 333",155 ],156 )157 self.dbg.GetCategory("CCCSynth2").SetEnabled(False)158 159 self.dbg.GetCategory("CCCSynth").SetEnabled(True)160 self.expect(161 "frame variable ccc",162 matching=True,163 substrs=[164 "CCC object with leading value (int) a = 111",165 "a = 111",166 "b = 222",167 "c = 333",168 ],169 )170 171 self.dbg.GetCategory("BarIntSynth").SetEnabled(True)172 self.expect(173 "frame variable bar_int",174 matching=True,175 substrs=[176 "(int) bar_int = 20 bar_int synthetic: No value",177 ],178 )179 180 foo_var = (181 self.dbg.GetSelectedTarget()182 .GetProcess()183 .GetSelectedThread()184 .GetSelectedFrame()185 .FindVariable("foo")186 )187 self.assertTrue(foo_var.IsValid(), "could not find foo")188 self.assertTrue(189 foo_var.GetDeclaration().IsValid(), "foo declaration is invalid"190 )191 192 self.assertEqual(193 foo_var.GetNumChildren(),194 2,195 "synthetic value has wrong number of child items (synth)",196 )197 self.assertEqual(198 foo_var.GetChildMemberWithName("X").GetValueAsUnsigned(),199 1,200 "foo_synth.X has wrong value (synth)",201 )202 self.assertFalse(203 foo_var.GetChildMemberWithName("B").IsValid(),204 "foo_synth.B is valid but should not (synth)",205 )206 207 self.dbg.GetCategory("JASSynth").SetEnabled(False)208 foo_var = (209 self.dbg.GetSelectedTarget()210 .GetProcess()211 .GetSelectedThread()212 .GetSelectedFrame()213 .FindVariable("foo")214 )215 self.assertTrue(foo_var.IsValid(), "could not find foo")216 217 self.assertNotEqual(foo_var.GetNumChildren(), 2, "still seeing synthetic value")218 219 filter = lldb.SBTypeFilter(0)220 filter.AppendExpressionPath("A")221 filter.AppendExpressionPath("D")222 category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)223 self.expect("frame variable foo", substrs=["A = 1", "D = 6.28"])224 225 foo_var = (226 self.dbg.GetSelectedTarget()227 .GetProcess()228 .GetSelectedThread()229 .GetSelectedFrame()230 .FindVariable("foo")231 )232 self.assertTrue(foo_var.IsValid(), "could not find foo")233 234 self.assertEqual(235 foo_var.GetNumChildren(),236 2,237 "synthetic value has wrong number of child items (filter)",238 )239 self.assertEqual(240 foo_var.GetChildMemberWithName("X").GetValueAsUnsigned(),241 0,242 "foo_synth.X has wrong value (filter)",243 )244 self.assertEqual(245 foo_var.GetChildMemberWithName("A").GetValueAsUnsigned(),246 1,247 "foo_synth.A has wrong value (filter)",248 )249 250 self.assertTrue(251 filter.ReplaceExpressionPathAtIndex(0, "C"),252 "failed to replace an expression path in filter",253 )254 self.expect("frame variable foo", substrs=["A = 1", "D = 6.28"])255 category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)256 self.expect("frame variable foo", substrs=["C = 'e'", "D = 6.28"])257 category.AddTypeFilter(lldb.SBTypeNameSpecifier("FooType"), filter)258 filter.ReplaceExpressionPathAtIndex(1, "F")259 self.expect("frame variable foo", substrs=["C = 'e'", "D = 6.28"])260 category.AddTypeFilter(lldb.SBTypeNameSpecifier("JustAStruct"), filter)261 self.expect("frame variable foo", substrs=["C = 'e'", "F = 0"])262 self.expect("frame variable bar", substrs=["C = 'e'", "D = 6.28"])263 264 foo_var = (265 self.dbg.GetSelectedTarget()266 .GetProcess()267 .GetSelectedThread()268 .GetSelectedFrame()269 .FindVariable("foo")270 )271 self.assertTrue(foo_var.IsValid(), "could not find foo")272 self.assertEqual(273 foo_var.GetChildMemberWithName("C").GetValueAsUnsigned(),274 ord("e"),275 "foo_synth.C has wrong value (filter)",276 )277 278 chosen = self.dbg.GetFilterForType(lldb.SBTypeNameSpecifier("JustAStruct"))279 self.assertEqual(chosen.count, 2, "wrong filter found for JustAStruct")280 self.assertEqual(281 chosen.GetExpressionPathAtIndex(0),282 "C",283 "wrong item at index 0 for JustAStruct",284 )285 self.assertEqual(286 chosen.GetExpressionPathAtIndex(1),287 "F",288 "wrong item at index 1 for JustAStruct",289 )290 291 self.assertFalse(292 category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("NoSuchType")),293 "deleting a non-existing filter worked",294 )295 self.assertFalse(296 category.DeleteTypeSummary(lldb.SBTypeNameSpecifier("NoSuchType")),297 "deleting a non-existing summary worked",298 )299 self.assertFalse(300 category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("NoSuchType")),301 "deleting a non-existing format worked",302 )303 self.assertFalse(304 category.DeleteTypeSynthetic(lldb.SBTypeNameSpecifier("NoSuchType")),305 "deleting a non-existing synthetic worked",306 )307 308 self.assertFalse(309 category.DeleteTypeFilter(lldb.SBTypeNameSpecifier("")),310 "deleting a filter for '' worked",311 )312 self.assertFalse(313 category.DeleteTypeSummary(lldb.SBTypeNameSpecifier("")),314 "deleting a summary for '' worked",315 )316 self.assertFalse(317 category.DeleteTypeFormat(lldb.SBTypeNameSpecifier("")),318 "deleting a format for '' worked",319 )320 self.assertFalse(321 category.DeleteTypeSynthetic(lldb.SBTypeNameSpecifier("")),322 "deleting a synthetic for '' worked",323 )324 325 try:326 self.assertFalse(327 category.AddTypeSummary(lldb.SBTypeNameSpecifier("NoneSuchType"), None),328 "adding a summary valued None worked",329 )330 except:331 pass332 else:333 self.assertFalse(True, "adding a summary valued None worked")334 335 try:336 self.assertFalse(337 category.AddTypeFilter(lldb.SBTypeNameSpecifier("NoneSuchType"), None),338 "adding a filter valued None worked",339 )340 except:341 pass342 else:343 self.assertFalse(True, "adding a filter valued None worked")344 345 try:346 self.assertFalse(347 category.AddTypeSynthetic(348 lldb.SBTypeNameSpecifier("NoneSuchType"), None349 ),350 "adding a synthetic valued None worked",351 )352 except:353 pass354 else:355 self.assertFalse(True, "adding a synthetic valued None worked")356 357 try:358 self.assertFalse(359 category.AddTypeFormat(lldb.SBTypeNameSpecifier("NoneSuchType"), None),360 "adding a format valued None worked",361 )362 except:363 pass364 else:365 self.assertFalse(True, "adding a format valued None worked")366 367 self.assertFalse(368 category.AddTypeSummary(369 lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeSummary()370 ),371 "adding a summary without value worked",372 )373 self.assertFalse(374 category.AddTypeFilter(375 lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeFilter()376 ),377 "adding a filter without value worked",378 )379 self.assertFalse(380 category.AddTypeSynthetic(381 lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeSynthetic()382 ),383 "adding a synthetic without value worked",384 )385 self.assertFalse(386 category.AddTypeFormat(387 lldb.SBTypeNameSpecifier("EmptySuchType"), lldb.SBTypeFormat()388 ),389 "adding a format without value worked",390 )391 392 self.assertFalse(393 category.AddTypeSummary(394 lldb.SBTypeNameSpecifier(""),395 lldb.SBTypeSummary.CreateWithSummaryString(""),396 ),397 "adding a summary for an invalid type worked",398 )399 self.assertFalse(400 category.AddTypeFilter(lldb.SBTypeNameSpecifier(""), lldb.SBTypeFilter(0)),401 "adding a filter for an invalid type worked",402 )403 self.assertFalse(404 category.AddTypeSynthetic(405 lldb.SBTypeNameSpecifier(""),406 lldb.SBTypeSynthetic.CreateWithClassName(""),407 ),408 "adding a synthetic for an invalid type worked",409 )410 self.assertFalse(411 category.AddTypeFormat(412 lldb.SBTypeNameSpecifier(""), lldb.SBTypeFormat(lldb.eFormatHex)413 ),414 "adding a format for an invalid type worked",415 )416 417 new_category = self.dbg.CreateCategory("newbar")418 new_category.AddTypeSummary(419 lldb.SBTypeNameSpecifier("JustAStruct"),420 lldb.SBTypeSummary.CreateWithScriptCode("return 'hello scripted world';"),421 )422 self.expect(423 "frame variable foo", matching=False, substrs=["hello scripted world"]424 )425 new_category.SetEnabled(True)426 self.expect(427 "frame variable foo", matching=True, substrs=["hello scripted world"]428 )429 430 self.expect(431 "frame variable foo_ptr", matching=True, substrs=["hello scripted world"]432 )433 new_category.AddTypeSummary(434 lldb.SBTypeNameSpecifier("JustAStruct"),435 lldb.SBTypeSummary.CreateWithScriptCode(436 "return 'hello scripted world';", lldb.eTypeOptionSkipPointers437 ),438 )439 self.expect(440 "frame variable foo", matching=True, substrs=["hello scripted world"]441 )442 443 frame = (444 self.dbg.GetSelectedTarget()445 .GetProcess()446 .GetSelectedThread()447 .GetSelectedFrame()448 )449 foo_ptr = frame.FindVariable("foo_ptr")450 summary = foo_ptr.GetTypeSummary()451 452 self.assertFalse(453 summary.IsValid(), "summary found for foo* when none was planned"454 )455 456 self.expect(457 "frame variable foo_ptr", matching=False, substrs=["hello scripted world"]458 )459 460 new_category.AddTypeSummary(461 lldb.SBTypeNameSpecifier("JustAStruct"),462 lldb.SBTypeSummary.CreateWithSummaryString(463 "hello static world", lldb.eTypeOptionNone464 ),465 )466 467 summary = foo_ptr.GetTypeSummary()468 469 self.assertTrue(470 summary.IsValid(), "no summary found for foo* when one was in place"471 )472 self.assertEqual(473 summary.GetData(), "hello static world", "wrong summary found for foo*"474 )475 476 self.expect("frame variable e1", substrs=["I am an empty Empty1 {}"])477 self.expect("frame variable e2", substrs=["I am an empty Empty2"])478 self.expect(479 "frame variable e2", substrs=["I am an empty Empty2 {}"], matching=False480 )481 482 self.assertIsNotNone(483 self.dbg.GetCategory(lldb.eLanguageTypeObjC), "ObjC category is None"484 )485 486 def test_force_synth_off(self):487 """Test that one can have the public API return non-synthetic SBValues if desired"""488 self.build(dictionary={"EXE": "no_synth"})489 self.setTearDownCleanup()490 491 self.runCmd("file " + self.getBuildArtifact("no_synth"), CURRENT_EXECUTABLE_SET)492 493 lldbutil.run_break_set_by_file_and_line(494 self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True495 )496 497 self.runCmd("run", RUN_SUCCEEDED)498 499 # The stop reason of the thread should be breakpoint.500 self.expect(501 "thread list",502 STOPPED_DUE_TO_BREAKPOINT,503 substrs=["stopped", "stop reason = breakpoint"],504 )505 506 # This is the function to remove the custom formats in order to have a507 # clean slate for the next test case.508 def cleanup():509 self.runCmd("type format clear", check=False)510 self.runCmd("type summary clear", check=False)511 self.runCmd("type filter clear", check=False)512 self.runCmd("type synthetic clear", check=False)513 self.runCmd("type category delete foobar", check=False)514 self.runCmd("type category delete JASSynth", check=False)515 self.runCmd("type category delete newbar", check=False)516 self.runCmd("settings set target.enable-synthetic-value true")517 518 # Execute the cleanup function during test case tear down.519 self.addTearDownHook(cleanup)520 521 frame = (522 self.dbg.GetSelectedTarget()523 .GetProcess()524 .GetSelectedThread()525 .GetSelectedFrame()526 )527 int_vector = frame.FindVariable("int_vector")528 if self.TraceOn():529 print(int_vector)530 self.assertEqual(int_vector.GetNumChildren(), 0, "synthetic vector is empty")531 532 self.runCmd("settings set target.enable-synthetic-value false")533 frame = (534 self.dbg.GetSelectedTarget()535 .GetProcess()536 .GetSelectedThread()537 .GetSelectedFrame()538 )539 int_vector = frame.FindVariable("int_vector")540 if self.TraceOn():541 print(int_vector)542 self.assertNotEqual(543 int_vector.GetNumChildren(), 0, '"physical" vector is not empty'544 )545 546 self.runCmd("settings set target.enable-synthetic-value true")547 frame = (548 self.dbg.GetSelectedTarget()549 .GetProcess()550 .GetSelectedThread()551 .GetSelectedFrame()552 )553 int_vector = frame.FindVariable("int_vector")554 if self.TraceOn():555 print(int_vector)556 self.assertEqual(557 int_vector.GetNumChildren(), 0, "synthetic vector is still empty"558 )559