flan/web/examples/check.sh
Joseph Ferano aa82364066 Two aliases for the checks nobody ran, and one word that names them all
@page runs web/examples/check.sh and web/examples/quotes.sh against the compiler
dune just built. @cells runs spike/x86/cells.sh, which was a real pass/fail check
-- four builds, two backends, 22 22 against 42 42 -- that nothing in the tree ran.
@checks is @page, @x86 and @cells together, and its comment argues for where the
boundary sits: everything you can run while making coffee is in, @sanitize and
@valgrind are out because folding tens of minutes in would make the umbrella the
thing nobody has time for, which is the disease rather than the cure.

All three scripts learned to resolve FLAN to an absolute path, which is what
actually stood between them and a dune rule: %{workspace_root} expands relative to
the directory the rule is written in, and every one of these scripts cd's somewhere
before using it. The first run of @page failed with twenty diffs all saying
'../bin/main.exe: No such file or directory', which is at least a failure that says
what is wrong.

docs/BUILT.md carried the same colon-spelled renderer block index.html did, from the
same sweep. Nothing checks BUILT.md, so it is corrected here by hand.
2026-09-14 10:26:48 +07:00

63 lines
2.4 KiB
Bash

#!/bin/sh
# Every Flan program shown on index.html is in this directory, and this script
# runs all of them and compares what they print against the .out file beside
# them. An example that does not compile is worse than no example, so the page
# quotes only what this script has been green on.
#
# $ dune build && sh web/examples/check.sh
#
# FLAN overrides the compiler; the default is the one dune just built.
here=$(cd "$(dirname "$0")" && pwd)
root=$(cd "$here/../.." && pwd)
FLAN=${FLAN:-$root/_build/default/bin/main.exe}
# Made absolute before the cd below, because a relative FLAN stops meaning what
# it meant the moment the working directory changes. dune hands one over:
# %{workspace_root} expands relative to the directory the rule is written in.
case $FLAN in /*) ;; *) FLAN=$(cd "$(dirname "$FLAN")" && pwd)/$(basename "$FLAN") ;; esac
tmp=${TMPDIR:-/tmp}/flan-web-check.$$
cd "$here" || exit 1
fail=0
ok() { echo "ok $1"; }
bad() { echo "FAIL $1"; fail=1; }
for f in *.flan; do
# Two programs are not run by `flan run`; each is checked its own way below.
[ "$f" = shimdemo.flan ] && continue # calls raylib
[ "$f" = breakdemo.flan ] && continue # stops and waits, on purpose
got=$( { "$FLAN" run "$f"; echo "exit $?"; } 2>&1 )
if [ "$got" = "$(cat "${f%.flan}.out")" ]; then ok "$f"; else
bad "$f"
printf '%s\n' "$got" | diff -u "${f%.flan}.out" - || true
fi
done
# shimdemo.flan is the declare-c example: what it demonstrates is the C the
# compiler writes, so it is checked by generating that rather than by running.
if "$FLAN" shim shimdemo.flan | grep -q 'GetMousePosition(void)'; then
ok "shimdemo.flan (flan shim)"
else
bad "shimdemo.flan (flan shim)"
fi
# breakdemo.flan is the break loop: an unhandled error stops the program and
# waits for someone to pick a restart, so it never exits on its own. It needs
# a --dev build (the hook lives in vendor/agent) and it is killed after a few
# seconds; what is checked is the banner it printed before it stopped.
if command -v timeout >/dev/null 2>&1; then
if "$FLAN" build breakdemo.flan --dev -o "$tmp" >/dev/null 2>&1; then
got=$(timeout 5 "$tmp" 2>&1)
rm -f "$tmp"
if [ "$got" = "$(cat breakdemo.out)" ]; then ok "breakdemo.flan (break loop)"; else
bad "breakdemo.flan (break loop)"
printf '%s\n' "$got" | diff -u breakdemo.out - || true
fi
else
bad "breakdemo.flan (build --dev)"
fi
else
echo "skip breakdemo.flan (no timeout(1))"
fi
exit $fail