Template
Wire the full pipeline into the binary: parse + validate the KDL buildfile, discover extensions, bridge Lua, detect the C toolchain, and emit ./configure. Adds the project's own stupid.kdl build file and a temp-dir-isolated self-host integration test proving the generated configure + make rebuild the tool with -std=c23. tests/run.sh tests 6+8 re-pin the interim 'accepted, no read' CLI assertions to the wired 'missing buildfile -> exit 1' behavior.
188 lines
6.0 KiB
Bash
Executable File
188 lines
6.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# tests/run.sh - test runner for stupidtools (skeleton).
|
|
#
|
|
# Grows with the project; today it proves the toolchain works end to end:
|
|
# the binary must exist, run, and report its version.
|
|
#
|
|
# POSIX sh only (dash/bash/zsh safe). Fails fast on the first failed check.
|
|
|
|
TOP_DIR=$(cd "$(dirname "$0")/.." && pwd) || {
|
|
echo "FAIL: cannot resolve project root" >&2
|
|
exit 1
|
|
}
|
|
BIN="$TOP_DIR/src/stupidtools"
|
|
|
|
TESTS_RUN=0
|
|
TESTS_FAILED=0
|
|
|
|
pass() {
|
|
TESTS_RUN=$((TESTS_RUN + 1))
|
|
printf 'ok %d - %s\n' "$TESTS_RUN" "$1"
|
|
}
|
|
|
|
fail() {
|
|
TESTS_RUN=$((TESTS_RUN + 1))
|
|
TESTS_FAILED=$((TESTS_FAILED + 1))
|
|
printf 'not ok %d - %s\n' "$TESTS_RUN" "$1" >&2
|
|
}
|
|
|
|
# --- 1. the built binary must exist and be executable -------------------
|
|
if [ -x "$BIN" ]; then
|
|
pass "binary exists and is executable: $BIN"
|
|
else
|
|
fail "binary missing: $BIN (run 'make' first)"
|
|
printf 'FAILED: %d/%d checks failed\n' "$TESTS_FAILED" "$TESTS_RUN" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --- 2. --version must exit 0 and print exactly 'stupidtools <version>' -
|
|
version_out=
|
|
if version_out=$("$BIN" --version 2>&1); then
|
|
if [ "$version_out" = "stupidtools 1.0.0" ]; then
|
|
pass "--version reports: $version_out"
|
|
else
|
|
fail "--version output unexpected: '$version_out' (want 'stupidtools 1.0.0')"
|
|
fi
|
|
else
|
|
rc=$?
|
|
fail "--version exited non-zero (rc=$rc): $version_out"
|
|
fi
|
|
|
|
# --- 3. --help must exit 0 and print usage on stdout ----------------------
|
|
help_out=
|
|
help_rc=0
|
|
help_out=$("$BIN" --help 2>/dev/null) || help_rc=$?
|
|
if [ "$help_rc" -eq 0 ]; then
|
|
case "$help_out" in
|
|
*"Usage: "*)
|
|
pass "--help exits 0 and prints usage on stdout" ;;
|
|
*)
|
|
fail "--help printed no usage on stdout: '$help_out'" ;;
|
|
esac
|
|
else
|
|
fail "--help exited non-zero (rc=$help_rc): $help_out"
|
|
fi
|
|
|
|
# --- 4. unknown option must exit 2, usage on stderr, silent stdout -------
|
|
bogus_out=
|
|
bogus_rc=0
|
|
bogus_out=$("$BIN" --bogus 2>&1 >/dev/null) || bogus_rc=$?
|
|
if [ "$bogus_rc" -eq 2 ]; then
|
|
case "$bogus_out" in
|
|
*"Usage: "*)
|
|
pass "--bogus exits 2 and prints usage on stderr" ;;
|
|
*)
|
|
fail "--bogus printed no usage on stderr: '$bogus_out'" ;;
|
|
esac
|
|
else
|
|
fail "--bogus exited rc=$bogus_rc (want 2): $bogus_out"
|
|
fi
|
|
if [ -z "$("$BIN" --bogus 2>/dev/null)" ]; then
|
|
pass "--bogus prints nothing on stdout"
|
|
else
|
|
fail "--bogus leaked output on stdout"
|
|
fi
|
|
|
|
# --- 5. no arguments must exit 1 with usage on stderr ---------------------
|
|
noargs_out=
|
|
noargs_rc=0
|
|
noargs_out=$("$BIN" 2>&1 >/dev/null) || noargs_rc=$?
|
|
if [ "$noargs_rc" -eq 1 ]; then
|
|
case "$noargs_out" in
|
|
*"Usage: "*)
|
|
pass "no arguments exits 1 and prints usage on stderr" ;;
|
|
*)
|
|
fail "no arguments printed no usage on stderr: '$noargs_out'" ;;
|
|
esac
|
|
else
|
|
fail "no arguments exited rc=$noargs_rc (want 1): $noargs_out"
|
|
fi
|
|
|
|
# --- 6. a missing buildfile is a runtime error (exit 1) -------------------
|
|
"$BIN" buildfile.kdl >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq 1 ]; then
|
|
pass "missing buildfile exits 1 (runtime error)"
|
|
else
|
|
fail "missing buildfile exited rc=$rc (want 1)"
|
|
fi
|
|
|
|
# --- 7. --version=1 is an unknown option form -> exit 2 -------------------
|
|
"$BIN" --version=1 >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq 2 ]; then
|
|
pass "--version=1 exits 2 (unknown option)"
|
|
else
|
|
fail "--version=1 exited rc=$rc (want 2)"
|
|
fi
|
|
|
|
# --- 8. -- ends option parsing; following text is positional --------------
|
|
"$BIN" -- --bogus >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq 1 ]; then
|
|
pass "-- terminates option parsing (--bogus taken as a missing buildfile: rc=1, not 2)"
|
|
else
|
|
fail "-- --bogus exited rc=$rc (want 1, proving --bogus was a buildfile not an option)"
|
|
fi
|
|
|
|
# --- 9. two positionals are a usage error -> exit 2 -----------------------
|
|
"$BIN" a.kdl b.kdl >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq 2 ]; then
|
|
pass "two positionals exit 2 (usage error)"
|
|
else
|
|
fail "two positionals exited rc=$rc (want 2)"
|
|
fi
|
|
|
|
# --- 10. unit tests (tests/unit/*.c via munit) ----------------------------
|
|
# Harness contract (see .omo/notepads/stupidtools/learnings.md):
|
|
# - each tests/unit/<name>.c declares its extra link sources on its FIRST
|
|
# line as: /* LINK: ../../src/foo.c ../../src/bar.c */
|
|
# (paths relative to tests/unit/, space-separated)
|
|
# - the harness adds -I <repo>/thirdparty/munit -I <repo>/src and
|
|
# thirdparty/munit/munit.c automatically, compiles with
|
|
# -std=c23 -Wall -Wextra -Wpedantic, and runs each binary.
|
|
# - a missing LINK line, a compile failure, or a non-zero exit all FAIL.
|
|
UNIT_DIR="$TOP_DIR/tests/unit"
|
|
UNIT_BUILD="$TOP_DIR/tests/.unit-build"
|
|
if [ -d "$UNIT_DIR" ]; then
|
|
if ! mkdir -p "$UNIT_BUILD"; then
|
|
fail "cannot create unit build dir: $UNIT_BUILD"
|
|
fi
|
|
for t in "$UNIT_DIR"/*.c; do
|
|
[ -e "$t" ] || continue
|
|
name=$(basename "$t" .c)
|
|
# first line only: /* LINK: src1.c src2.c */
|
|
link=$(sed -n '1s|^/\* LINK: \(.*\) \*/$|\1|p' "$t")
|
|
if [ -z "$link" ]; then
|
|
fail "unit test $name: missing LINK comment on line 1"
|
|
continue
|
|
fi
|
|
# compile with cwd=tests/unit so LINK paths resolve relative to it;
|
|
# absolute paths for everything else.
|
|
if (cd "$UNIT_DIR" && cc -std=c23 -Wall -Wextra -Wpedantic \
|
|
-I "$TOP_DIR/thirdparty/munit" -I "$TOP_DIR/src" \
|
|
"$TOP_DIR/thirdparty/munit/munit.c" $link "$t" \
|
|
-o "$UNIT_BUILD/unit_$name") 2>"$UNIT_BUILD/unit_$name.build.log"
|
|
then
|
|
:
|
|
else
|
|
fail "unit test $name: compile failed (see $UNIT_BUILD/unit_$name.build.log)"
|
|
continue
|
|
fi
|
|
if "$UNIT_BUILD/unit_$name" >"$UNIT_BUILD/unit_$name.log" 2>&1; then
|
|
pass "unit test $name passed"
|
|
else
|
|
rc=$?
|
|
fail "unit test $name exited rc=$rc (see $UNIT_BUILD/unit_$name.log)"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# --- summary -------------------------------------------------------------
|
|
if [ "$TESTS_FAILED" -ne 0 ]; then
|
|
printf 'FAILED: %d/%d checks failed\n' "$TESTS_FAILED" "$TESTS_RUN" >&2
|
|
exit 1
|
|
fi
|
|
printf 'All %d checks passed.\n' "$TESTS_RUN"
|