[Lldb-commits] [lldb] b415f8e - [lldb] [llgs] Add base nonstop fork/vfork tests

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 28 12:49:25 PDT 2022


Author: Michał Górny
Date: 2022-06-28T21:49:16+02:00
New Revision: b415f8e3dfb839a886b5290bbebbdd42344c07a9

URL: https://github.com/llvm/llvm-project/commit/b415f8e3dfb839a886b5290bbebbdd42344c07a9
DIFF: https://github.com/llvm/llvm-project/commit/b415f8e3dfb839a886b5290bbebbdd42344c07a9.diff

LOG: [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

Added: 
    

Modified: 
    lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py

Removed: 
    


################################################################################
diff  --git a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
index 70cea2f85f6ec..8b8e30c9b7379 100644
--- a/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
+++ b/lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
@@ -9,10 +9,12 @@ class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase):
 
     fork_regex = ("[$]T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
                   "{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
+    fork_regex_nonstop = ("%Stop:T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
+                          "{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
     fork_capture = {1: "parent_pid", 2: "parent_tid",
                     3: "child_pid", 4: "child_tid"}
 
-    def start_fork_test(self, args, variant="fork"):
+    def start_fork_test(self, args, variant="fork", nonstop=False):
         self.build()
         self.prep_debug_monitor_and_inferior(inferior_args=args)
         self.add_qSupported_packets(["multiprocess+",
@@ -22,11 +24,24 @@ def start_fork_test(self, args, variant="fork"):
         self.reset_test_sequence()
 
         # continue and expect fork
-        self.test_sequence.add_log_lines([
-            "read packet: $c#00",
-            {"direction": "send", "regex": self.fork_regex.format(variant),
-             "capture": self.fork_capture},
-        ], True)
+        if nonstop:
+            self.test_sequence.add_log_lines([
+                "read packet: $QNonStop:1#00",
+                "send packet: $OK#00",
+                "read packet: $c#00",
+                "send packet: $OK#00",
+                {"direction": "send",
+                 "regex": self.fork_regex_nonstop.format(variant),
+                 "capture": self.fork_capture},
+                "read packet: $vStopped#00",
+                "send packet: $OK#00",
+            ], True)
+        else:
+            self.test_sequence.add_log_lines([
+                "read packet: $c#00",
+                {"direction": "send", "regex": self.fork_regex.format(variant),
+                 "capture": self.fork_capture},
+            ], True)
         ret = self.expect_gdbremote_sequence()
         self.reset_test_sequence()
 
@@ -45,9 +60,9 @@ def test_fork_multithreaded(self):
         ], True)
         self.expect_gdbremote_sequence()
 
-    def fork_and_detach_test(self, variant):
+    def fork_and_detach_test(self, variant, nonstop=False):
         parent_pid, parent_tid, child_pid, child_tid = (
-            self.start_fork_test([variant], variant))
+            self.start_fork_test([variant], variant, nonstop=nonstop))
 
         # detach the forked child
         self.test_sequence.add_log_lines([
@@ -77,6 +92,20 @@ def test_fork(self):
         ], True)
         self.expect_gdbremote_sequence()
 
+    @add_test_categories(["fork"])
+    def test_fork_nonstop(self):
+        parent_pid, _ = self.fork_and_detach_test("fork", nonstop=True)
+
+        # resume the parent
+        self.test_sequence.add_log_lines([
+            "read packet: $c#00",
+            "send packet: $OK#00",
+            "send packet: %Stop:W00;process:{}#00".format(parent_pid),
+            "read packet: $vStopped#00",
+            "send packet: $OK#00",
+        ], True)
+        self.expect_gdbremote_sequence()
+
     @add_test_categories(["fork"])
     def test_vfork(self):
         parent_pid, parent_tid = self.fork_and_detach_test("vfork")
@@ -93,9 +122,32 @@ def test_vfork(self):
         ], True)
         self.expect_gdbremote_sequence()
 
-    def fork_and_follow_test(self, variant):
+    @add_test_categories(["fork"])
+    def test_vfork_nonstop(self):
+        parent_pid, parent_tid = self.fork_and_detach_test("vfork",
+                                                           nonstop=True)
+
+        # resume the parent
+        self.test_sequence.add_log_lines([
+            "read packet: $c#00",
+            "send packet: $OK#00",
+            {"direction": "send",
+             "regex": r"%Stop:T05thread:p{}[.]{}.*vforkdone.*".format(
+                 parent_pid, parent_tid),
+             },
+            "read packet: $vStopped#00",
+            "send packet: $OK#00",
+            "read packet: $c#00",
+            "send packet: $OK#00",
+            "send packet: %Stop:W00;process:{}#00".format(parent_pid),
+            "read packet: $vStopped#00",
+            "send packet: $OK#00",
+        ], True)
+        self.expect_gdbremote_sequence()
+
+    def fork_and_follow_test(self, variant, nonstop=False):
         parent_pid, parent_tid, child_pid, child_tid = (
-            self.start_fork_test([variant], variant))
+            self.start_fork_test([variant], variant, nonstop=nonstop))
 
         # switch to the forked child
         self.test_sequence.add_log_lines([
@@ -113,18 +165,37 @@ def fork_and_follow_test(self, variant):
             "send packet: $OK#00",
             # then resume the child
             "read packet: $c#00",
-            "send packet: $W00;process:{}#00".format(child_pid),
         ], True)
