1
2import os
3from time import sleep
4
5import gdbremote_testcase
6import lldbgdbserverutils
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class TestGdbRemoteAttachWait(gdbremote_testcase.GdbRemoteTestCaseBase):
13
14    @skipIfWindows # This test is flaky on Windows
15    def test_attach_with_vAttachWait(self):
16        exe = '%s_%d' % (self.testMethodName, os.getpid())
17        exe_to_attach = exe
18        args = []
19
20        def launch_inferior():
21            inferior = self.launch_process_for_attach(
22                inferior_args=args,
23                exe_path=self.getBuildArtifact(exe))
24            self.assertIsNotNone(inferior)
25            self.assertTrue(inferior.pid > 0)
26            self.assertTrue(
27                lldbgdbserverutils.process_is_running(
28                    inferior.pid, True))
29            return inferior
30
31        self.build(dictionary={'EXE': exe, 'CXX_SOURCES': 'main.cpp'})
32        if self.getPlatform() != "windows":
33            # Use a shim to ensure that the process is ready to be attached from
34            # the get-go.
35            args = [self.getBuildArtifact(exe)]
36            exe = "shim"
37            self.build(dictionary={'EXE': exe, 'CXX_SOURCES': 'shim.cpp'})
38
39        self.set_inferior_startup_attach_manually()
40
41        server = self.connect_to_debug_monitor()
42        self.assertIsNotNone(server)
43
44        # Launch the first inferior (we shouldn't attach to this one).
45        launch_inferior()
46
47        self.do_handshake()
48        self.test_sequence.add_log_lines([
49            # Do the attach.
50            "read packet: $vAttachWait;{}#00".format(
51                lldbgdbserverutils.gdbremote_hex_encode_string(exe_to_attach)),
52        ], True)
53        # Run the stream until attachWait.
54        context = self.expect_gdbremote_sequence()
55        self.assertIsNotNone(context)
56
57        # Sleep so we're sure that the inferior is launched after we ask for the attach.
58        sleep(1)
59
60        # Launch the second inferior (we SHOULD attach to this one).
61        inferior_to_attach = launch_inferior()
62
63        # Make sure the attach succeeded.
64        self.test_sequence.add_log_lines([
65            {"direction": "send",
66             "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$",
67             "capture": {1: "stop_signal_hex"}},
68        ], True)
69        self.add_process_info_collection_packets()
70
71
72        # Run the stream sending the response..
73        context = self.expect_gdbremote_sequence()
74        self.assertIsNotNone(context)
75
76        # Gather process info response.
77        process_info = self.parse_process_info_response(context)
78        self.assertIsNotNone(process_info)
79
80        # Ensure the process id matches what we expected.
81        pid_text = process_info.get('pid', None)
82        self.assertIsNotNone(pid_text)
83        reported_pid = int(pid_text, base=16)
84        self.assertEqual(reported_pid, inferior_to_attach.pid)
85