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    def test_continue_in_watchpoint_command(self):
100        """Test continue in a watchpoint command."""
101        self.build(dictionary=self.d)
102        self.setTearDownCleanup(dictionary=self.d)
103
104        exe = self.getBuildArtifact(self.exe_name)
105        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
106
107        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
108        lldbutil.run_break_set_by_file_and_line(
109            self, None, self.line, num_expected_locations=1)
110
111        # Run the program.
112        self.runCmd("run", RUN_SUCCEEDED)
113
114        # We should be stopped again due to the breakpoint.
115        # The stop reason of the thread should be breakpoint.
116        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
117                    substrs=['stopped',
118                             'stop reason = breakpoint'])
119
120        # Now let's set a write-type watchpoint for 'global'.
121        self.expect(
122            "watchpoint set variable -w write global",
123            WATCHPOINT_CREATED,
124            substrs=[
125                'Watchpoint created',
126                'size = 4',
127                'type = w',
128                '%s:%d' %
129                (self.source,
130                 self.decl)])
131
132        cmd_script_file = os.path.join(self.getSourceDir(),
133                                       "watchpoint_command.py")
134        self.runCmd("command script import '%s'" % (cmd_script_file))
135
136        self.runCmd(
137            'watchpoint command add -F watchpoint_command.watchpoint_command')
138
139        # List the watchpoint command we just added.
140        self.expect("watchpoint command list 1",
141                    substrs=['watchpoint_command.watchpoint_command'])
142
143        self.runCmd("process continue")
144
145        # We should be stopped again due to the watchpoint (write type).
146        # The stop reason of the thread should be watchpoint.
147        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
148                    substrs=['stop reason = watchpoint'])
149
150        # We should have hit the watchpoint once, set cookie to 888, then continued to the
151        # second hit and set it to 999
152        self.expect("frame variable --show-globals cookie",
153                    substrs=['(int32_t)', 'cookie = 999'])
154
155