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