aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--org/tests_for_document_abstraction_shell_scripts.org435
-rwxr-xr-xtest/run-tests.sh9
-rwxr-xr-xtest/test-abstraction-db.sh8
-rwxr-xr-xtest/test-ocn-alignment.sh155
4 files changed, 472 insertions, 135 deletions
diff --git a/org/tests_for_document_abstraction_shell_scripts.org b/org/tests_for_document_abstraction_shell_scripts.org
index 0f41ca6..b4d71f8 100644
--- a/org/tests_for_document_abstraction_shell_scripts.org
+++ b/org/tests_for_document_abstraction_shell_scripts.org
@@ -45,7 +45,8 @@
# 2 test-abstraction-ssp-roundtrip.sh the .ssp can be read back whole
# 3 test-abstraction-db.sh the two serialisations agree
# 4 test-abstraction-db-roundtrip.sh the .db can be read back whole
-# 5 test-epub-validity.sh the epubs a reader can actually open
+# 5 test-ocn-alignment.sh the languages agree on their ocns
+# 6 test-epub-validity.sh the epubs a reader can actually open
#
# None of them calls another, and each can be run on its own. The order
# matters only for reading the result:
@@ -59,6 +60,11 @@
# - 3 and 4 generate both artefacts themselves and depend on nothing
# committed. Since the database is built from the .ssp, they are checks
# on the reader rather than on two independent writers.
+# - 5 is about the sample documents rather than about a serialisation: it
+# asserts that spine reports the two known divergences in live-manual's
+# translations and reports nothing about the other documents. It will
+# fail if those translations are mended, which is the right moment to
+# hear about it.
set -e
@@ -84,6 +90,7 @@ TESTS="test-abstraction-ssp.sh
test-abstraction-ssp-roundtrip.sh
test-abstraction-db.sh
test-abstraction-db-roundtrip.sh
+test-ocn-alignment.sh
test-epub-validity.sh"
PASSED=0
@@ -122,8 +129,8 @@ else
fi
#+END_SRC
-** ssp ocda abstraction
-*** document.ssp abstraction test/test-abstraction-ssp.sh
+** 1&2. ssp ocda abstraction
+*** 1. document.ssp abstraction test/test-abstraction-ssp.sh
#+HEADER: :tangle ../test/test-abstraction-ssp.sh
#+HEADER: :tangle-mode (identity #o755)
@@ -314,7 +321,7 @@ else
fi
#+END_SRC
-*** document.ssp abstraction test/test-abstraction-ssp-roundtrip.sh
+*** 2. document.ssp abstraction test/test-abstraction-ssp-roundtrip.sh
#+HEADER: :tangle ../test/test-abstraction-ssp-roundtrip.sh
#+HEADER: :tangle-mode (identity #o755)
@@ -404,8 +411,8 @@ else
fi
#+END_SRC
-** db ocda abstraction
-*** document db ocda test/test-abstraction-db.sh
+** 3&4. db ocda abstraction
+*** 3. document db ocda test/test-abstraction-db.sh
#+HEADER: :tangle ../test/test-abstraction-db.sh
#+HEADER: :tangle-mode (identity #o755)
@@ -646,7 +653,11 @@ for ssp in $(find "$OUT_DIR/pod" -name "*.ssp" 2>/dev/null | sort); do
done
# the header blocks: every @source/@meta/@make/@doc_has property in the .ssp
- # must be in the database under its own key, with the same value. this is
+ # must be in the database under its own key, with the same value. the three
+ # excluded keys are the database's own notes about the artefact rather than
+ # properties of the document: what it was built from (source.filename,
+ # source.ssp_digest) and how its languages compared once they had all been
+ # read (translation.ocn_aligned), which no single .ssp can state. this is
# what catches a header property that reaches one artefact and not the
# other, which a count of objects cannot see.
awk '
@@ -661,7 +672,7 @@ for ssp in $(find "$OUT_DIR/pod" -name "*.ssp" 2>/dev/null | sort); do
' "$ssp" | sort > "$OUT_DIR/.sspmeta.$$"
sqlite3 -separator "$(printf '\t')" "$db" \
"select key, value from metadata where doc_id=$did and key not in
- ('source.filename','source.ssp_digest');" \
+ ('source.filename','source.ssp_digest','translation.ocn_aligned');" \
2>/dev/null | sort > "$OUT_DIR/.dbmeta.$$"
if ! diff -q "$OUT_DIR/.sspmeta.$$" "$OUT_DIR/.dbmeta.$$" > /dev/null 2>&1; then
[ $doc_fail -eq 0 ] && echo "$base"
@@ -726,7 +737,7 @@ else
fi
#+END_SRC
*
-*** document db ocda test-abstraction-db-roundtrip.sh
+*** 4. document db ocda test-abstraction-db-roundtrip.sh
#+HEADER: :tangle ../test/test-abstraction-db-roundtrip.sh
#+HEADER: :tangle-mode (identity #o755)
@@ -868,6 +879,289 @@ else
fi
#+END_SRC
+** 5. test ocn alignment
+
+#+HEADER: :tangle ../test/test-ocn-alignment.sh
+#+HEADER: :tangle-mode (identity #o755)
+#+HEADER: :shebang "#!/usr/bin/env sh"
+#+BEGIN_SRC shell
+# test-ocn-alignment.sh
+#
+# The languages of a document share their object numbering, and spine warns
+# when they stop doing so. This checks that the warning appears where it
+# should and, just as importantly, nowhere else.
+#
+# The sample set is the fixture, and it is a good one because it contains
+# both answers:
+#
+# live-manual ten languages, two of which diverge.
+# ja has two fewer numbered objects than en. A missing
+# translation of a short paragraph; everything below it
+# is renumbered.
+# pl has the same count, but the object at ocn 313 is a
+# paragraph in en and a heading in pl. A heading given as
+# running text, or running text given as a heading.
+# everything else single language, or aligned. Silent.
+#
+# A check that only ever fires is as useless as one that never does, so the
+# silence over the other documents is asserted too.
+#
+# 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
+
+# what it said
+if ! grep -q "^WARNING ocn alignment: live-manual$" "$OUT_DIR/run.err"; then
+ fail "no ocn alignment warning for live-manual"
+fi
+if ! grep -q "^ \[ja\] differs from \[en\]$" "$OUT_DIR/run.err"; then
+ fail "ja not reported as differing from en"
+fi
+if ! grep -q "numbered objects: en 1019, ja 1017 (-2)" "$OUT_DIR/run.err"; then
+ fail "ja's object count difference not reported as -2"
+fi
+if ! grep -q "^ \[pl\] differs from \[en\]$" "$OUT_DIR/run.err"; then
+ fail "pl not reported as differing from en"
+fi
+if ! grep -q "ocn 313: para in en, heading:2 in pl" "$OUT_DIR/run.err"; then
+ fail "pl's substituted heading at ocn 313 not reported"
+fi
+
+# and what it did not say: exactly one document warned about, exactly two
+# languages of it
+n_docs=$(grep -c "^WARNING ocn alignment: " "$OUT_DIR/run.err" || true)
+if [ "$n_docs" != "1" ]; then
+ fail "$n_docs documents warned about, expected 1"
+ grep "^WARNING ocn alignment: " "$OUT_DIR/run.err" | sed 's/^/ /'
+fi
+n_langs=$(grep -c "^ \[.*\] differs from " "$OUT_DIR/run.err" || true)
+if [ "$n_langs" != "2" ]; then
+ fail "$n_langs languages reported, expected 2 (ja and pl)"
+ grep "^ \[.*\] differs from " "$OUT_DIR/run.err" | sed 's/^/ /'
+fi
+
+# --strict makes the same run fail
+set +e
+$SPINE_BIN --show-abstraction --skip-output --strict \
+ --output="$OUT_DIR/strict" "$SAMPLES_DIR"/live-manual \
+ > "$OUT_DIR/strict.out" 2> "$OUT_DIR/strict.err"
+STRICT_RC=$?
+set -e
+if [ "$STRICT_RC" -eq 0 ]; then
+ fail "--strict exited 0 on a document whose languages diverge"
+fi
+
+# and does not fail a document whose languages agree, or one that has only
+# the one language
+set +e
+$SPINE_BIN --show-abstraction --skip-output --strict \
+ --output="$OUT_DIR/strict-ok" "$SAMPLES_DIR"/the_wealth_of_networks.yochai_benkler \
+ > "$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 single language document"
+ head -5 "$OUT_DIR/strict-ok.err"
+fi
+
+rm -rf "$OUT_DIR"
+
+if [ "$FAILURES" -eq 0 ]; then
+ echo "PASS: ja and pl reported on live-manual, silent elsewhere, --strict fails"
+ exit 0
+else
+ echo "FAIL: $FAILURES check(s)"
+ exit 1
+fi
+#+END_SRC
+** 6. test epub validity
+
+#+HEADER: :tangle ../test/test-epub-validity.sh
+#+HEADER: :tangle-mode (identity #o755)
+#+HEADER: :shebang "#!/usr/bin/env sh"
+#+BEGIN_SRC shell
+# epubcheck over the sample set, as a regression guard.
+#
+# Every epub spine writes is checked with epubcheck. A *fatal* is never
+# acceptable: it means a reader cannot parse the file at all. Errors are
+# compared against a recorded allowance, so that the ones known to be
+# outstanding do not fail the run while any new one does.
+#
+# The allowance is deliberately a single number rather than a list of
+# messages: a list invites adding to it. When the number goes down, lower it
+# here in the same commit that lowers it in the output.
+#
+# Usage:
+# SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod \
+# ./test/test-epub-validity.sh ./bin/spine-ldc
+#
+# Exit codes:
+# 0 no fatals, and errors within the allowance
+# 1 a fatal, or more errors than allowed
+# 2 set-up problem (no $SpinePOD, no binary, no epubcheck, no samples)
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+SPINE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
+
+# What is known to be outstanding over the whole sample set. Both numbers are
+# a ceiling, so a regression fails and an improvement does not; lower them in
+# the commit that lowers the output, and say in that commit what went.
+#
+# There is no allowance for a fatal, and there must never be one. The last
+# one - the_public_domain, chapter_2: a bare url ending a footnote body
+# swallowed the "}~" close delimiter, so the note closed inside the link
+# markup and left an unbalanced </a> behind - was a url boundary defect in
+# the abstraction, and is fixed.
+#
+# No error is allowed either, and none is outstanding. Both numbers being
+# zero is the point: anything at all that epubcheck calls an error is a
+# regression, and there is no list to add to.
+#
+# No warning is outstanding either, though warnings are not counted here.
+FATALS_ALLOWED=${SpineEpubFatalsAllowed:-0}
+ERRORS_ALLOWED=${SpineEpubErrorsAllowed:-0}
+
+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
+SPINE_BIN="${1:-}"
+# find spine binary
+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
+if [ ! -d "$SAMPLES_DIR" ]; then
+ echo "ERROR: samples not found: $SAMPLES_DIR" >&2
+ exit 2
+fi
+if ! command -v epubcheck >/dev/null 2>&1; then
+ echo "ERROR: epubcheck not on PATH." >&2
+ echo " e.g. nix shell \"nixpkgs#epubcheck\" -c $0 $SPINE_BIN" >&2
+ exit 2
+fi
+
+echo "spine binary: $SPINE_BIN"
+echo "samples: $SAMPLES_DIR"
+
+OUT_DIR="$(mktemp -d)"
+trap 'rm -rf "$OUT_DIR"' EXIT
+
+echo "Generating epubs ..."
+"$SPINE_BIN" --epub --output="$OUT_DIR" "$SAMPLES_DIR"/* 2>&1 | tail -1
+
+FATALS=0
+ERRORS=0
+DOCS=0
+for f in $(find "$OUT_DIR" -name '*.epub' | sort); do
+ DOCS=$((DOCS + 1))
+ msg=$(epubcheck "$f" 2>&1 | grep -E '^Messages:' || true)
+ ff=$(echo "$msg" | sed -n 's/.*: \([0-9]*\) fatal.*/\1/p')
+ ee=$(echo "$msg" | sed -n 's/.*\/ \([0-9]*\) error.*/\1/p')
+ ff=${ff:-0}; ee=${ee:-0}
+ FATALS=$((FATALS + ff))
+ ERRORS=$((ERRORS + ee))
+ if [ "$ff" -gt 0 ]; then
+ echo " FATAL in $(basename "$f"): $ff"
+ epubcheck "$f" 2>&1 | grep -i 'FATAL' | head -3 | sed 's/^/ /'
+ fi
+done
+
+echo "checked $DOCS epubs: $FATALS fatal (allowed $FATALS_ALLOWED), $ERRORS errors (allowed $ERRORS_ALLOWED)"
+
+if [ "$FATALS" -gt "$FATALS_ALLOWED" ]; then
+ echo "FAIL: $FATALS fatal(s), more than the $FATALS_ALLOWED allowed;"
+ echo " a fatal means a reader cannot parse that file at all"
+ exit 1
+fi
+if [ "$ERRORS" -gt "$ERRORS_ALLOWED" ]; then
+ echo "FAIL: $ERRORS errors, more than the $ERRORS_ALLOWED allowed"
+ echo " if this is a deliberate change, say why and adjust ERRORS_ALLOWED"
+ exit 1
+fi
+echo "PASS: $FATALS fatal and $ERRORS errors, both within what is recorded"
+exit 0
+#+END_SRC
* collection search db + cgi form
** test search db schema
@@ -1317,126 +1611,3 @@ else
exit 1
fi
#+END_SRC
-
-** test epub validity
-
-#+HEADER: :tangle ../test/test-epub-validity.sh
-#+HEADER: :tangle-mode (identity #o755)
-#+HEADER: :shebang "#!/usr/bin/env sh"
-#+BEGIN_SRC shell
-# epubcheck over the sample set, as a regression guard.
-#
-# Every epub spine writes is checked with epubcheck. A *fatal* is never
-# acceptable: it means a reader cannot parse the file at all. Errors are
-# compared against a recorded allowance, so that the ones known to be
-# outstanding do not fail the run while any new one does.
-#
-# The allowance is deliberately a single number rather than a list of
-# messages: a list invites adding to it. When the number goes down, lower it
-# here in the same commit that lowers it in the output.
-#
-# Usage:
-# SpinePOD=../../markup/sisudoc-spine-samples/markup/pod-samples/pod \
-# ./test/test-epub-validity.sh ./bin/spine-ldc
-#
-# Exit codes:
-# 0 no fatals, and errors within the allowance
-# 1 a fatal, or more errors than allowed
-# 2 set-up problem (no $SpinePOD, no binary, no epubcheck, no samples)
-
-set -e
-
-SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
-SPINE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
-
-# What is known to be outstanding over the whole sample set. Both numbers are
-# a ceiling, so a regression fails and an improvement does not; lower them in
-# the commit that lowers the output, and say in that commit what went.
-#
-# There is no allowance for a fatal, and there must never be one. The last
-# one - the_public_domain, chapter_2: a bare url ending a footnote body
-# swallowed the "}~" close delimiter, so the note closed inside the link
-# markup and left an unbalanced </a> behind - was a url boundary defect in
-# the abstraction, and is fixed.
-#
-# No error is allowed either, and none is outstanding. Both numbers being
-# zero is the point: anything at all that epubcheck calls an error is a
-# regression, and there is no list to add to.
-#
-# No warning is outstanding either, though warnings are not counted here.
-FATALS_ALLOWED=${SpineEpubFatalsAllowed:-0}
-ERRORS_ALLOWED=${SpineEpubErrorsAllowed:-0}
-
-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
-SPINE_BIN="${1:-}"
-# find spine binary
-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
-if [ ! -d "$SAMPLES_DIR" ]; then
- echo "ERROR: samples not found: $SAMPLES_DIR" >&2
- exit 2
-fi
-if ! command -v epubcheck >/dev/null 2>&1; then
- echo "ERROR: epubcheck not on PATH." >&2
- echo " e.g. nix shell \"nixpkgs#epubcheck\" -c $0 $SPINE_BIN" >&2
- exit 2
-fi
-
-echo "spine binary: $SPINE_BIN"
-echo "samples: $SAMPLES_DIR"
-
-OUT_DIR="$(mktemp -d)"
-trap 'rm -rf "$OUT_DIR"' EXIT
-
-echo "Generating epubs ..."
-"$SPINE_BIN" --epub --output="$OUT_DIR" "$SAMPLES_DIR"/* 2>&1 | tail -1
-
-FATALS=0
-ERRORS=0
-DOCS=0
-for f in $(find "$OUT_DIR" -name '*.epub' | sort); do
- DOCS=$((DOCS + 1))
- msg=$(epubcheck "$f" 2>&1 | grep -E '^Messages:' || true)
- ff=$(echo "$msg" | sed -n 's/.*: \([0-9]*\) fatal.*/\1/p')
- ee=$(echo "$msg" | sed -n 's/.*\/ \([0-9]*\) error.*/\1/p')
- ff=${ff:-0}; ee=${ee:-0}
- FATALS=$((FATALS + ff))
- ERRORS=$((ERRORS + ee))
- if [ "$ff" -gt 0 ]; then
- echo " FATAL in $(basename "$f"): $ff"
- epubcheck "$f" 2>&1 | grep -i 'FATAL' | head -3 | sed 's/^/ /'
- fi
-done
-
-echo "checked $DOCS epubs: $FATALS fatal (allowed $FATALS_ALLOWED), $ERRORS errors (allowed $ERRORS_ALLOWED)"
-
-if [ "$FATALS" -gt "$FATALS_ALLOWED" ]; then
- echo "FAIL: $FATALS fatal(s), more than the $FATALS_ALLOWED allowed;"
- echo " a fatal means a reader cannot parse that file at all"
- exit 1
-fi
-if [ "$ERRORS" -gt "$ERRORS_ALLOWED" ]; then
- echo "FAIL: $ERRORS errors, more than the $ERRORS_ALLOWED allowed"
- echo " if this is a deliberate change, say why and adjust ERRORS_ALLOWED"
- exit 1
-fi
-echo "PASS: $FATALS fatal and $ERRORS errors, both within what is recorded"
-exit 0
-#+END_SRC
diff --git a/test/run-tests.sh b/test/run-tests.sh
index 2f27892..4d950dc 100755
--- a/test/run-tests.sh
+++ b/test/run-tests.sh
@@ -22,7 +22,8 @@
# 2 test-abstraction-ssp-roundtrip.sh the .ssp can be read back whole
# 3 test-abstraction-db.sh the two serialisations agree
# 4 test-abstraction-db-roundtrip.sh the .db can be read back whole
-# 5 test-epub-validity.sh the epubs a reader can actually open
+# 5 test-ocn-alignment.sh the languages agree on their ocns
+# 6 test-epub-validity.sh the epubs a reader can actually open
#
# None of them calls another, and each can be run on its own. The order
# matters only for reading the result:
@@ -36,6 +37,11 @@
# - 3 and 4 generate both artefacts themselves and depend on nothing
# committed. Since the database is built from the .ssp, they are checks
# on the reader rather than on two independent writers.
+# - 5 is about the sample documents rather than about a serialisation: it
+# asserts that spine reports the two known divergences in live-manual's
+# translations and reports nothing about the other documents. It will
+# fail if those translations are mended, which is the right moment to
+# hear about it.
set -e
@@ -61,6 +67,7 @@ TESTS="test-abstraction-ssp.sh
test-abstraction-ssp-roundtrip.sh
test-abstraction-db.sh
test-abstraction-db-roundtrip.sh
+test-ocn-alignment.sh
test-epub-validity.sh"
PASSED=0
diff --git a/test/test-abstraction-db.sh b/test/test-abstraction-db.sh
index 2fac414..78c27b9 100755
--- a/test/test-abstraction-db.sh
+++ b/test/test-abstraction-db.sh
@@ -234,7 +234,11 @@ for ssp in $(find "$OUT_DIR/pod" -name "*.ssp" 2>/dev/null | sort); do
done
# the header blocks: every @source/@meta/@make/@doc_has property in the .ssp
- # must be in the database under its own key, with the same value. this is
+ # must be in the database under its own key, with the same value. the three
+ # excluded keys are the database's own notes about the artefact rather than
+ # properties of the document: what it was built from (source.filename,
+ # source.ssp_digest) and how its languages compared once they had all been
+ # read (translation.ocn_aligned), which no single .ssp can state. this is
# what catches a header property that reaches one artefact and not the
# other, which a count of objects cannot see.
awk '
@@ -249,7 +253,7 @@ for ssp in $(find "$OUT_DIR/pod" -name "*.ssp" 2>/dev/null | sort); do
' "$ssp" | sort > "$OUT_DIR/.sspmeta.$$"
sqlite3 -separator "$(printf '\t')" "$db" \
"select key, value from metadata where doc_id=$did and key not in
- ('source.filename','source.ssp_digest');" \
+ ('source.filename','source.ssp_digest','translation.ocn_aligned');" \
2>/dev/null | sort > "$OUT_DIR/.dbmeta.$$"
if ! diff -q "$OUT_DIR/.sspmeta.$$" "$OUT_DIR/.dbmeta.$$" > /dev/null 2>&1; then
[ $doc_fail -eq 0 ] && echo "$base"
diff --git a/test/test-ocn-alignment.sh b/test/test-ocn-alignment.sh
new file mode 100755
index 0000000..f00a8ec
--- /dev/null
+++ b/test/test-ocn-alignment.sh
@@ -0,0 +1,155 @@
+#!/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 that the warning appears where it
+# should and, just as importantly, nowhere else.
+#
+# The sample set is the fixture, and it is a good one because it contains
+# both answers:
+#
+# live-manual ten languages, two of which diverge.
+# ja has two fewer numbered objects than en. A missing
+# translation of a short paragraph; everything below it
+# is renumbered.
+# pl has the same count, but the object at ocn 313 is a
+# paragraph in en and a heading in pl. A heading given as
+# running text, or running text given as a heading.
+# everything else single language, or aligned. Silent.
+#
+# A check that only ever fires is as useless as one that never does, so the
+# silence over the other documents is asserted too.
+#
+# 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
+
+# what it said
+if ! grep -q "^WARNING ocn alignment: live-manual$" "$OUT_DIR/run.err"; then
+ fail "no ocn alignment warning for live-manual"
+fi
+if ! grep -q "^ \[ja\] differs from \[en\]$" "$OUT_DIR/run.err"; then
+ fail "ja not reported as differing from en"
+fi
+if ! grep -q "numbered objects: en 1019, ja 1017 (-2)" "$OUT_DIR/run.err"; then
+ fail "ja's object count difference not reported as -2"
+fi
+if ! grep -q "^ \[pl\] differs from \[en\]$" "$OUT_DIR/run.err"; then
+ fail "pl not reported as differing from en"
+fi
+if ! grep -q "ocn 313: para in en, heading:2 in pl" "$OUT_DIR/run.err"; then
+ fail "pl's substituted heading at ocn 313 not reported"
+fi
+
+# and what it did not say: exactly one document warned about, exactly two
+# languages of it
+n_docs=$(grep -c "^WARNING ocn alignment: " "$OUT_DIR/run.err" || true)
+if [ "$n_docs" != "1" ]; then
+ fail "$n_docs documents warned about, expected 1"
+ grep "^WARNING ocn alignment: " "$OUT_DIR/run.err" | sed 's/^/ /'
+fi
+n_langs=$(grep -c "^ \[.*\] differs from " "$OUT_DIR/run.err" || true)
+if [ "$n_langs" != "2" ]; then
+ fail "$n_langs languages reported, expected 2 (ja and pl)"
+ grep "^ \[.*\] differs from " "$OUT_DIR/run.err" | sed 's/^/ /'
+fi
+
+# --strict makes the same run fail
+set +e
+$SPINE_BIN --show-abstraction --skip-output --strict \
+ --output="$OUT_DIR/strict" "$SAMPLES_DIR"/live-manual \
+ > "$OUT_DIR/strict.out" 2> "$OUT_DIR/strict.err"
+STRICT_RC=$?
+set -e
+if [ "$STRICT_RC" -eq 0 ]; then
+ fail "--strict exited 0 on a document whose languages diverge"
+fi
+
+# and does not fail a document whose languages agree, or one that has only
+# the one language
+set +e
+$SPINE_BIN --show-abstraction --skip-output --strict \
+ --output="$OUT_DIR/strict-ok" "$SAMPLES_DIR"/the_wealth_of_networks.yochai_benkler \
+ > "$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 single language document"
+ head -5 "$OUT_DIR/strict-ok.err"
+fi
+
+rm -rf "$OUT_DIR"
+
+if [ "$FAILURES" -eq 0 ]; then
+ echo "PASS: ja and pl reported on live-manual, silent elsewhere, --strict fails"
+ exit 0
+else
+ echo "FAIL: $FAILURES check(s)"
+ exit 1
+fi