xref: /llvm-project/lldb/test/API/tools/lldb-server/TestNonStop.py (revision 5a658ee933065d0e4ef1a65d9a6ddfba2874ee98)
1from lldbsuite.test.decorators import *
2from lldbsuite.test.lldbtest import *
3
4import gdbremote_testcase
5
6
7class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
8    @skipIfWindows  # no SIGSEGV support
9    @add_test_categories(["llgs"])
10    def test_run(self):
11        self.build()
12        self.set_inferior_startup_launch()
13        thread_num = 3
14        procs = self.prep_debug_monitor_and_inferior(
15            inferior_args=["thread:segfault"] + thread_num * ["thread:new"]
16        )
17        self.test_sequence.add_log_lines(
18            [
19                "read packet: $QNonStop:1#00",
20                "send packet: $OK#00",
21                "read packet: $c#63",
22                "send packet: $OK#00",
23            ],
24            True,
25        )
26        self.expect_gdbremote_sequence()
27
28        segv_signo = lldbutil.get_signal_number("SIGSEGV")
29        all_threads = set()
30        all_segv_threads = []
31
32        # we should get segfaults from all the threads
33        for segv_no in range(thread_num):
34            # first wait for the notification event
35            self.reset_test_sequence()
36            self.test_sequence.add_log_lines(
37                [
38                    {
39                        "direction": "send",
40                        "regex": r"^%Stop:(T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
41                        "capture": {1: "packet", 2: "signo", 3: "thread_id"},
42                    },
43                ],
44                True,
45            )
46            m = self.expect_gdbremote_sequence()
47            del m["O_content"]
48            threads = [m]
49
50            # then we may get events for the remaining threads
51            # (but note that not all threads may have been started yet)
52            while True:
53                self.reset_test_sequence()
54                self.test_sequence.add_log_lines(
55                    [
56                        "read packet: $vStopped#00",
57                        {
58                            "direction": "send",
59                            "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
60                            "capture": {1: "packet", 2: "signo", 3: "thread_id"},
61                        },
62                    ],
63                    True,
64                )
65                m = self.expect_gdbremote_sequence()
66                if m["packet"] == "OK":
67                    break
68                del m["O_content"]
69                threads.append(m)
70
71            segv_threads = []
72            other_threads = []
73            for t in threads:
74                signo = int(t["signo"], 16)
75                if signo == segv_signo:
76                    segv_threads.append(t["thread_id"])
77                else:
78                    self.assertEqual(signo, 0)
79                    other_threads.append(t["thread_id"])
80
81            # verify that exactly one thread segfaulted
82            self.assertEqual(len(segv_threads), 1)
83            # we should get only one segv from every thread
84            self.assertNotIn(segv_threads[0], all_segv_threads)
85            all_segv_threads.extend(segv_threads)
86            # segv_threads + other_threads should always be a superset
87            # of all_threads, i.e. we should get states for all threads
88            # already started
89            self.assertFalse(all_threads.difference(other_threads + segv_threads))
90            all_threads.update(other_threads + segv_threads)
91
92            # verify that `?` returns the same result
93            self.reset_test_sequence()
94            self.test_sequence.add_log_lines(
95                [
96                    "read packet: $?#00",
97                ],
98                True,
99            )
100            threads_verify = []
101            while True:
102                self.test_sequence.add_log_lines(
103                    [
104                        {
105                            "direction": "send",
106                            "regex": r"^\$(OK|T([0-9a-fA-F]{2})thread:([0-9a-fA-F]+);)",
107                            "capture": {1: "packet", 2: "signo", 3: "thread_id"},
108                        },
109                    ],
110                    True,
111                )
112                m = self.expect_gdbremote_sequence()
113                if m["packet"] == "OK":
114                    break
115                del m["O_content"]
116                threads_verify.append(m)
117                self.reset_test_sequence()
118                self.test_sequence.add_log_lines(
119                    [
120                        "read packet: $vStopped#00",
121                    ],
122                    True,
123                )
124
125            self.assertEqual(threads, threads_verify)
126
127            self.reset_test_sequence()
128            self.test_sequence.add_log_lines(
129                [
130                    "read packet: $vCont;C{:02x}:{};c#00".format(
131                        segv_signo, segv_threads[0]
132                    ),
133                    "send packet: $OK#00",
134                ],
135                True,
136            )
137            self.expect_gdbremote_sequence()
138
139        # finally, verify that all threads have started
140        self.assertEqual(len(all_threads), thread_num + 1)
141
142    @add_test_categories(["llgs"])
143    def test_vCtrlC(self):
144        self.build()
145        self.set_inferior_startup_launch()
146        procs = self.prep_debug_monitor_and_inferior(inferior_args=["thread:new"])
147        self.test_sequence.add_log_lines(
148            [
149                "read packet: $QNonStop:1#00",
150                "send packet: $OK#00",
151                "read packet: $c#63",
152                "send packet: $OK#00",
153                "read packet: $vCtrlC#00",
154                "send packet: $OK#00",
155                {
156                    "direction": "send",
157                    "regex": r"^%Stop:T",
158                },
159            ],
160            True,
161        )
162        self.expect_gdbremote_sequence()
163
164    @add_test_categories(["llgs"])
165    def test_exit(self):
166        self.build()
167        self.set_inferior_startup_launch()
168        procs = self.prep_debug_monitor_and_inferior()
169        self.test_sequence.add_log_lines(
170            [
171                "read packet: $QNonStop:1#00",
172                "send packet: $OK#00",
173                "read packet: $c#63",
174                "send packet: $OK#00",
175                "send packet: %Stop:W00#00",
176                "read packet: $vStopped#00",
177                "send packet: $OK#00",
178            ],
179            True,
180        )
181        self.expect_gdbremote_sequence()
182
183    @skipIfWindows  # no clue, the result makes zero sense
184    @add_test_categories(["llgs"])
185    def test_exit_query(self):
186        self.build()
187        self.set_inferior_startup_launch()
188        procs = self.prep_debug_monitor_and_inferior()
189        self.test_sequence.add_log_lines(
190            [
191                "read packet: $QNonStop:1#00",
192                "send packet: $OK#00",
193                "read packet: $c#63",
194                "send packet: $OK#00",
195                "send packet: %Stop:W00#00",
196                "read packet: $?#00",
197                "send packet: $W00#00",
198                "read packet: $vStopped#00",
199                "send packet: $OK#00",
200            ],
201            True,
202        )
203        self.expect_gdbremote_sequence()
204
205    def multiple_resume_test(self, second_command):
206        self.build()
207        self.set_inferior_startup_launch()
208        procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:15"])
209        self.test_sequence.add_log_lines(
210            [
211                "read packet: $QNonStop:1#00",
212                "send packet: $OK#00",
213                "read packet: $c#63",
214                "send packet: $OK#00",
215                "read packet: ${}#00".format(second_command),
216                "send packet: $E37#00",
217            ],
218            True,
219        )
220        self.expect_gdbremote_sequence()
221
222    @add_test_categories(["llgs"])
223    def test_multiple_C_continue_with_signal(self):
224        self.multiple_resume_test("C05")
225
226    @add_test_categories(["llgs"])
227    def test_multiple_c_continue_with_addr(self):
228        self.multiple_resume_test("c")
229
230    @add_test_categories(["llgs"])
231    def test_multiple_s_single_step_with_addr(self):
232        self.multiple_resume_test("s")
233
234    @skipIfWindows
235    @add_test_categories(["llgs"])
236    def test_multiple_vCont(self):
237        self.build()
238        self.set_inferior_startup_launch()
239        procs = self.prep_debug_monitor_and_inferior(
240            inferior_args=["thread:new", "stop", "sleep:15"]
241        )
242        self.test_sequence.add_log_lines(
243            [
244                "read packet: $QNonStop:1#00",
245                "send packet: $OK#00",
246                "read packet: $c#63",
247                "send packet: $OK#00",
248                {
249                    "direction": "send",
250                    "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
251                    "capture": {1: "tid1"},
252                },
253                "read packet: $vStopped#63",
254                {
255                    "direction": "send",
256                    "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
257                    "capture": {1: "tid2"},
258                },
259                "read packet: $vStopped#63",
260                "send packet: $OK#00",
261            ],
262            True,
263        )
264        ret = self.expect_gdbremote_sequence()
265
266        self.reset_test_sequence()
267        self.test_sequence.add_log_lines(
268            [
269                "read packet: $vCont;c:{}#00".format(ret["tid1"]),
270                "send packet: $OK#00",
271                "read packet: $vCont;c:{}#00".format(ret["tid2"]),
272                "send packet: $E37#00",
273            ],
274            True,
275        )
276        self.expect_gdbremote_sequence()
277
278    @add_test_categories(["llgs"])
279    @skipIfWindows  # Sometimes results in '$E37' instead of expected '$OK'
280    def test_vCont_then_stop(self):
281        self.build()
282        self.set_inferior_startup_launch()
283        procs = self.prep_debug_monitor_and_inferior(inferior_args=["sleep:15"])
284        self.test_sequence.add_log_lines(
285            [
286                "read packet: $QNonStop:1#00",
287                "send packet: $OK#00",
288                "read packet: $c#63",
289                "send packet: $OK#00",
290                "read packet: $vCont;t#00",
291                "send packet: $OK#00",
292            ],
293            True,
294        )
295        self.expect_gdbremote_sequence()
296
297    def vCont_then_partial_stop_test(self, run_both):
298        self.build()
299        self.set_inferior_startup_launch()
300        procs = self.prep_debug_monitor_and_inferior(
301            inferior_args=["thread:new", "stop", "sleep:15"]
302        )
303        self.test_sequence.add_log_lines(
304            [
305                "read packet: $QNonStop:1#00",
306                "send packet: $OK#00",
307                "read packet: $c#63",
308                "send packet: $OK#00",
309                {
310                    "direction": "send",
311                    "regex": r"^%Stop:T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
312                    "capture": {1: "tid1"},
313                },
314                "read packet: $vStopped#63",
315                {
316                    "direction": "send",
317                    "regex": r"^[$]T[0-9a-fA-F]{2}thread:([0-9a-fA-F]+);",
318                    "capture": {1: "tid2"},
319                },
320                "read packet: $vStopped#63",
321                "send packet: $OK#00",
322            ],
323            True,
324        )
325        ret = self.expect_gdbremote_sequence()
326
327        self.reset_test_sequence()
328        if run_both:
329            self.test_sequence.add_log_lines(
330                [
331                    "read packet: $vCont;c#00",
332                ],
333                True,
334            )
335        else:
336            self.test_sequence.add_log_lines(
337                [
338                    "read packet: $vCont;c:{}#00".format(ret["tid1"]),
339                ],
340                True,
341            )
342        self.test_sequence.add_log_lines(
343            [
344                "send packet: $OK#00",
345                "read packet: $vCont;t:{}#00".format(ret["tid2"]),
346                "send packet: $E03#00",
347            ],
348            True,
349        )
350        self.expect_gdbremote_sequence()
351
352    @skipIfWindows
353    @add_test_categories(["llgs"])
354    def test_vCont_then_partial_stop(self):
355        self.vCont_then_partial_stop_test(False)
356
357    @skipIfWindows
358    @add_test_categories(["llgs"])
359    def test_vCont_then_partial_stop_run_both(self):
360        self.vCont_then_partial_stop_test(True)
361
362    @skipIfWindows
363    @add_test_categories(["llgs"])
364    def test_stdio(self):
365        self.build()
366        self.set_inferior_startup_launch()
367        # Since we can't easily ensure that lldb will send output in two parts,
368        # just put a stop in the middle.  Since we don't clear vStdio,
369        # the second message won't be delivered immediately.
370        self.prep_debug_monitor_and_inferior(
371            inferior_args=["message 1", "stop", "message 2"]
372        )
373        self.test_sequence.add_log_lines(
374            [
375                "read packet: $QNonStop:1#00",
376                "send packet: $OK#00",
377                "read packet: $c#63",
378                "send packet: $OK#00",
379                {"direction": "send", "regex": r"^%Stop:T.*"},
380                "read packet: $vStopped#00",
381                "send packet: $OK#00",
382                "read packet: $c#63",
383                "send packet: $OK#00",
384                "send packet: %Stop:W00#00",
385            ],
386            True,
387        )
388        ret = self.expect_gdbremote_sequence()
389
390        # We know there will be at least two messages, but there may be more.
391        # Loop until we have everything. The first message waiting for us in the
392        # packet queue.
393        count = 1
394        output = self._server.get_raw_output_packet()
395        while not (b"message 2\r\n" in output):
396            self._server.send_packet(b"vStdio")
397            output += self._server.get_raw_output_packet()
398            count += 1
399        self.assertGreaterEqual(count, 2)
400
401        self.reset_test_sequence()
402        self.test_sequence.add_log_lines(
403            [
404                "read packet: $vStdio#00",
405                "send packet: $OK#00",
406                "read packet: $vStopped#00",
407                "send packet: $OK#00",
408            ],
409            True,
410        )
411        self.expect_gdbremote_sequence()
412
413    @skipIfWindows
414    @add_test_categories(["llgs"])
415    def test_stop_reason_while_running(self):
416        self.build()
417        self.set_inferior_startup_launch()
418        procs = self.prep_debug_monitor_and_inferior(
419            inferior_args=["thread:new", "thread:new", "stop", "sleep:15"]
420        )
421        self.test_sequence.add_log_lines(
422            [
423                "read packet: $QNonStop:1#00",
424                "send packet: $OK#00",
425                # stop is used to synchronize starting threads
426                "read packet: $c#63",
427                "send packet: $OK#00",
428                {"direction": "send", "regex": "%Stop:T.*"},
429                "read packet: $c#63",
430                "send packet: $OK#00",
431                "read packet: $?#00",
432                "send packet: $OK#00",
433            ],
434            True,
435        )
436        self.expect_gdbremote_sequence()
437
438    @skipIfWindows
439    @add_test_categories(["llgs"])
440    def test_leave_nonstop(self):
441        self.build()
442        self.set_inferior_startup_launch()
443        procs = self.prep_debug_monitor_and_inferior(
444            inferior_args=["thread:new", "thread:new", "stop", "sleep:15"]
445        )
446        self.test_sequence.add_log_lines(
447            [
448                "read packet: $QNonStop:1#00",
449                "send packet: $OK#00",
450                # stop is used to synchronize starting threads
451                "read packet: $c#63",
452                "send packet: $OK#00",
453                {"direction": "send", "regex": "%Stop:T.*"},
454                "read packet: $c#63",
455                "send packet: $OK#00",
456                # verify that the threads are running now
457                "read packet: $?#00",
458                "send packet: $OK#00",
459                "read packet: $QNonStop:0#00",
460                "send packet: $OK#00",
461                # we should issue some random request now to verify that the stub
462                # did not send stop reasons -- we may verify whether notification
463                # queue was cleared while at it
464                "read packet: $vStopped#00",
465                "send packet: $Eff#00",
466                "read packet: $?#00",
467                {"direction": "send", "regex": "[$]T.*"},
468            ],
469            True,
470        )
471        self.expect_gdbremote_sequence()
472