sq_newslot(-3) expects a [table, key, value] three-level stack; the code pushed only the value, so the slot write silently targeted the native frame's mode argument (a string, not a table) and was skipped. Handles therefore had methods but empty _path/_data, making read()/getSize() throw 'file not readable' on every platform where the stack layout did not accidentally alias the table. Fix cardgame's ui.sameLine() calls to pass an id (the binding requires one), and make the example smoke failure output print non-frame-error lines so future CI failures carry the real root cause instead of being buried under per-frame error spam.
138 lines
3.7 KiB
Bash
138 lines
3.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Smoke-test every runnable example under examples/.
|
|
#
|
|
# Each example is launched as `eve run` from inside its own directory (the same
|
|
# thing `make run GAME=examples/<name>` does) and killed after a few seconds.
|
|
# Its stdout/stderr is scanned for known error markers; a clean run reports
|
|
# PASS, otherwise FAIL with the offending lines.
|
|
#
|
|
# Usage:
|
|
# scripts/smoke_examples.sh # all examples
|
|
# scripts/smoke_examples.sh basic tree-generator # only these examples
|
|
# EVE=.../eve.exe RUN_SECONDS=8 scripts/smoke_examples.sh
|
|
#
|
|
# Exit status is non-zero if any example failed.
|
|
|
|
set -uo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
EXAMPLES_DIR="$ROOT/examples"
|
|
|
|
# Host debug binary (win32 / linux / macosx).
|
|
if [[ -n "${EVE:-}" ]]; then
|
|
EVE_BIN="$EVE"
|
|
elif [[ -x "$ROOT/build/win32-debug/src/engine/eve.exe" ]]; then
|
|
EVE_BIN="$ROOT/build/win32-debug/src/engine/eve.exe"
|
|
elif [[ -x "$ROOT/build/linux-debug/src/engine/eve" ]]; then
|
|
EVE_BIN="$ROOT/build/linux-debug/src/engine/eve"
|
|
else
|
|
EVE_BIN="$ROOT/build/macosx-debug/src/engine/eve"
|
|
fi
|
|
|
|
RUN_SECONDS_PER="${RUN_SECONDS:-6}"
|
|
|
|
# Extra args appended to every `eve run` invocation (e.g. EVE_RUN_ARGS="--debug").
|
|
RUN_ARGS="${EVE_RUN_ARGS:-}"
|
|
|
|
is_windows() {
|
|
case "$(uname -s)" in
|
|
MINGW*|MSYS*|CYGWIN*) return 0 ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
# Error markers emitted by load.nut / Run.cpp / Squirrel failures.
|
|
read -r -d '' MARKERS_SCRIPT <<'EOF' || true
|
|
frame error
|
|
Run failed:
|
|
Runtime error
|
|
eve_init failed
|
|
present error
|
|
Cannot chdir
|
|
Cannot open root
|
|
failed to load:
|
|
EOF
|
|
mapfile -t MARKERS <<<"$MARKERS_SCRIPT"
|
|
|
|
# Runnable examples = dirs containing a main.nut.
|
|
if [[ $# -gt 0 ]]; then
|
|
EXAMPLES=("$@")
|
|
else
|
|
EXAMPLES=()
|
|
for d in "$EXAMPLES_DIR"/*/; do
|
|
name="$(basename "$d")"
|
|
[[ -f "$d/main.nut" ]] && EXAMPLES+=("$name")
|
|
done
|
|
fi
|
|
|
|
FAILED=0
|
|
PASSED=0
|
|
declare -a FAILED_NAMES=()
|
|
|
|
for name in "${EXAMPLES[@]}"; do
|
|
dir="$EXAMPLES_DIR/$name"
|
|
[[ -f "$dir/main.nut" ]] || { echo "SKIP $name (no main.nut)"; continue; }
|
|
|
|
# devlab's whole point is DevTools: always smoke it with --debug.
|
|
extra="$RUN_ARGS"
|
|
if [[ "$name" == "devlab" ]]; then
|
|
extra="$extra --debug"
|
|
fi
|
|
|
|
log="$(mktemp)"
|
|
if is_windows; then
|
|
# GNU timeout on MSYS cannot reliably terminate the native Windows GUI
|
|
# process (SIGTERM is ignored), so launch in background and force-kill by
|
|
# image name with taskkill.
|
|
(
|
|
cd "$dir" || exit 1
|
|
"$EVE_BIN" run $extra >"$log" 2>&1 &
|
|
pid=$!
|
|
sleep "$RUN_SECONDS_PER"
|
|
taskkill //F //IM "$(basename "$EVE_BIN")" >/dev/null 2>&1 || true
|
|
kill "$pid" 2>/dev/null || true
|
|
wait "$pid" 2>/dev/null || true
|
|
)
|
|
else
|
|
if command -v timeout >/dev/null 2>&1; then
|
|
( cd "$dir" && timeout -k 3 "$RUN_SECONDS_PER" "$EVE_BIN" run $extra >"$log" 2>&1 )
|
|
else
|
|
( cd "$dir" && "$EVE_BIN" run $extra >"$log" 2>&1 ) &
|
|
pid=$!
|
|
sleep "$RUN_SECONDS_PER"
|
|
kill "$pid" 2>/dev/null || true
|
|
wait "$pid" 2>/dev/null || true
|
|
fi
|
|
fi
|
|
|
|
hit=""
|
|
for m in "${MARKERS[@]}"; do
|
|
if grep -qF "$m" "$log"; then
|
|
hit="$m"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [[ -n "$hit" ]]; then
|
|
echo "FAIL $name (marker: $hit)"
|
|
grep -nF "$hit" "$log" 2>/dev/null | head -3 | sed 's/^/ /'
|
|
echo " --- key output (non-frame-error lines, head 30) ---"
|
|
grep -vF "frame error" "$log" 2>/dev/null | head -n 30 | sed 's/^/ | /'
|
|
echo " --- example output (last 10 lines) ---"
|
|
tail -n 10 "$log" | sed 's/^/ | /'
|
|
FAILED=$((FAILED + 1))
|
|
FAILED_NAMES+=("$name")
|
|
else
|
|
echo "PASS $name"
|
|
PASSED=$((PASSED + 1))
|
|
fi
|
|
rm -f "$log"
|
|
done
|
|
|
|
echo
|
|
echo "Summary: $PASSED passed, $FAILED failed"
|
|
if [[ $FAILED -gt 0 ]]; then
|
|
printf 'Failed: %s\n' "${FAILED_NAMES[*]}"
|
|
exit 1
|
|
fi
|