1""" 2Test breakpoint names. 3""" 4 5 6 7import os 8import lldb 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12 13 14class BreakpointNames(TestBase): 15 16 mydir = TestBase.compute_mydir(__file__) 17 NO_DEBUG_INFO_TESTCASE = True 18 19 @add_test_categories(['pyapi']) 20 def test_setting_names(self): 21 """Use Python APIs to test that we can set breakpoint names.""" 22 self.build() 23 self.setup_target() 24 self.do_check_names() 25 26 def test_illegal_names(self): 27 """Use Python APIs to test that we don't allow illegal names.""" 28 self.build() 29 self.setup_target() 30 self.do_check_illegal_names() 31 32 def test_using_names(self): 33 """Use Python APIs to test that operations on names works correctly.""" 34 self.build() 35 self.setup_target() 36 self.do_check_using_names() 37 38 def test_configuring_names(self): 39 """Use Python APIs to test that configuring options on breakpoint names works correctly.""" 40 self.build() 41 self.make_a_dummy_name() 42 self.setup_target() 43 self.do_check_configuring_names() 44 45 def test_configuring_permissions_sb(self): 46 """Use Python APIs to test that configuring permissions on names works correctly.""" 47 self.build() 48 self.setup_target() 49 self.do_check_configuring_permissions_sb() 50 51 def test_configuring_permissions_cli(self): 52 """Use Python APIs to test that configuring permissions on names works correctly.""" 53 self.build() 54 self.setup_target() 55 self.do_check_configuring_permissions_cli() 56 57 def setup_target(self): 58 exe = self.getBuildArtifact("a.out") 59 60 # Create a targets we are making breakpoint in and copying to: 61 self.target = self.dbg.CreateTarget(exe) 62 self.assertTrue(self.target, VALID_TARGET) 63 self.main_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "main.c")) 64 65 def check_name_in_target(self, bkpt_name): 66 name_list = lldb.SBStringList() 67 self.target.GetBreakpointNames(name_list) 68 found_it = False 69 for name in name_list: 70 if name == bkpt_name: 71 found_it = True 72 break 73 self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name)) 74 75 def setUp(self): 76 # Call super's setUp(). 77 TestBase.setUp(self) 78 79 # These are the settings we're going to be putting into names & breakpoints: 80 self.bp_name_string = "ABreakpoint" 81 self.is_one_shot = True 82 self.ignore_count = 1000 83 self.condition = "1 == 2" 84 self.auto_continue = True 85 self.tid = 0xaaaa 86 self.tidx = 10 87 self.thread_name = "Fooey" 88 self.queue_name = "Blooey" 89 self.cmd_list = lldb.SBStringList() 90 self.cmd_list.AppendString("frame var") 91 self.cmd_list.AppendString("bt") 92 self.help_string = "I do something interesting" 93 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(matches, "Adding a name means we didn't match the name we just set") 120 self.check_name_in_target(other_bkpt_name) 121 122 # Remove the name and make sure we no longer match it: 123 bkpt.RemoveName(bkpt_name) 124 matches = bkpt.MatchesName(bkpt_name) 125 self.assertTrue(not matches,"We still match a name after removing it.") 126 127 # Make sure the name list has the remaining name: 128 name_list = lldb.SBStringList() 129 bkpt.GetNames(name_list) 130 num_names = name_list.GetSize() 131 self.assertEquals(num_names, 1, "Name list has %d items, expected 1."%(num_names)) 132 133 name = name_list.GetStringAtIndex(0) 134 self.assertEquals(name, other_bkpt_name, "Remaining name was: %s expected %s."%(name, other_bkpt_name)) 135 136 def do_check_illegal_names(self): 137 """Use Python APIs to check that we reject illegal names.""" 138 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 139 bad_names = ["-CantStartWithADash", 140 "1CantStartWithANumber", 141 "^CantStartWithNonAlpha", 142 "CantHave-ADash", 143 "Cant Have Spaces"] 144 for bad_name in bad_names: 145 success = bkpt.AddNameWithErrorHandling(bad_name) 146 self.assertTrue(success.Fail(), "We allowed an illegal name: %s"%(bad_name)) 147 bp_name = lldb.SBBreakpointName(self.target, bad_name) 148 self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name)); 149 150 retval =lldb.SBCommandReturnObject() 151 self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval) 152 self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name)) 153 154 def do_check_using_names(self): 155 """Use Python APIs to check names work in place of breakpoint ID's.""" 156 157 # Create a dummy breakpoint to use up ID 1 158 _ = self.target.BreakpointCreateByLocation(self.main_file_spec, 30) 159 160 # Create a breakpoint to test with 161 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 162 bkpt_name = "ABreakpoint" 163 bkpt_id = bkpt.GetID() 164 other_bkpt_name= "_AnotherBreakpoint" 165 166 # Add a name and make sure we match it: 167 success = bkpt.AddNameWithErrorHandling(bkpt_name) 168 self.assertSuccess(success, "We couldn't add a legal name to a breakpoint.") 169 170 bkpts = lldb.SBBreakpointList(self.target) 171 self.target.FindBreakpointsByName(bkpt_name, bkpts) 172 173 self.assertEquals(bkpts.GetSize(), 1, "One breakpoint matched.") 174 found_bkpt = bkpts.GetBreakpointAtIndex(0) 175 self.assertEquals(bkpt.GetID(), found_bkpt.GetID(),"The right breakpoint.") 176 self.assertEquals(bkpt.GetID(), bkpt_id,"With the same ID as before.") 177 178 retval = lldb.SBCommandReturnObject() 179 self.dbg.GetCommandInterpreter().HandleCommand("break disable %s"%(bkpt_name), retval) 180 self.assertTrue(retval.Succeeded(), "break disable failed with: %s."%(retval.GetError())) 181 self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.") 182 183 # Also make sure we don't apply commands to non-matching names: 184 self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval) 185 self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError())) 186 self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.") 187 188 def check_option_values(self, bp_object): 189 self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot") 190 self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount") 191 self.assertEqual(bp_object.GetCondition(), self.condition, "Condition") 192 self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue") 193 self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID") 194 self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index") 195 self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name") 196 self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name") 197 set_cmds = lldb.SBStringList() 198 bp_object.GetCommandLineCommands(set_cmds) 199 self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands") 200 for idx in range(0, set_cmds.GetSize()): 201 self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx)) 202 203 def make_a_dummy_name(self): 204 "This makes a breakpoint name in the dummy target to make sure it gets copied over" 205 206 dummy_target = self.dbg.GetDummyTarget() 207 self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.") 208 209 def cleanup (): 210 self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string) 211 212 # Execute the cleanup function during test case tear down. 213 self.addTearDownHook(cleanup) 214 215 # Now find it in the dummy target, and make sure these settings took: 216 bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) 217 # Make sure the name is right: 218 self.assertEqual(bp_name.GetName(), self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName())) 219 bp_name.SetOneShot(self.is_one_shot) 220 bp_name.SetIgnoreCount(self.ignore_count) 221 bp_name.SetCondition(self.condition) 222 bp_name.SetAutoContinue(self.auto_continue) 223 bp_name.SetThreadID(self.tid) 224 bp_name.SetThreadIndex(self.tidx) 225 bp_name.SetThreadName(self.thread_name) 226 bp_name.SetQueueName(self.queue_name) 227 bp_name.SetCommandLineCommands(self.cmd_list) 228 229 # Now look it up again, and make sure it got set correctly. 230 bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) 231 self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") 232 self.check_option_values(bp_name) 233 234 def do_check_configuring_names(self): 235 """Use Python APIs to check that configuring breakpoint names works correctly.""" 236 other_bp_name_string = "AnotherBreakpointName" 237 cl_bp_name_string = "CLBreakpointName" 238 239 # Now find the version copied in from the dummy target, and make sure these settings took: 240 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) 241 self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") 242 self.check_option_values(bp_name) 243 244 # Now add this name to a breakpoint, and make sure it gets configured properly 245 bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 246 success = bkpt.AddNameWithErrorHandling(self.bp_name_string) 247 self.assertSuccess(success, "Couldn't add this name to the breakpoint") 248 self.check_option_values(bkpt) 249 250 # Now make a name from this breakpoint, and make sure the new name is properly configured: 251 new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string) 252 self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.") 253 self.check_option_values(bkpt) 254 255 # Now change the name's option and make sure it gets propagated to 256 # the breakpoint: 257 new_auto_continue = not self.auto_continue 258 bp_name.SetAutoContinue(new_auto_continue) 259 self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name") 260 self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.") 261 262 # Now make this same breakpoint name - but from the command line 263 cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"%(cl_bp_name_string, 264 self.is_one_shot, 265 self.ignore_count, 266 self.condition, 267 self.auto_continue, 268 self.tid, 269 self.tidx, 270 self.thread_name, 271 self.queue_name, 272 self.help_string) 273 for cmd in self.cmd_list: 274 cmd_str += " -C '%s'"%(cmd) 275 276 self.runCmd(cmd_str, check=True) 277 # Now look up this name again and check its options: 278 cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string) 279 self.check_option_values(cl_name) 280 # Also check the help string: 281 self.assertEqual(self.help_string, cl_name.GetHelpString(), "Help string didn't match") 282 # Change the name and make sure that works: 283 new_help = "I do something even more interesting" 284 cl_name.SetHelpString(new_help) 285 self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't") 286 287 # We should have three names now, make sure the target can list them: 288 name_list = lldb.SBStringList() 289 self.target.GetBreakpointNames(name_list) 290 for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]: 291 self.assertIn(name_string, name_list, "Didn't find %s in names"%(name_string)) 292 293 # Delete the name from the current target. Make sure that works and deletes the 294 # name from the breakpoint as well: 295 self.target.DeleteBreakpointName(self.bp_name_string) 296 name_list.Clear() 297 self.target.GetBreakpointNames(name_list) 298 self.assertNotIn(self.bp_name_string, name_list, "Didn't delete %s from a real target"%(self.bp_name_string)) 299 # Also make sure the name got removed from breakpoints holding it: 300 self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") 301 302 # Test that deleting the name we injected into the dummy target works (there's also a 303 # cleanup that will do this, but that won't test the result... 304 dummy_target = self.dbg.GetDummyTarget() 305 dummy_target.DeleteBreakpointName(self.bp_name_string) 306 name_list.Clear() 307 dummy_target.GetBreakpointNames(name_list) 308 self.assertNotIn(self.bp_name_string, name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string)) 309 # Also make sure the name got removed from breakpoints holding it: 310 self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") 311 312 def check_permission_results(self, bp_name): 313 self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.") 314 protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 315 protected_id = protected_bkpt.GetID() 316 317 unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 318 unprotected_id = unprotected_bkpt.GetID() 319 320 success = protected_bkpt.AddNameWithErrorHandling(self.bp_name_string) 321 self.assertSuccess(success, "Couldn't add this name to the breakpoint") 322 323 self.target.DisableAllBreakpoints() 324 self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") 325 self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") 326 327 # Try from the command line too: 328 unprotected_bkpt.SetEnabled(True) 329 result = lldb.SBCommandReturnObject() 330 self.dbg.GetCommandInterpreter().HandleCommand("break disable", result) 331 self.assertTrue(result.Succeeded()) 332 self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") 333 self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") 334 335 self.target.DeleteAllBreakpoints() 336 bkpt = self.target.FindBreakpointByID(protected_id) 337 self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") 338 bkpt = self.target.FindBreakpointByID(unprotected_id) 339 self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") 340 341 # Remake the unprotected breakpoint and try again from the command line: 342 unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) 343 unprotected_id = unprotected_bkpt.GetID() 344 345 self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result) 346 self.assertTrue(result.Succeeded()) 347 bkpt = self.target.FindBreakpointByID(protected_id) 348 self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") 349 bkpt = self.target.FindBreakpointByID(unprotected_id) 350 self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") 351 352 def do_check_configuring_permissions_sb(self): 353 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) 354 355 # Make a breakpoint name with delete disallowed: 356 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) 357 self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.") 358 359 bp_name.SetAllowDelete(False) 360 bp_name.SetAllowDisable(False) 361 bp_name.SetAllowList(False) 362 self.check_permission_results(bp_name) 363 364 def do_check_configuring_permissions_cli(self): 365 # Make the name with the right options using the command line: 366 self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True) 367 # Now look up the breakpoint we made, and check that it works. 368 bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) 369 self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.") 370 self.check_permission_results(bp_name) 371