165 lines
5.6 KiB
Python
165 lines
5.6 KiB
Python
"""
|
|
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.log")
|
|
(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, spawn_helper=self.spawnSubprocess
|
|
)
|
|
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,
|
|
spawn_helper=self.spawnSubprocess,
|
|
)
|
|
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")
|