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