477 lines · python
1"""2Test breakpoint names.3"""4 5 6import os7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10from lldbsuite.test import lldbutil11 12 13class BreakpointNames(TestBase):14 NO_DEBUG_INFO_TESTCASE = True15 16 @add_test_categories(["pyapi"])17 def test_setting_names(self):18 """Use Python APIs to test that we can set breakpoint names."""19 self.build()20 self.setup_target()21 self.do_check_names()22 23 def test_illegal_names(self):24 """Use Python APIs to test that we don't allow illegal names."""25 self.build()26 self.setup_target()27 self.do_check_illegal_names()28 29 def test_using_names(self):30 """Use Python APIs to test that operations on names works correctly."""31 self.build()32 self.setup_target()33 self.do_check_using_names()34 35 def test_configuring_names(self):36 """Use Python APIs to test that configuring options on breakpoint names works correctly."""37 self.build()38 self.make_a_dummy_name()39 self.setup_target()40 self.do_check_configuring_names()41 42 def test_configuring_permissions_sb(self):43 """Use Python APIs to test that configuring permissions on names works correctly."""44 self.build()45 self.setup_target()46 self.do_check_configuring_permissions_sb()47 48 def test_configuring_permissions_cli(self):49 """Use Python APIs to test that configuring permissions on names works correctly."""50 self.build()51 self.setup_target()52 self.do_check_configuring_permissions_cli()53 54 def setup_target(self):55 exe = self.getBuildArtifact("a.out")56 57 # Create a targets we are making breakpoint in and copying to:58 self.target = self.dbg.CreateTarget(exe)59 self.assertTrue(self.target, VALID_TARGET)60 self.main_file_spec = lldb.SBFileSpec(61 os.path.join(self.getSourceDir(), "main.c")62 )63 64 def check_name_in_target(self, bkpt_name):65 name_list = lldb.SBStringList()66 self.target.GetBreakpointNames(name_list)67 found_it = False68 for name in name_list:69 if name == bkpt_name:70 found_it = True71 break72 self.assertTrue(73 found_it, "Didn't find the name %s in the target's name list:" % (bkpt_name)74 )75 76 def setUp(self):77 # Call super's setUp().78 TestBase.setUp(self)79 80 # These are the settings we're going to be putting into names & breakpoints:81 self.bp_name_string = "ABreakpoint"82 self.is_one_shot = True83 self.ignore_count = 100084 self.condition = "1 == 2"85 self.auto_continue = True86 self.tid = 0xAAAA87 self.tidx = 1088 self.thread_name = "Fooey"89 self.queue_name = "Blooey"90 self.cmd_list = lldb.SBStringList()91 self.cmd_list.AppendString("frame var")92 self.cmd_list.AppendString("bt")93 self.help_string = "I do something interesting"94 95 def do_check_names(self):96 """Use Python APIs to check that we can set & retrieve breakpoint names"""97 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)98 bkpt_name = "ABreakpoint"99 other_bkpt_name = "_AnotherBreakpoint"100 101 # Add a name and make sure we match it:102 success = bkpt.AddNameWithErrorHandling(bkpt_name)103 self.assertSuccess(success, "We couldn't add a legal name to a breakpoint.")104 105 matches = bkpt.MatchesName(bkpt_name)106 self.assertTrue(matches, "We didn't match the name we just set")107 108 # Make sure we don't match irrelevant names:109 matches = bkpt.MatchesName("NotABreakpoint")110 self.assertTrue(not matches, "We matched a name we didn't set.")111 112 # Make sure the name is also in the target:113 self.check_name_in_target(bkpt_name)114 115 # Add another name, make sure that works too:116 bkpt.AddNameWithErrorHandling(other_bkpt_name)117 118 matches = bkpt.MatchesName(bkpt_name)119 self.assertTrue(120 matches, "Adding a name means we didn't match the name we just set"121 )122 self.check_name_in_target(other_bkpt_name)123 124 # Remove the name and make sure we no longer match it:125 bkpt.RemoveName(bkpt_name)126 matches = bkpt.MatchesName(bkpt_name)127 self.assertTrue(not matches, "We still match a name after removing it.")128 129 # Make sure the name list has the remaining name:130 name_list = lldb.SBStringList()131 bkpt.GetNames(name_list)132 num_names = name_list.GetSize()133 self.assertEqual(134 num_names, 1, "Name list has %d items, expected 1." % (num_names)135 )136 137 name = name_list.GetStringAtIndex(0)138 self.assertEqual(139 name,140 other_bkpt_name,141 "Remaining name was: %s expected %s." % (name, other_bkpt_name),142 )143 144 def do_check_illegal_names(self):145 """Use Python APIs to check that we reject illegal names."""146 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)147 bad_names = [148 "-CantStartWithADash",149 "1CantStartWithANumber",150 "^CantStartWithNonAlpha",151 "CantHave-ADash",152 "Cant Have Spaces",153 ]154 for bad_name in bad_names:155 success = bkpt.AddNameWithErrorHandling(bad_name)156 self.assertTrue(157 success.Fail(), "We allowed an illegal name: %s" % (bad_name)158 )159 bp_name = lldb.SBBreakpointName(self.target, bad_name)160 self.assertFalse(161 bp_name.IsValid(),162 "We made a breakpoint name with an illegal name: %s" % (bad_name),163 )164 165 retval = lldb.SBCommandReturnObject()166 self.dbg.GetCommandInterpreter().HandleCommand(167 "break set -n whatever -N '%s'" % (bad_name), retval168 )169 self.assertTrue(170 not retval.Succeeded(),171 "break set succeeded with: illegal name: %s" % (bad_name),172 )173 174 def do_check_using_names(self):175 """Use Python APIs to check names work in place of breakpoint ID's."""176 177 # Create a dummy breakpoint to use up ID 1178 _ = self.target.BreakpointCreateByLocation(self.main_file_spec, 30)179 180 # Create a breakpoint to test with181 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)182 bkpt_name = "ABreakpoint"183 bkpt_id = bkpt.GetID()184 other_bkpt_name = "_AnotherBreakpoint"185 186 # Add a name and make sure we match it:187 success = bkpt.AddNameWithErrorHandling(bkpt_name)188 self.assertSuccess(success, "We couldn't add a legal name to a breakpoint.")189 190 bkpts = lldb.SBBreakpointList(self.target)191 self.target.FindBreakpointsByName(bkpt_name, bkpts)192 193 self.assertEqual(bkpts.GetSize(), 1, "One breakpoint matched.")194 found_bkpt = bkpts.GetBreakpointAtIndex(0)195 self.assertEqual(bkpt.GetID(), found_bkpt.GetID(), "The right breakpoint.")196 self.assertEqual(bkpt.GetID(), bkpt_id, "With the same ID as before.")197 198 retval = lldb.SBCommandReturnObject()199 self.dbg.GetCommandInterpreter().HandleCommand(200 "break disable %s" % (bkpt_name), retval201 )202 self.assertTrue(203 retval.Succeeded(), "break disable failed with: %s." % (retval.GetError())204 )205 self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.")206 207 # Also make sure we don't apply commands to non-matching names:208 self.dbg.GetCommandInterpreter().HandleCommand(209 "break modify --one-shot 1 %s" % (other_bkpt_name), retval210 )211 self.assertTrue(212 retval.Succeeded(), "break modify failed with: %s." % (retval.GetError())213 )214 self.assertTrue(215 not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint."216 )217 218 def check_option_values(self, bp_object):219 self.assertEqual(bp_object.one_shot, self.is_one_shot, "IsOneShot")220 self.assertEqual(bp_object.ignore_count, self.ignore_count, "IgnoreCount")221 self.assertEqual(bp_object.condition, self.condition, "Condition")222 self.assertEqual(bp_object.auto_continue, self.auto_continue, "AutoContinue")223 self.assertEqual(bp_object.thread_id, self.tid, "Thread ID")224 self.assertEqual(bp_object.thread_index, self.tidx, "Thread Index")225 self.assertEqual(bp_object.thread_name, self.thread_name, "Thread Name")226 self.assertEqual(bp_object.queue_name, self.queue_name, "Queue Name")227 set_cmds = lldb.SBStringList()228 bp_object.GetCommandLineCommands(set_cmds)229 self.assertEqual(230 set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands"231 )232 for idx in range(0, set_cmds.GetSize()):233 self.assertEqual(234 self.cmd_list.GetStringAtIndex(idx),235 set_cmds.GetStringAtIndex(idx),236 "Command %d" % (idx),237 )238 239 def make_a_dummy_name(self):240 "This makes a breakpoint name in the dummy target to make sure it gets copied over"241 242 dummy_target = self.dbg.GetDummyTarget()243 self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.")244 245 def cleanup():246 self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string)247 248 # Execute the cleanup function during test case tear down.249 self.addTearDownHook(cleanup)250 251 # Now find it in the dummy target, and make sure these settings took:252 bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)253 # Make sure the name is right:254 self.assertEqual(255 bp_name.GetName(),256 self.bp_name_string,257 "Wrong bp_name: %s" % (bp_name.GetName()),258 )259 bp_name.SetOneShot(self.is_one_shot)260 bp_name.SetIgnoreCount(self.ignore_count)261 bp_name.SetCondition(self.condition)262 bp_name.SetAutoContinue(self.auto_continue)263 bp_name.SetThreadID(self.tid)264 bp_name.SetThreadIndex(self.tidx)265 bp_name.SetThreadName(self.thread_name)266 bp_name.SetQueueName(self.queue_name)267 bp_name.SetCommandLineCommands(self.cmd_list)268 269 # Now look it up again, and make sure it got set correctly.270 bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string)271 self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")272 self.check_option_values(bp_name)273 274 def do_check_configuring_names(self):275 """Use Python APIs to check that configuring breakpoint names works correctly."""276 other_bp_name_string = "AnotherBreakpointName"277 cl_bp_name_string = "CLBreakpointName"278 279 # Now find the version copied in from the dummy target, and make sure these settings took:280 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)281 self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.")282 self.check_option_values(bp_name)283 284 # Now add this name to a breakpoint, and make sure it gets configured properly285 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)286 success = bkpt.AddNameWithErrorHandling(self.bp_name_string)287 self.assertSuccess(success, "Couldn't add this name to the breakpoint")288 self.check_option_values(bkpt)289 290 # Now make a name from this breakpoint, and make sure the new name is properly configured:291 new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string)292 self.assertTrue(293 new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint."294 )295 self.check_option_values(bkpt)296 297 # Now change the name's option and make sure it gets propagated to298 # the breakpoint:299 new_auto_continue = not self.auto_continue300 bp_name.SetAutoContinue(new_auto_continue)301 self.assertEqual(302 bp_name.GetAutoContinue(),303 new_auto_continue,304 "Couldn't change auto-continue on the name",305 )306 self.assertEqual(307 bkpt.GetAutoContinue(),308 new_auto_continue,309 "Option didn't propagate to the breakpoint.",310 )311 312 # Now make this same breakpoint name - but from the command line313 cmd_str = (314 "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"315 % (316 cl_bp_name_string,317 self.is_one_shot,318 self.ignore_count,319 self.condition,320 self.auto_continue,321 self.tid,322 self.tidx,323 self.thread_name,324 self.queue_name,325 self.help_string,326 )327 )328 for cmd in self.cmd_list:329 cmd_str += " -C '%s'" % (cmd)330 331 self.runCmd(cmd_str, check=True)332 # Now look up this name again and check its options:333 cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string)334 self.check_option_values(cl_name)335 # Also check the help string:336 self.assertEqual(337 self.help_string, cl_name.GetHelpString(), "Help string didn't match"338 )339 # Change the name and make sure that works:340 new_help = "I do something even more interesting"341 cl_name.SetHelpString(new_help)342 self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't")343 344 # We should have three names now, make sure the target can list them:345 name_list = lldb.SBStringList()346 self.target.GetBreakpointNames(name_list)347 for name_string in [348 self.bp_name_string,349 other_bp_name_string,350 cl_bp_name_string,351 ]:352 self.assertIn(353 name_string, name_list, "Didn't find %s in names" % (name_string)354 )355 356 # Delete the name from the current target. Make sure that works and deletes the357 # name from the breakpoint as well:358 self.target.DeleteBreakpointName(self.bp_name_string)359 name_list.Clear()360 self.target.GetBreakpointNames(name_list)361 self.assertNotIn(362 self.bp_name_string,363 name_list,364 "Didn't delete %s from a real target" % (self.bp_name_string),365 )366 # Also make sure the name got removed from breakpoints holding it:367 self.assertFalse(368 bkpt.MatchesName(self.bp_name_string),369 "Didn't remove the name from the breakpoint.",370 )371 372 # Test that deleting the name we injected into the dummy target works (there's also a373 # cleanup that will do this, but that won't test the result...374 dummy_target = self.dbg.GetDummyTarget()375 dummy_target.DeleteBreakpointName(self.bp_name_string)376 name_list.Clear()377 dummy_target.GetBreakpointNames(name_list)378 self.assertNotIn(379 self.bp_name_string,380 name_list,381 "Didn't delete %s from the dummy target" % (self.bp_name_string),382 )383 # Also make sure the name got removed from breakpoints holding it:384 self.assertFalse(385 bkpt.MatchesName(self.bp_name_string),386 "Didn't remove the name from the breakpoint.",387 )388 389 def check_permission_results(self, bp_name):390 self.assertFalse(bp_name.GetAllowDelete(), "Didn't set allow delete.")391 protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10)392 protected_id = protected_bkpt.GetID()393 394 unprotected_bkpt = self.target.BreakpointCreateByLocation(395 self.main_file_spec, 10396 )397 unprotected_id = unprotected_bkpt.GetID()398 399 success = protected_bkpt.AddNameWithErrorHandling(self.bp_name_string)400 self.assertSuccess(success, "Couldn't add this name to the breakpoint")401 402 self.target.DisableAllBreakpoints()403 self.assertTrue(404 protected_bkpt.IsEnabled(), "Didnt' keep breakpoint from being disabled"405 )406 self.assertFalse(407 unprotected_bkpt.IsEnabled(),408 "Protected too many breakpoints from disabling.",409 )410 411 # Try from the command line too:412 unprotected_bkpt.SetEnabled(True)413 result = lldb.SBCommandReturnObject()414 self.dbg.GetCommandInterpreter().HandleCommand("break disable", result)415 self.assertTrue(result.Succeeded())416 self.assertTrue(417 protected_bkpt.IsEnabled(), "Didnt' keep breakpoint from being disabled"418 )419 self.assertFalse(420 unprotected_bkpt.IsEnabled(),421 "Protected too many breakpoints from disabling.",422 )423 424 self.target.DeleteAllBreakpoints()425 bkpt = self.target.FindBreakpointByID(protected_id)426 self.assertTrue(427 bkpt.IsValid(), "Didn't keep the breakpoint from being deleted."428 )429 bkpt = self.target.FindBreakpointByID(unprotected_id)430 self.assertFalse(431 bkpt.IsValid(), "Protected too many breakpoints from deletion."432 )433 434 # Remake the unprotected breakpoint and try again from the command line:435 unprotected_bkpt = self.target.BreakpointCreateByLocation(436 self.main_file_spec, 10437 )438 unprotected_id = unprotected_bkpt.GetID()439 440 self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result)441 self.assertTrue(result.Succeeded())442 bkpt = self.target.FindBreakpointByID(protected_id)443 self.assertTrue(444 bkpt.IsValid(), "Didn't keep the breakpoint from being deleted."445 )446 bkpt = self.target.FindBreakpointByID(unprotected_id)447 self.assertFalse(448 bkpt.IsValid(), "Protected too many breakpoints from deletion."449 )450 451 def do_check_configuring_permissions_sb(self):452 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)453 454 # Make a breakpoint name with delete disallowed:455 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)456 self.assertTrue(457 bp_name.IsValid(), "Failed to make breakpoint name for valid name."458 )459 460 bp_name.SetAllowDelete(False)461 bp_name.SetAllowDisable(False)462 bp_name.SetAllowList(False)463 self.check_permission_results(bp_name)464 465 def do_check_configuring_permissions_cli(self):466 # Make the name with the right options using the command line:467 self.runCmd(468 "breakpoint name configure -L 0 -D 0 -A 0 %s" % (self.bp_name_string),469 check=True,470 )471 # Now look up the breakpoint we made, and check that it works.472 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string)473 self.assertTrue(474 bp_name.IsValid(), "Didn't make a breakpoint name we could find."475 )476 self.check_permission_results(bp_name)477