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