#!/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