xref: /llvm-project/lldb/test/API/commands/watchpoints/watchpoint_commands/TestWatchpointCommands.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""
2Test watchpoint list, enable, disable, and delete commands.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class WatchpointCommandsTestCase(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14
15    def setUp(self):
16        # Call super's setUp().
17        TestBase.setUp(self)
18        # Our simple source filename.
19        self.source = "main.c"
20        # Find the line number to break inside main().
21        self.line = line_number(self.source, "// Set break point at this line.")
22        self.line2 = line_number(
23            self.source, "// Set 2nd break point for disable_then_enable test case."
24        )
25        # And the watchpoint variable declaration line number.
26        self.decl = line_number(self.source, "// Watchpoint variable declaration.")
27        # Build dictionary to have unique executable names for each test
28        # method.
29        self.exe_name = self.testMethodName
30        self.d = {"C_SOURCES": self.source, "EXE": self.exe_name}
31
32    # Read-write watchpoints not supported on SystemZ
33    @expectedFailureAll(archs=["s390x"])
34    def test_rw_watchpoint(self):
35        """Test read_write watchpoint and expect to stop two times."""
36        self.build(dictionary=self.d)
37        self.setTearDownCleanup(dictionary=self.d)
38
39        exe = self.getBuildArtifact(self.exe_name)
40        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
41
42        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
43        lldbutil.run_break_set_by_file_and_line(
44            self, None, self.line, num_expected_locations=1
45        )
46
47        # Run the program.
48        self.runCmd("run", RUN_SUCCEEDED)
49
50        # We should be stopped again due to the breakpoint.
51        # The stop reason of the thread should be breakpoint.
52        self.expect(
53            "thread list",
54            STOPPED_DUE_TO_BREAKPOINT,
55            substrs=["stopped", "stop reason = breakpoint"],
56        )
57
58        # Now let's set a read_write-type watchpoint for 'global'.
59        # There should be two watchpoint hits (see main.c).
60        self.expect(
61            "watchpoint set variable -w read_write global",
62            WATCHPOINT_CREATED,
63            substrs=[
64                "Watchpoint created",
65                "size = 4",
66                "type = rw",
67                "%s:%d" % (self.source, self.decl),
68            ],
69        )
70
71        # Use the '-v' option to do verbose listing of the watchpoint.
72        # The hit count should be 0 initially.
73        self.expect(
74            "watchpoint list -v",
75            substrs=["Number of supported hardware watchpoints:", "hit_count = 0"],
76        )
77
78        self.runCmd("process continue")
79
80        # We should be stopped again due to the watchpoint (read_write type).
81        # The stop reason of the thread should be watchpoint.
82        self.expect(
83            "thread backtrace",
84            STOPPED_DUE_TO_WATCHPOINT,
85            substrs=["stop reason = watchpoint"],
86        )
87
88        self.runCmd("process continue")
89
90        # We should be stopped again due to the watchpoint (read_write type).
91        # The stop reason of the thread should be watchpoint.
92        self.expect(
93            "thread backtrace",
94            STOPPED_DUE_TO_WATCHPOINT,
95            substrs=["stop reason = watchpoint"],
96        )
97
98        self.runCmd("process continue")
99
100        # There should be no more watchpoint hit and the process status should
101        # be 'exited'.
102        self.expect("process status", substrs=["exited"])
103
104        # Use the '-v' option to do verbose listing of the watchpoint.
105        # The hit count should now be 2.
106        self.expect("watchpoint list -v", substrs=["hit_count = 2"])
107
108    # Read-write watchpoints not supported on SystemZ
109    @expectedFailureAll(archs=["s390x"])
110    def test_rw_watchpoint_delete(self):
111        """Test delete watchpoint and expect not to stop for watchpoint."""
112        self.build()
113        lldbutil.run_to_line_breakpoint(self, lldb.SBFileSpec(self.source), self.line)
114
115        # Now let's set a read_write-type watchpoint for 'global'.
116        # There should be two watchpoint hits (see main.c).
117        self.expect(
118            "watchpoint set variable -w read_write global",
119            WATCHPOINT_CREATED,
120            substrs=[
121                "Watchpoint created",
122                "size = 4",
123                "type = rw",
124                "%s:%d" % (self.source, self.decl),
125            ],
126        )
127
128        # Delete the watchpoint immediately, but set auto-confirm to true
129        # first.
130        self.runCmd("settings set auto-confirm true")
131        self.expect("watchpoint delete", substrs=["All watchpoints removed."])
132        # Restore the original setting of auto-confirm.
133        self.runCmd("settings clear auto-confirm")
134
135        target = self.dbg.GetSelectedTarget()
136        self.assertTrue(target and not target.GetNumWatchpoints())
137
138        # Now let's set a read_write-type watchpoint for 'global'.
139        # There should be two watchpoint hits (see main.c).
140        self.expect(
141            "watchpoint set variable -w read_write global",
142            WATCHPOINT_CREATED,
143            substrs=[
144                "Watchpoint created",
145                "size = 4",
146                "type = rw",
147                "%s:%d" % (self.source, self.decl),
148            ],
149        )
150
151        # Delete the watchpoint immediately using the force option.
152        self.expect("watchpoint delete --force", substrs=["All watchpoints removed."])
153
154        self.assertTrue(target and not target.GetNumWatchpoints())
155
156        self.runCmd("process continue")
157
158        # There should be no more watchpoint hit and the process status should
159        # be 'exited'.
160        self.expect("process status", substrs=["exited"])
161
162    # Read-write watchpoints not supported on SystemZ
163    @expectedFailureAll(archs=["s390x"])
164    def test_rw_watchpoint_set_ignore_count(self):
165        """Test watchpoint ignore count and expect to not to stop at all."""
166        self.build(dictionary=self.d)
167        self.setTearDownCleanup(dictionary=self.d)
168
169        exe = self.getBuildArtifact(self.exe_name)
170        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
171
172        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
173        lldbutil.run_break_set_by_file_and_line(
174            self, None, self.line, num_expected_locations=1
175        )
176
177        # Run the program.
178        self.runCmd("run", RUN_SUCCEEDED)
179
180        # We should be stopped again due to the breakpoint.
181        # The stop reason of the thread should be breakpoint.
182        self.expect(
183            "thread list",
184            STOPPED_DUE_TO_BREAKPOINT,
185            substrs=["stopped", "stop reason = breakpoint"],
186        )
187
188        # Now let's set a read_write-type watchpoint for 'global'.
189        # There should be two watchpoint hits (see main.c).
190        self.expect(
191            "watchpoint set variable -w read_write global",
192            WATCHPOINT_CREATED,
193            substrs=[
194                "Watchpoint created",
195                "size = 4",
196                "type = rw",
197                "%s:%d" % (self.source, self.decl),
198            ],
199        )
200
201        # Set the ignore count of the watchpoint immediately.
202        self.expect("watchpoint ignore -i 2", substrs=["All watchpoints ignored."])
203
204        # Use the '-v' option to do verbose listing of the watchpoint.
205        # Expect to find an ignore_count of 2.
206        self.expect("watchpoint list -v", substrs=["hit_count = 0", "ignore_count = 2"])
207
208        self.runCmd("process continue")
209
210        # There should be no more watchpoint hit and the process status should
211        # be 'exited'.
212        self.expect("process status", substrs=["exited"])
213
214        # Use the '-v' option to do verbose listing of the watchpoint.
215        # Expect to find a hit_count of 2 as well.
216        self.expect("watchpoint list -v", substrs=["hit_count = 2", "ignore_count = 2"])
217
218    # Read-write watchpoints not supported on SystemZ
219    @expectedFailureAll(archs=["s390x"])
220    def test_rw_disable_after_first_stop(self):
221        """Test read_write watchpoint but disable it after the first stop."""
222        self.build(dictionary=self.d)
223        self.setTearDownCleanup(dictionary=self.d)
224
225        exe = self.getBuildArtifact(self.exe_name)
226        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
227
228        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
229        lldbutil.run_break_set_by_file_and_line(
230            self, None, self.line, num_expected_locations=1
231        )
232
233        # Run the program.
234        self.runCmd("run", RUN_SUCCEEDED)
235
236        # We should be stopped again due to the breakpoint.
237        # The stop reason of the thread should be breakpoint.
238        self.expect(
239            "thread list",
240            STOPPED_DUE_TO_BREAKPOINT,
241            substrs=["stopped", "stop reason = breakpoint"],
242        )
243
244        # Now let's set a read_write-type watchpoint for 'global'.
245        # There should be two watchpoint hits (see main.c).
246        self.expect(
247            "watchpoint set variable -w read_write global",
248            WATCHPOINT_CREATED,
249            substrs=[
250                "Watchpoint created",
251                "size = 4",
252                "type = rw",
253                "%s:%d" % (self.source, self.decl),
254            ],
255        )
256
257        # Use the '-v' option to do verbose listing of the watchpoint.
258        # The hit count should be 0 initially.
259        self.expect("watchpoint list -v", substrs=["state = enabled", "hit_count = 0"])
260
261        self.runCmd("process continue")
262
263        # We should be stopped again due to the watchpoint (read_write type).
264        # The stop reason of the thread should be watchpoint.
265        self.expect(
266            "thread backtrace",
267            STOPPED_DUE_TO_WATCHPOINT,
268            substrs=["stop reason = watchpoint"],
269        )
270
271        # Before continuing, we'll disable the watchpoint, which means we won't
272        # stop again after this.
273        self.runCmd("watchpoint disable")
274
275        self.expect("watchpoint list -v", substrs=["state = disabled", "hit_count = 1"])
276
277        self.runCmd("process continue")
278
279        # There should be no more watchpoint hit and the process status should
280        # be 'exited'.
281        self.expect("process status", substrs=["exited"])
282
283        # Use the '-v' option to do verbose listing of the watchpoint.
284        # The hit count should be 1.
285        self.expect("watchpoint list -v", substrs=["hit_count = 1"])
286
287    # Read-write watchpoints not supported on SystemZ
288    @expectedFailureAll(archs=["s390x"])
289    def test_rw_disable_then_enable(self):
290        """Test read_write watchpoint, disable initially, then enable it."""
291        self.build(dictionary=self.d)
292        self.setTearDownCleanup(dictionary=self.d)
293
294        exe = self.getBuildArtifact(self.exe_name)
295        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
296
297        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
298        lldbutil.run_break_set_by_file_and_line(
299            self, None, self.line, num_expected_locations=1
300        )
301        lldbutil.run_break_set_by_file_and_line(
302            self, None, self.line2, num_expected_locations=1
303        )
304
305        # Run the program.
306        self.runCmd("run", RUN_SUCCEEDED)
307
308        # We should be stopped again due to the breakpoint.
309        # The stop reason of the thread should be breakpoint.
310        self.expect(
311            "thread list",
312            STOPPED_DUE_TO_BREAKPOINT,
313            substrs=["stopped", "stop reason = breakpoint"],
314        )
315
316        # Now let's set a read_write-type watchpoint for 'global'.
317        # There should be two watchpoint hits (see main.c).
318        self.expect(
319            "watchpoint set variable -w read_write global",
320            WATCHPOINT_CREATED,
321            substrs=[
322                "Watchpoint created",
323                "size = 4",
324                "type = rw",
325                "%s:%d" % (self.source, self.decl),
326            ],
327        )
328
329        # Immediately, we disable the watchpoint.  We won't be stopping due to a
330        # watchpoint after this.
331        self.runCmd("watchpoint disable")
332
333        # Use the '-v' option to do verbose listing of the watchpoint.
334        # The hit count should be 0 initially.
335        self.expect("watchpoint list -v", substrs=["state = disabled", "hit_count = 0"])
336
337        self.runCmd("process continue")
338
339        # We should be stopped again due to the breakpoint.
340        self.expect(
341            "thread backtrace",
342            STOPPED_DUE_TO_BREAKPOINT,
343            substrs=["stop reason = breakpoint"],
344        )
345
346        # Before continuing, we'll enable the watchpoint, which means we will
347        # stop again after this.
348        self.runCmd("watchpoint enable")
349
350        self.expect("watchpoint list -v", substrs=["state = enabled", "hit_count = 0"])
351
352        self.runCmd("process continue")
353
354        # We should be stopped again due to the watchpoint (read_write type).
355        # The stop reason of the thread should be watchpoint.
356        self.expect(
357            "thread backtrace",
358            STOPPED_DUE_TO_WATCHPOINT,
359            substrs=["stop reason = watchpoint"],
360        )
361
362        self.runCmd("process continue")
363
364        # There should be no more watchpoint hit and the process status should
365        # be 'exited'.
366        self.expect("process status", substrs=["exited"])
367
368        # Use the '-v' option to do verbose listing of the watchpoint.
369        # The hit count should be 1.
370        self.expect("watchpoint list -v", substrs=["hit_count = 1"])
371