1656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project"""
2656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source ProjectTest that lldb watchpoint works for multiple threads.
3656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project"""
4656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
5656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectimport os, time
6656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectimport unittest2
7656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectimport re
8656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectimport lldb
9656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectfrom lldbtest import *
10656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectimport lldbutil
11656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
12656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectclass WatchpointForMultipleThreadsTestCase(TestBase):
13656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
14656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    mydir = os.path.join("functionalities", "watchpoint", "multiple_threads")
15656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
16656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
17656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @dsym_test
18656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def test_watchpoint_multiple_threads_with_dsym(self):
19656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads."""
20656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.buildDsym(dictionary=self.d)
21656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.setTearDownCleanup(dictionary=self.d)
22656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.hello_multiple_threads()
23656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
24656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @expectedFailureFreeBSD('llvm.org/pr16706') # Watchpoints fail on FreeBSD
25656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate
26656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @dwarf_test
27656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def test_watchpoint_multiple_threads_with_dwarf(self):
28656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads."""
29656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.buildDwarf(dictionary=self.d)
30656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.setTearDownCleanup(dictionary=self.d)
31656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.hello_multiple_threads()
32656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
33656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
34656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @dsym_test
35656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dsym(self):
36656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
37656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.buildDsym(dictionary=self.d)
38656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.setTearDownCleanup(dictionary=self.d)
39656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.hello_multiple_threads_wp_set_and_then_delete()
40656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
41656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @expectedFailureFreeBSD('llvm.org/pr16706') # Watchpoints fail on FreeBSD
42656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate
43656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    @dwarf_test
44656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dwarf(self):
45656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
46656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.buildDwarf(dictionary=self.d)
47656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.setTearDownCleanup(dictionary=self.d)
48656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.hello_multiple_threads_wp_set_and_then_delete()
49656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
50656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def setUp(self):
51656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Call super's setUp().
52656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        TestBase.setUp(self)
53656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Our simple source filename.
54656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.source = 'main.cpp'
55656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Find the line number to break inside main().
56656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.first_stop = line_number(self.source, '// Set break point at this line')
57656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Build dictionary to have unique executable names for each test method.
58656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.exe_name = self.testMethodName
59674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
60656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
61656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def hello_multiple_threads(self):
62656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads."""
63656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        exe = os.path.join(os.getcwd(), self.exe_name)
64656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
65656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
66656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
67656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        lldbutil.run_break_set_by_file_and_line (self, None, self.first_stop, num_expected_locations=1)
68656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
69656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Run the program.
70656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.runCmd("run", RUN_SUCCEEDED)
71656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
72656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # We should be stopped again due to the breakpoint.
73656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # The stop reason of the thread should be breakpoint.
74656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
75656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            substrs = ['stopped',
76656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                       'stop reason = breakpoint'])
77656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
78656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Now let's set a write-type watchpoint for variable 'g_val'.
79656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # The main.cpp, by design, misbehaves by not following the agreed upon
80656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # protocol of using a mutex while accessing the global pool and by not
81656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # writing to the variable.
82656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED,
83656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            substrs = ['Watchpoint created', 'size = 4', 'type = w'])
84656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
85656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Use the '-v' option to do verbose listing of the watchpoint.
86656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # The hit count should be 0 initially.
87656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.expect("watchpoint list -v",
88656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            substrs = ['hit_count = 0'])
89656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
90656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        while True:
91656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            self.runCmd("process continue")
92656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
93656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            self.runCmd("thread list")
94656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            if "stop reason = watchpoint" in self.res.GetOutput():
95656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                # Good, we verified that the watchpoint works!
96656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.runCmd("thread backtrace all")
97656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                break
98656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            else:
99656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.fail("The stop reason should be either break or watchpoint")
100656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
101656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # Use the '-v' option to do verbose listing of the watchpoint.
102656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        # The hit count should now be 1.
103656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.expect("watchpoint list -v",
104656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            substrs = ['hit_count = 1'])
105656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
106656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    def hello_multiple_threads_wp_set_and_then_delete(self):
107656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
108656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        exe = os.path.join(os.getcwd(), self.exe_name)
109656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
110656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
111674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
112674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        lldbutil.run_break_set_by_file_and_line (self, None, self.first_stop, num_expected_locations=1)
113674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom
114674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # Run the program.
115674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        self.runCmd("run", RUN_SUCCEEDED)
116674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom
117674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # We should be stopped again due to the breakpoint.
118674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # The stop reason of the thread should be breakpoint.
119674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
120674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom            substrs = ['stopped',
121674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom                       'stop reason = breakpoint'])
122674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom
123674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # Now let's set a write-type watchpoint for variable 'g_val'.
124674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # The main.cpp, by design, misbehaves by not following the agreed upon
125674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # protocol of using a mutex while accessing the global pool and by not
126674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # writing to the variable.
127674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED,
128674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom            substrs = ['Watchpoint created', 'size = 4', 'type = w'])
129674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom
130674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # Use the '-v' option to do verbose listing of the watchpoint.
131674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        # The hit count should be 0 initially.
132674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        self.expect("watchpoint list -v",
133674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom            substrs = ['hit_count = 0'])
134674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom
135674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        watchpoint_stops = 0
136674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom        while True:
137656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            self.runCmd("process continue")
138656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            self.runCmd("process status")
139674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom            if re.search("Process .* exited", self.res.GetOutput()):
140656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                # Great, we are done with this test!
141656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                break
142656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
143656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            self.runCmd("thread list")
144656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            if "stop reason = watchpoint" in self.res.GetOutput():
145656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.runCmd("thread backtrace all")
146656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                watchpoint_stops += 1
147656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                if watchpoint_stops > 1:
148656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                    self.fail("Watchpoint hits not supposed to exceed 1 by design!")
149656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                # Good, we verified that the watchpoint works!  Now delete the watchpoint.
150656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                if self.TraceOn():
151656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                    print "watchpoint_stops=%d at the moment we delete the watchpoint" % watchpoint_stops
152656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.runCmd("watchpoint delete 1")
153656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.expect("watchpoint list -v",
154656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                    substrs = ['No watchpoints currently set.'])
155656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                continue
156656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project            else:
157656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project                self.fail("The stop reason should be either break or watchpoint")
158656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
159656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project
160656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Projectif __name__ == '__main__':
161656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    import atexit
162656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    lldb.SBDebugger.Initialize()
163656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    atexit.register(lambda: lldb.SBDebugger.Terminate())
164656d9c7f52f88b3a3daccafa7655dec086c4756eThe Android Open Source Project    unittest2.main()
165674ff29eb647c577ba1ef822c373ead69dc386cfBrian Carlstrom