Files
hakorune/tools/hako_check/run_tests.sh
nyash-codex 772149c86d Analyzer安定化完了: NYASH_DISABLE_PLUGINS=1復元 + plugin無効化根治
## 修正内容
1. **hako_check.sh/run_tests.sh**: NYASH_DISABLE_PLUGINS=1 + NYASH_BOX_FACTORY_POLICY=builtin_first追加
2. **src/box_factory/plugin.rs**: NYASH_DISABLE_PLUGINS=1チェック追加
3. **src/box_factory/mod.rs**: plugin shortcut pathでNYASH_DISABLE_PLUGINS尊重
4. **tools/hako_check/render/graphviz.hako**: smart quotes修正(parse error解消)

## 根本原因
- NYASH_USE_PLUGIN_BUILTINS=1が自動設定され、ArrayBox/MapBoxがplugin経由で生成を試行
- bid/registry.rsで"Plugin loading temporarily disabled"の状態でも試行されエラー
- mod.rs:272のshortcut pathがNYASH_DISABLE_PLUGINSを無視していた

## テスト結果
- 10/11 PASS(HC011,13-18,21-22,31)
- HC012: 既存issue(JSON安定化未完)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 15:49:25 +09:00

148 lines
5.0 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
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"
# 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 )
# Restrict rules to the target under test for stability
local base
base="$(basename "$dir")"
local rules_key=""
case "$base" in
HC011_*) rules_key="dead_methods" ;;
HC012_*) rules_key="dead_static_box" ;;
HC013_*) rules_key="duplicate_method" ;;
HC014_*) rules_key="missing_entrypoint" ;;
HC015_*) rules_key="arity_mismatch" ;;
HC016_*) rules_key="unused_alias" ;;
HC017_*) rules_key="non_ascii_quotes" ;;
HC018_*) rules_key="top_level_local" ;;
HC021_*) rules_key="analyzer_io_safety" ;;
HC022_*) rules_key="stage3_gate" ;;
HC031_*) rules_key="brace_heuristics" ;;
*) rules_key="" ;;
esac
if [ -n "$rules_key" ]; then ARGS+=( --rules "$rules_key" ); fi
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
# Ensure plugin path is set
export LD_LIBRARY_PATH="${ROOT}/target/release:${LD_LIBRARY_PATH:-}"
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 \
NYASH_DISABLE_PLUGINS=1 \
NYASH_BOX_FACTORY_POLICY=builtin_first \
NYASH_JSON_ONLY=1 \
"$BIN" --backend vm "$ROOT/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
echo "[TEST/FAIL] $dir" >&2
diff -u "$expected" "$tmp_norm" || true
fail=$((fail+1))
else
echo "[TEST/OK] $dir"
fi
rm -f "$tmp_out" "$tmp_norm" "$tmp_json"
}
# 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
if [ $fail -ne 0 ]; then
echo "[TEST/SUMMARY] failures=$fail" >&2
exit 1
fi
echo "[TEST/SUMMARY] all green"
exit 0