1"""
2Test watchpoint slots we should not be able to install multiple watchpoints
3within same word boundary. We should be able to install individual watchpoints
4on any of the bytes, half-word, or word. This is only for ARM/AArch64 targets.
5"""
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class WatchpointSlotsTestCase(TestBase):
15    NO_DEBUG_INFO_TESTCASE = True
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20
21        # Source filename.
22        self.source = "main.c"
23
24        # Output filename.
25        self.exe_name = self.getBuildArtifact("a.out")
26        self.d = {"C_SOURCES": self.source, "EXE": self.exe_name}
27
28    # This is a arm and aarch64 specific test case. No other architectures tested.
29    @skipIf(archs=no_match(["arm", "aarch64"]))
30    def test_multiple_watchpoints_on_same_word(self):
31        self.build(dictionary=self.d)
32        self.setTearDownCleanup(dictionary=self.d)
33
34        exe = self.getBuildArtifact(self.exe_name)
35        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
36
37        # Detect line number after which we are going to increment arrayName.
38        loc_line = line_number("main.c", "// About to write byteArray")
39
40        # Set a breakpoint on the line detected above.
41        lldbutil.run_break_set_by_file_and_line(
42            self, "main.c", loc_line, num_expected_locations=1, loc_exact=True
43        )
44
45        # Run the program.
46        self.runCmd("run", RUN_SUCCEEDED)
47
48        # The stop reason of the thread should be breakpoint.
49        self.expect(
50            "thread list",
51            STOPPED_DUE_TO_BREAKPOINT,
52            substrs=["stopped", "stop reason = breakpoint"],
53        )
54
55        # Delete breakpoint we just hit.
56        self.expect("breakpoint delete 1", substrs=["1 breakpoints deleted"])
57
58        # Set a watchpoint at byteArray[0]
59        self.expect(
60            "watchpoint set variable byteArray[0]",
61            WATCHPOINT_CREATED,
62            substrs=["Watchpoint created", "size = 1"],
63        )
64
65        # Use the '-v' option to do verbose listing of the watchpoint.
66        # The hit count should be 0 initially.
67        self.expect("watchpoint list -v 1", substrs=["hit_count = 0"])
68
69        # debugserver on ios doesn't give an error, it creates another watchpoint,
70        # only expect errors on non-darwin platforms.
71        if not self.platformIsDarwin():
72            # Try setting a watchpoint at byteArray[1]
73            self.expect(
74                "watchpoint set variable byteArray[1]",
75                error=True,
76                substrs=["Watchpoint creation failed"],
77            )
78
79        self.runCmd("process continue")
80
81        # We should be stopped due to the watchpoint.
82        # The stop reason of the thread should be watchpoint.
83        self.expect(
84            "thread list",
85            STOPPED_DUE_TO_WATCHPOINT,
86            substrs=["stopped", "stop reason = watchpoint 1"],
87        )
88
89        # Delete the watchpoint we hit above successfully.
90        self.expect("watchpoint delete 1", substrs=["1 watchpoints deleted"])
91
92        # Set a watchpoint at byteArray[3]
93        self.expect(
94            "watchpoint set variable byteArray[3]",
95            WATCHPOINT_CREATED,
96            substrs=["Watchpoint created", "size = 1"],
97        )
98
99        # Resume inferior.
100        self.runCmd("process continue")
101
102        # We should be stopped due to the watchpoint.
103        # The stop reason of the thread should be watchpoint.
104        if self.platformIsDarwin():
105            # On darwin we'll hit byteArray[3] which is watchpoint 2
106            self.expect(
107                "thread list",
108                STOPPED_DUE_TO_WATCHPOINT,
109                substrs=["stopped", "stop reason = watchpoint 2"],
110            )
111        else:
112            self.expect(
113                "thread list",
114                STOPPED_DUE_TO_WATCHPOINT,
115                substrs=["stopped", "stop reason = watchpoint 3"],
116            )
117
118        # Resume inferior.
119        self.runCmd("process continue")
120