#!/usr/bin/env sh # test-ocn-alignment.sh # # The languages of a document share their object numbering, and spine warns # when they stop doing so. This checks both halves of that: that the sample # set is silent, and that a document whose languages really do diverge is # reported. # # Two fixtures, because one cannot say both things: # # the sample set every document aligned, so nothing is reported at # all. This is the half that would fail if a change # made the check cry wolf, and the half that changed on # 2026-09-18 when live-manual's ja and pl translations # were mended. Until then ja was two objects short of # en and pl had a stray heading at ocn 313, and this # script asserted those two by name. # # a broken copy live-manual copied out of the sample set with one # paragraph removed from one language, which is a count # divergence and must be reported. Built here rather # than relied upon, so that mending a translation # cannot quietly leave the check untested. A check that # never fires proves as little as one that always does. # # It also asserts that --strict turns the warning into a non-zero exit, and # that without --strict the run still succeeds: a document with a diverging # translation is still a document. # # Usage: # SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod \ # ./test/test-ocn-alignment.sh ./bin/spine-ldc # # Exit codes: # 0 the check reports what it should, and nothing else # 1 it does not (printed) # 2 set-up problem (no $SpinePOD, no binary, no samples) set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SPINE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" if [ -z "$SpinePOD" ]; then echo "ERROR: \$SpinePOD is not set." >&2 echo " e.g. SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod" >&2 exit 2 fi SAMPLES_RAW="$SPINE_DIR/$SpinePOD" if [ -d "$SAMPLES_RAW" ]; then SAMPLES_DIR="$(cd "$SAMPLES_RAW" && pwd)" else SAMPLES_DIR="$SAMPLES_RAW" fi if [ ! -d "$SAMPLES_DIR" ]; then echo "ERROR: sample documents not found at $SAMPLES_DIR" >&2 exit 2 fi SPINE_BIN="${1:-}" if [ -z "$SPINE_BIN" ]; then if [ -x "$SPINE_DIR/result/bin/spine" ]; then SPINE_BIN="$SPINE_DIR/result/bin/spine" elif [ -x "$SPINE_DIR/bin/spine-ldc" ]; then SPINE_BIN="$SPINE_DIR/bin/spine-ldc" elif [ -x "$SPINE_DIR/bin/spine" ]; then SPINE_BIN="$SPINE_DIR/bin/spine" else echo "ERROR: spine binary not found. Specify path as argument." >&2 exit 2 fi fi OUT_DIR="$SCRIPT_DIR/current-ocn-alignment" rm -rf "$OUT_DIR" mkdir -p "$OUT_DIR" echo "spine binary: $SPINE_BIN" echo "samples: $SAMPLES_DIR" FAILURES=0 fail() { echo " FAIL: $*"; FAILURES=$((FAILURES + 1)); } # the whole sample set, abstraction only: the check does not need outputs echo "Abstracting the sample set ..." set +e $SPINE_BIN --show-abstraction --skip-output \ --output="$OUT_DIR" "$SAMPLES_DIR"/* \ > "$OUT_DIR/run.out" 2> "$OUT_DIR/run.err" RUN_RC=$? set -e # without --strict a diverging document is still built if [ "$RUN_RC" -ne 0 ]; then fail "the run exited $RUN_RC without --strict; a warning must not fail a run" head -5 "$OUT_DIR/run.err" fi # it must say nothing at all: every document in the set is aligned n_docs=$(grep -c "^WARNING ocn alignment: " "$OUT_DIR/run.err" || true) if [ "$n_docs" != "0" ]; then fail "$n_docs document(s) reported over the sample set, expected none" grep -A 3 "^WARNING ocn alignment: " "$OUT_DIR/run.err" | head -12 | sed 's/^/ /' fi # --strict over the whole set therefore passes too set +e $SPINE_BIN --show-abstraction --skip-output --strict \ --output="$OUT_DIR/strict-ok" "$SAMPLES_DIR"/live-manual \ > "$OUT_DIR/strict-ok.out" 2> "$OUT_DIR/strict-ok.err" STRICT_OK_RC=$? set -e if [ "$STRICT_OK_RC" -ne 0 ]; then fail "--strict exited $STRICT_OK_RC on a document whose languages agree" head -5 "$OUT_DIR/strict-ok.err" fi # and now the other half: a document that really does diverge. # # Built here, from a copy, by removing one paragraph from one language. The # sample set no longer contains a divergence, and a check that never fires # proves as little as one that always does. echo "Breaking a copy, to see the check fire ..." BROKEN="$OUT_DIR/broken" mkdir -p "$BROKEN" cp -a "$SAMPLES_DIR/live-manual" "$BROKEN/live-manual" TARGET="$BROKEN/live-manual/media/text/de/about_manual.ssi" if [ ! -f "$TARGET" ]; then echo "ERROR: fixture not found: $TARGET" >&2 exit 2 fi # the first paragraph after the first heading, whole: a numbered object, so # removing it renumbers everything below it in this language and no other. # # The whole of it, to the blank line that ends it. Dropping a single line of # a wrapped paragraph leaves the paragraph there, one line shorter, and the # object count unchanged: the first version of this fixture did that and the # check correctly said nothing. awk ' BEGIN { state = 0 } state == 0 && /^[A-Za-z]/ && !/^[0-9A-D]~/ && !/^:[A-D]~/ && !/^%/ && !/^@/ \ { state = 1; next } state == 1 && /^[[:space:]]*$/ { state = 2; next } state == 1 { next } { print } ' "$TARGET" > "$TARGET.new" && mv "$TARGET.new" "$TARGET" set +e $SPINE_BIN --show-abstraction --skip-output \ --output="$OUT_DIR/broken-out" "$BROKEN/live-manual" \ > "$OUT_DIR/broken.out" 2> "$OUT_DIR/broken.err" BROKEN_RC=$? set -e if [ "$BROKEN_RC" -ne 0 ]; then fail "the run over the broken copy exited $BROKEN_RC; a warning must not fail a run" head -5 "$OUT_DIR/broken.err" fi if ! grep -q "^WARNING ocn alignment: live-manual$" "$OUT_DIR/broken.err"; then fail "the removed paragraph was not reported" head -5 "$OUT_DIR/broken.err" | sed 's/^/ /' fi if ! grep -q "^ \[de\] differs from \[en\]$" "$OUT_DIR/broken.err"; then fail "de not reported as differing from en" fi if ! grep -q "numbered objects: en .*, de .* (-1)" "$OUT_DIR/broken.err"; then fail "de's object count not reported as one short" grep "numbered objects" "$OUT_DIR/broken.err" | sed 's/^/ /' fi # only the language that was broken n_langs=$(grep -c "^ \[.*\] differs from " "$OUT_DIR/broken.err" || true) if [ "$n_langs" != "1" ]; then fail "$n_langs languages reported on the broken copy, expected 1 (de)" grep "^ \[.*\] differs from " "$OUT_DIR/broken.err" | sed 's/^/ /' fi # and --strict makes that a failed run set +e $SPINE_BIN --show-abstraction --skip-output --strict \ --output="$OUT_DIR/broken-strict" "$BROKEN/live-manual" \ > "$OUT_DIR/broken-strict.out" 2> "$OUT_DIR/broken-strict.err" STRICT_RC=$? set -e if [ "$STRICT_RC" -eq 0 ]; then fail "--strict exited 0 on a document whose languages diverge" fi rm -rf "$OUT_DIR" if [ "$FAILURES" -eq 0 ]; then echo "PASS: the sample set is aligned, a broken copy is reported, --strict fails" exit 0 else echo "FAIL: $FAILURES check(s)" exit 1 fi