165 lines · python
1"""2Test lldb-dap server integration.3"""4 5import os6import signal7import tempfile8import time9 10import dap_server11from lldbsuite.test.decorators import *12from lldbsuite.test.lldbtest import *13import lldbdap_testcase14 15 16class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):17 def start_server(18 self, connection, connection_timeout=None, wait_seconds_for_termination=None19 ):20 log_file_path = self.getBuildArtifact("dap.txt")21 (process, connection) = dap_server.DebugAdapterServer.launch(22 executable=self.lldbDAPExec,23 connection=connection,24 connection_timeout=connection_timeout,25 log_file=log_file_path,26 )27 28 def cleanup():29 if wait_seconds_for_termination is not None:30 process.wait(wait_seconds_for_termination)31 else:32 process.terminate()33 34 self.addTearDownHook(cleanup)35 36 return (process, connection)37 38 def run_debug_session(self, connection, name, sleep_seconds_in_middle=None):39 self.dap_server = dap_server.DebugAdapterServer(40 connection=connection, spawn_helper=self.spawnSubprocess41 )42 program = self.getBuildArtifact("a.out")43 source = "main.c"44 breakpoint_line = line_number(source, "// breakpoint")45 46 self.launch(47 program,48 args=[name],49 disconnectAutomatically=False,50 )51 if sleep_seconds_in_middle is not None:52 time.sleep(sleep_seconds_in_middle)53 self.set_source_breakpoints(source, [breakpoint_line])54 self.continue_to_next_stop()55 self.continue_to_exit()56 output = self.get_stdout()57 self.assertEqual(output, f"Hello {name}!\r\n")58 self.dap_server.request_disconnect()59 60 @skipIfWindows61 def test_server_port(self):62 """63 Test launching a binary with a lldb-dap in server mode on a specific port.64 """65 self.build()66 (_, connection) = self.start_server(connection="listen://localhost:0")67 self.run_debug_session(connection, "Alice")68 self.run_debug_session(connection, "Bob")69 70 @skipIfWindows71 def test_server_unix_socket(self):72 """73 Test launching a binary with a lldb-dap in server mode on a unix socket.74 """75 dir = tempfile.gettempdir()76 name = dir + "/dap-connection-" + str(os.getpid())77 78 def cleanup():79 os.unlink(name)80 81 self.addTearDownHook(cleanup)82 83 self.build()84 (_, connection) = self.start_server(connection="accept://" + name)85 self.run_debug_session(connection, "Alice")86 self.run_debug_session(connection, "Bob")87 88 @skipIfWindows89 def test_server_interrupt(self):90 """91 Test launching a binary with lldb-dap in server mode and shutting down the server while the debug session is still active.92 """93 self.build()94 (process, connection) = self.start_server(connection="listen://localhost:0")95 self.dap_server = dap_server.DebugAdapterServer(96 connection=connection,97 spawn_helper=self.spawnSubprocess,98 )99 program = self.getBuildArtifact("a.out")100 source = "main.c"101 breakpoint_line = line_number(source, "// breakpoint")102 103 self.launch(104 program,105 args=["Alice"],106 disconnectAutomatically=False,107 )108 self.set_source_breakpoints(source, [breakpoint_line])109 self.continue_to_next_stop()110 111 # Interrupt the server which should disconnect all clients.112 process.send_signal(signal.SIGINT)113 114 # Wait for both events since they can happen in any order.115 self.dap_server.wait_for_event(["terminated", "exited"])116 self.dap_server.wait_for_event(["terminated", "exited"])117 self.assertIsNotNone(118 self.dap_server.exit_status,119 "Process exited before interrupting lldb-dap server",120 )121 122 @skipIfWindows123 def test_connection_timeout_at_server_start(self):124 """125 Test launching lldb-dap in server mode with connection timeout and waiting for it to terminate automatically when no client connects.126 """127 self.build()128 self.start_server(129 connection="listen://localhost:0",130 connection_timeout=1,131 wait_seconds_for_termination=5,132 )133 134 @skipIfWindows135 def test_connection_timeout_long_debug_session(self):136 """137 Test launching lldb-dap in server mode with connection timeout and terminating the server after the a long debug session.138 """139 self.build()140 (_, connection) = self.start_server(141 connection="listen://localhost:0",142 connection_timeout=1,143 wait_seconds_for_termination=5,144 )145 # The connection timeout should not cut off the debug session146 self.run_debug_session(connection, "Alice", 1.5)147 148 @skipIfWindows149 def test_connection_timeout_multiple_sessions(self):150 """151 Test launching lldb-dap in server mode with connection timeout and terminating the server after the last debug session.152 """153 self.build()154 (_, connection) = self.start_server(155 connection="listen://localhost:0",156 connection_timeout=1,157 wait_seconds_for_termination=5,158 )159 time.sleep(0.5)160 # Should be able to connect to the server.161 self.run_debug_session(connection, "Alice")162 time.sleep(0.5)163 # Should be able to connect to the server, because it's still within the connection timeout.164 self.run_debug_session(connection, "Bob")165