Target coverage: a klammer states the targets it serves
kdesc gains --coverage, which reports for every klammer the set of targets it can render to, and — the point of it — which klammers' coverage cannot be derived and must therefore be declared. Three rules: coverage is DERIVED where the definitions determine it (a general body of klammer calls covers the intersection of what those klammers cover, by a greatest fixpoint after loading), DECLARED where the engine cannot interpret what decides it (an @eval body, whose targets are undecidable), and UNKNOWN where nothing is written — which never means "deliberately unavailable". Two new spellings in a definition's name. A comma-separated target list, "@@table.html,tex :: ...", gives one body several targets; it is surface syntax, expanded at registration, and each member goes through the redefinition rules on its own. And "@@date.* :: ..." writes the general target out, asserting that the klammer works for EVERY target including ones not yet defined — a stronger claim than a list of the targets defined today, and the one target declaration that could be mechanically falsified. The Standard Klammer Set was swept accordingly: it now has no general definitions at all, every klammer names the targets it serves, six use ".*", and tex and pdf are at zero undecided. kdesc's flags are reorganised on two rules: a flag reached for often gets a single letter (-k klammers, -t targets, -c characters, -i input), a more specialised topic a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets, --coverage, --klammerset, --font); and -v says how much to show about PROCESSING, never what the RESULT contains — so the katom regex column is "--katoms full" and the coverage detail "--coverage all". NOTE: "-k" now lists klammers (optionally filtered by a name/description search); the katom table moved to "--katoms". Fixes carried along: an option written with no value crashed the command with SIGSEGV instead of reporting the mistake; two required positional arguments never parsed; kdesc and kdiag printed an error and exited 0; and definition diagnostics counted registrations rather than what was written, so one line could be reported as two definitions and then printed twice. Four new test suites: target_list, coverage, command_option, kdesc. (from dev 46f54080bd9a)
This commit is contained in:
158
tst/kdesc_test.sh
Executable file
158
tst/kdesc_test.sh
Executable file
@@ -0,0 +1,158 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# kdesc_test.sh — the kdesc command's interface.
|
||||
#
|
||||
# The flag structure was reorganised 2026-08-11
|
||||
# (notes/modifying_the_kdesc_arguments.md) on two rules:
|
||||
#
|
||||
# * a flag a user reaches for often gets a single letter (-k klammers,
|
||||
# -t targets, -c character codes, -i input); a more specialised topic gets
|
||||
# a multi-letter name (--argtypes, --katoms, --rewrite, --optionsets,
|
||||
# --coverage, --klammerset, --font);
|
||||
# * -v says how much to show about the command's PROCESSING and never what
|
||||
# its RESULT contains. So the katom regex column is "--katoms full" and
|
||||
# the coverage file column is "--coverage all", not verbosity levels.
|
||||
#
|
||||
# "-k" is the one rename that changes a name's MEANING rather than retiring
|
||||
# it: it used to show katom types (now --katoms). A name-based guard cannot
|
||||
# catch that -- the old spelling still works and does something else -- so
|
||||
# these tests pin the new meaning down.
|
||||
#
|
||||
# Usage: ./kdesc_test.sh (needs KLAMMERTEXT_HOME set; kdesc on PATH)
|
||||
# Exit code: 0 if all tests pass, 1 otherwise.
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
KDESC=kdesc
|
||||
K=${KLAMMERTEXT_HOME:?KLAMMERTEXT_HOME must be set}
|
||||
DIR="$(cd "$(dirname "$0")" && pwd)/coverage"
|
||||
|
||||
red=$'\033[31m'
|
||||
green=$'\033[32m'
|
||||
bold=$'\033[1m'
|
||||
reset=$'\033[0m'
|
||||
|
||||
plain() { sed 's/\x1b\[[0-9;]*m//g'; }
|
||||
|
||||
# shows NAME PATTERN CMD... — exits 0 and the output matches PATTERN.
|
||||
shows() {
|
||||
local name="$1" pattern="$2"; shift 2
|
||||
local out status
|
||||
out=$(timeout 60 "$@" 2>&1 | plain); status=$?
|
||||
if [ $status -gt 128 ]; then
|
||||
echo "${red}FAIL${reset} $name — died by signal $((status-128))"; FAIL=$((FAIL+1)); return
|
||||
fi
|
||||
if printf '%s' "$out" | grep -Eq -- "$pattern"; then
|
||||
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
||||
else
|
||||
echo "${red}FAIL${reset} $name — no line matching [$pattern]"
|
||||
echo " got: $(printf '%s' "$out" | head -2)"; FAIL=$((FAIL+1))
|
||||
fi
|
||||
}
|
||||
|
||||
# absent NAME PATTERN CMD... — the output does NOT match PATTERN.
|
||||
absent() {
|
||||
local name="$1" pattern="$2"; shift 2
|
||||
if timeout 60 "$@" 2>&1 | plain | grep -Eq -- "$pattern"; then
|
||||
echo "${red}FAIL${reset} $name — unexpected match [$pattern]"; FAIL=$((FAIL+1))
|
||||
else
|
||||
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "${bold}kdesc interface tests${reset}"
|
||||
echo "====================="
|
||||
echo
|
||||
|
||||
echo "-- the single-letter flags --"
|
||||
shows " 1. -k lists klammers" '@table' "$KDESC" -k
|
||||
shows " 2. -t lists targets" 'html' "$KDESC" -t
|
||||
shows " 3. -c lists character codes" '.' "$KDESC" -c
|
||||
shows " 4. -i reads the named input" '@x' "$KDESC" -i "$DIR/split.k" -k
|
||||
|
||||
echo
|
||||
echo "-- the multi-letter topics --"
|
||||
shows " 5. --katoms lists katom types" 'katom' "$KDESC" --katoms
|
||||
shows " 6. --argtypes lists argtypes" 'fraction' "$KDESC" --argtypes
|
||||
shows " 7. --rewrite lists rewrites" '.' "$KDESC" --rewrite
|
||||
shows " 8. --optionsets lists sets" 'caption_args' "$KDESC" --optionsets
|
||||
|
||||
echo
|
||||
echo "-- result detail is a word, not a verbosity level --"
|
||||
shows " 9. --katoms full adds the regex column" 'Regex' "$KDESC" --katoms full
|
||||
absent "10. --katoms alone omits it" 'Regex' "$KDESC" --katoms
|
||||
shows "11. --coverage all adds the file column" 'sks/table/table\.k' "$KDESC" --coverage all
|
||||
absent "12. --coverage alone omits it" 'sks/table/table\.k' "$KDESC" --coverage
|
||||
# "all" is one word for both kinds of missing information: if you want some of
|
||||
# it you probably want all of it. It shows an empty REPORTING category -- a
|
||||
# designer's checklist of the shapes a klammer set can have -- but not an
|
||||
# empty PROBLEM one, which would state the opposite of the "Needs attention"
|
||||
# banner above it.
|
||||
# Against a FIXTURE, not the SKS: which categories are empty there changes as
|
||||
# the klammer set is worked on, and a test pinned to that state fails for a
|
||||
# reason that has nothing to do with what it is testing. (It did: adopting
|
||||
# ".*" in the SKS made "All targets, declared" non-empty.)
|
||||
shows "12a. --coverage all shows an empty reporting category" \
|
||||
'All targets, declared \(0\)' "$KDESC" -i "$DIR/cycle.k" --coverage all
|
||||
absent "12b. ... hidden without it" \
|
||||
'All targets, declared \(0\)' "$KDESC" -i "$DIR/cycle.k" --coverage
|
||||
absent "12c. an empty problem category stays hidden" \
|
||||
'Declared but never defined \(0\)' "$KDESC" -i "$DIR/cycle.k" --coverage all
|
||||
absent "13. -v adds no result detail" 'Regex' "$KDESC" --katoms -v 3
|
||||
|
||||
echo
|
||||
echo "-- -v is about processing only --"
|
||||
shows "14. -v names the input it read" 'input_filenames' "$KDESC" -t -v 1
|
||||
absent "15. ... and is silent without it" 'input_filenames' "$KDESC" -t
|
||||
|
||||
echo
|
||||
echo "-- the klammer search --"
|
||||
shows "16. a name matches" '@table' "$KDESC" -k table
|
||||
absent "17. ... and others are excluded" '@document' "$KDESC" -k table
|
||||
shows "18. matching is case-insensitive" '@table' "$KDESC" -k TABLE
|
||||
shows "19. a description word matches" '@' "$KDESC" -k verbatim
|
||||
# The words after -k are one phrase, and whitespace is collapsed on both
|
||||
# sides -- a description written across several lines in a .k file must still
|
||||
# match a phrase typed on one.
|
||||
shows "20. several words are one phrase" '@' "$KDESC" -k displayed verbatim
|
||||
shows "21. ... with runs of space collapsed" '@' "$KDESC" -k displayed verbatim
|
||||
shows "22. no match says so" 'No klammer names or descriptions contained "zzqq"\.' "$KDESC" -k zzqq
|
||||
absent "23. ... and lists nothing" '^ @' "$KDESC" -k zzqq
|
||||
|
||||
echo
|
||||
echo "-- the subcommand words --"
|
||||
shows "24. --coverage help explains" 'Coverage commands' "$KDESC" --coverage help
|
||||
shows "25. --katoms help explains" 'Katom commands' "$KDESC" --katoms help
|
||||
shows "26. an unknown coverage word" 'Unrecognized coverage command' "$KDESC" --coverage nonsense
|
||||
shows "27. an unknown katom word" 'Unrecognized katom command' "$KDESC" --katoms nonsense
|
||||
|
||||
echo
|
||||
echo "-- the usage text --"
|
||||
shows "28. -k shows its optional argument" '\-k \[<text>\]' "$KDESC"
|
||||
shows "29. -i shows its filename" '\-i <filename>' "$KDESC"
|
||||
# Ordered by likely use: the single letters come before the long names.
|
||||
# Line numbers, not a multi-line pattern -- grep is line-oriented.
|
||||
usage=$(timeout 60 "$KDESC" 2>&1 | plain)
|
||||
k_line=$(printf '%s\n' "$usage" | grep -n -- '-k \[<text>\]' | head -1 | cut -d: -f1)
|
||||
katoms_line=$(printf '%s\n' "$usage" | grep -n -- '--katoms' | head -1 | cut -d: -f1)
|
||||
if [ -n "$k_line" ] && [ -n "$katoms_line" ] && [ "$k_line" -lt "$katoms_line" ]; then
|
||||
echo "${green}PASS${reset} 30. -k is listed before --katoms"; PASS=$((PASS+1))
|
||||
else
|
||||
echo "${red}FAIL${reset} 30. usage order: -k at line $k_line, --katoms at $katoms_line"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "-- a no-result search is not an error --"
|
||||
timeout 60 "$KDESC" -k zzqq >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "${green}PASS${reset} 31. finding nothing exits 0"; PASS=$((PASS+1))
|
||||
else
|
||||
echo "${red}FAIL${reset} 31. finding nothing exits nonzero"; FAIL=$((FAIL+1))
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "====================="
|
||||
echo "Results: ${PASS} passed, ${FAIL} failed"
|
||||
[ "$FAIL" -eq 0 ] || exit 1
|
||||
exit 0
|
||||
Reference in New Issue
Block a user