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
172    def multiple_resume_test(self, second_command):
173        self.build()
174        self.set_inferior_startup_launch()
175        procs = self.prep_debug_monitor_and_inferior(
176                inferior_args=["sleep:15"])
177        self.test_sequence.add_log_lines(
178            ["read packet: $QNonStop:1#00",
179             "send packet: $OK#00",
180             "read packet: $c#63",
181             "send packet: $OK#00",
182             "read packet: ${}#00".format(second_command),
183             "send packet: $E37#00",
184             ], True)
185        self.expect_gdbremote_sequence()
186
187    @add_test_categories(["llgs"])
188    def test_multiple_C(self):
189        self.multiple_resume_test("C05")
190
191    @add_test_categories(["llgs"])
192    def test_multiple_c(self):
193        self.multiple_resume_test("c")
194
195    @add_test_categories(["llgs"])
196    def test_multiple_s(self):
197        self.multiple_resume_test("s")
198
199    @add_test_categories(["llgs"])
200    def test_multiple_vCont(self):
201        self.build()
202        self.set_inferior_startup_launch()
203        procs = self.prep_debug_monitor_and_inferior(
204                inferior_args=["thread:new", "stop", "sleep:15"])
205        self.test_sequence.add_log_lines(
206            ["read packet: $QNonStop:1#00",
207             "send packet: $OK#00",
208             "read packet: $c#63",
209             "send packet: $OK#00",
210             {"direction": "send",
211              "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
212              "capture": {1: "tid1"},
213              },
214             "read packet: $vStopped#63",
215             {"direction": "send",
216              "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
217              "capture": {1: "tid2"},
218              },
219             "read packet: $vStopped#63",
220             "send packet: $OK#00",
221             ], True)
222        ret = self.expect_gdbremote_sequence()
223
224        self.reset_test_sequence()
225        self.test_sequence.add_log_lines(
226            ["read packet: $vCont;c:{}#00".format(ret["tid1"]),
227             "send packet: $OK#00",
228             "read packet: $vCont;c:{}#00".format(ret["tid2"]),
229             "send packet: $E37#00",
230             ], True)
231        self.expect_gdbremote_sequence()
232
233    @add_test_categories(["llgs"])
234    def test_vCont_then_stop(self):
235        self.build()
236        self.set_inferior_startup_launch()
237        procs = self.prep_debug_monitor_and_inferior(
238                inferior_args=["sleep:15"])
239        self.test_sequence.add_log_lines(
240            ["read packet: $QNonStop:1#00",
241             "send packet: $OK#00",
242             "read packet: $c#63",
243             "send packet: $OK#00",
244             "read packet: $vCont;t#00",
245             "send packet: $OK#00",
246             ], True)
247        self.expect_gdbremote_sequence()
248
249    def vCont_then_partial_stop_test(self, run_both):
250        self.build()
251        self.set_inferior_startup_launch()
252        procs = self.prep_debug_monitor_and_inferior(
253                inferior_args=["thread:new", "stop", "sleep:15"])
254        self.test_sequence.add_log_lines(
255            ["read packet: $QNonStop:1#00",
256             "send packet: $OK#00",
257             "read packet: $c#63",
258             "send packet: $OK#00",
259             {"direction": "send",
260              "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
261              "capture": {1: "tid1"},
262              },
263             "read packet: $vStopped#63",
264             {"direction": "send",
265              "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
266              "capture": {1: "tid2"},
267              },
268             "read packet: $vStopped#63",
269             "send packet: $OK#00",
270             ], True)
271        ret = self.expect_gdbremote_sequence()
272
273        self.reset_test_sequence()
274        if run_both:
275            self.test_sequence.add_log_lines(
276                ["read packet: $vCont;c#00",
277                 ], True)
278        else:
279            self.test_sequence.add_log_lines(
280                ["read packet: $vCont;c:{}#00".format(ret["tid1"]),
281                 ], True)
282        self.test_sequence.add_log_lines(
283            ["send packet: $OK#00",
284             "read packet: $vCont;t:{}#00".format(ret["tid2"]),
285             "send packet: $E03#00",
286             ], True)
287        self.expect_gdbremote_sequence()
288
289    @add_test_categories(["llgs"])
290    def test_vCont_then_partial_stop(self):
291        self.vCont_then_partial_stop_test(False)
292
293    @add_test_categories(["llgs"])
294    def test_vCont_then_partial_stop_run_both(self):
295        self.vCont_then_partial_stop_test(True)
296