aboutsummaryrefslogtreecommitdiff
path: root/test/cli.t
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-17 15:45:27 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-17 15:45:27 +0200
commitc06ebb7344b7f267c325b832632f7cd4e81939e7 (patch)
treec246bda5176d2add869e74be3a2e632e075ea97a /test/cli.t
parentcba04b3033f23b5c2515c9e648f2b83344716224 (diff)
downloadcolitur-c06ebb7344b7f267c325b832632f7cd4e81939e7.tar.gz
colitur-c06ebb7344b7f267c325b832632f7cd4e81939e7.zip
feat(cli): install the runtime data, and resolve it in three ways
`dune install` produced a colitur that could not run: the binary locates its data relative to its own path, nothing installed the four .sexp files anywhere, and an installed colitur exited 2 unable to read sanctoral.sexp. `dune build @install` produced an empty tree. data/dune installs the four RUNTIME files into <prefix>/share/colitur/ef. Deliberately not the two allow-lists: those describe where colitur and a comparison oracle disagree, are read only by the differential and oracle tests, and are meaningless to a running colitur -- installing them would ship an assertion about lectio's and missalemeum's behaviour as though it were calendar data. No glob, on purpose: a glob would silently start shipping them again the moment one was renamed. Resolution now probes rather than computing one path and hoping. An installed prefix is tried first, the build tree second, and a candidate counts only if sanctoral.sexp is actually readable inside it -- so a failed or half-removed install falls through to a working tree instead of shadowing it and failing later with a per-file error. COLITUR_DATA_DIR overrides both and NEVER falls through. This was the one real design question and the first version got it wrong: it treated the override as just another candidate, and a deliberately bogus value produced a full, plausible, entirely un-flagged year computed off the build tree. Someone who names a directory has stated an intent, and silently calendaring off a different one is the silent substitution this project refuses everywhere else. It is now exit 2 naming the directory. Verified end to end, not inferred: installed to a scratch prefix, then ran the binary from an unrelated cwd with no build tree near it, and confirmed 2038-03-06 still resolves Perpetua and Felicitas through the Common route. All four paths exercised -- build tree, valid override, bogus override, and an empty share/ falling through. Environment reads stay confined to bin/. The kernel's contract forbids them and nothing below the CLI learns where the data came from; the loaders take a path.
Diffstat (limited to 'test/cli.t')
-rw-r--r--test/cli.t20
1 files changed, 20 insertions, 0 deletions
diff --git a/test/cli.t b/test/cli.t
index 8de4591..288356c 100644
--- a/test/cli.t
+++ b/test/cli.t
@@ -191,3 +191,23 @@ A year outside the supported domain is rejected (exit 2):
$ colitur readings 1000
colitur: year 1000 out of range 1583..9999
[2]
+
+An explicit COLITUR_DATA_DIR that does not hold the data is an error (exit 2),
+never a silent fall-back to some other copy. A packager or operator who names
+a directory has stated an intent; quietly calendaring off a different one
+because theirs was wrong is the silent substitution this project refuses
+everywhere else. The first version of this resolution DID fall through, and a
+deliberately bogus value produced a full, plausible, entirely un-flagged year:
+
+ $ COLITUR_DATA_DIR=/nonexistent/xyz colitur readings 2026
+ colitur: COLITUR_DATA_DIR is set to /nonexistent/xyz, which contains no sanctoral.sexp
+ colitur: refusing to fall back to another data directory -- unset it, or point it at one
+ [2]
+
+An empty or half-populated installed directory is a different case and DOES
+fall through to the build tree: nobody stated an intent there, and a failed or
+partially removed install must not shadow a working tree and then fail later
+with a confusing per-file error. (Exercised directly in the task, by creating
+_build/default/share/colitur/ef and confirming the year still resolves; not
+reproduced here because the cram sandbox's own exe path makes the layout
+awkward to stage without asserting on dune internals.)