[lldb-dap] Improving tests logging to understand CI failures. (#139311)
To improve logging this adjusts two properties of the existing tests:
* Forwards stderr from lldb-dap to the process in case errors are
reported to stderr.
* Adjusts `DebugAdapterServer.terminate` to close stdin and wait for the
process to exit instead of sending SIGTERM. Additionally, if we end up
with a non-zero exit status we now raise an error to note the unexpected
exit status.
With these changes, I did find one test case in
`TestDAP_console.test_diagnositcs` that was not waiting to ensure the
expected event had arrived by the time it performed an assert.
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index c974866..73f7b0e 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -8,6 +8,7 @@
import socket
import string
import subprocess
+import signal
import sys
import threading
import time
@@ -1263,7 +1264,7 @@
args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
+ stderr=sys.stderr,
env=adapter_env,
)
@@ -1296,13 +1297,38 @@
def terminate(self):
super(DebugAdapterServer, self).terminate()
if self.process is not None:
- self.process.terminate()
- try:
- self.process.wait(timeout=20)
- except subprocess.TimeoutExpired:
- self.process.kill()
- self.process.wait()
+ process = self.process
self.process = None
+ try:
+ # When we close stdin it should signal the lldb-dap that no
+ # new messages will arrive and it should shutdown on its own.
+ process.stdin.close()
+ process.wait(timeout=20)
+ except subprocess.TimeoutExpired:
+ process.kill()
+ process.wait()
+ if process.returncode != 0:
+ raise DebugAdapterProcessError(process.returncode)
+
+
+class DebugAdapterError(Exception):
+ pass
+
+
+class DebugAdapterProcessError(DebugAdapterError):
+ """Raised when the lldb-dap process exits with a non-zero exit status."""
+
+ def __init__(self, returncode):
+ self.returncode = returncode
+
+ def __str__(self):
+ if self.returncode and self.returncode < 0:
+ try:
+ return f"lldb-dap died with {signal.Signals(-self.returncode).name}."
+ except ValueError:
+ return f"lldb-dap died with unknown signal {-self.returncode}."
+ else:
+ return f"lldb-dap returned non-zero exit status {self.returncode}."
def attach_options_specified(options):
diff --git a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
index 9cdb978..0b42899 100644
--- a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
+++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py
@@ -176,9 +176,12 @@
f"target create --core {core}", context="repl"
)
- output = self.get_important(timeout=2.0)
+ diagnostics = self.collect_important(
+ timeout_secs=self.timeoutval, pattern="minidump file"
+ )
+
self.assertIn(
"warning: unable to retrieve process ID from minidump file",
- output,
+ diagnostics,
"diagnostic found in important output",
)
diff --git a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py
index f05f876..b72b98d 100644
--- a/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py
+++ b/lldb/test/API/tools/lldb-dap/io/TestDAP_io.py
@@ -22,13 +22,9 @@
process.terminate()
process.wait()
stdout_data = process.stdout.read().decode()
- stderr_data = process.stderr.read().decode()
print("========= STDOUT =========", file=sys.stderr)
print(stdout_data, file=sys.stderr)
print("========= END =========", file=sys.stderr)
- print("========= STDERR =========", file=sys.stderr)
- print(stderr_data, file=sys.stderr)
- print("========= END =========", file=sys.stderr)
print("========= DEBUG ADAPTER PROTOCOL LOGS =========", file=sys.stderr)
with open(log_file_path, "r") as file:
print(file.read(), file=sys.stderr)