2025-11-07 21:04:01 +09:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2025-11-08 00:46:34 +09:00
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
2025-11-07 21:04:01 +09:00
|
|
|
BIN="${NYASH_BIN:-$ROOT/target/release/hakorune}"
|
|
|
|
|
|
|
|
|
|
if [ ! -x "$BIN" ]; then
|
|
|
|
|
echo "[TEST] hakorune not built: $BIN" >&2
|
|
|
|
|
echo "Run: cargo build --release" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
TARGET_DIR="$ROOT/tools/hako_check/tests"
|
|
|
|
|
fail=0
|
|
|
|
|
|
|
|
|
|
run_case() {
|
|
|
|
|
local dir="$1"
|
|
|
|
|
local expected="$dir/expected.json"
|
|
|
|
|
local input_ok="$dir/ok.hako"
|
|
|
|
|
local input_ng="$dir/ng.hako"
|
|
|
|
|
if [ ! -f "$expected" ]; then echo "[TEST] skip (no expected): $dir"; return; fi
|
|
|
|
|
if [ ! -f "$input_ok" ] && [ ! -f "$input_ng" ]; then echo "[TEST] skip (no inputs): $dir"; return; fi
|
|
|
|
|
local tmp_out="/tmp/hako_test_$$.json"
|
2025-11-08 00:46:34 +09:00
|
|
|
# Build a tiny wrapper program to call HakoAnalyzerBox.run with constructed argv
|
|
|
|
|
local path_ok text_ok
|
|
|
|
|
local path_ng text_ng
|
|
|
|
|
if [ -f "$input_ok" ]; then
|
|
|
|
|
path_ok="$input_ok"
|
|
|
|
|
text_ok="$(sed 's/\r$//' "$input_ok")"
|
|
|
|
|
else
|
|
|
|
|
:
|
|
|
|
|
fi
|
|
|
|
|
if [ -f "$input_ng" ]; then
|
|
|
|
|
path_ng="$input_ng"
|
|
|
|
|
text_ng="$(sed 's/\r$//' "$input_ng")"
|
|
|
|
|
else
|
|
|
|
|
:
|
|
|
|
|
fi
|
|
|
|
|
# Build argv array for analyzer CLI (preserve newlines in text)
|
|
|
|
|
ARGS=( --debug --format json-lsp )
|
|
|
|
|
if [ -f "$input_ok" ]; then ARGS+=( --source-file "$path_ok" "$text_ok" ); fi
|
|
|
|
|
if [ -f "$input_ng" ]; then ARGS+=( --source-file "$path_ng" "$text_ng" ); fi
|
|
|
|
|
|
|
|
|
|
# Directly invoke analyzer CLI with args via '--', avoid wrapper/FS
|
2025-11-07 21:04:01 +09:00
|
|
|
NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \
|
|
|
|
|
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_SEAM_TOLERANT=1 HAKO_PARSER_SEAM_TOLERANT=1 \
|
|
|
|
|
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 NYASH_USING_AST=1 \
|
2025-11-08 02:59:54 +09:00
|
|
|
NYASH_JSON_ONLY=1 \
|
2025-11-08 00:46:34 +09:00
|
|
|
"$BIN" --backend vm tools/hako_check/cli.hako -- "${ARGS[@]}" >"$tmp_out" 2>&1 || true
|
|
|
|
|
# Extract diagnostics JSON (one-line or pretty block)
|
|
|
|
|
tmp_json="/tmp/hako_test_json_$$.json"
|
|
|
|
|
json_line=$(grep -m1 '^\{"diagnostics"' "$tmp_out" || true)
|
|
|
|
|
if [ -n "$json_line" ] && echo "$json_line" | grep -q '\]}' ; then
|
|
|
|
|
echo "$json_line" > "$tmp_json"
|
|
|
|
|
else
|
|
|
|
|
json_block=$(awk '/^\{"diagnostics"/{f=1} f{print} /\]\}/{exit}' "$tmp_out" )
|
|
|
|
|
if [ -z "$json_block" ]; then
|
|
|
|
|
echo "[TEST/ERROR] no diagnostics JSON found; possible VM error. log head:" >&2
|
|
|
|
|
sed -n '1,120p' "$tmp_out" >&2 || true
|
|
|
|
|
json_block='{"diagnostics":[]}'
|
|
|
|
|
fi
|
|
|
|
|
printf "%s\n" "$json_block" > "$tmp_json"
|
|
|
|
|
fi
|
|
|
|
|
# Normalize absolute paths to basenames for stable comparison
|
|
|
|
|
tmp_norm="/tmp/hako_test_norm_$$.json"
|
|
|
|
|
cp "$tmp_json" "$tmp_norm"
|
|
|
|
|
if [ -f "$input_ok" ]; then
|
|
|
|
|
base_ok="$(basename "$input_ok")"; abs_ok="$input_ok"
|
|
|
|
|
sed -i "s#\"file\":\"$abs_ok\"#\"file\":\"$base_ok\"#g" "$tmp_norm"
|
|
|
|
|
sed -i "s#${abs_ok//\//\/}#${base_ok//\//\/}#g" "$tmp_norm"
|
|
|
|
|
fi
|
|
|
|
|
if [ -f "$input_ng" ]; then
|
|
|
|
|
base_ng="$(basename "$input_ng")"; abs_ng="$input_ng"
|
|
|
|
|
sed -i "s#\"file\":\"$abs_ng\"#\"file\":\"$base_ng\"#g" "$tmp_norm"
|
|
|
|
|
sed -i "s#${abs_ng//\//\/}#${base_ng//\//\/}#g" "$tmp_norm"
|
|
|
|
|
fi
|
|
|
|
|
# Align trailing blank line behavior to expected (tolerate one extra blank line)
|
|
|
|
|
if [ -f "$expected" ]; then
|
|
|
|
|
if [ -z "$(tail -n1 "$tmp_norm")" ]; then :; else
|
|
|
|
|
if [ -z "$(tail -n1 "$expected")" ]; then printf "\n" >> "$tmp_norm"; fi
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
# Replace absolute path occurrences in message with PLACEHOLDER
|
|
|
|
|
if [ -f "$input_ng" ]; then
|
|
|
|
|
sed -i "s#${abs_ng//\//\/}#PLACEHOLDER#g" "$tmp_norm"
|
|
|
|
|
fi
|
|
|
|
|
if ! diff -u "$expected" "$tmp_norm" >/dev/null; then
|
2025-11-07 21:04:01 +09:00
|
|
|
echo "[TEST/FAIL] $dir" >&2
|
2025-11-08 00:46:34 +09:00
|
|
|
diff -u "$expected" "$tmp_norm" || true
|
2025-11-07 21:04:01 +09:00
|
|
|
fail=$((fail+1))
|
|
|
|
|
else
|
|
|
|
|
echo "[TEST/OK] $dir"
|
|
|
|
|
fi
|
2025-11-08 00:46:34 +09:00
|
|
|
rm -f "$tmp_out" "$tmp_norm" "$tmp_json"
|
2025-11-07 21:04:01 +09:00
|
|
|
}
|
|
|
|
|
|
2025-11-08 04:17:57 +09:00
|
|
|
# Handle arguments: if provided, test only specified dirs; otherwise test all
|
|
|
|
|
if [ $# -gt 0 ]; then
|
|
|
|
|
# Test only specified directories
|
|
|
|
|
for arg in "$@"; do
|
|
|
|
|
# Convert relative path to absolute
|
|
|
|
|
if [[ "$arg" == /* ]]; then
|
|
|
|
|
d="$arg"
|
|
|
|
|
else
|
|
|
|
|
d="$ROOT/$arg"
|
|
|
|
|
fi
|
|
|
|
|
[ -d "$d" ] || { echo "[TEST] not a directory: $d" >&2; continue; }
|
|
|
|
|
run_case "$d"
|
|
|
|
|
done
|
|
|
|
|
else
|
|
|
|
|
# Test all directories
|
|
|
|
|
for d in "$TARGET_DIR"/*; do
|
|
|
|
|
[ -d "$d" ] || continue
|
|
|
|
|
run_case "$d"
|
|
|
|
|
done
|
|
|
|
|
fi
|
2025-11-07 21:04:01 +09:00
|
|
|
|
|
|
|
|
if [ $fail -ne 0 ]; then
|
|
|
|
|
echo "[TEST/SUMMARY] failures=$fail" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
echo "[TEST/SUMMARY] all green"
|
|
|
|
|
exit 0
|