lldb test: clean

This commit is contained in:
Li Jie
2024-09-19 21:49:41 +08:00
parent d6b26c9975
commit 0c11afad7a

View File

@@ -3,15 +3,12 @@ import io
import os import os
import sys import sys
import argparse import argparse
import signal
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import List from typing import List
import cmd
import signal
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, line_buffering=False)
def print_to_lldb(*args, **kwargs): def log(*args, **kwargs):
print(*args, **kwargs, flush=True) print(*args, **kwargs, flush=True)
@@ -74,7 +71,6 @@ class LLDBDebugger:
if self.plugin_path: if self.plugin_path:
self.debugger.HandleCommand( self.debugger.HandleCommand(
f'command script import "{self.plugin_path}"') f'command script import "{self.plugin_path}"')
self.target = self.debugger.CreateTarget(self.executable_path) self.target = self.debugger.CreateTarget(self.executable_path)
if not self.target: if not self.target:
raise Exception(f"Failed to create target for { raise Exception(f"Failed to create target for {
@@ -93,7 +89,6 @@ class LLDBDebugger:
self.process = self.target.LaunchSimple(None, None, os.getcwd()) self.process = self.target.LaunchSimple(None, None, os.getcwd())
else: else:
self.process.Continue() self.process.Continue()
if self.process.GetState() != lldb.eStateStopped: if self.process.GetState() != lldb.eStateStopped:
raise Exception("Process didn't stop at breakpoint") raise Exception("Process didn't stop at breakpoint")
@@ -236,9 +231,9 @@ class LLDBDebugger:
lldb.SBDebugger.Destroy(self.debugger) lldb.SBDebugger.Destroy(self.debugger)
def run_console(self): def run_console(self):
print_to_lldb( log(
"\nEntering LLDB interactive mode. Type 'quit' to exit and continue with the next test case.") "\nEntering LLDB interactive mode. Type 'quit' to exit and continue with the next test case.")
print_to_lldb( log(
"Use Ctrl+D to exit and continue, or Ctrl+C to abort all tests.") "Use Ctrl+D to exit and continue, or Ctrl+C to abort all tests.")
old_stdin, old_stdout, old_stderr = sys.stdin, sys.stdout, sys.stderr old_stdin, old_stdout, old_stderr = sys.stdin, sys.stdout, sys.stderr
@@ -253,7 +248,7 @@ class LLDBDebugger:
def keyboard_interrupt_handler(sig, frame): def keyboard_interrupt_handler(sig, frame):
nonlocal continue_tests nonlocal continue_tests
print_to_lldb("\nTest execution aborted by user.") log("\nTest execution aborted by user.")
continue_tests = False continue_tests = False
raise KeyboardInterrupt raise KeyboardInterrupt
@@ -262,27 +257,25 @@ class LLDBDebugger:
try: try:
while continue_tests: while continue_tests:
print_to_lldb("\n(lldb) ", end="") log("\n(lldb) ", end="")
try: try:
command = input().strip() command = input().strip()
except EOFError: except EOFError:
print_to_lldb( log(
"\nExiting LLDB interactive mode. Continuing with next test case.") "\nExiting LLDB interactive mode. Continuing with next test case.")
break break
except KeyboardInterrupt: except KeyboardInterrupt:
break break
if command.lower() == 'quit': if command.lower() == 'quit':
print_to_lldb( log(
"\nExiting LLDB interactive mode. Continuing with next test case.") "\nExiting LLDB interactive mode. Continuing with next test case.")
break break
result = lldb.SBCommandReturnObject() result = lldb.SBCommandReturnObject()
interpreter.HandleCommand(command, result) interpreter.HandleCommand(command, result)
if result.Succeeded(): log(result.GetOutput().rstrip(
print_to_lldb(result.GetOutput().rstrip()) ) if result.Succeeded() else result.GetError().rstrip())
else:
print_to_lldb(result.GetError().rstrip())
finally: finally:
signal.signal(signal.SIGINT, original_handler) signal.signal(signal.SIGINT, original_handler)
@@ -324,9 +317,9 @@ def run_tests(executable_path, source_files, verbose, interactive, plugin_path):
debugger = LLDBDebugger(executable_path, plugin_path) debugger = LLDBDebugger(executable_path, plugin_path)
test_cases = parse_expected_values(source_files) test_cases = parse_expected_values(source_files)
if verbose: if verbose:
print_to_lldb( log(
f"Running tests for {', '.join(source_files)} with {executable_path}") f"Running tests for {', '.join(source_files)} with {executable_path}")
print_to_lldb(f"Found {len(test_cases)} test cases") log(f"Found {len(test_cases)} test cases")
try: try:
debugger.setup() debugger.setup()
@@ -337,7 +330,7 @@ def run_tests(executable_path, source_files, verbose, interactive, plugin_path):
os._exit(1) os._exit(1)
except Exception as e: except Exception as e:
print_to_lldb(f"Error: {str(e)}") log(f"Error: {str(e)}")
finally: finally:
debugger.cleanup() debugger.cleanup()
@@ -362,17 +355,17 @@ def execute_tests(debugger, test_cases, interactive):
results.failed += sum(1 for r in case_result.results if r.status != 'pass') results.failed += sum(1 for r in case_result.results if r.status != 'pass')
results.case_results.append(case_result) results.case_results.append(case_result)
print_to_lldb(f"\nTest case: {case_result.test_case.source_file}:{ log(f"\nTest case: {case_result.test_case.source_file}:{
case_result.test_case.start_line}-{case_result.test_case.end_line} in function '{case_result.function}'") case_result.test_case.start_line}-{case_result.test_case.end_line} in function '{case_result.function}'")
for result in case_result.results: for result in case_result.results:
print_test_result(result, True) print_test_result(result, True)
if interactive and any(r.status != 'pass' for r in case_result.results): if interactive and any(r.status != 'pass' for r in case_result.results):
print_to_lldb( log(
"\nTest case failed. Entering LLDB interactive mode.") "\nTest case failed. Entering LLDB interactive mode.")
continue_tests = debugger.run_console() continue_tests = debugger.run_console()
if not continue_tests: if not continue_tests:
print_to_lldb("Aborting all tests.") log("Aborting all tests.")
break break
# After exiting the console, we need to ensure the process is in a valid state # After exiting the console, we need to ensure the process is in a valid state
@@ -422,7 +415,7 @@ def execute_all_variables_test(test, all_variable_names):
def execute_single_variable_test(debugger, test): def execute_single_variable_test(debugger, test):
actual_value = debugger.get_variable_value(test.variable) actual_value = debugger.get_variable_value(test.variable)
if actual_value is None: if actual_value is None:
print_to_lldb(f"Unable to fetch value for {test.variable}") log(f"Unable to fetch value for {test.variable}")
return TestResult( return TestResult(
test=test, test=test,
status='error', status='error',
@@ -450,19 +443,19 @@ def execute_single_variable_test(debugger, test):
def print_test_results(results: TestResults, verbose): def print_test_results(results: TestResults, verbose):
for case_result in results.case_results: for case_result in results.case_results:
print_to_lldb(f"\nTest case: {case_result.test_case.source_file}:{ log(f"\nTest case: {case_result.test_case.source_file}:{
case_result.test_case.start_line}-{case_result.test_case.end_line} in function '{case_result.function}'") case_result.test_case.start_line}-{case_result.test_case.end_line} in function '{case_result.function}'")
for result in case_result.results: for result in case_result.results:
print_test_result(result, verbose) print_test_result(result, verbose)
print_to_lldb("\nTest results:") log("\nTest results:")
print_to_lldb(f" Total tests: {results.total}") log(f" Total tests: {results.total}")
print_to_lldb(f" Passed tests: {results.passed}") log(f" Passed tests: {results.passed}")
print_to_lldb(f" Failed tests: {results.failed}") log(f" Failed tests: {results.failed}")
if results.total == results.passed: if results.total == results.passed:
print_to_lldb("All tests passed!") log("All tests passed!")
else: else:
print_to_lldb("Some tests failed") log("Some tests failed")
def print_test_result(result: TestResult, verbose): def print_test_result(result: TestResult, verbose):
@@ -471,33 +464,33 @@ def print_test_result(result: TestResult, verbose):
if result.status == 'pass': if result.status == 'pass':
if verbose: if verbose:
print_to_lldb( log(
f"{status_symbol} Line {result.test.line_number}, {result.test.variable}: {status_text}") f"{status_symbol} Line {result.test.line_number}, {result.test.variable}: {status_text}")
if result.test.variable == 'all variables': if result.test.variable == 'all variables':
print_to_lldb(f" Variables: { log(f" Variables: {
', '.join(sorted(result.actual))}") ', '.join(sorted(result.actual))}")
else: # fail or error else: # fail or error
print_to_lldb( log(
f"{status_symbol} Line {result.test.line_number}, {result.test.variable}: {status_text}") f"{status_symbol} Line {result.test.line_number}, {result.test.variable}: {status_text}")
if result.test.variable == 'all variables': if result.test.variable == 'all variables':
if result.missing: if result.missing:
print_to_lldb( log(
f" Missing variables: {', '.join(sorted(result.missing))}") f" Missing variables: {', '.join(sorted(result.missing))}")
if result.extra: if result.extra:
print_to_lldb( log(
f" Extra variables: {', '.join(sorted(result.extra))}") f" Extra variables: {', '.join(sorted(result.extra))}")
print_to_lldb( log(
f" Expected: {', '.join(sorted(result.test.expected_value.split()))}") f" Expected: {', '.join(sorted(result.test.expected_value.split()))}")
print_to_lldb(f" Actual: {', '.join(sorted(result.actual))}") log(f" Actual: {', '.join(sorted(result.actual))}")
elif result.status == 'error': elif result.status == 'error':
print_to_lldb(f" Error: {result.message}") log(f" Error: {result.message}")
else: else:
print_to_lldb(f" Expected: {result.test.expected_value}") log(f" Expected: {result.test.expected_value}")
print_to_lldb(f" Actual: {result.actual}") log(f" Actual: {result.actual}")
def main(): def main():
print_to_lldb(sys.argv) log(sys.argv)
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="LLDB 18 Debug Script with DWARF 5 Support") description="LLDB 18 Debug Script with DWARF 5 Support")
parser.add_argument("executable", help="Path to the executable") parser.add_argument("executable", help="Path to the executable")
@@ -520,7 +513,7 @@ if __name__ == "__main__":
def run_commands(debugger, command, result, internal_dict): def run_commands(debugger, command, result, internal_dict):
print_to_lldb(sys.argv) log(sys.argv)
main() main()
debugger.HandleCommand("quit") debugger.HandleCommand("quit")