aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/cli.t29
-rw-r--r--test/dune9
-rw-r--r--test/test_lectionary_of.ml80
3 files changed, 102 insertions, 16 deletions
diff --git a/test/cli.t b/test/cli.t
index f604872..00bbc21 100644
--- a/test/cli.t
+++ b/test/cli.t
@@ -578,10 +578,10 @@ error, exit 2, leaving stdout clean for whatever the caller was really trying
to capture.
$ colitur --help | head -1
- colitur -- deterministic liturgical calendar engine (Roman rite, 1962)
+ colitur -- deterministic liturgical calendar engine (Roman rite, EF 1962 and OF)
$ colitur -h | head -1
- colitur -- deterministic liturgical calendar engine (Roman rite, 1962)
+ colitur -- deterministic liturgical calendar engine (Roman rite, EF 1962 and OF)
$ colitur --help > /dev/null
$ colitur -h > /dev/null
@@ -601,21 +601,26 @@ is the check that catches help text drifting away from the dispatch:
$ for c in easter temporal day readings rubrics; do colitur $c 2026 > /dev/null || echo "$c FAILED"; done
`rubrics`' own field count drifted once already (Task 5 landed a fourth
-column, creed; --help's "output formats" section and its worked example
+column, creed; the documented "output formats" section and its worked example
still showed three, and stayed wrong for a whole review round because
-nothing here pinned the help BODY, only command dispatch above). This
-compares --help's own worked example against what `rubrics` actually
+nothing here pinned the documentation BODY, only command dispatch above). This
+compares the DOCUMENTED worked example against what `rubrics` actually
prints for the identical day, so the two cannot silently drift apart
-again in either direction:
+again in either direction.
- $ colitur --help | grep '^ rubrics date'
- rubrics date, formulary slug, source, creed, gloria, preface [name] -- TAB-separated
+The comparison reads the man page, not --help: --help was trimmed to one
+screen and now points at colitur(1) for every format, so this is where the
+worked example lives. The man page is named in test/dune's own cram deps for
+exactly this reason -- a cram sandbox holds only what that stanza lists.
- $ colitur --help | sed -n '/^ rubrics date/{n;p}'
- 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity[TAB]In Octava Nativitatis Domini
+ $ grep -c 'formulary\\-slug .TAB. source .TAB. creed' ../man/colitur.1
+ 1
+
+ $ sed 's/\\//g' ../man/colitur.1 | grep -o '2026-01-01 \[TAB\] ef-circumcision.*' | head -1
+ 2026-01-01 [TAB] ef-circumcision [TAB] own [TAB] true [TAB] true [TAB] nativity [TAB] In Octava Nativitatis Domini
- $ colitur rubrics 2026 | grep '^2026-01-01' | sed $'s/\t/[TAB]/g'
- 2026-01-01[TAB]ef-circumcision[TAB]own[TAB]true[TAB]true[TAB]nativity
+ $ colitur rubrics 2026 | grep '^2026-01-01' | sed $'s/\t/ [TAB] /g'
+ 2026-01-01 [TAB] ef-circumcision [TAB] own [TAB] true [TAB] true [TAB] nativity
--version prints the version alone, to standard output, exit 0. Deliberately
not embedded in the help text above: this pin would then have to be edited
diff --git a/test/dune b/test/dune
index 0a3ade6..85facc9 100644
--- a/test/dune
+++ b/test/dune
@@ -105,4 +105,11 @@
../schema/day-v1.json
; Same trap, same fix: Task 8's --sigla-tradition flag makes the CLI read
; this file, and a cram sandbox holds only what this stanza names.
- ../lang/traditions.ini))
+ ../lang/traditions.ini
+ ; The man page is a DEP, not a runtime file the binary reads: cli.t's own
+ ; rubrics anti-drift check compares the documented worked example against
+ ; what `rubrics` actually prints, and that documentation now lives here
+ ; rather than in --help (trimmed to one screen). The check exists because
+ ; this exact field list drifted once and stayed wrong for a whole review
+ ; round; moving the prose without moving the check would quietly retire it.
+ ../man/colitur.1))
diff --git a/test/test_lectionary_of.ml b/test/test_lectionary_of.ml
index dc02176..cbffdd2 100644
--- a/test/test_lectionary_of.ml
+++ b/test/test_lectionary_of.ml
@@ -201,7 +201,7 @@ let test_sha256_pinned () =
and test_citation_coverage_of.ml), and the header's "Epistle" wording
is fixed to "First". Re-derived the same way, same discipline. *)
Alcotest.(check string) "data/of/lectionary.sexp SHA-256"
- "788ddc6d2d783286b6e64882a5372ae213cd5462c887e68aa2bea22388cdb4f7" (sha256_of_file lectionary_path)
+ "aaa57bd7229bbd1fb3372fb9467251419885af6f02dbd19d328a6c410030868d" (sha256_of_file lectionary_path)
(* lectio's OWN of-lectionary.ini SHA-256, pinned inside data/of/
lectionary.sexp's own provenance header (tools/bootstrap_lectionary_of
@@ -216,7 +216,7 @@ let test_source_sha256_pinned_in_header () =
let n = in_channel_length ic in
let content = really_input_string ic n in
close_in ic;
- let needle = "SHA-256: f0b527aef58b93e6ccdfbeafe52b340ed2a9d7d72805bf5083e3da04b080123c" in
+ let needle = "SHA-256: 7b6c6a26abf222312c3000aeaae131887bbb1e2af3863c68a3e5ad005cd07ba9" in
let contains haystack needle =
let hl = String.length haystack and nl = String.length needle in
let rec go i = i + nl <= hl && (String.sub haystack i nl = needle || go (i + 1)) in
@@ -488,6 +488,77 @@ let test_christmas_date_keyed_no_drift () =
check_year 2024;
check_year 2025
+(* ------------------------------------------------------------------ *)
+(* In ORDINARY TIME the OF weekday Gospel does not depend on which year of
+ the two-year cycle is running: OLM n. 69 point 4 alternates the FIRST
+ reading between Year I and Year II and leaves the Gospel a single
+ one-year series. So for every [of-ordinary-time-<n>-<day>-i] there is an
+ [...-ii] whose Gospel reference is the SAME STRING, and a pair that
+ disagrees is a data defect rather than a liturgical fact.
+
+ This is deliberately scoped to Ordinary Time. The same sweep over the
+ whole file reports 17 further disagreeing pairs in [of-advent-3/4-*] and
+ [of-christmas-*] -- all of them CORRECT: those weekdays are keyed to the
+ calendar DATE (17-24 December, and the Christmas octave, OLM n. 69
+ point 3, the rule [date_keyed_slug] above implements), so their -i/-ii
+ entries describe two different dates rather than two years of one cycle.
+ An unscoped version of this test would report seventeen false positives
+ and would, correctly, be switched off by whoever next read it.
+
+ CLOSED (2026-08-28, same day it was opened). Six pairs violated this when
+ the test was written, every one the same transcription fault: a Year II
+ Gospel ending at verse 22 where the OLM ends it at 20. All six are now
+ corrected upstream in lectio's own internal/caldata/of-lectionary.ini and
+ this file regenerated from it, so the expected violation set is EMPTY and
+ the test asserts the invariant outright rather than pinning exceptions to
+ it. Four further corruptions the same exercise found -- three First
+ readings and of-advent-2-saturday's "Matthew 17:9a,10-135", a verse
+ Matthew 17 does not have -- are fixed in the same upstream commit but are
+ invisible to THIS check by construction: no I/II symmetry constrains a
+ First reading, and Advent has no year cycle. They were caught by comparing
+ against litcal instead, and the two SHA-256 pins above are what stop the
+ data regressing underneath either.
+
+ Corrections confirmed verbatim in the Latin OLM 1981: "Mc 1, 14-20",
+ "Mc 4, 1-20", "Mc 5, 1-20", "Mt 7, 15-20", "Mt 17, 14-20",
+ "Mt 18, 15-20". *)
+let known_year_ii_gospel_defects = []
+
+let test_ordinary_time_gospel_is_year_independent () =
+ let entries = Lectionary.entries (real_lectionary ()) in
+ let gospel_of cits =
+ match List.find_opt (fun c -> c.Colitur_kernel.Citation.part = Colitur_kernel.Citation.Gospel) cits with
+ | Some c -> Some c.Colitur_kernel.Citation.reference
+ | None -> None
+ in
+ let by_slug = List.map (fun (s, c) -> (Slug.to_string s, gospel_of c)) entries in
+ let find s = match List.assoc_opt s by_slug with Some g -> g | None -> None in
+ let has_prefix p s = String.length s >= String.length p && String.sub s 0 (String.length p) = p in
+ let has_suffix suf s =
+ String.length s >= String.length suf && String.sub s (String.length s - String.length suf) (String.length suf) = suf
+ in
+ let ordinary_time_stems =
+ List.filter_map
+ (fun (s, _) ->
+ if has_prefix "of-ordinary-time-" s && has_suffix "-i" s && not (has_suffix "-ii" s) then
+ Some (String.sub s 0 (String.length s - 2))
+ else None)
+ by_slug
+ in
+ let stems = List.sort_uniq compare ordinary_time_stems in
+ let violations =
+ List.filter
+ (fun stem ->
+ match (find (stem ^ "-i"), find (stem ^ "-ii")) with
+ | Some a, Some b -> a <> b
+ | _ -> false)
+ stems
+ in
+ Alcotest.(check bool) "the sweep actually found Ordinary Time pairs to check" true (List.length stems > 100);
+ Alcotest.(check (list string))
+ "Ordinary Time: Year I and Year II share one Gospel, with no exceptions"
+ known_year_ii_gospel_defects (List.sort compare violations)
+
let suite =
[ Alcotest.test_case "Sunday cycle table (OLM n.66, straddles Advent I)" `Quick test_sunday_cycle_table;
Alcotest.test_case "weekday cycle table (OLM n.69.4, straddles Advent I)" `Quick test_weekday_cycle_table;
@@ -504,5 +575,8 @@ let suite =
Alcotest.test_case "O-Antiphon date-keyed reading does not drift (17 December)" `Quick
test_o_antiphon_no_drift;
Alcotest.test_case "Christmas-season date-keyed reading does not drift (2 January)" `Quick
- test_christmas_date_keyed_no_drift
+ test_christmas_date_keyed_no_drift;
+ Alcotest.test_case
+ "Ordinary Time Gospel is year-independent (OLM n. 69.4)" `Quick
+ test_ordinary_time_gospel_is_year_independent
]