blob: 12b321cf427788f2a13795f7e0450d1d0ad5a1a0 [file] [log] [blame]
"""
Test lldb-dap server integration.
"""
import os
import signal
import tempfile
import time
import dap_server
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
import lldbdap_testcase
class TestDAP_server(lldbdap_testcase.DAPTestCaseBase):
def start_server(
self, connection, connection_timeout=None, wait_seconds_for_termination=None
):
log_file_path = self.getBuildArtifact("dap.txt")
(process, connection) = dap_server.DebugAdapterServer.launch(
executable=self.lldbDAPExec,
connection=connection,
connection_timeout=connection_timeout,
log_file=log_file_path,
)
def cleanup():
if wait_seconds_for_termination is not None:
process.wait(wait_seconds_for_termination)
else:
process.terminate()
self.addTearDownHook(cleanup)
return (process, connection)
def run_debug_session(self, connection, name, sleep_seconds_in_middle=None):
self.dap_server = dap_server.DebugAdapterServer(
connection=connection,
)
program = self.getBuildArtifact("a.out")
source = "main.c"
breakpoint_line = line_number(source, "// breakpoint")
self.launch(
program,
args=[name],
disconnectAutomatically=False,
)
if sleep_seconds_in_middle is not None:
time.sleep(sleep_seconds_in_middle)
self.set_source_breakpoints(source, [breakpoint_line])
self.continue_to_next_stop()
self.continue_to_exit()
output = self.get_stdout()
self.assertEqual(output, f"Hello {name}!\r\n")
self.dap_server.request_disconnect()
@skipIfWindows
def test_server_port(self):
"""
Test launching a binary with a lldb-dap in server mode on a specific port.
"""
self.build()
(_, connection) = self.start_server(connection="listen://localhost:0")
self.run_debug_session(connection, "Alice")
self.run_debug_session(connection, "Bob")
@skipIfWindows
def test_server_unix_socket(self):
"""
Test launching a binary with a lldb-dap in server mode on a unix socket.
"""
dir = tempfile.gettempdir()
name = dir + "/dap-connection-" + str(os.getpid())
def cleanup():
os.unlink(name)
self.addTearDownHook(cleanup)
self.build()
(_, connection) = self.start_server(connection="accept://" + name)
self.run_debug_session(connection, "Alice")
self.run_debug_session(connection, "Bob")
@skipIfWindows
def test_server_interrupt(self):
"""
Test launching a binary with lldb-dap in server mode and shutting down the server while the debug session is still active.
"""
self.build()
(process, connection) = self.start_server(connection="listen://localhost:0")
self.dap_server = dap_server.DebugAdapterServer(
connection=connection,
)
program = self.getBuildArtifact("a.out")
source = "main.c"
breakpoint_line = line_number(source, "// breakpoint")
self.launch(
program,
args=["Alice"],
disconnectAutomatically=False,
)
self.set_source_breakpoints(source, [breakpoint_line])
self.continue_to_next_stop()
# Interrupt the server which should disconnect all clients.
process.send_signal(signal.SIGINT)
# Wait for both events since they can happen in any order.
self.dap_server.wait_for_event(["terminated", "exited"])
self.dap_server.wait_for_event(["terminated", "exited"])
self.assertIsNotNone(
self.dap_server.exit_status,
"Process exited before interrupting lldb-dap server",
)
@skipIfWindows
def test_connection_timeout_at_server_start(self):
"""
Test launching lldb-dap in server mode with connection timeout and waiting for it to terminate automatically when no client connects.
"""
self.build()
self.start_server(
connection="listen://localhost:0",
connection_timeout=1,
wait_seconds_for_termination=5,
)
@skipIfWindows
def test_connection_timeout_long_debug_session(self):
"""
Test launching lldb-dap in server mode with connection timeout and terminating the server after the a long debug session.
"""
self.build()
(_, connection) = self.start_server(
connection="listen://localhost:0",
connection_timeout=1,
wait_seconds_for_termination=5,
)
# The connection timeout should not cut off the debug session
self.run_debug_session(connection, "Alice", 1.5)
@skipIfWindows
def test_connection_timeout_multiple_sessions(self):
"""
Test launching lldb-dap in server mode with connection timeout and terminating the server after the last debug session.
"""
self.build()
(_, connection) = self.start_server(
connection="listen://localhost:0",
connection_timeout=1,
wait_seconds_for_termination=5,
)
time.sleep(0.5)
# Should be able to connect to the server.
self.run_debug_session(connection, "Alice")
time.sleep(0.5)
# Should be able to connect to the server, because it's still within the connection timeout.
self.run_debug_session(connection, "Bob")