182ba3f44SPavel Labath
282ba3f44SPavel Labathimport os
382ba3f44SPavel Labathfrom time import sleep
482ba3f44SPavel Labath
582ba3f44SPavel Labathimport gdbremote_testcase
682ba3f44SPavel Labathimport lldbgdbserverutils
782ba3f44SPavel Labathfrom lldbsuite.test.decorators import *
882ba3f44SPavel Labathfrom lldbsuite.test.lldbtest import *
982ba3f44SPavel Labathfrom lldbsuite.test import lldbutil
1082ba3f44SPavel Labath
1182ba3f44SPavel Labath
1282ba3f44SPavel Labathclass TestGdbRemoteAttachWait(gdbremote_testcase.GdbRemoteTestCaseBase):
1382ba3f44SPavel Labath
14*d955185bSPavel Labath    def _set_up_inferior(self):
15*d955185bSPavel Labath        self._exe_to_attach = '%s_%d' % (self.testMethodName, os.getpid())
16*d955185bSPavel Labath        self.build(dictionary={'EXE': self._exe_to_attach, 'CXX_SOURCES': 'main.cpp'})
1782ba3f44SPavel Labath
18*d955185bSPavel Labath        if self.getPlatform() != "windows":
19*d955185bSPavel Labath            # Use a shim to ensure that the process is ready to be attached from
20*d955185bSPavel Labath            # the get-go.
21*d955185bSPavel Labath            self._exe_to_run = "shim"
22*d955185bSPavel Labath            self._run_args = [self.getBuildArtifact(self._exe_to_attach)]
23*d955185bSPavel Labath            self.build(dictionary={'EXE': self._exe_to_run, 'CXX_SOURCES':
24*d955185bSPavel Labath                'shim.cpp'})
25*d955185bSPavel Labath        else:
26*d955185bSPavel Labath            self._exe_to_run = self._exe_to_attach
27*d955185bSPavel Labath            self._run_args = []
28*d955185bSPavel Labath
29*d955185bSPavel Labath    def _launch_inferior(self, args):
30*d955185bSPavel Labath        inferior = self.spawnSubprocess(self.getBuildArtifact(self._exe_to_run),
31*d955185bSPavel Labath                args)
3282ba3f44SPavel Labath        self.assertIsNotNone(inferior)
3382ba3f44SPavel Labath        self.assertTrue(inferior.pid > 0)
3482ba3f44SPavel Labath        self.assertTrue(
3582ba3f44SPavel Labath            lldbgdbserverutils.process_is_running(
3682ba3f44SPavel Labath                inferior.pid, True))
3782ba3f44SPavel Labath        return inferior
3882ba3f44SPavel Labath
39*d955185bSPavel Labath    def _launch_and_wait_for_init(self):
40*d955185bSPavel Labath        sync_file_path = lldbutil.append_to_process_working_directory(self,
41*d955185bSPavel Labath                "process_ready")
42*d955185bSPavel Labath        inferior = self._launch_inferior(self._run_args + [sync_file_path])
43*d955185bSPavel Labath        lldbutil.wait_for_file_on_target(self, sync_file_path)
44*d955185bSPavel Labath        return inferior
45*d955185bSPavel Labath
46*d955185bSPavel Labath    def _attach_packet(self, packet_type):
47*d955185bSPavel Labath        return "read packet: ${};{}#00".format(packet_type,
48*d955185bSPavel Labath                lldbgdbserverutils.gdbremote_hex_encode_string(self._exe_to_attach))
49*d955185bSPavel Labath
50*d955185bSPavel Labath
51*d955185bSPavel Labath    @skipIfWindows # This test is flaky on Windows
52*d955185bSPavel Labath    def test_attach_with_vAttachWait(self):
53*d955185bSPavel Labath        self._set_up_inferior()
5482ba3f44SPavel Labath
5582ba3f44SPavel Labath        self.set_inferior_startup_attach_manually()
5682ba3f44SPavel Labath        server = self.connect_to_debug_monitor()
57*d955185bSPavel Labath        self.do_handshake()
5882ba3f44SPavel Labath
5982ba3f44SPavel Labath        # Launch the first inferior (we shouldn't attach to this one).
60*d955185bSPavel Labath        self._launch_and_wait_for_init()
6182ba3f44SPavel Labath
62*d955185bSPavel Labath        self.test_sequence.add_log_lines([self._attach_packet("vAttachWait")],
63*d955185bSPavel Labath                True)
6482ba3f44SPavel Labath        # Run the stream until attachWait.
6582ba3f44SPavel Labath        context = self.expect_gdbremote_sequence()
6682ba3f44SPavel Labath        self.assertIsNotNone(context)
6782ba3f44SPavel Labath
6882ba3f44SPavel Labath        # Sleep so we're sure that the inferior is launched after we ask for the attach.
6982ba3f44SPavel Labath        sleep(1)
7082ba3f44SPavel Labath
7182ba3f44SPavel Labath        # Launch the second inferior (we SHOULD attach to this one).
72*d955185bSPavel Labath        inferior_to_attach = self._launch_inferior(self._run_args)
7382ba3f44SPavel Labath
7482ba3f44SPavel Labath        # Make sure the attach succeeded.
7582ba3f44SPavel Labath        self.test_sequence.add_log_lines([
7682ba3f44SPavel Labath            {"direction": "send",
7782ba3f44SPavel Labath             "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$",
7882ba3f44SPavel Labath             "capture": {1: "stop_signal_hex"}},
7982ba3f44SPavel Labath        ], True)
8082ba3f44SPavel Labath        self.add_process_info_collection_packets()
8182ba3f44SPavel Labath
8282ba3f44SPavel Labath
8382ba3f44SPavel Labath        # Run the stream sending the response..
8482ba3f44SPavel Labath        context = self.expect_gdbremote_sequence()
8582ba3f44SPavel Labath        self.assertIsNotNone(context)
8682ba3f44SPavel Labath
8782ba3f44SPavel Labath        # Gather process info response.
8882ba3f44SPavel Labath        process_info = self.parse_process_info_response(context)
8982ba3f44SPavel Labath        self.assertIsNotNone(process_info)
9082ba3f44SPavel Labath
9182ba3f44SPavel Labath        # Ensure the process id matches what we expected.
9282ba3f44SPavel Labath        pid_text = process_info.get('pid', None)
9382ba3f44SPavel Labath        self.assertIsNotNone(pid_text)
9482ba3f44SPavel Labath        reported_pid = int(pid_text, base=16)
9582ba3f44SPavel Labath        self.assertEqual(reported_pid, inferior_to_attach.pid)
96*d955185bSPavel Labath
97*d955185bSPavel Labath    @skipIfWindows # This test is flaky on Windows
98*d955185bSPavel Labath    def test_launch_before_attach_with_vAttachOrWait(self):
99*d955185bSPavel Labath        self._set_up_inferior()
100*d955185bSPavel Labath
101*d955185bSPavel Labath        self.set_inferior_startup_attach_manually()
102*d955185bSPavel Labath        server = self.connect_to_debug_monitor()
103*d955185bSPavel Labath        self.do_handshake()
104*d955185bSPavel Labath
105*d955185bSPavel Labath        inferior = self._launch_and_wait_for_init()
106*d955185bSPavel Labath
107*d955185bSPavel Labath        # Add attach packets.
108*d955185bSPavel Labath        self.test_sequence.add_log_lines([
109*d955185bSPavel Labath            # Do the attach.
110*d955185bSPavel Labath            self._attach_packet("vAttachOrWait"),
111*d955185bSPavel Labath            # Expect a stop notification from the attach.
112*d955185bSPavel Labath            {"direction": "send",
113*d955185bSPavel Labath             "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$",
114*d955185bSPavel Labath             "capture": {1: "stop_signal_hex"}},
115*d955185bSPavel Labath        ], True)
116*d955185bSPavel Labath        self.add_process_info_collection_packets()
117*d955185bSPavel Labath
118*d955185bSPavel Labath        # Run the stream
119*d955185bSPavel Labath        context = self.expect_gdbremote_sequence()
120*d955185bSPavel Labath        self.assertIsNotNone(context)
121*d955185bSPavel Labath
122*d955185bSPavel Labath        # Gather process info response
123*d955185bSPavel Labath        process_info = self.parse_process_info_response(context)
124*d955185bSPavel Labath        self.assertIsNotNone(process_info)
125*d955185bSPavel Labath
126*d955185bSPavel Labath        # Ensure the process id matches what we expected.
127*d955185bSPavel Labath        pid_text = process_info.get('pid', None)
128*d955185bSPavel Labath        self.assertIsNotNone(pid_text)
129*d955185bSPavel Labath        reported_pid = int(pid_text, base=16)
130*d955185bSPavel Labath        self.assertEqual(reported_pid, inferior.pid)
131*d955185bSPavel Labath
132*d955185bSPavel Labath    @skipIfWindows # This test is flaky on Windows
133*d955185bSPavel Labath    def test_launch_after_attach_with_vAttachOrWait(self):
134*d955185bSPavel Labath        self._set_up_inferior()
135*d955185bSPavel Labath
136*d955185bSPavel Labath        self.set_inferior_startup_attach_manually()
137*d955185bSPavel Labath        server = self.connect_to_debug_monitor()
138*d955185bSPavel Labath        self.do_handshake()
139*d955185bSPavel Labath
140*d955185bSPavel Labath        self.test_sequence.add_log_lines([self._attach_packet("vAttachOrWait")],
141*d955185bSPavel Labath                True)
142*d955185bSPavel Labath        # Run the stream until attachWait.
143*d955185bSPavel Labath        context = self.expect_gdbremote_sequence()
144*d955185bSPavel Labath        self.assertIsNotNone(context)
145*d955185bSPavel Labath
146*d955185bSPavel Labath        # Sleep so we're sure that the inferior is launched after we ask for the attach.
147*d955185bSPavel Labath        sleep(1)
148*d955185bSPavel Labath
149*d955185bSPavel Labath        # Launch the inferior.
150*d955185bSPavel Labath        inferior = self._launch_inferior(self._run_args)
151*d955185bSPavel Labath
152*d955185bSPavel Labath        # Make sure the attach succeeded.
153*d955185bSPavel Labath        self.test_sequence.add_log_lines([
154*d955185bSPavel Labath            {"direction": "send",
155*d955185bSPavel Labath             "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$",
156*d955185bSPavel Labath             "capture": {1: "stop_signal_hex"}},
157*d955185bSPavel Labath        ], True)
158*d955185bSPavel Labath        self.add_process_info_collection_packets()
159*d955185bSPavel Labath
160*d955185bSPavel Labath
161*d955185bSPavel Labath        # Run the stream sending the response..
162*d955185bSPavel Labath        context = self.expect_gdbremote_sequence()
163*d955185bSPavel Labath        self.assertIsNotNone(context)
164*d955185bSPavel Labath
165*d955185bSPavel Labath        # Gather process info response.
166*d955185bSPavel Labath        process_info = self.parse_process_info_response(context)
167*d955185bSPavel Labath        self.assertIsNotNone(process_info)
168*d955185bSPavel Labath
169*d955185bSPavel Labath        # Ensure the process id matches what we expected.
170*d955185bSPavel Labath        pid_text = process_info.get('pid', None)
171*d955185bSPavel Labath        self.assertIsNotNone(pid_text)
172*d955185bSPavel Labath        reported_pid = int(pid_text, base=16)
173*d955185bSPavel Labath        self.assertEqual(reported_pid, inferior.pid)
174