1""" 2Test the "process continue -b" option. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class TestContinueToBkpts(TestBase): 13 14 NO_DEBUG_INFO_TESTCASE = True 15 mydir = TestBase.compute_mydir(__file__) 16 17 @add_test_categories(['pyapi']) 18 def test_continue_to_breakpoints(self): 19 """Test that the continue to breakpoints feature works correctly.""" 20 self.build() 21 self.do_test_continue_to_breakpoint() 22 23 def setUp(self): 24 # Call super's setUp(). 25 TestBase.setUp(self) 26 self.main_source_spec = lldb.SBFileSpec("main.c") 27 28 def continue_and_check(self, stop_list, bkpt_to_hit, loc_to_hit = 0): 29 """Build up a command that will run a continue -b commands using the breakpoints on stop_list, and 30 ensure that we hit bkpt_to_hit. 31 If loc_to_hit is not 0, also verify that we hit that location.""" 32 command = "process continue" 33 for elem in stop_list: 34 command += " -b {0}".format(elem) 35 self.expect(command) 36 self.assertEqual(self.thread.stop_reason, lldb.eStopReasonBreakpoint, "Hit a breakpoint") 37 self.assertEqual(self.thread.GetStopReasonDataAtIndex(0), bkpt_to_hit, "Hit the right breakpoint") 38 if loc_to_hit != 0: 39 self.assertEqual(self.thread.GetStopReasonDataAtIndex(1), loc_to_hit, "Hit the right location") 40 for bkpt_id in self.bkpt_list: 41 bkpt = self.target.FindBreakpointByID(bkpt_id) 42 self.assertTrue(bkpt.IsValid(), "Breakpoint id's round trip") 43 if bkpt.MatchesName("disabled"): 44 self.assertFalse(bkpt.IsEnabled(), "Disabled breakpoints stay disabled: {0}".format(bkpt.GetID())) 45 else: 46 self.assertTrue(bkpt.IsEnabled(), "Enabled breakpoints stay enabled: {0}".format(bkpt.GetID())) 47 # Also do our multiple location one: 48 bkpt = self.target.FindBreakpointByID(self.multiple_loc_id) 49 self.assertTrue(bkpt.IsValid(), "Breakpoint with locations round trip") 50 for i in range(1,3): 51 loc = bkpt.FindLocationByID(i) 52 self.assertTrue(loc.IsValid(), "Locations round trip") 53 if i == 2: 54 self.assertTrue(loc.IsEnabled(), "Locations that were enabled stay enabled") 55 else: 56 self.assertFalse(loc.IsEnabled(), "Locations that were disabled stay disabled") 57 58 def do_test_continue_to_breakpoint(self): 59 """Test the continue to breakpoint feature.""" 60 (self.target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 61 "Stop here to get started", self.main_source_spec) 62 63 # Now set up all our breakpoints: 64 bkpt_pattern = "This is the {0} stop" 65 bkpt_elements = ["zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"] 66 disabled_bkpts = ["first", "eigth"] 67 bkpts_for_MyBKPT = ["first", "sixth", "nineth"] 68 self.bkpt_list = [] 69 for elem in bkpt_elements: 70 bkpt = self.target.BreakpointCreateBySourceRegex(bkpt_pattern.format(elem), self.main_source_spec) 71 self.assertGreater(bkpt.GetNumLocations(), 0, "Found a bkpt match") 72 self.bkpt_list.append(bkpt.GetID()) 73 bkpt.AddName(elem) 74 if elem in disabled_bkpts: 75 bkpt.AddName("disabled") 76 bkpt.SetEnabled(False) 77 if elem in bkpts_for_MyBKPT: 78 bkpt.AddName("MyBKPT") 79 # Also make one that has several locations, so we can test locations: 80 mult_bkpt = self.target.BreakpointCreateBySourceRegex(bkpt_pattern.format("(seventh|eighth|nineth)"), self.main_source_spec) 81 self.assertEqual(mult_bkpt.GetNumLocations(), 3, "Got three matches") 82 mult_bkpt.AddName("Locations") 83 # Disable all of these: 84 for i in range(1,4): 85 loc = mult_bkpt.FindLocationByID(i) 86 self.assertTrue(loc.IsValid(), "Location {0} is valid".format(i)) 87 loc.SetEnabled(False) 88 self.assertFalse(loc.IsEnabled(), "Loc {0} wasn't disabled".format(i)) 89 self.multiple_loc_id = mult_bkpt.GetID() 90 91 # First test out various error conditions 92 93 # All locations of the multiple_loc_id are disabled, so running to this should be an error: 94 self.expect("process continue -b {0}".format(self.multiple_loc_id), error=True, msg="Running to a disabled breakpoint by number") 95 96 # Now re-enable the middle one so we can run to it: 97 loc = mult_bkpt.FindLocationByID(2) 98 loc.SetEnabled(True) 99 100 self.expect("process continue -b {0}".format(self.bkpt_list[1]), error=True, msg="Running to a disabled breakpoint by number") 101 self.expect("process continue -b {0}.1".format(self.bkpt_list[1]), error=True, msg="Running to a location of a disabled breakpoint") 102 self.expect("process continue -b disabled", error=True, msg="Running to a disabled set of breakpoints") 103 self.expect("process continue -b {0}.{1}".format(self.multiple_loc_id, 1), error=True, msg="Running to a disabled breakpoint location") 104 self.expect("process continue -b {0}".format("THERE_ARE_NO_BREAKPOINTS_BY_THIS_NAME"), error=True, msg="Running to no such name") 105 self.expect("process continue -b {0}".format(1000), error=True, msg="Running to no such breakpoint") 106 self.expect("process continue -b {0}.{1}".format(self.multiple_loc_id, 1000), error=True, msg="Running to no such location") 107 108 # Now move forward, this time with breakpoint numbers. First time we don't skip other bkpts. 109 bkpt = self.bkpt_list[0] 110 self.continue_and_check([str(bkpt)], bkpt) 111 112 # Now skip to the third stop, do it by name and supply one of the later breakpoints as well: 113 # This continue has to muck with the sync mode of the debugger, so let's make sure we 114 # put it back. First try if it was in sync mode: 115 orig_async = self.dbg.GetAsync() 116 self.dbg.SetAsync(True) 117 self.continue_and_check([bkpt_elements[2], bkpt_elements[7]], self.bkpt_list[2]) 118 after_value = self.dbg.GetAsync() 119 self.dbg.SetAsync(orig_async) 120 self.assertTrue(after_value, "Preserve async as True if it started that way") 121 122 # Now try a name that has several breakpoints. 123 # This time I'm also going to check that we put the debugger async mode back if 124 # if was False to begin with: 125 self.dbg.SetAsync(False) 126 self.continue_and_check(["MyBKPT"], self.bkpt_list[6]) 127 after_value = self.dbg.GetAsync() 128 self.dbg.SetAsync(orig_async) 129 self.assertFalse(after_value, "Preserve async as False if it started that way") 130 131 # Now let's run to a particular location. Also specify a breakpoint we've already hit: 132 self.continue_and_check([self.bkpt_list[0], self.multiple_loc_id], self.multiple_loc_id, 2) 133