1""" 2Test 'watchpoint command'. 3""" 4 5 6import os 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class WatchpointPythonCommandTestCase(TestBase): 14 NO_DEBUG_INFO_TESTCASE = True 15 16 def setUp(self): 17 # Call super's setUp(). 18 TestBase.setUp(self) 19 # Our simple source filename. 20 self.source = "main.cpp" 21 # Find the line number to break inside main(). 22 self.line = line_number(self.source, "// Set break point at this line.") 23 self.second_line = line_number(self.source, "// Set another breakpoint here.") 24 # And the watchpoint variable declaration line number. 25 self.decl = line_number(self.source, "// Watchpoint variable declaration.") 26 # Build dictionary to have unique executable names for each test 27 # method. 28 self.exe_name = self.testMethodName 29 self.d = {"CXX_SOURCES": self.source, "EXE": self.exe_name} 30 31 def test_watchpoint_command(self): 32 """Test 'watchpoint command'.""" 33 self.build(dictionary=self.d) 34 self.setTearDownCleanup(dictionary=self.d) 35 36 exe = self.getBuildArtifact(self.exe_name) 37 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 38 39 # Add a breakpoint to set a watchpoint when stopped on the breakpoint. 40 lldbutil.run_break_set_by_file_and_line( 41 self, None, self.line, num_expected_locations=1 42 ) 43 44 # Run the program. 45 self.runCmd("run", RUN_SUCCEEDED) 46 47 # We should be stopped again due to the breakpoint. 48 # The stop reason of the thread should be breakpoint. 49 self.expect( 50 "thread list", 51 STOPPED_DUE_TO_BREAKPOINT, 52 substrs=["stopped", "stop reason = breakpoint"], 53 ) 54 55 # Now let's set a write-type watchpoint for 'global'. 56 self.expect( 57 "watchpoint set variable -w write global", 58 WATCHPOINT_CREATED, 59 substrs=[ 60 "Watchpoint created", 61 "size = 4", 62 "type = w", 63 "%s:%d" % (self.source, self.decl), 64 ], 65 ) 66 67 self.runCmd( 68 "watchpoint command add -s python 1 -o 'frame.EvaluateExpression(\"cookie = 777\")'" 69 ) 70 71 # List the watchpoint command we just added. 72 self.expect( 73 "watchpoint command list 1", 74 substrs=["frame.EvaluateExpression", "cookie = 777"], 75 ) 76 77 # Use the '-v' option to do verbose listing of the watchpoint. 78 # The hit count should be 0 initially. 79 self.expect("watchpoint list -v", substrs=["hit_count = 0"]) 80 81 self.runCmd("process continue") 82 83 # We should be stopped again due to the watchpoint (write type). 84 # The stop reason of the thread should be watchpoint. 85 self.expect( 86 "thread backtrace", 87 STOPPED_DUE_TO_WATCHPOINT, 88 substrs=["stop reason = watchpoint"], 89 ) 90 91 # Check that the watchpoint snapshoting mechanism is working. 92 self.expect("watchpoint list -v", substrs=["old value: 0", "new value: 1"]) 93 94 # The watchpoint command "forced" our global variable 'cookie' to 95 # become 777. 96 self.expect( 97 "frame variable --show-globals cookie", 98 substrs=["(int32_t)", "cookie = 777"], 99 ) 100 101 def test_continue_in_watchpoint_command(self): 102 """Test continue in a watchpoint command.""" 103 self.build(dictionary=self.d) 104 self.setTearDownCleanup(dictionary=self.d) 105 106 exe = self.getBuildArtifact(self.exe_name) 107 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 108 109 # Add a breakpoint to set a watchpoint when stopped on the breakpoint. 110 lldbutil.run_break_set_by_file_and_line( 111 self, None, self.line, num_expected_locations=1 112 ) 113 114 # Run the program. 115 self.runCmd("run", RUN_SUCCEEDED) 116 117 # We should be stopped again due to the breakpoint. 118 # The stop reason of the thread should be breakpoint. 119 self.expect( 120 "thread list", 121 STOPPED_DUE_TO_BREAKPOINT, 122 substrs=["stopped", "stop reason = breakpoint"], 123 ) 124 125 # Now let's set a write-type watchpoint for 'global'. 126 self.expect( 127 "watchpoint set variable -w write global", 128 WATCHPOINT_CREATED, 129 substrs=[ 130 "Watchpoint created", 131 "size = 4", 132 "type = w", 133 "%s:%d" % (self.source, self.decl), 134 ], 135 ) 136 137 cmd_script_file = os.path.join(self.getSourceDir(), "watchpoint_command.py") 138 self.runCmd("command script import '%s'" % (cmd_script_file)) 139 140 self.runCmd("watchpoint command add -F watchpoint_command.watchpoint_command") 141 142 # List the watchpoint command we just added. 143 self.expect( 144 "watchpoint command list 1", 145 substrs=["watchpoint_command.watchpoint_command"], 146 ) 147 148 self.runCmd("process continue") 149 150 # We should be stopped again due to the watchpoint (write type). 151 # The stop reason of the thread should be watchpoint. 152 self.expect( 153 "thread backtrace", 154 STOPPED_DUE_TO_WATCHPOINT, 155 substrs=["stop reason = watchpoint"], 156 ) 157 158 # We should have hit the watchpoint once, set cookie to 888, since the 159 # user callback returned True. 160 self.expect( 161 "frame variable --show-globals cookie", 162 substrs=["(int32_t)", "cookie = 888"], 163 ) 164 165 self.runCmd("process continue") 166 167 # We should be stopped again due to the watchpoint (write type). 168 # The stop reason of the thread should be watchpoint. 169 self.expect( 170 "thread backtrace", 171 STOPPED_DUE_TO_WATCHPOINT, 172 substrs=["stop reason = watchpoint"], 173 ) 174 175 # We should have hit the watchpoint a second time, set cookie to 666, 176 # even if the user callback didn't return anything and then continue. 177 self.expect( 178 "frame variable --show-globals cookie", 179 substrs=["(int32_t)", "cookie = 666"], 180 ) 181 182 # Add a breakpoint to set a watchpoint when stopped on the breakpoint. 183 lldbutil.run_break_set_by_file_and_line( 184 self, None, self.second_line, num_expected_locations=1 185 ) 186 187 self.runCmd("process continue") 188 189 self.expect( 190 "thread backtrace", 191 STOPPED_DUE_TO_BREAKPOINT, 192 substrs=["stop reason = breakpoint"], 193 ) 194 195 # We should have hit the watchpoint once, set cookie to 888, then continued to the 196 # second hit and set it to 999 197 self.expect( 198 "frame variable --show-globals cookie", 199 substrs=["(int32_t)", "cookie = 999"], 200 ) 201