xref: /llvm-project/lldb/test/API/commands/watchpoints/multiple_threads/TestWatchpointMultipleThreads.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1"""
2Test that lldb watchpoint works for multiple threads.
3"""
4
5import re
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class WatchpointForMultipleThreadsTestCase(TestBase):
13    NO_DEBUG_INFO_TESTCASE = True
14    main_spec = lldb.SBFileSpec("main.cpp", False)
15
16    @skipIfWindows  # This test is flaky on Windows
17    def test_watchpoint_before_thread_start(self):
18        """Test that we can hit a watchpoint we set before starting another thread"""
19        self.do_watchpoint_test("Before running the thread")
20
21    @skipIfWindows  # This test is flaky on Windows
22    def test_watchpoint_after_thread_launch(self):
23        """Test that we can hit a watchpoint we set after launching another thread"""
24        self.do_watchpoint_test("After launching the thread")
25
26    def test_watchpoint_after_thread_start(self):
27        """Test that we can hit a watchpoint we set after another thread starts"""
28        self.do_watchpoint_test("After running the thread")
29
30    def do_watchpoint_test(self, line):
31        self.build()
32        lldbutil.run_to_source_breakpoint(self, line, self.main_spec)
33
34        # Now let's set a write-type watchpoint for variable 'g_val'.
35        self.expect(
36            "watchpoint set variable -w write g_val",
37            WATCHPOINT_CREATED,
38            substrs=["Watchpoint created", "size = 4", "type = w"],
39        )
40
41        # Use the '-v' option to do verbose listing of the watchpoint.
42        # The hit count should be 0 initially.
43        self.expect("watchpoint list -v", substrs=["hit_count = 0"])
44
45        self.runCmd("process continue")
46
47        self.runCmd("thread list")
48        if "stop reason = watchpoint" in self.res.GetOutput():
49            # Good, we verified that the watchpoint works!
50            self.runCmd("thread backtrace all")
51        else:
52            self.fail("The stop reason should be either break or watchpoint")
53
54        # Use the '-v' option to do verbose listing of the watchpoint.
55        # The hit count should now be 1.
56        self.expect("watchpoint list -v", substrs=["hit_count = 1"])
57
58    def test_watchpoint_multiple_threads_wp_set_and_then_delete(self):
59        """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
60        self.build()
61        self.setTearDownCleanup()
62
63        lldbutil.run_to_source_breakpoint(
64            self, "After running the thread", self.main_spec
65        )
66
67        # Now let's set a write-type watchpoint for variable 'g_val'.
68        self.expect(
69            "watchpoint set variable -w write g_val",
70            WATCHPOINT_CREATED,
71            substrs=["Watchpoint created", "size = 4", "type = w"],
72        )
73
74        # Use the '-v' option to do verbose listing of the watchpoint.
75        # The hit count should be 0 initially.
76        self.expect("watchpoint list -v", substrs=["hit_count = 0"])
77
78        watchpoint_stops = 0
79        while True:
80            self.runCmd("process continue")
81            self.runCmd("process status")
82            if re.search("Process .* exited", self.res.GetOutput()):
83                # Great, we are done with this test!
84                break
85
86            self.runCmd("thread list")
87            if "stop reason = watchpoint" in self.res.GetOutput():
88                self.runCmd("thread backtrace all")
89                watchpoint_stops += 1
90                if watchpoint_stops > 1:
91                    self.fail("Watchpoint hits not supposed to exceed 1 by design!")
92                # Good, we verified that the watchpoint works!  Now delete the
93                # watchpoint.
94                if self.TraceOn():
95                    print(
96                        "watchpoint_stops=%d at the moment we delete the watchpoint"
97                        % watchpoint_stops
98                    )
99                self.runCmd("watchpoint delete 1")
100                self.expect(
101                    "watchpoint list -v", substrs=["No watchpoints currently set."]
102                )
103                continue
104            else:
105                self.fail("The stop reason should be either break or watchpoint")
106