lldb: refactor plugin and test scripts
This commit is contained in:
36
_lldb/common.sh
Normal file
36
_lldb/common.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Function to find LLDB 18+
|
||||||
|
find_lldb() {
|
||||||
|
local lldb_paths=(
|
||||||
|
"/opt/homebrew/bin/lldb"
|
||||||
|
"/usr/local/bin/lldb"
|
||||||
|
"/usr/bin/lldb"
|
||||||
|
"lldb" # This will use the system PATH
|
||||||
|
)
|
||||||
|
|
||||||
|
for lldb_path in "${lldb_paths[@]}"; do
|
||||||
|
if command -v "$lldb_path" >/dev/null 2>&1; then
|
||||||
|
local version=$("$lldb_path" --version | grep -oE '[0-9]+' | head -1)
|
||||||
|
if [ "$version" -ge 18 ]; then
|
||||||
|
echo "$lldb_path"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Error: LLDB 18 or higher not found" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find LLDB 18+
|
||||||
|
LLDB_PATH=$(find_lldb)
|
||||||
|
|
||||||
|
# Default package path
|
||||||
|
DEFAULT_PACKAGE_PATH="./cl/_testdata/debug"
|
||||||
|
|
||||||
|
# Function to build the project
|
||||||
|
build_project() {
|
||||||
|
local package_path="$1"
|
||||||
|
go run ./cmd/llgo build -o "${package_path}/out" -dbg "${package_path}"
|
||||||
|
}
|
||||||
@@ -2,5 +2,17 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
go run ./cmd/llgo build -o ./cl/_testdata/debug/out -dbg ./cl/_testdata/debug/
|
# Source common functions and variables
|
||||||
lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
source "$(dirname "$0")/common.sh"
|
||||||
|
|
||||||
|
# Check if a package path is provided as an argument
|
||||||
|
package_path="$DEFAULT_PACKAGE_PATH"
|
||||||
|
if [ $# -eq 1 ]; then
|
||||||
|
package_path="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
build_project "$package_path"
|
||||||
|
|
||||||
|
# Run LLDB
|
||||||
|
"$LLDB_PATH" "${package_path}/out"
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
# LLDB can't be load from Python 3.12, should load Python script by lldb command
|
|
||||||
# See https://github.com/llvm/llvm-project/issues/70453
|
|
||||||
|
|
||||||
# go run ./cmd/llgo build -o cl/_testdata/debug/out -dbg ./cl/_testdata/debug
|
|
||||||
# lldb -S _lldb/runtest.lldb
|
|
||||||
|
|
||||||
command script import _lldb/test.py
|
|
||||||
script main.run_tests("cl/_testdata/debug/out", ["cl/_testdata/debug/in.go"], True, False, None)
|
|
||||||
quit
|
|
||||||
@@ -2,6 +2,54 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
go run ./cmd/llgo build -o ./cl/_testdata/debug/out -dbg ./cl/_testdata/debug/
|
# Source common functions and variables
|
||||||
|
source "$(dirname "$0")/common.sh"
|
||||||
|
|
||||||
/opt/homebrew/bin/lldb -S _lldb/runtest.lldb
|
# Parse command-line arguments
|
||||||
|
package_path="$DEFAULT_PACKAGE_PATH"
|
||||||
|
verbose=False
|
||||||
|
interactive=False
|
||||||
|
plugin_path=None
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-v|--verbose)
|
||||||
|
verbose=True
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-i|--interactive)
|
||||||
|
interactive=True
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-p|--plugin)
|
||||||
|
plugin_path="\"$2\""
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
package_path="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
build_project "$package_path"
|
||||||
|
|
||||||
|
# Prepare LLDB commands
|
||||||
|
lldb_commands=(
|
||||||
|
"command script import _lldb/test.py"
|
||||||
|
"script test.run_tests(\\\"${package_path}/out\\\", [\\\"${package_path}/in.go\\\"], ${verbose}, ${interactive}, ${plugin_path})"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add quit command if not in interactive mode
|
||||||
|
if [ "$interactive" = False ]; then
|
||||||
|
lldb_commands+=("quit")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run LLDB with prepared commands
|
||||||
|
lldb_command_string=""
|
||||||
|
for cmd in "${lldb_commands[@]}"; do
|
||||||
|
lldb_command_string+=" -O \"$cmd\""
|
||||||
|
done
|
||||||
|
|
||||||
|
eval "$LLDB_PATH $lldb_command_string"
|
||||||
|
|||||||
127
_lldb/test.py
127
_lldb/test.py
@@ -5,7 +5,7 @@ import sys
|
|||||||
import argparse
|
import argparse
|
||||||
import signal
|
import signal
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List
|
from typing import List, Optional, Set, Dict, Any
|
||||||
import lldb
|
import lldb
|
||||||
import llgo_plugin # Add this import
|
import llgo_plugin # Add this import
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ class LLDBTestException(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def log(*args, **kwargs):
|
def log(*args: Any, **kwargs: Any) -> None:
|
||||||
print(*args, **kwargs, flush=True)
|
print(*args, **kwargs, flush=True)
|
||||||
|
|
||||||
|
|
||||||
@@ -30,10 +30,10 @@ class Test:
|
|||||||
class TestResult:
|
class TestResult:
|
||||||
test: Test
|
test: Test
|
||||||
status: str
|
status: str
|
||||||
actual: str = None
|
actual: Optional[str] = None
|
||||||
message: str = None
|
message: Optional[str] = None
|
||||||
missing: set = None
|
missing: Optional[Set[str]] = None
|
||||||
extra: set = None
|
extra: Optional[Set[str]] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -60,42 +60,41 @@ class TestResults:
|
|||||||
|
|
||||||
|
|
||||||
class LLDBDebugger:
|
class LLDBDebugger:
|
||||||
def __init__(self, executable_path, plugin_path=None):
|
def __init__(self, executable_path: str, plugin_path: Optional[str] = None):
|
||||||
self.executable_path = executable_path
|
self.executable_path: str = executable_path
|
||||||
self.plugin_path = plugin_path
|
self.plugin_path: Optional[str] = plugin_path
|
||||||
self.debugger = lldb.SBDebugger.Create()
|
self.debugger: lldb.SBDebugger = lldb.SBDebugger.Create()
|
||||||
self.debugger.SetAsync(False)
|
self.debugger.SetAsync(False)
|
||||||
self.target = None
|
self.target: Optional[lldb.SBTarget] = None
|
||||||
self.process = None
|
self.process: Optional[lldb.SBProcess] = None
|
||||||
self.type_mapping = {
|
self.type_mapping: Dict[str, str] = {
|
||||||
'long': 'int',
|
'long': 'int',
|
||||||
'unsigned long': 'uint',
|
'unsigned long': 'uint',
|
||||||
# Add more mappings as needed
|
# Add more mappings as needed
|
||||||
}
|
}
|
||||||
|
|
||||||
def setup(self):
|
def setup(self) -> None:
|
||||||
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 LLDBTestException(f"Failed to create target for {
|
raise LLDBTestException(f"Failed to create target for {
|
||||||
self.executable_path}")
|
self.executable_path}")
|
||||||
|
|
||||||
self.debugger.HandleCommand(
|
self.debugger.HandleCommand(
|
||||||
'command script add -f llgo_plugin.print_go_expression p')
|
'command script add -f llgo_plugin.print_go_expression p')
|
||||||
self.debugger.HandleCommand(
|
self.debugger.HandleCommand(
|
||||||
'command script add -f llgo_plugin.print_all_variables v')
|
'command script add -f llgo_plugin.print_all_variables v')
|
||||||
|
|
||||||
def set_breakpoint(self, file_spec, line_number):
|
def set_breakpoint(self, file_spec: str, line_number: int) -> lldb.SBBreakpoint:
|
||||||
bp = self.target.BreakpointCreateByLocation(
|
bp = self.target.BreakpointCreateByLocation(file_spec, line_number)
|
||||||
file_spec, line_number)
|
|
||||||
if not bp.IsValid():
|
if not bp.IsValid():
|
||||||
raise LLDBTestException(f"Failed to set breakpoint at {
|
raise LLDBTestException(f"Failed to set breakpoint at {
|
||||||
file_spec}:{line_number}")
|
file_spec}:{line_number}")
|
||||||
return bp
|
return bp
|
||||||
|
|
||||||
def run_to_breakpoint(self):
|
def run_to_breakpoint(self) -> None:
|
||||||
if not self.process:
|
if not self.process:
|
||||||
self.process = self.target.LaunchSimple(None, None, os.getcwd())
|
self.process = self.target.LaunchSimple(None, None, os.getcwd())
|
||||||
else:
|
else:
|
||||||
@@ -103,10 +102,9 @@ class LLDBDebugger:
|
|||||||
if self.process.GetState() != lldb.eStateStopped:
|
if self.process.GetState() != lldb.eStateStopped:
|
||||||
raise LLDBTestException("Process didn't stop at breakpoint")
|
raise LLDBTestException("Process didn't stop at breakpoint")
|
||||||
|
|
||||||
def get_variable_value(self, var_expression):
|
def get_variable_value(self, var_expression: str) -> Optional[str]:
|
||||||
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
||||||
|
|
||||||
# 处理结构体成员访问、指针解引用和数组索引
|
|
||||||
parts = var_expression.split('.')
|
parts = var_expression.split('.')
|
||||||
var = frame.FindVariable(parts[0])
|
var = frame.FindVariable(parts[0])
|
||||||
|
|
||||||
@@ -114,12 +112,10 @@ class LLDBDebugger:
|
|||||||
if not var.IsValid():
|
if not var.IsValid():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 处理数组索引
|
|
||||||
if '[' in part and ']' in part:
|
if '[' in part and ']' in part:
|
||||||
array_name, index = part.split('[')
|
array_name, index = part.split('[')
|
||||||
index = int(index.rstrip(']'))
|
index = int(index.rstrip(']'))
|
||||||
var = var.GetChildAtIndex(index)
|
var = var.GetChildAtIndex(index)
|
||||||
# 处理指针解引用
|
|
||||||
elif var.GetType().IsPointerType():
|
elif var.GetType().IsPointerType():
|
||||||
var = var.Dereference()
|
var = var.Dereference()
|
||||||
var = var.GetChildMemberWithName(part)
|
var = var.GetChildMemberWithName(part)
|
||||||
@@ -128,24 +124,23 @@ class LLDBDebugger:
|
|||||||
|
|
||||||
return llgo_plugin.format_value(var, self.debugger) if var.IsValid() else None
|
return llgo_plugin.format_value(var, self.debugger) if var.IsValid() else None
|
||||||
|
|
||||||
def get_all_variable_names(self):
|
def get_all_variable_names(self) -> Set[str]:
|
||||||
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
||||||
return set(var.GetName() for var in frame.GetVariables(True, True, True, False))
|
return set(var.GetName() for var in frame.GetVariables(True, True, True, False))
|
||||||
|
|
||||||
def get_current_function_name(self):
|
def get_current_function_name(self) -> str:
|
||||||
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
||||||
return frame.GetFunctionName()
|
return frame.GetFunctionName()
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self) -> None:
|
||||||
if self.process and self.process.IsValid():
|
if self.process and self.process.IsValid():
|
||||||
self.process.Kill()
|
self.process.Kill()
|
||||||
lldb.SBDebugger.Destroy(self.debugger)
|
lldb.SBDebugger.Destroy(self.debugger)
|
||||||
|
|
||||||
def run_console(self):
|
def run_console(self) -> bool:
|
||||||
log("\nEntering LLDB interactive mode.")
|
log("\nEntering LLDB interactive mode.")
|
||||||
log("Type 'quit' to exit and continue with the next test case.")
|
log("Type 'quit' to exit and continue with the next test case.")
|
||||||
log(
|
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
|
||||||
sys.stdin, sys.stdout, sys.stderr = sys.__stdin__, sys.__stdout__, sys.__stderr__
|
sys.stdin, sys.stdout, sys.stderr = sys.__stdin__, sys.__stdout__, sys.__stderr__
|
||||||
@@ -157,7 +152,7 @@ class LLDBDebugger:
|
|||||||
interpreter = self.debugger.GetCommandInterpreter()
|
interpreter = self.debugger.GetCommandInterpreter()
|
||||||
continue_tests = True
|
continue_tests = True
|
||||||
|
|
||||||
def keyboard_interrupt_handler(_sig, _frame):
|
def keyboard_interrupt_handler(_sig: Any, _frame: Any) -> None:
|
||||||
nonlocal continue_tests
|
nonlocal continue_tests
|
||||||
log("\nTest execution aborted by user.")
|
log("\nTest execution aborted by user.")
|
||||||
continue_tests = False
|
continue_tests = False
|
||||||
@@ -172,21 +167,19 @@ class LLDBDebugger:
|
|||||||
try:
|
try:
|
||||||
command = input().strip()
|
command = input().strip()
|
||||||
except EOFError:
|
except EOFError:
|
||||||
log(
|
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':
|
||||||
log(
|
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)
|
||||||
log(result.GetOutput().rstrip(
|
log(result.GetOutput().rstrip() if result.Succeeded()
|
||||||
) if result.Succeeded() else result.GetError().rstrip())
|
else result.GetError().rstrip())
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
signal.signal(signal.SIGINT, original_handler)
|
signal.signal(signal.SIGINT, original_handler)
|
||||||
@@ -195,7 +188,7 @@ class LLDBDebugger:
|
|||||||
return continue_tests
|
return continue_tests
|
||||||
|
|
||||||
|
|
||||||
def parse_expected_values(source_files):
|
def parse_expected_values(source_files: List[str]) -> List[TestCase]:
|
||||||
test_cases = []
|
test_cases = []
|
||||||
for source_file in source_files:
|
for source_file in source_files:
|
||||||
with open(source_file, 'r', encoding='utf-8') as f:
|
with open(source_file, 'r', encoding='utf-8') as f:
|
||||||
@@ -224,7 +217,7 @@ def parse_expected_values(source_files):
|
|||||||
return test_cases
|
return test_cases
|
||||||
|
|
||||||
|
|
||||||
def execute_tests(executable_path, test_cases, verbose, interactive, plugin_path):
|
def execute_tests(executable_path: str, test_cases: List[TestCase], verbose: bool, interactive: bool, plugin_path: Optional[str]) -> TestResults:
|
||||||
results = TestResults()
|
results = TestResults()
|
||||||
|
|
||||||
for test_case in test_cases:
|
for test_case in test_cases:
|
||||||
@@ -234,8 +227,7 @@ def execute_tests(executable_path, test_cases, verbose, interactive, plugin_path
|
|||||||
log(f"Setting breakpoint at {
|
log(f"Setting breakpoint at {
|
||||||
test_case.source_file}:{test_case.end_line}")
|
test_case.source_file}:{test_case.end_line}")
|
||||||
debugger.setup()
|
debugger.setup()
|
||||||
debugger.set_breakpoint(
|
debugger.set_breakpoint(test_case.source_file, test_case.end_line)
|
||||||
test_case.source_file, test_case.end_line)
|
|
||||||
debugger.run_to_breakpoint()
|
debugger.run_to_breakpoint()
|
||||||
|
|
||||||
all_variable_names = debugger.get_all_variable_names()
|
all_variable_names = debugger.get_all_variable_names()
|
||||||
@@ -250,9 +242,10 @@ def execute_tests(executable_path, test_cases, verbose, interactive, plugin_path
|
|||||||
|
|
||||||
case = case_result.test_case
|
case = case_result.test_case
|
||||||
loc = f"{case.source_file}:{case.start_line}-{case.end_line}"
|
loc = f"{case.source_file}:{case.start_line}-{case.end_line}"
|
||||||
log(f"\nTest case: {loc} in function '{case_result.function}'")
|
if verbose or interactive or any(r.status != 'pass' for r in case_result.results):
|
||||||
|
log(f"\nTest case: {loc} 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, verbose=verbose)
|
||||||
|
|
||||||
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):
|
||||||
log("\nTest case failed. Entering LLDB interactive mode.")
|
log("\nTest case failed. Entering LLDB interactive mode.")
|
||||||
@@ -267,21 +260,21 @@ def execute_tests(executable_path, test_cases, verbose, interactive, plugin_path
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def run_tests(executable_path, source_files, verbose, interactive, plugin_path):
|
def run_tests(executable_path: str, source_files: List[str], verbose: bool, interactive: bool, plugin_path: Optional[str]) -> None:
|
||||||
test_cases = parse_expected_values(source_files)
|
test_cases = parse_expected_values(source_files)
|
||||||
if verbose:
|
if verbose:
|
||||||
log(f"Running tests for {
|
log(f"Running tests for {
|
||||||
', '.join(source_files)} with {executable_path}")
|
', '.join(source_files)} with {executable_path}")
|
||||||
log(f"Found {len(test_cases)} test cases")
|
log(f"Found {len(test_cases)} test cases")
|
||||||
|
|
||||||
results = execute_tests(executable_path, test_cases, verbose,
|
results = execute_tests(executable_path, test_cases,
|
||||||
interactive, plugin_path)
|
verbose, interactive, plugin_path)
|
||||||
|
|
||||||
if results.total != results.passed:
|
if results.total != results.passed:
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
|
|
||||||
def execute_test_case(debugger, test_case, all_variable_names):
|
def execute_test_case(debugger: LLDBDebugger, test_case: TestCase, all_variable_names: Set[str]) -> CaseResult:
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for test in test_case.tests:
|
for test in test_case.tests:
|
||||||
@@ -294,7 +287,7 @@ def execute_test_case(debugger, test_case, all_variable_names):
|
|||||||
return CaseResult(test_case, debugger.get_current_function_name(), results)
|
return CaseResult(test_case, debugger.get_current_function_name(), results)
|
||||||
|
|
||||||
|
|
||||||
def execute_all_variables_test(test, all_variable_names):
|
def execute_all_variables_test(test: Test, all_variable_names: Set[str]) -> TestResult:
|
||||||
expected_vars = set(test.expected_value.split())
|
expected_vars = set(test.expected_value.split())
|
||||||
if expected_vars == all_variable_names:
|
if expected_vars == all_variable_names:
|
||||||
return TestResult(
|
return TestResult(
|
||||||
@@ -312,7 +305,7 @@ def execute_all_variables_test(test, all_variable_names):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def execute_single_variable_test(debugger, test):
|
def execute_single_variable_test(debugger: LLDBDebugger, test: Test) -> TestResult:
|
||||||
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:
|
||||||
return TestResult(
|
return TestResult(
|
||||||
@@ -321,11 +314,9 @@ def execute_single_variable_test(debugger, test):
|
|||||||
message=f'Unable to fetch value for {test.variable}'
|
message=f'Unable to fetch value for {test.variable}'
|
||||||
)
|
)
|
||||||
|
|
||||||
# 移除可能的空格,但保留括号
|
|
||||||
actual_value = actual_value.strip()
|
actual_value = actual_value.strip()
|
||||||
expected_value = test.expected_value.strip()
|
expected_value = test.expected_value.strip()
|
||||||
|
|
||||||
# 比较处理后的值
|
|
||||||
if actual_value == expected_value:
|
if actual_value == expected_value:
|
||||||
return TestResult(
|
return TestResult(
|
||||||
test=test,
|
test=test,
|
||||||
@@ -340,7 +331,7 @@ def execute_single_variable_test(debugger, test):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def print_test_results(results: TestResults, verbose):
|
def print_test_results(results: TestResults, verbose: bool) -> None:
|
||||||
for case_result in results.case_results:
|
for case_result in results.case_results:
|
||||||
case = case_result.test_case
|
case = case_result.test_case
|
||||||
loc = f"{case.source_file}:{case.start_line}-{case.end_line}"
|
loc = f"{case.source_file}:{case.start_line}-{case.end_line}"
|
||||||
@@ -358,30 +349,28 @@ def print_test_results(results: TestResults, verbose):
|
|||||||
log("Some tests failed")
|
log("Some tests failed")
|
||||||
|
|
||||||
|
|
||||||
def print_test_result(result: TestResult, verbose):
|
def print_test_result(result: TestResult, verbose: bool) -> None:
|
||||||
status_symbol = "✓" if result.status == 'pass' else "✗"
|
status_symbol = "✓" if result.status == 'pass' else "✗"
|
||||||
status_text = "Pass" if result.status == 'pass' else "Fail"
|
status_text = "Pass" if result.status == 'pass' else "Fail"
|
||||||
test = result.test
|
test = result.test
|
||||||
|
|
||||||
if result.status == 'pass':
|
if result.status == 'pass':
|
||||||
if verbose:
|
if verbose:
|
||||||
log(
|
log(f"{status_symbol} Line {test.line_number}, {
|
||||||
f"{status_symbol} Line {test.line_number}, {test.variable}: {status_text}")
|
test.variable}: {status_text}")
|
||||||
if test.variable == 'all variables':
|
if test.variable == 'all variables':
|
||||||
log(f" Variables: {
|
log(f" Variables: {', '.join(sorted(result.actual))}")
|
||||||
', '.join(sorted(result.actual))}")
|
|
||||||
else: # fail or error
|
else: # fail or error
|
||||||
log(
|
log(f"{status_symbol} Line {test.line_number}, {
|
||||||
f"{status_symbol} Line {test.line_number}, {test.variable}: {status_text}")
|
test.variable}: {status_text}")
|
||||||
if test.variable == 'all variables':
|
if test.variable == 'all variables':
|
||||||
if result.missing:
|
if result.missing:
|
||||||
log(
|
log(f" Missing variables: {
|
||||||
f" Missing variables: {', '.join(sorted(result.missing))}")
|
', '.join(sorted(result.missing))}")
|
||||||
if result.extra:
|
if result.extra:
|
||||||
log(
|
log(f" Extra variables: {', '.join(sorted(result.extra))}")
|
||||||
f" Extra variables: {', '.join(sorted(result.extra))}")
|
log(f" Expected: {
|
||||||
log(
|
', '.join(sorted(test.expected_value.split()))}")
|
||||||
f" Expected: {', '.join(sorted(test.expected_value.split()))}")
|
|
||||||
log(f" Actual: {', '.join(sorted(result.actual))}")
|
log(f" Actual: {', '.join(sorted(result.actual))}")
|
||||||
elif result.status == 'error':
|
elif result.status == 'error':
|
||||||
log(f" Error: {result.message}")
|
log(f" Error: {result.message}")
|
||||||
@@ -390,7 +379,7 @@ def print_test_result(result: TestResult, verbose):
|
|||||||
log(f" Actual: {result.actual}")
|
log(f" Actual: {result.actual}")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
log(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")
|
||||||
@@ -411,9 +400,3 @@ def main():
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
def __lldb_init_module(debugger, _internal_dict):
|
|
||||||
run_tests("cl/_testdata/debug/out",
|
|
||||||
["cl/_testdata/debug/in.go"], True, False, None)
|
|
||||||
debugger.HandleCommand('quit')
|
|
||||||
|
|||||||
@@ -156,7 +156,91 @@ func FuncWithAllTypeParams(
|
|||||||
return 1, errors.New("some error")
|
return 1, errors.New("some error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TinyStruct struct {
|
||||||
|
I int
|
||||||
|
}
|
||||||
|
|
||||||
|
type SmallStruct struct {
|
||||||
|
I int
|
||||||
|
J int
|
||||||
|
}
|
||||||
|
|
||||||
|
type MidStruct struct {
|
||||||
|
I int
|
||||||
|
J int
|
||||||
|
K int
|
||||||
|
}
|
||||||
|
|
||||||
|
type BigStruct struct {
|
||||||
|
I int
|
||||||
|
J int
|
||||||
|
K int
|
||||||
|
L int
|
||||||
|
M int
|
||||||
|
N int
|
||||||
|
O int
|
||||||
|
P int
|
||||||
|
Q int
|
||||||
|
R int
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuncStructParams(t TinyStruct, s SmallStruct, m MidStruct, b BigStruct) {
|
||||||
|
println(&t, &s, &m, &b)
|
||||||
|
// Expected:
|
||||||
|
// all variables: t s m b
|
||||||
|
// t.I: 1
|
||||||
|
// s.I: 2
|
||||||
|
// s.J: 3
|
||||||
|
// m.I: 4
|
||||||
|
// m.J: 5
|
||||||
|
// m.K: 6
|
||||||
|
// b.I: 7
|
||||||
|
// b.J: 8
|
||||||
|
// b.K: 9
|
||||||
|
// b.L: 10
|
||||||
|
// b.M: 11
|
||||||
|
// b.N: 12
|
||||||
|
// b.O: 13
|
||||||
|
// b.P: 14
|
||||||
|
// b.Q: 15
|
||||||
|
// b.R: 16
|
||||||
|
t.I = 10
|
||||||
|
// Expected:
|
||||||
|
// all variables: t s m b
|
||||||
|
// t.I: 10
|
||||||
|
println("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuncStructPtrParams(t *TinyStruct, s *SmallStruct, m *MidStruct, b *BigStruct) {
|
||||||
|
println(t, s, m, b)
|
||||||
|
// Expected:
|
||||||
|
// all variables: t s m b
|
||||||
|
// t.I: 1
|
||||||
|
// s.I: 2
|
||||||
|
// s.J: 3
|
||||||
|
// m.I: 4
|
||||||
|
// m.J: 5
|
||||||
|
// m.K: 6
|
||||||
|
// b.I: 7
|
||||||
|
// b.J: 8
|
||||||
|
// b.K: 9
|
||||||
|
// b.L: 10
|
||||||
|
// b.M: 11
|
||||||
|
// b.N: 12
|
||||||
|
// b.O: 13
|
||||||
|
// b.P: 14
|
||||||
|
// b.Q: 15
|
||||||
|
// b.R: 16
|
||||||
|
t.I = 10
|
||||||
|
// Expected:
|
||||||
|
// all variables: t s m b
|
||||||
|
// t.I: 10
|
||||||
|
println("done")
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
FuncStructParams(TinyStruct{I: 1}, SmallStruct{I: 2, J: 3}, MidStruct{I: 4, J: 5, K: 6}, BigStruct{I: 7, J: 8, K: 9, L: 10, M: 11, N: 12, O: 13, P: 14, Q: 15, R: 16})
|
||||||
|
FuncStructPtrParams(&TinyStruct{I: 1}, &SmallStruct{I: 2, J: 3}, &MidStruct{I: 4, J: 5, K: 6}, &BigStruct{I: 7, J: 8, K: 9, L: 10, M: 11, N: 12, O: 13, P: 14, Q: 15, R: 16})
|
||||||
i := 100
|
i := 100
|
||||||
s := StructWithAllTypeFields{
|
s := StructWithAllTypeFields{
|
||||||
i8: 1,
|
i8: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user