1from lldbsuite.test.decorators import *
2from lldbsuite.test.lldbtest import *
3
4import gdbremote_testcase
5
6
7class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
8
9    @skipIfWindows  # no SIGSEGV support
10    @add_test_categories(["llgs"])
11    def test_run(self):
12        self.build()
13        self.set_inferior_startup_launch()
14        thread_num = 3
15        procs = self.prep_debug_monitor_and_inferior(
16                inferior_args=["thread:segfault"] + thread_num * ["thread:new"])
17        self.test_sequence.add_log_lines(
18            ["read packet: $QNonStop:1#00",
19             "send packet: $OK#00",
20             "read packet: $c#63",
21             "send packet: $OK#00",
22             ], True)
23        self.expect_gdbremote_sequence()
24
25        segv_signo = lldbutil.get_signal_number('SIGSEGV')
26        all_threads = set()
27        all_segv_threads = []
28
29        # we should get segfaults from all the threads
30        for segv_no in range(thread_num):
31            # first wait for the notification event
32            self.reset_test_sequence()
33            self.test_sequence.add_log_lines(
34                [{"direction": "send",
35                  "regex": r"^%Stop:(T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
36                  "capture": {1: "packet", 2: "signo", 3: "thread_id"},
37                  },
38                 ], True)
39            m = self.expect_gdbremote_sequence()
40            del m["O_content"]
41            threads = [m]
42
43            # then we may get events for the remaining threads
44            # (but note that not all threads may have been started yet)
45            while True:
46                self.reset_test_sequence()
47                self.test_sequence.add_log_lines(
48                    ["read packet: $vStopped#00",
49                     {"direction": "send",
50                      "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
51                      "capture": {1: "packet", 2: "signo", 3: "thread_id"},
52                      },
53                     ], True)
54                m = self.expect_gdbremote_sequence()
55                if m["packet"] == "OK":
56                    break
57                del m["O_content"]
58                threads.append(m)
59
60            segv_threads = []
61            other_threads = []
62            for t in threads:
63                signo = int(t["signo"], 16)
64                if signo == segv_signo:
65                    segv_threads.append(t["thread_id"])
66                else:
67                    self.assertEqual(signo, 0)
68                    other_threads.append(t["thread_id"])
69
70            # verify that exactly one thread segfaulted
71            self.assertEqual(len(segv_threads), 1)
72            # we should get only one segv from every thread
73            self.assertNotIn(segv_threads[0], all_segv_threads)
74            all_segv_threads.extend(segv_threads)
75            # segv_threads + other_threads should always be a superset
76            # of all_threads, i.e. we should get states for all threads
77            # already started
78            self.assertFalse(
79                    all_threads.difference(other_threads + segv_threads))
80            all_threads.update(other_threads + segv_threads)
81
82            # verify that `?` returns the same result
83            self.reset_test_sequence()
84            self.test_sequence.add_log_lines(
85                ["read packet: $?#00",
86                 ], True)
87            threads_verify = []
88            while True:
89                self.test_sequence.add_log_lines(
90                    [{"direction": "send",
91                      "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
92                      "capture": {1: "packet", 2: "signo", 3: "thread_id"},
93                      },
94                     ], True)
95                m = self.expect_gdbremote_sequence()
96                if m["packet"] == "OK":
97                    break
98                del m["O_content"]
99                threads_verify.append(m)
100                self.reset_test_sequence()
101                self.test_sequence.add_log_lines(
102                    ["read packet: $vStopped#00",
103                     ], True)
104
105            self.assertEqual(threads, threads_verify)
106
107            self.reset_test_sequence()
108            self.test_sequence.add_log_lines(
109                ["read packet: $vCont;C{:02x}:{};c#00"
110                 .format(segv_signo, segv_threads[0]),
111                 "send packet: $OK#00",
112                 ], True)
113            self.expect_gdbremote_sequence()
114
115        # finally, verify that all threads have started
116        self.assertEqual(len(all_threads), thread_num + 1)
117
118    @add_test_categories(["llgs"])
119    def test_vCtrlC(self):
120        self.build()
121        self.set_inferior_startup_launch()
122        procs = self.prep_debug_monitor_and_inferior(
123                inferior_args=["thread:new"])
124        self.test_sequence.add_log_lines(
125            ["read packet: $QNonStop:1#00",
126             "send packet: $OK#00",
127             "read packet: $c#63",
128             "send packet: $OK#00",
129             "read packet: $vCtrlC#00",
130             "send packet: $OK#00",
131             {"direction": "send",
132              "regex": r"^%Stop:T",
133              },
134             ], True)
135        self.expect_gdbremote_sequence()
136
137    @add_test_categories(["llgs"])
138    def test_exit(self):
139        self.build()
140        self.set_inferior_startup_launch()
141        procs = self.prep_debug_monitor_and_inferior()
142        self.test_sequence.add_log_lines(
143            ["read packet: $QNonStop:1#00",
144             "send packet: $OK#00",
145             "read packet: $c#63",
146             "send packet: $OK#00",
147             "send packet: %Stop:W00#00",
148             "read packet: $vStopped#00",
149             "send packet: $OK#00",
150             ], True)
151        self.expect_gdbremote_sequence()
152
153    @skipIfWindows  # no clue, the result makes zero sense
154    @add_test_categories(["llgs"])
155    def test_exit_query(self):
156        self.build()
157        self.set_inferior_startup_launch()
158        procs = self.prep_debug_monitor_and_inferior()
159        self.test_sequence.add_log_lines(
160            ["read packet: $QNonStop:1#00",
161             "send packet: $OK#00",
162             "read packet: $c#63",
163             "send packet: $OK#00",
164             "send packet: %Stop:W00#00",
165             "read packet: $?#00",
166             "send packet: $W00#00",
167             "read packet: $vStopped#00",
168             "send packet: $OK#00",
169             ], True)
170        self.expect_gdbremote_sequence()
171