blob: 8937621fb60128d42e8407f26706c9086d90b31f [file] [log] [blame]
import gdbremote_testcase
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase):
mydir = TestBase.compute_mydir(__file__)
def fork_and_detach_test(self, variant):
self.build()
self.prep_debug_monitor_and_inferior(inferior_args=[variant])
self.add_qSupported_packets(["multiprocess+",
"{}-events+".format(variant)])
ret = self.expect_gdbremote_sequence()
self.assertIn("{}-events+".format(variant), ret["qSupported_response"])
self.reset_test_sequence()
# continue and expect fork
fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant)
self.test_sequence.add_log_lines([
"read packet: $c#00",
{"direction": "send", "regex": fork_regex,
"capture": {1: "pid", 2: "tid"}},
], True)
ret = self.expect_gdbremote_sequence()
pid = int(ret["pid"], 16)
self.reset_test_sequence()
# detach the forked child
self.test_sequence.add_log_lines([
"read packet: $D;{:x}#00".format(pid),
{"direction": "send", "regex": r"[$]OK#.*"},
], True)
ret = self.expect_gdbremote_sequence()
self.reset_test_sequence()
@add_test_categories(["fork"])
def test_fork(self):
self.fork_and_detach_test("fork")
# resume the parent
self.test_sequence.add_log_lines([
"read packet: $c#00",
{"direction": "send", "regex": r"[$]W00#.*"},
], True)
self.expect_gdbremote_sequence()
@add_test_categories(["fork"])
def test_vfork(self):
self.fork_and_detach_test("vfork")
# resume the parent
self.test_sequence.add_log_lines([
"read packet: $c#00",
{"direction": "send", "regex": r"[$]T.*vforkdone.*"},
"read packet: $c#00",
{"direction": "send", "regex": r"[$]W00#.*"},
], True)
self.expect_gdbremote_sequence()
def fork_and_follow_test(self, variant):
self.build()
self.prep_debug_monitor_and_inferior(inferior_args=[variant])
self.add_qSupported_packets(["multiprocess+",
"{}-events+".format(variant)])
ret = self.expect_gdbremote_sequence()
self.assertIn("{}-events+".format(variant), ret["qSupported_response"])
self.reset_test_sequence()
# continue and expect fork
procinfo_regex = "[$]pid:([0-9a-f]+);.*"
fork_regex = "[$]T.*;{}:p([0-9a-f]+)[.]([0-9a-f]+).*".format(variant)
self.test_sequence.add_log_lines([
"read packet: $qProcessInfo#00",
{"direction": "send", "regex": procinfo_regex,
"capture": {1: "parent_pid"}},
"read packet: $c#00",
{"direction": "send", "regex": fork_regex,
"capture": {1: "pid", 2: "tid"}},
], True)
ret = self.expect_gdbremote_sequence()
parent_pid, pid, tid = (int(ret[x], 16) for x
in ("parent_pid", "pid", "tid"))
self.reset_test_sequence()
# switch to the forked child
self.test_sequence.add_log_lines([
"read packet: $Hgp{:x}.{:x}#00".format(pid, tid),
{"direction": "send", "regex": r"[$]OK#.*"},
"read packet: $Hcp{:x}.{:x}#00".format(pid, tid),
{"direction": "send", "regex": r"[$]OK#.*"},
], True)
# detach the parent
self.test_sequence.add_log_lines([
"read packet: $D;{:x}#00".format(parent_pid),
{"direction": "send", "regex": r"[$]OK#.*"},
], True)
ret = self.expect_gdbremote_sequence()
self.reset_test_sequence()
# resume the child
self.test_sequence.add_log_lines([
"read packet: $c#00",
{"direction": "send", "regex": r"[$]W00#.*"},
], 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_vfork_follow(self):
self.fork_and_follow_test("vfork")
@add_test_categories(["fork"])
def test_select_wrong_pid(self):
self.build()
self.prep_debug_monitor_and_inferior()
self.add_qSupported_packets(["multiprocess+"])
ret = self.expect_gdbremote_sequence()
self.assertIn("multiprocess+", ret["qSupported_response"])
self.reset_test_sequence()
# get process pid
procinfo_regex = "[$]pid:([0-9a-f]+);.*"
self.test_sequence.add_log_lines([
"read packet: $qProcessInfo#00",
{"direction": "send", "regex": procinfo_regex,
"capture": {1: "pid"}},
"read packet: $qC#00",
{"direction": "send", "regex": "[$]QC([0-9a-f]+)#.*",
"capture": {1: "tid"}},
], True)
ret = self.expect_gdbremote_sequence()
pid, tid = (int(ret[x], 16) for x in ("pid", "tid"))
self.reset_test_sequence()
# try switching to correct pid
self.test_sequence.add_log_lines([
"read packet: $Hgp{:x}.{:x}#00".format(pid, tid),
{"direction": "send", "regex": r"[$]OK#.*"},
"read packet: $Hcp{:x}.{:x}#00".format(pid, tid),
{"direction": "send", "regex": r"[$]OK#.*"},
], True)
ret = self.expect_gdbremote_sequence()
# try switching to invalid tid
self.test_sequence.add_log_lines([
"read packet: $Hgp{:x}.{:x}#00".format(pid, tid+1),
{"direction": "send", "regex": r"[$]E15#.*"},
"read packet: $Hcp{:x}.{:x}#00".format(pid, tid+1),
{"direction": "send", "regex": r"[$]E15#.*"},
], True)
ret = self.expect_gdbremote_sequence()
# try switching to invalid pid
self.test_sequence.add_log_lines([
"read packet: $Hgp{:x}.{:x}#00".format(pid+1, tid),
{"direction": "send", "regex": r"[$]Eff#.*"},
"read packet: $Hcp{:x}.{:x}#00".format(pid+1, tid),
{"direction": "send", "regex": r"[$]Eff#.*"},
], True)
ret = self.expect_gdbremote_sequence()
@add_test_categories(["fork"])
def test_detach_current(self):
self.build()
self.prep_debug_monitor_and_inferior()
self.add_qSupported_packets(["multiprocess+"])
ret = self.expect_gdbremote_sequence()
self.assertIn("multiprocess+", ret["qSupported_response"])
self.reset_test_sequence()
# get process pid
procinfo_regex = "[$]pid:([0-9a-f]+);.*"
self.test_sequence.add_log_lines([
"read packet: $qProcessInfo#00",
{"direction": "send", "regex": procinfo_regex,
"capture": {1: "pid"}},
], True)
ret = self.expect_gdbremote_sequence()
pid = int(ret["pid"], 16)
self.reset_test_sequence()
# detach the process
self.test_sequence.add_log_lines([
"read packet: $D;{:x}#00".format(pid),
{"direction": "send", "regex": r"[$]OK#.*"},
"read packet: $qC#00",
{"direction": "send", "regex": r"[$]E44#.*"},
], True)
ret = self.expect_gdbremote_sequence()