aboutsummaryrefslogtreecommitdiff
path: root/test/test_golden.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 20:15:42 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-13 20:15:42 +0200
commit84333a8c74ddb3988ad88398632ca5e1c7788e56 (patch)
tree08b998e72818752dad163343c98f70a78243e33e /test/test_golden.ml
parent3364e23fc49dc5b49576a97315326de030376e31 (diff)
downloadcolitur-84333a8c74ddb3988ad88398632ca5e1c7788e56.tar.gz
colitur-84333a8c74ddb3988ad88398632ca5e1c7788e56.zip
test(ef): commemoration, transfer, and privilege coverage for the Major Litanies
test_precedence_ef.ml: a privilege_cases row for RG109(f), deliberately rank Class4 so it cannot pass via the pre-existing "of a I-class day" branch by accident. Three disposition_cases rows: the two RG80 trigger shapes (Transfer, not Commemorate) and a synthetic third row proving the winner-slug guard is specific to the two named trigger days, not "any I-class winner". Two transfer_target unit tests, both using a pathological always-blocking occupant to prove no RG96 search runs at all for this candidate -- a much stronger witness than a cooperative occupant, which could pass by accident. test_golden.ml: three new pinned tests through the real data pipeline -- the ordinary case (2026-04-25, matches the oracle's own M5 date), the four Sunday-displacement years in 2005-2050 (2010, 2021, 2027, 2032, RG111(b)), and the Easter-Monday transfer shape (2011, complementing the Easter-Sunday shape already pinned by the existing 1666/2038 Easter-extreme tests, now widened to include the transfer and its target). test_rite_ef.ml: the existing "no transfer lands inside the Easter octave" property gets a named, cited exemption for the Major Litanies (RG80's own deliberate exception), plus a positive companion test asserting the exemption is not vacuous (exactly two landings in 2005-2050, both Easter+2). That companion test was written but never registered in its own suite list -- caught while mutation-testing the transfer (a mutation that should have failed it passed silently); fixed by registering it. Mutation-tested, each of the three parts separately (recorded in the task's own report): moving the data entity off 25 April fails 7 tests (golden + oracle only -- zero unit tests, since they build synthetic candidates); corrupting the transfer's winner-slug guard fails 6 (the two disposition_cases rows, 3 golden pins, and the newly-registered transfer-count test); flipping the privilege to Ordinary fails 9 (privilege_cases, the disposition SYNTHETIC row, the oracle's count pin, 5 golden pins, and the exhaustive Validate property sweep).
Diffstat (limited to 'test/test_golden.ml')
-rw-r--r--test/test_golden.ml138
1 files changed, 134 insertions, 4 deletions
diff --git a/test/test_golden.ml b/test/test_golden.ml
index fdfc01d..7b461bf 100644
--- a/test/test_golden.ml
+++ b/test/test_golden.ml
@@ -173,7 +173,18 @@ let test_easter_extreme_1598 () =
(* 1666: latest Gregorian Easter possible, 25 April -- hand-verified via
Gauss's algorithm (a = 13, b = 16, c = 66, ..., h = 29, l = 5, m = 0 ->
- 25 April). Same citations as 1598 above. *)
+ 25 April). Same citations as 1598 above.
+
+ ef-major-litanies task: 25 April = Easter Sunday is RG 80's own FIRST
+ trigger condition ("si vero eo die occurrit dominica Paschatis...
+ transferuntur in sequentem feriam III") -- this pin, already the
+ project's own hand-verified latest-Easter witness, now ALSO carries the
+ transfer this rule requires: [major-litanies] departs 25 April for
+ 27 April (Easter+2, "the following Tuesday" -- Precedence_ef.transfer_
+ target's own Litanies branch has the full citation). Nothing else about
+ this day changes: [observed]/[comms]/[in] are exactly as before,
+ proving the Litanies departure is additive, not disruptive, to the
+ day Easter itself owns outright. *)
let test_easter_extreme_1666 () =
check ~msg:"1666-04-24 Holy Saturday: still Passiontide, violet (RG 128)" 1666 4 24
"1666-04-24 saturday season=passiontide week=2 slug=ef-passiontide-2-saturday rank=class-1 colour=violet subject=lord \
@@ -181,7 +192,21 @@ let test_easter_extreme_1666 () =
check ~msg:"1666-04-25 latest possible Easter (Gauss-verified): Paschaltide begins, white, class-1" 1666 4
25
"1666-04-25 sunday season=paschaltide week=1 slug=ef-easter-sunday rank=class-1 colour=white subject=temporal name_la=- comms=[] in=- \
- out=[]"
+ out=[major-litanies->1666-04-27]";
+ (* The transfer's own target, positively pinned (not merely inferred from
+ [out] above): an ordinary Easter-octave Tuesday, I class, white (RG
+ 119 -- white "a Missa Vigiliae paschalis usque ad Missam vigiliae
+ Pentecostis"), with the Litanies as its own sole, privileged
+ commemoration (RG 109(f); RG 111(a), "I class: none save one
+ privileged" -- {!PE.admit}'s own [Class1] case). No [transferred_in]
+ printed: [Liturgical_day.transferred_in] only ever names a candidate
+ that went on to WIN the day (calendar.ml's own [build_day]), and the
+ Litanies structurally never can (RG 81, Commemoration_only) -- this is
+ the SAME asymmetry {!Colitur_kernel.Calendar}'s own [settled_at] fix
+ (this task) exists to get right on the OTHER side of the ledger. *)
+ check ~msg:"1666-04-27 Easter+2: the Litanies' own transfer target, commemorated and privileged" 1666 4 27
+ "1666-04-27 tuesday season=paschaltide week=1 slug=ef-easter-1-tuesday rank=class-1 colour=white subject=temporal \
+ name_la=- comms=[major-litanies:privileged] in=- out=[]"
(* 2038: the brief's "late modern case" -- Easter also 25 April (Gauss-
verified: a = 5, b = 20, c = 38, ..., h = 29, l = 5, m = 0 -> 25 April,
@@ -203,13 +228,24 @@ let test_easter_extreme_1666 () =
temporal-cycle-only test regardless (the two concerns -- Easter-extreme
arithmetic and a sanctoral occurrence rule -- stay separate pins even
though nothing forces that any more). *)
+(* ef-major-litanies task: 2038 is this file's own worked example for the
+ OTHER RG 80 trigger shape checked elsewhere in this task (Easter Monday
+ = 25 April, e.g. 2011) landing on the identical target (Easter+2) --
+ here Easter SUNDAY itself is 25 April, so the "following Tuesday" is
+ two days later, 27 April, not one; both shapes converge on Easter+2,
+ never on Easter+1 or Easter+3 (precedence_ef.ml's own [transfer_target]
+ Litanies branch has the full RG 80 citation and the arithmetic for
+ both shapes). *)
let test_easter_extreme_2038_late_modern () =
check ~msg:"2038-04-24 Holy Saturday: still Passiontide, violet (RG 128)" 2038 4 24
"2038-04-24 saturday season=passiontide week=2 slug=ef-passiontide-2-saturday rank=class-1 colour=violet subject=lord \
name_la=Sabbato sancto comms=[] in=- out=[]";
check ~msg:"2038-04-25 late-modern instance of the latest possible Easter (Gauss-verified)" 2038 4 25
"2038-04-25 sunday season=paschaltide week=1 slug=ef-easter-sunday rank=class-1 colour=white subject=temporal name_la=- comms=[] in=- \
- out=[]"
+ out=[major-litanies->2038-04-27]";
+ check ~msg:"2038-04-27 Easter+2: the Litanies' own transfer target, commemorated and privileged" 2038 4 27
+ "2038-04-27 tuesday season=paschaltide week=1 slug=ef-easter-1-tuesday rank=class-1 colour=white subject=temporal \
+ name_la=- comms=[major-litanies:privileged] in=- out=[]"
(* ------------------------------------------------------------------ *)
(* Annunciation transfer, 25 March inside Holy Week (register §4, RG 96
@@ -958,6 +994,91 @@ let test_bvm_saturday_excludes_mt_carmel_2033 () =
rank=class-4 colour=white subject=bvm name_la=Officium sanctae Mariae in sabbato comms=[] in=- out=[]"
(describe d)
+(* ------------------------------------------------------------------ *)
+(* RG 80/81/109(f), the Major Litanies (ef-major-litanies task). Every
+ date below independently derived from the primary text, not read off a
+ `colitur day` run first and rationalised (this file's own header, rule
+ 3): Easter's own date for each civil year comes from Computus (already
+ independently Gauss-cross-checked by this file's own extreme-year
+ pins), 25 April's Easter-offset and weekday follow arithmetically from
+ that, and the RULE applied at each offset (RG 80's transfer condition;
+ RG 91 entries 15/16 for the Sunday-vs-Mark band comparison; RG 111(b)'s
+ privilege-overrides-ordinary clause) is quoted at
+ Rite_ef.Precedence_ef's own [disposition]/[admit]/[transfer_target] and
+ at data/ef/expected-divergences-missalemeum.sexp's own M5/M20 entries,
+ which independently adjudicate the one substantive rubric question here
+ (WHO wins the Sunday's single slot) against the missalemeum oracle. *)
+(* ------------------------------------------------------------------ *)
+
+(* The ORDINARY case (~97.7% of years, register's own measurement): 25
+ April 2026 is a Saturday (independently checked via `date -d
+ 2026-04-25 +%A`, this file's own header rule 2), Easter+20 (Easter 2026
+ = 5 April, itself independently checked the same way against a
+ published 2026 Easter date). St Mark (II class, RG 91 entry 16) wins the day outright
+ over the ordinary Class4 Paschaltide feria (entry 28); the Litanies,
+ Commemoration_only, is the day's ONLY other candidate and is admitted
+ uncontested ({!Rite_ef.Precedence_ef.admit}'s [Class2, false] case: one
+ slot, table order alone, no rival). This is the SAME date and shape
+ data/ef/expected-divergences-missalemeum.sexp's own [M5] entry
+ adjudicates against the real missalemeum oracle (verdict colitur, a
+ naming-convention difference only -- "The Major Litanies" vs
+ missalemeum's own "Pro rogationibus"). *)
+let test_major_litanies_ordinary_2026 () =
+ check ~msg:"2026-04-25: St Mark observed outright (RG91 e16 > e28); the Major Litanies (RG80/109(f)) ride \
+ along uncontested" 2026 4 25
+ "2026-04-25 saturday season=paschaltide week=3 slug=mark rank=class-2 colour=red subject=saint name_la=- \
+ comms=[major-litanies:privileged] in=- out=[]"
+
+(* The FOUR Sunday-displacement years in 2005-2050 (this task's own
+ measurement, register): 25 April is a Sunday, so St Mark (entry 16, II
+ class) loses to it exactly as any other II-class feast would (entry 15
+ < entry 16), becoming an ordinary commemoration CANDIDATE rather than
+ the observed day -- and then loses the day's own single slot to the
+ Litanies (RG 111(b): "quæ tamen omittitur si commemoratio privilegiata
+ facienda sit" -- the ordinary de-festo-II-classis commemoration is
+ DROPPED once a privileged one is due). [omitted_has] on each date below
+ confirms Mark is genuinely reported dropped, not silently absent --
+ "omitted: admission limit reached", {!Precedence.resolve}'s own generic
+ reason for a candidate [disposition] admitted to the contest but
+ [admit] then cut. Two different generic Sunday slugs appear (week 4 in
+ 2010/2021, week 5 in 2027/2032) because Easter falls on a different
+ date in each pair -- neither is hand-picked, both are what
+ [Temporal_ef.sunday_slug] actually computes. *)
+let test_major_litanies_displaces_mark_on_ii_class_sunday () =
+ List.iter
+ (fun (y, week) ->
+ let d = fetch y 4 25 in
+ Alcotest.(check bool)
+ (Printf.sprintf "%d-04-25: St Mark is in [omitted] (RG111(b)'s privileged-commemoration override), not \
+ silently dropped" y)
+ true (omitted_has d "mark");
+ Alcotest.(check string)
+ (Printf.sprintf "%d-04-25: the Sunday observed (II class); ONLY the Litanies commemorated, Mark \
+ displaced (RG111(b))" y)
+ (Printf.sprintf
+ "%d-04-25 sunday season=paschaltide week=%d slug=ef-easter-sunday-%d rank=class-2 colour=white \
+ subject=temporal name_la=- comms=[major-litanies:privileged] in=- out=[]"
+ y week week)
+ (describe d))
+ [ (2010, 4); (2021, 4); (2027, 5); (2032, 5) ]
+
+(* The OTHER RG 80 trigger shape, complementing 1666/2038 above (Easter
+ Sunday itself = 25 April): here Easter MONDAY = 25 April (Easter = 24
+ April 2011, independently Gauss-derivable and already the domain's own
+ register-cited "Easter Monday" marker, [ef-easter-1-monday]). RG 80's
+ "following Tuesday" is one day later this time (26 April, not 27) --
+ both shapes converge on the SAME offset, Easter+2, never on a fixed
+ civil-date difference. *)
+let test_major_litanies_transfer_2011_easter_monday () =
+ check ~msg:"2011-04-25 Easter Monday (RG80's SECOND trigger): Litanies depart for the following Tuesday, \
+ 26 April" 2011 4 25
+ "2011-04-25 monday season=paschaltide week=1 slug=ef-easter-1-monday rank=class-1 colour=white \
+ subject=temporal name_la=- comms=[] in=- out=[major-litanies->2011-04-26]";
+ check ~msg:"2011-04-26 Easter+2: the Litanies land here, commemorated and privileged, exactly one day after \
+ origin (not two, unlike the Easter-Sunday shape)" 2011 4 26
+ "2011-04-26 tuesday season=paschaltide week=1 slug=ef-easter-1-tuesday rank=class-1 colour=white \
+ subject=temporal name_la=- comms=[major-litanies:privileged] in=- out=[]"
+
let suite =
( "golden pins (known-tricky years)",
[ Alcotest.test_case "Easter extreme: 1598 earliest (22 Mar, Gauss-verified)" `Quick
@@ -1026,5 +1147,14 @@ let suite =
Alcotest.test_case
"RG112(d), fix round 1 (F1): the BVM Saturday office excludes Mt Carmel's own commemoration \
(2033-07-16)"
- `Quick test_bvm_saturday_excludes_mt_carmel_2033
+ `Quick test_bvm_saturday_excludes_mt_carmel_2033;
+ Alcotest.test_case "RG80/109(f): the Major Litanies, ordinary year, St Mark wins outright (2026-04-25)"
+ `Quick test_major_litanies_ordinary_2026;
+ Alcotest.test_case
+ "RG111(b): the Major Litanies displace St Mark's own commemoration on a II-class Sunday (2010, 2021, \
+ 2027, 2032)"
+ `Quick test_major_litanies_displaces_mark_on_ii_class_sunday;
+ Alcotest.test_case
+ "RG80's second trigger: Easter Monday = 25 April, the Litanies transfer to Easter+2 (2011)" `Quick
+ test_major_litanies_transfer_2011_easter_monday
] )