1"""
2Test 'watchpoint command'.
3"""
4
5
6
7import os
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class WatchpointPythonCommandTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17    NO_DEBUG_INFO_TESTCASE = True
18
19    def setUp(self):
20        # Call super's setUp().
21        TestBase.setUp(self)
22        # Our simple source filename.
23        self.source = 'main.cpp'
24        # Find the line number to break inside main().
25        self.line = line_number(
26            self.source, '// Set break point at this line.')
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 = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
34
35    @skipIfFreeBSD  # timing out on buildbot
36    def test_watchpoint_command(self):
37        """Test 'watchpoint command'."""
38        self.build(dictionary=self.d)
39        self.setTearDownCleanup(dictionary=self.d)
40
41        exe = self.getBuildArtifact(self.exe_name)
42        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
43
44        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
45        lldbutil.run_break_set_by_file_and_line(
46            self, None, self.line, num_expected_locations=1)
47
48        # Run the program.
49        self.runCmd("run", RUN_SUCCEEDED)
50
51        # We should be stopped again due to the breakpoint.
52        # The stop reason of the thread should be breakpoint.
53        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
54                    substrs=['stopped',
55                             'stop reason = breakpoint'])
56
57        # Now let's set a write-type watchpoint for 'global'.
58        self.expect(
59            "watchpoint set variable -w write global",
60            WATCHPOINT_CREATED,
61            substrs=[
62                'Watchpoint created',
63                'size = 4',
64                'type = w',
65                '%s:%d' %
66                (self.source,
67                 self.decl)])
68
69        self.runCmd(
70            'watchpoint command add -s python 1 -o \'frame.EvaluateExpression("cookie = 777")\'')
71
72        # List the watchpoint command we just added.
73        self.expect("watchpoint command list 1",
74                    substrs=['frame.EvaluateExpression', 'cookie = 777'])
75
76        # Use the '-v' option to do verbose listing of the watchpoint.
77        # The hit count should be 0 initially.
78        self.expect("watchpoint list -v",
79                    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("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
86                    substrs=['stop reason = watchpoint'])
87
88        # Check that the watchpoint snapshoting mechanism is working.
89        self.expect("watchpoint list -v",
90                    substrs=['old value: 0',
91                             'new value: 1'])
92
93        # The watchpoint command "forced" our global variable 'cookie' to
94        # become 777.
95        self.expect("frame variable --show-globals cookie",
96                    substrs=['(int32_t)', 'cookie = 777'])
97
98    @skipIfFreeBSD  # timing out on buildbot
99    @skipIfReproducer
100    def test_continue_in_watchpoint_command(self):
101        """Test continue in a watchpoint command."""
102        self.build(dictionary=self.d)
103        self.setTearDownCleanup(dictionary=self.d)
104
105        exe = self.getBuildArtifact(self.exe_name)
106        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
107
108        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
109        lldbutil.run_break_set_by_file_and_line(
110            self, None, self.line, num_expected_locations=1)
111
112        # Run the program.
113        self.runCmd("run", RUN_SUCCEEDED)
114
115        # We should be stopped again due to the breakpoint.
116        # The stop reason of the thread should be breakpoint.
117        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
118                    substrs=['stopped',
119                             'stop reason = breakpoint'])
120
121        # Now let's set a write-type watchpoint for 'global'.
122        self.expect(
123            "watchpoint set variable -w write global",
124            WATCHPOINT_CREATED,
125            substrs=[
126                'Watchpoint created',
127                'size = 4',
128                'type = w',
129                '%s:%d' %
130                (self.source,
131                 self.decl)])
132
133        cmd_script_file = os.path.join(self.getSourceDir(),
134                                       "watchpoint_command.py")
135        self.runCmd("command script import '%s'" % (cmd_script_file))
136
137        self.runCmd(
138            'watchpoint command add -F watchpoint_command.watchpoint_command')
139
140        # List the watchpoint command we just added.
141        self.expect("watchpoint command list 1",
142                    substrs=['watchpoint_command.watchpoint_command'])
143
144        self.runCmd("process continue")
145
146        # We should be stopped again due to the watchpoint (write type).
147        # The stop reason of the thread should be watchpoint.
148        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
149                    substrs=['stop reason = watchpoint'])
150
151        # We should have hit the watchpoint once, set cookie to 888, then continued to the
152        # second hit and set it to 999
153        self.expect("frame variable --show-globals cookie",
154                    substrs=['(int32_t)', 'cookie = 999'])
155
156