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