156 lines
6.2 KiB
Bash
156 lines
6.2 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
#
|
||
|
|
# verbosity_test.sh — what "-v" says, and what it must not say.
|
||
|
|
#
|
||
|
|
# The output policy (CLAUDE.md, "Command output policy") fixes what each
|
||
|
|
# verbosity level is FOR, and a policy with no test drifts back — which is how
|
||
|
|
# the suites this session repaired got where they were. The rule:
|
||
|
|
#
|
||
|
|
# -v 0 silent. Nothing but the result.
|
||
|
|
# -v 1 every decision whose outcome the user COULD NOT HAVE READ OFF THEIR
|
||
|
|
# OWN INPUT: a klammerset symbol resolved to a file, a default applied,
|
||
|
|
# "-o" expanded into a directory and a basename, a filename regrouped,
|
||
|
|
# a klammer overridden by a definition in another klammer set.
|
||
|
|
# -v 2+ the trace: what the command DID, for someone reading the code.
|
||
|
|
#
|
||
|
|
# The boundary is the part worth testing. Andy's first formulation was "-v 1
|
||
|
|
# describes a change of state", and taken literally that swallows -v 2 — every
|
||
|
|
# definition is a change of state. So the test for -v 1 is not "did something
|
||
|
|
# happen" but "could the user have predicted the outcome from what they wrote".
|
||
|
|
# Registering a klammer the user wrote, in the file they wrote, is NOT -v 1
|
||
|
|
# material; resolving a symbol through a three-stage search path with shadowing
|
||
|
|
# is.
|
||
|
|
#
|
||
|
|
# Engine tier: no klammerset beyond what a case loads deliberately. The SKS
|
||
|
|
# half of this policy — font resolution and ":files" resolution — is in
|
||
|
|
# sks/tst/verbosity_test.sh, because those are @document's decisions.
|
||
|
|
#
|
||
|
|
# Usage: ./verbosity_test.sh (needs KLAMMERTEXT_HOME set; commands on PATH)
|
||
|
|
# Exit code: 0 if all tests pass, 1 otherwise.
|
||
|
|
|
||
|
|
PASS=0
|
||
|
|
FAIL=0
|
||
|
|
KTEXT=ktext
|
||
|
|
K=${KLAMMERTEXT_HOME:?KLAMMERTEXT_HOME must be set}
|
||
|
|
|
||
|
|
red=$'\033[31m'
|
||
|
|
green=$'\033[32m'
|
||
|
|
bold=$'\033[1m'
|
||
|
|
reset=$'\033[0m'
|
||
|
|
|
||
|
|
OUTF=$(mktemp /tmp/verb_out.XXXXXX)
|
||
|
|
ERRF=$(mktemp /tmp/verb_err.XXXXXX)
|
||
|
|
TMPD=$(mktemp -d /tmp/verb_dir.XXXXXX)
|
||
|
|
trap 'rm -f "$OUTF" "$ERRF"; rm -rf "$TMPD"' EXIT
|
||
|
|
|
||
|
|
plain() { sed 's/\x1b\[[0-9;]*m//g'; }
|
||
|
|
|
||
|
|
pass() { echo "${green}PASS${reset} $1"; PASS=$((PASS + 1)); }
|
||
|
|
fail() { echo "${red}FAIL${reset} $1"; [ -n "$2" ] && echo " $2"; FAIL=$((FAIL + 1)); }
|
||
|
|
|
||
|
|
# run CMD ARGS... — fills OUTF/ERRF, sets STATUS.
|
||
|
|
STATUS=0
|
||
|
|
run() { "$@" >"$OUTF" 2>"$ERRF"; STATUS=$?; }
|
||
|
|
|
||
|
|
# reports NAME PATTERN — ERRF matches PATTERN (the log is on stderr, always).
|
||
|
|
reports() {
|
||
|
|
if plain < "$ERRF" | grep -Eq -- "$2"; then pass "$1"
|
||
|
|
else fail "$1" "no [$2] in: $(plain < "$ERRF" | head -3 | tr '\n' ' ')"; fi
|
||
|
|
}
|
||
|
|
absent() {
|
||
|
|
if plain < "$ERRF" | grep -Eq -- "$2"; then fail "$1" "unexpected [$2]"
|
||
|
|
else pass "$1"; fi
|
||
|
|
}
|
||
|
|
|
||
|
|
echo "${bold}Verbosity tests${reset}"
|
||
|
|
echo "==============="
|
||
|
|
echo
|
||
|
|
|
||
|
|
echo "-- -v 0 is silent --"
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d
|
||
|
|
if [ $STATUS -eq 0 ] && [ "$(cat "$OUTF")" = "hello" ] && [ ! -s "$ERRF" ]; then
|
||
|
|
pass " 1. a successful run says nothing but its result"
|
||
|
|
else
|
||
|
|
fail " 1. exit $STATUS, stdout [$(cat "$OUTF")], stderr [$(head -1 "$ERRF")]"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "-- -v 1 answers \"what did the command think I asked for?\" --"
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d -v 1
|
||
|
|
reports " 2. the resolved argument list is shown" '\-s +: hello'
|
||
|
|
reports " 3. ... including a default the user did not write" '\-v +: 1'
|
||
|
|
# The document is on stdout and nothing shares it, whatever -v says.
|
||
|
|
if [ "$(cat "$OUTF")" = "hello" ]; then
|
||
|
|
pass " 4. and the result is still the only thing on stdout"
|
||
|
|
else
|
||
|
|
fail " 4. stdout carried [$(head -c 60 "$OUTF")]"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "-- -v 1 reports DERIVED values --"
|
||
|
|
# The output path: the user gave a target and an input name; the directory, the
|
||
|
|
# basename and the final filename were all constructed.
|
||
|
|
printf 'hello\n' > "$TMPD/doc.kt"
|
||
|
|
run "$KTEXT" "$TMPD/doc.kt" -t txt --klammersets none -v 1
|
||
|
|
reports " 5. the output directory it constructed" 'Output directory: '
|
||
|
|
reports " 6. the output basename it constructed" 'Output basename: doc'
|
||
|
|
reports " 7. the output filename it constructed" 'Output filename: .*doc\.txt'
|
||
|
|
|
||
|
|
# A klammerset symbol resolves through a three-stage search path with
|
||
|
|
# shadowing, so the FILE it landed on is the derived value. Both branches are
|
||
|
|
# checked: the default (no --klammersets at all) reported nothing until
|
||
|
|
# 2026-08-15, which was the commonest case of all.
|
||
|
|
run "$KTEXT" -s 'x' -d -v 1
|
||
|
|
reports " 8. the DEFAULT klammerset names the file it loaded" 'Klammerset \(default\): .*sks/sks\.k'
|
||
|
|
mkdir -p "$TMPD/kset"
|
||
|
|
printf '@@@klammerset kset | A set @@@\n' > "$TMPD/kset/kset.k"
|
||
|
|
run env KLAMMERTEXT_KLAMMERSETS="$TMPD" "$KTEXT" -s 'x' -d --klammersets kset -v 1
|
||
|
|
reports " 9. a symbol names the file it resolved to" 'Klammerset "kset": .*kset/kset\.k'
|
||
|
|
run "$KTEXT" -s 'x' -d --klammersets none -v 1
|
||
|
|
reports "10. and \"none\" says that none was loaded" 'Klammersets: none'
|
||
|
|
|
||
|
|
# An override: the definition being replaced usually lives somewhere the user
|
||
|
|
# cannot see, which is what earns it a place here rather than a warning.
|
||
|
|
run "$KTEXT" --klammersets none -t fx -d -v 1 \
|
||
|
|
-s '@@@target fx | F @@@ @@w.k : W @@ @@w.fx :: A @@ @@w.fx ::: B @@ @w@'
|
||
|
|
reports "11. a klammer overridden by a later definition" 'overridden'
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "-- the boundary: -v 2 is the trace, -v 1 is not --"
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d -v 1
|
||
|
|
v1=$(wc -l < "$ERRF")
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d -v 2
|
||
|
|
v2=$(wc -l < "$ERRF")
|
||
|
|
if [ "$v2" -gt "$v1" ]; then
|
||
|
|
pass "12. -v 2 says more than -v 1 ($v1 lines -> $v2)"
|
||
|
|
else
|
||
|
|
fail "12. -v 2 added nothing ($v1 -> $v2)"
|
||
|
|
fi
|
||
|
|
# The trace names the code; the -v 1 report never should. A source location in
|
||
|
|
# a level-1 line means a msg() or a stray log level, not a decision.
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d -v 1
|
||
|
|
absent "13. -v 1 does not name source files" '\[[a-z_]+\.cpp:[0-9]+\]'
|
||
|
|
run "$KTEXT" --klammersets none -s 'hello' -d -v 2
|
||
|
|
reports "14. ... while -v 2 does" '\[[a-z_]+\.(cpp|h):[0-9]+\]'
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "-- the other two commands honour -v as well --"
|
||
|
|
run kdesc --katoms -v 1
|
||
|
|
if [ $STATUS -eq 0 ] && [ -s "$OUTF" ]; then
|
||
|
|
pass "15. kdesc -v 1 still produces its result on stdout"
|
||
|
|
else
|
||
|
|
fail "15. exit $STATUS, stdout $(wc -c < "$OUTF") bytes"
|
||
|
|
fi
|
||
|
|
run kdiag -v 1 '@i-x'
|
||
|
|
if [ $STATUS -eq 0 ] && [ -s "$OUTF" ]; then
|
||
|
|
pass "16. kdiag -v 1 still produces its result on stdout"
|
||
|
|
else
|
||
|
|
fail "16. exit $STATUS, stdout $(wc -c < "$OUTF") bytes"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "==============="
|
||
|
|
echo "Results: ${PASS} passed, ${FAIL} failed"
|
||
|
|
[ "$FAIL" -eq 0 ] || exit 1
|
||
|
|
exit 0
|