Verbatim-safe typography, ^-punctuation quoting, full-range ^UUUU^, polyglot html
Typographic transforms (---, quote pairs, ~) no longer touch verbatim text: @c/@code/@source_listing content and ^'...'^ spans show exactly the characters written. "^" before any punctuation character quotes it in every target (the apostrophe excepted: ^' opens a literal span), with the new :resolve option on @@@target declaring per-target renderings. The ^UUUU^ code-point form accepts 4-6 hex digits, the full Unicode range. The html output and transform spellings are polyglot (XML-valid), in preparation for an EPUB target. New suites: transform_test, character_test (engine), typography_test (SKS). (from dev 07ce5ea86a0a)
This commit is contained in:
121
tst/state_test.sh
Executable file
121
tst/state_test.sh
Executable file
@@ -0,0 +1,121 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# state_test.sh — The @@@state system command and *name* substitution.
|
||||
#
|
||||
# Added 2026-08-22 by the error-gallery coverage review, which found that no
|
||||
# suite covered @@@state at all: its two error messages had never been
|
||||
# printed by any test. What is pinned here, each by outcome:
|
||||
#
|
||||
# * :value sets a variable and *name* substitutes it in a klammer BODY
|
||||
# (bodies are processed at application time). A top-level *name* of a
|
||||
# document-declared variable does NOT substitute — the same read-time
|
||||
# asymmetry @cond had before 2026-08-15; if that is ever changed, case 2
|
||||
# documents today's behaviour and should change with it.
|
||||
# * :replace replaces an existing value.
|
||||
# * Redefining WITHOUT :replace is an error that names the remedy.
|
||||
# * An undefined variable's error lists the frames it searched.
|
||||
# * A shell environment variable substitutes like any state variable.
|
||||
#
|
||||
# NOT to be confused with "state_test", the C++ diagnostic program built from
|
||||
# state_test.cpp in this directory: that one constructs engine objects and
|
||||
# prints what it gets, for a person to read, and asserts nothing (see the
|
||||
# `smoke` target in tst/Makefile). This is the regression suite. The ".sh"
|
||||
# is the only thing distinguishing them — the same collision as
|
||||
# eval_test/eval_test.sh, documented there first.
|
||||
#
|
||||
# Usage: ./state_test.sh (needs ktext on PATH)
|
||||
# Exit code: 0 if all tests pass, 1 otherwise.
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
KTEXT=ktext
|
||||
export KT_STATE_PROBE="probe-value" # for the environment-variable case
|
||||
|
||||
red=$'\033[31m'
|
||||
green=$'\033[32m'
|
||||
bold=$'\033[1m'
|
||||
reset=$'\033[0m'
|
||||
|
||||
# check_eq NAME EXPECTED KTEXT_ARGS... — trimmed stdout equals EXPECTED.
|
||||
check_eq() {
|
||||
local name="$1" expected="$2"
|
||||
shift 2
|
||||
local out status
|
||||
out=$("$KTEXT" "$@" 2>/dev/null)
|
||||
status=$?
|
||||
out=$(printf '%s' "$out" | sed -e 's/[ \t]*$//' | grep -v '^$')
|
||||
if [ $status -eq 0 ] && [ "$out" = "$expected" ]; then
|
||||
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
||||
else
|
||||
echo "${red}FAIL${reset} $name"
|
||||
echo " expected: [$expected]"; echo " got: [$out] (exit $status)"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
}
|
||||
|
||||
# check_error NAME PATTERN KTEXT_ARGS... — nonzero exit, PATTERN in the
|
||||
# message. Wrap-insensitive: error prose is justified to 80 columns, so a
|
||||
# phrase may wrap anywhere.
|
||||
check_error() {
|
||||
local name="$1" pattern="$2"
|
||||
shift 2
|
||||
local out status
|
||||
out=$("$KTEXT" "$@" 2>&1)
|
||||
status=$?
|
||||
if [ $status -eq 0 ]; then
|
||||
echo "${red}FAIL${reset} $name — expected an error but ktext succeeded"
|
||||
FAIL=$((FAIL+1)); return
|
||||
fi
|
||||
if printf '%s' "$out" | tr '\n' ' ' | tr -s ' ' | grep -qF "$pattern"; then
|
||||
echo "${green}PASS${reset} $name"; PASS=$((PASS+1))
|
||||
else
|
||||
echo "${red}FAIL${reset} $name — expected error to contain [$pattern]"
|
||||
echo " got: $(printf '%s' "$out" | sed 's/\x1b\[[0-9;]*m//g' | tr '\n' ' ' | head -c 200)"
|
||||
FAIL=$((FAIL+1))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "${bold}@@@state tests${reset}"
|
||||
echo "=============="
|
||||
echo
|
||||
|
||||
echo "-- setting and substituting --"
|
||||
check_eq " 1. :value sets; *name* substitutes in a body" \
|
||||
"[hello]" \
|
||||
--klammersets none -s '@@@state V :value hello @@@ @@f : [*V*] @@ @f@' -d
|
||||
|
||||
# Documents TODAY'S behaviour: a top-level *name* of a document-declared
|
||||
# variable is left as written (bodies substitute; the top level does not).
|
||||
check_eq " 2. a top-level *name* does not substitute (current behaviour)" \
|
||||
"[*V*]" \
|
||||
--klammersets none -s '@@@state V :value hello @@@ [*V*]' -d
|
||||
|
||||
check_eq " 3. an environment variable substitutes" \
|
||||
"[probe-value]" \
|
||||
--klammersets none -s '@@f : [*KT_STATE_PROBE*] @@ @f@' -d
|
||||
|
||||
echo
|
||||
echo "-- replacing --"
|
||||
check_eq " 4. :replace replaces an existing value" \
|
||||
"[b]" \
|
||||
--klammersets none \
|
||||
-s '@@@state V :value a @@@ @@@state V :replace b @@@ @@f : [*V*] @@ @f@' -d
|
||||
|
||||
check_error " 5. redefining without :replace is an error naming the remedy" \
|
||||
"Use ':replace <new-value>' to replace the current value" \
|
||||
--klammersets none -s '@@@state V :value a @@@ @@@state V :value b @@@' -d
|
||||
|
||||
echo
|
||||
echo "-- the undefined variable --"
|
||||
check_error " 6. an undefined *name* in a body is a located error" \
|
||||
'Variable "Missing" not defined' \
|
||||
--klammersets none -s '@@f : [*Missing*] @@ @f@' -d
|
||||
|
||||
check_error " 7. ... that lists the frames it searched" \
|
||||
"(searched:" \
|
||||
--klammersets none -s '@@f : [*Missing*] @@ @f@' -d
|
||||
|
||||
echo
|
||||
echo "=============="
|
||||
echo "Results: ${green}$PASS passed${reset}, ${red}$FAIL failed${reset}"
|
||||
[ $FAIL -eq 0 ]
|
||||
Reference in New Issue
Block a user