182ba3f44SPavel Labathimport os 282ba3f44SPavel Labathfrom time import sleep 382ba3f44SPavel Labath 482ba3f44SPavel Labathimport gdbremote_testcase 582ba3f44SPavel Labathimport lldbgdbserverutils 682ba3f44SPavel Labathfrom lldbsuite.test.decorators import * 782ba3f44SPavel Labathfrom lldbsuite.test.lldbtest import * 882ba3f44SPavel Labathfrom lldbsuite.test import lldbutil 982ba3f44SPavel Labath 1082ba3f44SPavel Labath 1182ba3f44SPavel Labathclass TestGdbRemoteAttachWait(gdbremote_testcase.GdbRemoteTestCaseBase): 12d955185bSPavel Labath def _set_up_inferior(self): 132238dcc3SJonas Devlieghere self._exe_to_attach = "%s_%d" % (self.testMethodName, os.getpid()) 142238dcc3SJonas Devlieghere self.build(dictionary={"EXE": self._exe_to_attach, "CXX_SOURCES": "main.cpp"}) 1582ba3f44SPavel Labath 16d955185bSPavel Labath if self.getPlatform() != "windows": 17d955185bSPavel Labath # Use a shim to ensure that the process is ready to be attached from 18d955185bSPavel Labath # the get-go. 19d955185bSPavel Labath self._exe_to_run = "shim" 20*d38ea8c4SDmitry Vasilyev self._exe_to_attach = lldbutil.install_to_target( 21*d38ea8c4SDmitry Vasilyev self, self.getBuildArtifact(self._exe_to_attach) 22*d38ea8c4SDmitry Vasilyev ) 23*d38ea8c4SDmitry Vasilyev self._run_args = [self._exe_to_attach] 242238dcc3SJonas Devlieghere self.build(dictionary={"EXE": self._exe_to_run, "CXX_SOURCES": "shim.cpp"}) 25d955185bSPavel Labath else: 26d955185bSPavel Labath self._exe_to_run = self._exe_to_attach 27d955185bSPavel Labath self._run_args = [] 28d955185bSPavel Labath 29d955185bSPavel Labath def _launch_inferior(self, args): 302238dcc3SJonas Devlieghere inferior = self.spawnSubprocess(self.getBuildArtifact(self._exe_to_run), args) 3182ba3f44SPavel Labath self.assertIsNotNone(inferior) 329c246882SJordan Rupprecht self.assertGreater(inferior.pid, 0) 332238dcc3SJonas Devlieghere self.assertTrue(lldbgdbserverutils.process_is_running(inferior.pid, True)) 3482ba3f44SPavel Labath return inferior 3582ba3f44SPavel Labath 36d955185bSPavel Labath def _launch_and_wait_for_init(self): 372238dcc3SJonas Devlieghere sync_file_path = lldbutil.append_to_process_working_directory( 382238dcc3SJonas Devlieghere self, "process_ready" 392238dcc3SJonas Devlieghere ) 40d955185bSPavel Labath inferior = self._launch_inferior(self._run_args + [sync_file_path]) 41d955185bSPavel Labath lldbutil.wait_for_file_on_target(self, sync_file_path) 42d955185bSPavel Labath return inferior 43d955185bSPavel Labath 44d955185bSPavel Labath def _attach_packet(self, packet_type): 452238dcc3SJonas Devlieghere return "read packet: ${};{}#00".format( 462238dcc3SJonas Devlieghere packet_type, 472238dcc3SJonas Devlieghere lldbgdbserverutils.gdbremote_hex_encode_string(self._exe_to_attach), 482238dcc3SJonas Devlieghere ) 49d955185bSPavel Labath 50d955185bSPavel Labath @skipIfWindows # This test is flaky on Windows 51d955185bSPavel Labath def test_attach_with_vAttachWait(self): 52d955185bSPavel Labath self._set_up_inferior() 5382ba3f44SPavel Labath 5482ba3f44SPavel Labath self.set_inferior_startup_attach_manually() 5582ba3f44SPavel Labath server = self.connect_to_debug_monitor() 56d955185bSPavel Labath self.do_handshake() 5782ba3f44SPavel Labath 5882ba3f44SPavel Labath # Launch the first inferior (we shouldn't attach to this one). 59d955185bSPavel Labath self._launch_and_wait_for_init() 6082ba3f44SPavel Labath 612238dcc3SJonas Devlieghere self.test_sequence.add_log_lines([self._attach_packet("vAttachWait")], True) 6282ba3f44SPavel Labath # Run the stream until attachWait. 6382ba3f44SPavel Labath context = self.expect_gdbremote_sequence() 6482ba3f44SPavel Labath self.assertIsNotNone(context) 6582ba3f44SPavel Labath 6682ba3f44SPavel Labath # Sleep so we're sure that the inferior is launched after we ask for the attach. 6782ba3f44SPavel Labath sleep(1) 6882ba3f44SPavel Labath 6982ba3f44SPavel Labath # Launch the second inferior (we SHOULD attach to this one). 70d955185bSPavel Labath inferior_to_attach = self._launch_inferior(self._run_args) 7182ba3f44SPavel Labath 7282ba3f44SPavel Labath # Make sure the attach succeeded. 732238dcc3SJonas Devlieghere self.test_sequence.add_log_lines( 742238dcc3SJonas Devlieghere [ 752238dcc3SJonas Devlieghere { 762238dcc3SJonas Devlieghere "direction": "send", 7782ba3f44SPavel Labath "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$", 782238dcc3SJonas Devlieghere "capture": {1: "stop_signal_hex"}, 792238dcc3SJonas Devlieghere }, 802238dcc3SJonas Devlieghere ], 812238dcc3SJonas Devlieghere True, 822238dcc3SJonas Devlieghere ) 8382ba3f44SPavel Labath self.add_process_info_collection_packets() 8482ba3f44SPavel Labath 8582ba3f44SPavel Labath # Run the stream sending the response.. 8682ba3f44SPavel Labath context = self.expect_gdbremote_sequence() 8782ba3f44SPavel Labath self.assertIsNotNone(context) 8882ba3f44SPavel Labath 8982ba3f44SPavel Labath # Gather process info response. 9082ba3f44SPavel Labath process_info = self.parse_process_info_response(context) 9182ba3f44SPavel Labath self.assertIsNotNone(process_info) 9282ba3f44SPavel Labath 9382ba3f44SPavel Labath # Ensure the process id matches what we expected. 942238dcc3SJonas Devlieghere pid_text = process_info.get("pid", None) 9582ba3f44SPavel Labath self.assertIsNotNone(pid_text) 9682ba3f44SPavel Labath reported_pid = int(pid_text, base=16) 9782ba3f44SPavel Labath self.assertEqual(reported_pid, inferior_to_attach.pid) 98d955185bSPavel Labath 99d955185bSPavel Labath @skipIfWindows # This test is flaky on Windows 100d955185bSPavel Labath def test_launch_before_attach_with_vAttachOrWait(self): 101d955185bSPavel Labath self._set_up_inferior() 102d955185bSPavel Labath 103d955185bSPavel Labath self.set_inferior_startup_attach_manually() 104d955185bSPavel Labath server = self.connect_to_debug_monitor() 105d955185bSPavel Labath self.do_handshake() 106d955185bSPavel Labath 107d955185bSPavel Labath inferior = self._launch_and_wait_for_init() 108d955185bSPavel Labath 109d955185bSPavel Labath # Add attach packets. 1102238dcc3SJonas Devlieghere self.test_sequence.add_log_lines( 1112238dcc3SJonas Devlieghere [ 112d955185bSPavel Labath # Do the attach. 113d955185bSPavel Labath self._attach_packet("vAttachOrWait"), 114d955185bSPavel Labath # Expect a stop notification from the attach. 1152238dcc3SJonas Devlieghere { 1162238dcc3SJonas Devlieghere "direction": "send", 117d955185bSPavel Labath "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$", 1182238dcc3SJonas Devlieghere "capture": {1: "stop_signal_hex"}, 1192238dcc3SJonas Devlieghere }, 1202238dcc3SJonas Devlieghere ], 1212238dcc3SJonas Devlieghere True, 1222238dcc3SJonas Devlieghere ) 123d955185bSPavel Labath self.add_process_info_collection_packets() 124d955185bSPavel Labath 125d955185bSPavel Labath # Run the stream 126d955185bSPavel Labath context = self.expect_gdbremote_sequence() 127d955185bSPavel Labath self.assertIsNotNone(context) 128d955185bSPavel Labath 129d955185bSPavel Labath # Gather process info response 130d955185bSPavel Labath process_info = self.parse_process_info_response(context) 131d955185bSPavel Labath self.assertIsNotNone(process_info) 132d955185bSPavel Labath 133d955185bSPavel Labath # Ensure the process id matches what we expected. 1342238dcc3SJonas Devlieghere pid_text = process_info.get("pid", None) 135d955185bSPavel Labath self.assertIsNotNone(pid_text) 136d955185bSPavel Labath reported_pid = int(pid_text, base=16) 137d955185bSPavel Labath self.assertEqual(reported_pid, inferior.pid) 138d955185bSPavel Labath 139d955185bSPavel Labath @skipIfWindows # This test is flaky on Windows 140d955185bSPavel Labath def test_launch_after_attach_with_vAttachOrWait(self): 141d955185bSPavel Labath self._set_up_inferior() 142d955185bSPavel Labath 143d955185bSPavel Labath self.set_inferior_startup_attach_manually() 144d955185bSPavel Labath server = self.connect_to_debug_monitor() 145d955185bSPavel Labath self.do_handshake() 146d955185bSPavel Labath 1472238dcc3SJonas Devlieghere self.test_sequence.add_log_lines([self._attach_packet("vAttachOrWait")], True) 148d955185bSPavel Labath # Run the stream until attachWait. 149d955185bSPavel Labath context = self.expect_gdbremote_sequence() 150d955185bSPavel Labath self.assertIsNotNone(context) 151d955185bSPavel Labath 152d955185bSPavel Labath # Sleep so we're sure that the inferior is launched after we ask for the attach. 153d955185bSPavel Labath sleep(1) 154d955185bSPavel Labath 155d955185bSPavel Labath # Launch the inferior. 156d955185bSPavel Labath inferior = self._launch_inferior(self._run_args) 157d955185bSPavel Labath 158d955185bSPavel Labath # Make sure the attach succeeded. 1592238dcc3SJonas Devlieghere self.test_sequence.add_log_lines( 1602238dcc3SJonas Devlieghere [ 1612238dcc3SJonas Devlieghere { 1622238dcc3SJonas Devlieghere "direction": "send", 163d955185bSPavel Labath "regex": r"^\$T([0-9a-fA-F]{2})[^#]*#[0-9a-fA-F]{2}$", 1642238dcc3SJonas Devlieghere "capture": {1: "stop_signal_hex"}, 1652238dcc3SJonas Devlieghere }, 1662238dcc3SJonas Devlieghere ], 1672238dcc3SJonas Devlieghere True, 1682238dcc3SJonas Devlieghere ) 169d955185bSPavel Labath self.add_process_info_collection_packets() 170d955185bSPavel Labath 171d955185bSPavel Labath # Run the stream sending the response.. 172d955185bSPavel Labath context = self.expect_gdbremote_sequence() 173d955185bSPavel Labath self.assertIsNotNone(context) 174d955185bSPavel Labath 175d955185bSPavel Labath # Gather process info response. 176d955185bSPavel Labath process_info = self.parse_process_info_response(context) 177d955185bSPavel Labath self.assertIsNotNone(process_info) 178d955185bSPavel Labath 179d955185bSPavel Labath # Ensure the process id matches what we expected. 1802238dcc3SJonas Devlieghere pid_text = process_info.get("pid", None) 181d955185bSPavel Labath self.assertIsNotNone(pid_text) 182d955185bSPavel Labath reported_pid = int(pid_text, base=16) 183d955185bSPavel Labath self.assertEqual(reported_pid, inferior.pid) 184