+
+        if nonstop:
+            self.test_sequence.add_log_lines([
+                "send packet: $OK#00",
+                "send packet: %Stop:W00;process:{}#00".format(child_pid),
+                "read packet: $vStopped#00",
+                "send packet: $OK#00",
+            ], True)
+        else:
+            self.test_sequence.add_log_lines([
+                "send packet: $W00;process:{}#00".format(child_pid),
+            ], True)
         self.expect_gdbremote_sequence()
 
     @add_test_categories(["fork"])
     def test_fork_follow(self):
         self.fork_and_follow_test("fork")
 
+    @add_test_categories(["fork"])
+    def test_fork_follow_nonstop(self):
+        self.fork_and_follow_test("fork", nonstop=True)
+
     @add_test_categories(["fork"])
     def test_vfork_follow(self):
         self.fork_and_follow_test("vfork")
 
+    @add_test_categories(["fork"])
+    def test_vfork_follow_nonstop(self):
+        self.fork_and_follow_test("vfork", nonstop=True)
+
     @add_test_categories(["fork"])
     def test_select_wrong_pid(self):
         self.build()
@@ -191,10 +262,9 @@ def test_detach_current(self):
         ], True)
         self.expect_gdbremote_sequence()
 
-    @add_test_categories(["fork"])
-    def test_detach_all(self):
+    def detach_all_test(self, nonstop=False):
         parent_pid, parent_tid, child_pid, child_tid = (
-            self.start_fork_test(["fork"]))
+            self.start_fork_test(["fork"], nonstop=nonstop))
 
         self.test_sequence.add_log_lines([
             # double-check our PIDs
@@ -213,6 +283,14 @@ def test_detach_all(self):
         ], True)
         self.expect_gdbremote_sequence()
 
+    @add_test_categories(["fork"])
+    def test_detach_all(self):
+        self.detach_all_test()
+
+    @add_test_categories(["fork"])
+    def test_detach_all_nonstop(self):
+        self.detach_all_test(nonstop=True)
+
     @add_test_categories(["fork"])
     def test_kill_all(self):
         parent_pid, _, child_pid, _ = self.start_fork_test(["fork"])
@@ -230,10 +308,51 @@ def test_kill_all(self):
         self.assertEqual(set([ret["pid1"], ret["pid2"]]),
                          set([parent_pid, child_pid]))
 
-    def vkill_test(self, kill_parent=False, kill_child=False):
+    @add_test_categories(["fork"])
+    def test_kill_all_nonstop(self):
+        parent_pid, _, child_pid, _ = self.start_fork_test(["fork"],
+                                                           nonstop=True)
+
+        exit_regex = "X09;process:([0-9a-f]+)"
+        # Depending on a potential race, the second kill may make it into
+        # the async queue before we issue vStopped or after.  In the former
+        # case, we should expect the exit status in reply to vStopped.
+        # In the latter, we should expect an OK response (queue empty),
+        # followed by another async notification.
+        vstop_regex = "[$](OK|{})#.*".format(exit_regex)
+        self.test_sequence.add_log_lines([
+            # kill all processes
+            "read packet: $k#00",
+            "send packet: $OK#00",
+            {"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
+             "capture": {1: "pid1"}},
+            "read packet: $vStopped#00",
+            {"direction": "send", "regex": vstop_regex,
+             "capture": {1: "vstop_reply", 2: "pid2"}},
+        ], True)
+        ret = self.expect_gdbremote_sequence()
+        pid1 = ret["pid1"]
+        if ret["vstop_reply"] == "OK":
+            self.reset_test_sequence()
+            self.test_sequence.add_log_lines([
+                {"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
+                 "capture": {1: "pid2"}},
+            ], True)
+            ret = self.expect_gdbremote_sequence()
+        pid2 = ret["pid2"]
+        self.reset_test_sequence()
+        self.test_sequence.add_log_lines([
+            "read packet: $vStopped#00",
+            "send packet: $OK#00",
+        ], True)
+        self.expect_gdbremote_sequence()
+        self.assertEqual(set([ret["pid1"], ret["pid2"]]),
+                         set([parent_pid, child_pid]))
+
+    def vkill_test(self, kill_parent=False, kill_child=False, nonstop=False):
         assert kill_parent or kill_child
         parent_pid, parent_tid, child_pid, child_tid = (
-            self.start_fork_test(["fork"]))
+            self.start_fork_test(["fork"], nonstop=nonstop))
 
         if kill_parent:
             self.test_sequence.add_log_lines([
@@ -269,6 +388,10 @@ def test_vkill_parent(self):
     def test_vkill_both(self):
         self.vkill_test(kill_parent=True, kill_child=True)
 
+    @add_test_categories(["fork"])
+    def test_vkill_both_nonstop(self):
+        self.vkill_test(kill_parent=True, kill_child=True, nonstop=True)
+
     def resume_one_test(self, run_order, use_vCont=False):
         parent_pid, parent_tid, child_pid, child_tid = (
             self.start_fork_test(["fork", "trap"]))


        


More information about the lldb-commits mailing list