TestWatchLocation.py revision dbd73cf5eb16e733b28e823554e1dacdba1ebd0b
1"""
2Test lldb watchpoint that uses '-x size' to watch a pointed location with size.
3"""
4
5import os, time
6import re
7import unittest2
8import lldb
9from lldbtest import *
10import lldbutil
11
12class HelloWatchLocationTestCase(TestBase):
13
14    mydir = os.path.join("functionalities", "watchpoint", "hello_watchlocation")
15
16    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
17    @dsym_test
18    def test_hello_watchlocation_with_dsym(self):
19        """Test watching a location with '-x size' option."""
20        self.buildDsym(dictionary=self.d)
21        self.setTearDownCleanup(dictionary=self.d)
22        self.hello_watchlocation()
23
24    @expectedFailureLinux # llvm.org/pr14416
25    @dwarf_test
26    def test_hello_watchlocation_with_dwarf(self):
27        """Test watching a location with '-x size' option."""
28        self.buildDwarf(dictionary=self.d)
29        self.setTearDownCleanup(dictionary=self.d)
30        self.hello_watchlocation()
31
32    def setUp(self):
33        # Call super's setUp().
34        TestBase.setUp(self)
35        # Our simple source filename.
36        self.source = 'main.cpp'
37        # Find the line number to break inside main().
38        self.line = line_number(self.source, '// Set break point at this line.')
39        # This is for verifying that watch location works.
40        self.violating_func = "do_bad_thing_with_location";
41        # Build dictionary to have unique executable names for each test method.
42        self.exe_name = self.testMethodName
43        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
44
45    def hello_watchlocation(self):
46        """Test watching a location with '-x size' option."""
47        exe = os.path.join(os.getcwd(), self.exe_name)
48        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
49
50        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
51        lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1, loc_exact=False)
52
53        # Run the program.
54        self.runCmd("run", RUN_SUCCEEDED)
55
56        # We should be stopped again due to the breakpoint.
57        # The stop reason of the thread should be breakpoint.
58        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
59            substrs = ['stopped',
60                       'stop reason = breakpoint'])
61
62        # Now let's set a write-type watchpoint pointed to by 'g_char_ptr'.
63        # The main.cpp, by design, misbehaves by not following the agreed upon
64        # protocol of using a mutex while accessing the global pool and by not
65        # incrmenting the global pool by 2.
66        self.expect("watchpoint set expression -w write -x 1 -- g_char_ptr", WATCHPOINT_CREATED,
67            substrs = ['Watchpoint created', 'size = 1', 'type = w'])
68        # Get a hold of the watchpoint id just created, it is used later on to
69        # match the watchpoint id which is expected to be fired.
70        match = re.match("Watchpoint created: Watchpoint (.*):", self.res.GetOutput().splitlines()[0])
71        if match:
72            expected_wp_id = int(match.group(1), 0)
73        else:
74            self.fail("Grokking watchpoint id faailed!")
75
76        self.runCmd("expr unsigned val = *g_char_ptr; val")
77        self.expect(self.res.GetOutput().splitlines()[0], exe=False,
78            endstr = ' = 0')
79
80        self.runCmd("watchpoint set expression -w write -x 4 -- &g_thread_1")
81
82        # Use the '-v' option to do verbose listing of the watchpoint.
83        # The hit count should be 0 initially.
84        self.expect("watchpoint list -v",
85            substrs = ['hit_count = 0'])
86
87        self.runCmd("process continue")
88
89        # We should be stopped again due to the watchpoint (write type), but
90        # only once.  The stop reason of the thread should be watchpoint.
91        self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
92            substrs = ['stopped',
93                       'stop reason = watchpoint %d' % expected_wp_id,
94                       self.violating_func])
95
96        # Switch to the thread stopped due to watchpoint and issue some commands.
97        self.switch_to_thread_with_stop_reason(lldb.eStopReasonWatchpoint)
98        self.runCmd("thread backtrace")
99        self.runCmd("expr unsigned val = *g_char_ptr; val")
100        self.expect(self.res.GetOutput().splitlines()[0], exe=False,
101            endstr = ' = 1')
102
103        # Use the '-v' option to do verbose listing of the watchpoint.
104        # The hit count should now be 1.
105        self.expect("watchpoint list -v",
106            substrs = ['hit_count = 1'])
107
108        self.runCmd("thread backtrace all")
109
110
111if __name__ == '__main__':
112    import atexit
113    lldb.SBDebugger.Initialize()
114    atexit.register(lambda: lldb.SBDebugger.Terminate())
115    unittest2.main()
116