1""" 2Test breakpoint ignore count features. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class BreakpointIgnoreCountTestCase(TestBase): 13 @skipIfWindows # This test will hang on windows llvm.org/pr21753 14 def test_with_run_command(self): 15 """Exercise breakpoint ignore count with 'breakpoint set -i <count>'.""" 16 self.build() 17 self.breakpoint_ignore_count() 18 19 @add_test_categories(["pyapi"]) 20 @skipIfWindows # This test will hang on windows llvm.org/pr21753 21 def test_with_python_api(self): 22 """Use Python APIs to set breakpoint ignore count.""" 23 self.build() 24 self.breakpoint_ignore_count_python() 25 26 @skipIfWindows # This test will hang on windows llvm.org/pr21753 27 def test_ignore_vrs_condition_bkpt(self): 28 self.build() 29 self.ignore_vrs_condition(False) 30 31 @skipIfWindows # This test will hang on windows llvm.org/pr21753 32 def test_ignore_vrs_condition_loc(self): 33 self.build() 34 self.ignore_vrs_condition(True) 35 36 def setUp(self): 37 # Call super's setUp(). 38 TestBase.setUp(self) 39 # Find the line number to of function 'c'. 40 self.stop_in_main = "Stop here at start of main" 41 self.line1 = line_number( 42 "main.c", '// Find the line number of function "c" here.' 43 ) 44 self.line2 = line_number( 45 "main.c", "// b(2) -> c(2) Find the call site of b(2)." 46 ) 47 self.line3 = line_number( 48 "main.c", "// a(3) -> c(3) Find the call site of c(3)." 49 ) 50 self.line4 = line_number( 51 "main.c", "// a(3) -> c(3) Find the call site of a(3)." 52 ) 53 self.line5 = line_number("main.c", "// Find the call site of c in main.") 54 55 def breakpoint_ignore_count(self): 56 """Exercise breakpoint ignore count with 'breakpoint set -i <count>'.""" 57 exe = self.getBuildArtifact("a.out") 58 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 59 60 # Create a breakpoint in main.c at line1. 61 lldbutil.run_break_set_by_file_and_line( 62 self, 63 "main.c", 64 self.line1, 65 extra_options="-i 1", 66 num_expected_locations=1, 67 loc_exact=True, 68 ) 69 70 # Now run the program. 71 self.runCmd("run", RUN_SUCCEEDED) 72 73 # The process should be stopped at this point. 74 self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"]) 75 76 # Also check the hit count, which should be 2, due to ignore count of 77 # 1. 78 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=2) 79 80 # The frame #0 should correspond to main.c:37, the executable statement 81 # in function name 'c'. And frame #2 should point to main.c:45. 82 self.expect( 83 "thread backtrace", 84 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, 85 # substrs = ["stop reason = breakpoint"], 86 patterns=[ 87 "frame #0.*main.c:%d" % self.line1, 88 "frame #2.*main.c:%d" % self.line2, 89 ], 90 ) 91 92 # continue -i 1 is the same as setting the ignore count to 1 again, try that: 93 # Now run the program. 94 self.runCmd("process continue -i 1", RUN_SUCCEEDED) 95 96 # The process should be stopped at this point. 97 self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"]) 98 99 # Also check the hit count, which should be 2, due to ignore count of 100 # 1. 101 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=4) 102 103 # The frame #0 should correspond to main.c:37, the executable statement 104 # in function name 'c'. And frame #2 should point to main.c:45. 105 self.expect( 106 "thread backtrace", 107 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, 108 # substrs = ["stop reason = breakpoint"], 109 patterns=[ 110 "frame #0.*main.c:%d" % self.line1, 111 "frame #1.*main.c:%d" % self.line5, 112 ], 113 ) 114 115 def breakpoint_ignore_count_python(self): 116 """Use Python APIs to set breakpoint ignore count.""" 117 target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( 118 self, self.stop_in_main, lldb.SBFileSpec("main.c") 119 ) 120 # Now create a breakpoint on main.c by name 'c'. 121 breakpoint = target.BreakpointCreateByName("c", "a.out") 122 self.assertTrue( 123 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT 124 ) 125 126 # Get the breakpoint location from breakpoint after we verified that, 127 # indeed, it has one location. 128 location = breakpoint.GetLocationAtIndex(0) 129 self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION) 130 131 # Set the ignore count on the breakpoint location. 132 location.SetIgnoreCount(2) 133 self.assertEqual( 134 location.GetIgnoreCount(), 2, "SetIgnoreCount() works correctly" 135 ) 136 137 # Now continue and hit our breakpoint on c: 138 process.Continue() 139 140 # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and 141 # frame#2 should be on main.c:48. 142 # lldbutil.print_stacktraces(process) 143 from lldbsuite.test.lldbutil import get_stopped_thread 144 145 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) 146 self.assertTrue( 147 thread.IsValid(), "There should be a thread stopped due to breakpoint" 148 ) 149 frame0 = thread.GetFrameAtIndex(0) 150 frame1 = thread.GetFrameAtIndex(1) 151 frame2 = thread.GetFrameAtIndex(2) 152 self.assertTrue( 153 frame0.GetLineEntry().GetLine() == self.line1 154 and frame1.GetLineEntry().GetLine() == self.line3 155 and frame2.GetLineEntry().GetLine() == self.line4, 156 STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT, 157 ) 158 159 # The hit count for the breakpoint should be 3. 160 self.assertEqual(breakpoint.GetHitCount(), 3) 161 162 def ignore_vrs_condition(self, use_location): 163 main_spec = lldb.SBFileSpec("main.c") 164 target, process, _, _ = lldbutil.run_to_source_breakpoint( 165 self, self.stop_in_main, main_spec 166 ) 167 168 # Now make a breakpoint on the loop, and set a condition and ignore count. 169 # Make sure that the condition fails don't count against the ignore count. 170 bkpt = target.BreakpointCreateBySourceRegex( 171 "Set a breakpoint here, with i", main_spec 172 ) 173 self.assertEqual(bkpt.GetNumLocations(), 1, "Wrong number of locations") 174 175 if use_location: 176 loc = bkpt.location[0] 177 self.assertTrue(loc.IsValid(), "Got a valid location") 178 loc.SetIgnoreCount(2) 179 loc.SetCondition("i >= 3") 180 else: 181 bkpt.SetIgnoreCount(2) 182 bkpt.SetCondition("i >= 3") 183 184 threads = lldbutil.continue_to_breakpoint(process, bkpt) 185 self.assertEqual(len(threads), 1, "Hit the breakpoint") 186 var = threads[0].frame[0].FindVariable("i") 187 self.assertTrue(var.IsValid(), "Didn't find the i variable") 188 val = var.GetValueAsUnsigned(10000) 189 self.assertNotEqual(val, 10000, "Got the fail value for i") 190 self.assertEqual(val, 5, "We didn't stop the right number of times") 191 self.assertEqual(bkpt.GetHitCount(), 3, "Hit count is not right") 192