Skip to content

Commit b415f8e

Browse files
committed
[lldb] [llgs] Add base nonstop fork/vfork tests
Extend the most of baseline fork tests to run in nonstop mode as well. For more cases, we're just testing one example scenario to save time. This patch does not cover tests that rely on correct exit handling, as fixing that is addressed in a followup patch. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.llvm.org/D128638
1 parent e095cdd commit b415f8e

File tree

1 file changed

+139
-16
lines changed

1 file changed

+139
-16
lines changed

Diff for: lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py

+139-16
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase):
99

1010
fork_regex = ("[$]T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
1111
"{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
12+
fork_regex_nonstop = ("%Stop:T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
13+
"{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
1214
fork_capture = {1: "parent_pid", 2: "parent_tid",
1315
3: "child_pid", 4: "child_tid"}
1416

15-
def start_fork_test(self, args, variant="fork"):
17+
def start_fork_test(self, args, variant="fork", nonstop=False):
1618
self.build()
1719
self.prep_debug_monitor_and_inferior(inferior_args=args)
1820
self.add_qSupported_packets(["multiprocess+",
@@ -22,11 +24,24 @@ def start_fork_test(self, args, variant="fork"):
2224
self.reset_test_sequence()
2325

2426
# continue and expect fork
25-
self.test_sequence.add_log_lines([
26-
"read packet: $c#00",
27-
{"direction": "send", "regex": self.fork_regex.format(variant),
28-
"capture": self.fork_capture},
29-
], True)
27+
if nonstop:
28+
self.test_sequence.add_log_lines([
29+
"read packet: $QNonStop:1#00",
30+
"send packet: $OK#00",
31+
"read packet: $c#00",
32+
"send packet: $OK#00",
33+
{"direction": "send",
34+
"regex": self.fork_regex_nonstop.format(variant),
35+
"capture": self.fork_capture},
36+
"read packet: $vStopped#00",
37+
"send packet: $OK#00",
38+
], True)
39+
else:
40+
self.test_sequence.add_log_lines([
41+
"read packet: $c#00",
42+
{"direction": "send", "regex": self.fork_regex.format(variant),
43+
"capture": self.fork_capture},
44+
], True)
3045
ret = self.expect_gdbremote_sequence()
3146
self.reset_test_sequence()
3247

@@ -45,9 +60,9 @@ def test_fork_multithreaded(self):
4560
], True)
4661
self.expect_gdbremote_sequence()
4762

48-
def fork_and_detach_test(self, variant):
63+
def fork_and_detach_test(self, variant, nonstop=False):
4964
parent_pid, parent_tid, child_pid, child_tid = (
50-
self.start_fork_test([variant], variant))
65+
self.start_fork_test([variant], variant, nonstop=nonstop))
5166

5267
# detach the forked child
5368
self.test_sequence.add_log_lines([
@@ -77,6 +92,20 @@ def test_fork(self):
7792
], True)
7893
self.expect_gdbremote_sequence()
7994

95+
@add_test_categories(["fork"])
96+
def test_fork_nonstop(self):
97+
parent_pid, _ = self.fork_and_detach_test("fork", nonstop=True)
98+
99+
# resume the parent
100+
self.test_sequence.add_log_lines([
101+
"read packet: $c#00",
102+
"send packet: $OK#00",
103+
"send packet: %Stop:W00;process:{}#00".format(parent_pid),
104+
"read packet: $vStopped#00",
105+
"send packet: $OK#00",
106+
], True)
107+
self.expect_gdbremote_sequence()
108+
80109
@add_test_categories(["fork"])
81110
def test_vfork(self):
82111
parent_pid, parent_tid = self.fork_and_detach_test("vfork")
@@ -93,9 +122,32 @@ def test_vfork(self):
93122
], True)
94123
self.expect_gdbremote_sequence()
95124

96-
def fork_and_follow_test(self, variant):
125+
@add_test_categories(["fork"])
126+
def test_vfork_nonstop(self):
127+
parent_pid, parent_tid = self.fork_and_detach_test("vfork",
128+
nonstop=True)
129+
130+
# resume the parent
131+
self.test_sequence.add_log_lines([
132+
"read packet: $c#00",
133+
"send packet: $OK#00",
134+
{"direction": "send",
135+
"regex": r"%Stop:T05thread:p{}[.]{}.*vforkdone.*".format(
136+
parent_pid, parent_tid),
137+
},
138+
"read packet: $vStopped#00",
139+
"send packet: $OK#00",
140+
"read packet: $c#00",
141+
"send packet: $OK#00",
142+
"send packet: %Stop:W00;process:{}#00".format(parent_pid),
143+
"read packet: $vStopped#00",
144+
"send packet: $OK#00",
145+
], True)
146+
self.expect_gdbremote_sequence()
147+
148+
def fork_and_follow_test(self, variant, nonstop=False):
97149
parent_pid, parent_tid, child_pid, child_tid = (
98-
self.start_fork_test([variant], variant))
150+
self.start_fork_test([variant], variant, nonstop=nonstop))
99151

100152
# switch to the forked child
101153
self.test_sequence.add_log_lines([
@@ -113,18 +165,37 @@ def fork_and_follow_test(self, variant):
113165
"send packet: $OK#00",
114166
# then resume the child
115167
"read packet: $c#00",
116-
"send packet: $W00;process:{}#00".format(child_pid),
117168
], True)
169+
170+
if nonstop:
171+
self.test_sequence.add_log_lines([
172+
"send packet: $OK#00",
173+
"send packet: %Stop:W00;process:{}#00".format(child_pid),
174+
"read packet: $vStopped#00",
175+
"send packet: $OK#00",
176+
], True)
177+
else:
178+
self.test_sequence.add_log_lines([
179+
"send packet: $W00;process:{}#00".format(child_pid),
180+
], True)
118181
self.expect_gdbremote_sequence()
119182

120183
@add_test_categories(["fork"])
121184
def test_fork_follow(self):
122185
self.fork_and_follow_test("fork")
123186

187+
@add_test_categories(["fork"])
188+
def test_fork_follow_nonstop(self):
189+
self.fork_and_follow_test("fork", nonstop=True)
190+
124191
@add_test_categories(["fork"])
125192
def test_vfork_follow(self):
126193
self.fork_and_follow_test("vfork")
127194

195+
@add_test_categories(["fork"])
196+
def test_vfork_follow_nonstop(self):
197+
self.fork_and_follow_test("vfork", nonstop=True)
198+
128199
@add_test_categories(["fork"])
129200
def test_select_wrong_pid(self):
130201
self.build()
@@ -191,10 +262,9 @@ def test_detach_current(self):
191262
], True)
192263
self.expect_gdbremote_sequence()
193264

194-
@add_test_categories(["fork"])
195-
def test_detach_all(self):
265+
def detach_all_test(self, nonstop=False):
196266
parent_pid, parent_tid, child_pid, child_tid = (
197-
self.start_fork_test(["fork"]))
267+
self.start_fork_test(["fork"], nonstop=nonstop))
198268

199269
self.test_sequence.add_log_lines([
200270
# double-check our PIDs
@@ -213,6 +283,14 @@ def test_detach_all(self):
213283
], True)
214284
self.expect_gdbremote_sequence()
215285

286+
@add_test_categories(["fork"])
287+
def test_detach_all(self):
288+
self.detach_all_test()
289+
290+
@add_test_categories(["fork"])
291+
def test_detach_all_nonstop(self):
292+
self.detach_all_test(nonstop=True)
293+
216294
@add_test_categories(["fork"])
217295
def test_kill_all(self):
218296
parent_pid, _, child_pid, _ = self.start_fork_test(["fork"])
@@ -230,10 +308,51 @@ def test_kill_all(self):
230308
self.assertEqual(set([ret["pid1"], ret["pid2"]]),
231309
set([parent_pid, child_pid]))
232310

233-
def vkill_test(self, kill_parent=False, kill_child=False):
311+
@add_test_categories(["fork"])
312+
def test_kill_all_nonstop(self):
313+
parent_pid, _, child_pid, _ = self.start_fork_test(["fork"],
314+
nonstop=True)
315+
316+
exit_regex = "X09;process:([0-9a-f]+)"
317+
# Depending on a potential race, the second kill may make it into
318+
# the async queue before we issue vStopped or after. In the former
319+
# case, we should expect the exit status in reply to vStopped.
320+
# In the latter, we should expect an OK response (queue empty),
321+
# followed by another async notification.
322+
vstop_regex = "[$](OK|{})#.*".format(exit_regex)
323+
self.test_sequence.add_log_lines([
324+
# kill all processes
325+
"read packet: $k#00",
326+
"send packet: $OK#00",
327+
{"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
328+
"capture": {1: "pid1"}},
329+
"read packet: $vStopped#00",
330+
{"direction": "send", "regex": vstop_regex,
331+
"capture": {1: "vstop_reply", 2: "pid2"}},
332+
], True)
333+
ret = self.expect_gdbremote_sequence()
334+
pid1 = ret["pid1"]
335+
if ret["vstop_reply"] == "OK":
336+
self.reset_test_sequence()
337+
self.test_sequence.add_log_lines([
338+
{"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
339+
"capture": {1: "pid2"}},
340+
], True)
341+
ret = self.expect_gdbremote_sequence()
342+
pid2 = ret["pid2"]
343+
self.reset_test_sequence()
344+
self.test_sequence.add_log_lines([
345+
"read packet: $vStopped#00",
346+
"send packet: $OK#00",
347+
], True)
348+
self.expect_gdbremote_sequence()
349+
self.assertEqual(set([ret["pid1"], ret["pid2"]]),
350+
set([parent_pid, child_pid]))
351+
352+
def vkill_test(self, kill_parent=False, kill_child=False, nonstop=False):
234353
assert kill_parent or kill_child
235354
parent_pid, parent_tid, child_pid, child_tid = (
236-
self.start_fork_test(["fork"]))
355+
self.start_fork_test(["fork"], nonstop=nonstop))
237356

238357
if kill_parent:
239358
self.test_sequence.add_log_lines([
@@ -269,6 +388,10 @@ def test_vkill_parent(self):
269388
def test_vkill_both(self):
270389
self.vkill_test(kill_parent=True, kill_child=True)
271390

391+
@add_test_categories(["fork"])
392+
def test_vkill_both_nonstop(self):
393+
self.vkill_test(kill_parent=True, kill_child=True, nonstop=True)
394+
272395
def resume_one_test(self, run_order, use_vCont=False):
273396
parent_pid, parent_tid, child_pid, child_tid = (
274397
self.start_fork_test(["fork", "trap"]))

0 commit comments

Comments
 (0)