aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-27 00:38:40 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-27 00:38:40 +0200
commite26d7da141f7985fadc53d8399a69dbaa1153c94 (patch)
tree38737b17dbf71faf9c357d8d2098e8f3f42aab0b /test
parent6e62e499aed1c5a31a18bcf5e9eaa7f2b0c4ff2e (diff)
downloadcolitur-e26d7da141f7985fadc53d8399a69dbaa1153c94.tar.gz
colitur-e26d7da141f7985fadc53d8399a69dbaa1153c94.zip
fix(of): correct the Annunciation's transfer_target slug, dead Rule 1
precedence_of.ml's transfer_target Rule 1 (Normae n. 60's fixed Easter+8 destination for the Annunciation falling in Holy Week) keyed off "of-annunciation", a placeholder that never matched the real shipped entry's own slug ("annunciation-of-the-lord", data/of/calendar-2002.sexp). Rule 1 was therefore dead code: it could only ever fire against test_precedence_of.ml's own synthetic candidate, which happened to carry the identical placeholder. Output was nonetheless correct on shipped data (latent, not live): Rule 3's general forward search structurally converges on the same Easter+8 target, because the Easter Octave occupies exactly Easter+1..+7 at band 20 and the 3-9 April window carries only memorials on the universal calendar. The exposure is an overlay placing a proper solemnity (band 40) or proper feast (band 80) anywhere in 3-9 April, where Rule 3 would diverge from Rule 1's fixed destination and Rule 1 would silently fail to override it. Fixed the slug, and updated the existing Rule-1 tests' own synthetic candidate to the real slug so they keep exercising Rule 1 rather than Rule 3's coincidental agreement. Added a test that tells the two rules apart rather than only checking the output they happen to agree on: it rigs the occupant callback to occupy Easter+8 with a synthetic Tabula-entry-3 candidate, confirms (via a control case using a different solemnity) that the rig genuinely forces Rule 3's search past that date, then shows the real shipped Annunciation still lands on Easter+8 despite the block -- only explicable by Rule 1 firing, not by Rule 3 happening to agree.
Diffstat (limited to 'test')
-rw-r--r--test/test_precedence_of.ml71
1 files changed, 70 insertions, 1 deletions
diff --git a/test/test_precedence_of.ml b/test/test_precedence_of.ml
index e2e8540..01ba92c 100644
--- a/test/test_precedence_of.ml
+++ b/test/test_precedence_of.ml
@@ -375,8 +375,18 @@ let test_vigil_feast_is_always_none () =
rather than a hand-made fiction. *)
let occupant d = (Rite_of.Temporal_of.temporal d).Temporal.office
+(* W6 (of-known-wrongs, 2026-08-26): this used to carry the placeholder slug
+ "of-annunciation" -- the very bug precedence_of.ml's own [annunciation_
+ slug] carried, so this synthetic candidate coincidentally matched the
+ bug rather than testing against it. Now the REAL shipped slug
+ (data/of/calendar-2002.sexp: "annunciation-of-the-lord"), so the tests
+ below that use it (Rule 1/n. 60) actually exercise Rule 1 against the
+ slug production code now checks -- see
+ [test_annunciation_rule1_actually_fires] below for the test that tells
+ "Rule 1 fired" apart from "Rule 3 happened to agree", which none of
+ these did before it. *)
let annunciation =
- mk ~subject:Subject.Lord ~slug:"of-annunciation" ~rank:Vocab_of.Sollemnitas
+ mk ~subject:Subject.Lord ~slug:"annunciation-of-the-lord" ~rank:Vocab_of.Sollemnitas
~origin:Precedence.Sanctoral ()
let iso s = Date.of_iso8601 s |> Result.get_ok
@@ -524,6 +534,62 @@ let test_all_souls_beats_an_ordinary_sunday () =
Alcotest.(check bool) "All Souls, not the Sunday, is observed" true
(resolution.Precedence.observed = all_souls_candidate)
+(* W6 (of-known-wrongs, 2026-08-26). [annunciation_slug] used to read
+ "of-annunciation", a placeholder that never matched the real shipped
+ entry -- Rule 1 (Normae n. 60's fixed Easter+8 destination) was DEAD
+ CODE, only ever exercised by this file's own synthetic candidate, which
+ happened to carry the identical placeholder. Every test above this one
+ proves nothing about whether Rule 1 fires against real data: they all
+ land on Easter+8, but Rule 3's general forward search converges on the
+ IDENTICAL date whenever the 3-9 April window is empty of anything at
+ Tabula entries 1-8 (true on the shipped universal calendar), so the
+ output is the same whichever rule actually answers.
+
+ This test tells the two apart. It loads the REAL shipped
+ "annunciation-of-the-lord" entry (not a synthetic reconstruction, the
+ same discipline [test_all_souls_beats_an_ordinary_sunday] above uses)
+ and RIGS the [occupant] callback to occupy Easter+8 itself with a
+ synthetic Tabula-entry-3 candidate (band 30, well inside entries 1-8).
+ Rule 3's search, if it were what answered, would have to step past that
+ occupied day onto Easter+9 -- confirmed by a CONTROL case, a different
+ solemnity on the same origin and the same rig, which can only reach
+ Rule 3 (it is neither the Annunciation nor St Joseph on Palm Sunday) and
+ does indeed land on Easter+9. Rule 1's own fixed computation never
+ consults [occupant] at all, so the rig has no effect on it: the real
+ Annunciation still landing on Easter+8 DESPITE the block is something
+ only Rule 1 firing can explain. *)
+let test_annunciation_rule1_actually_fires () =
+ let path = "../data/of/calendar-2002.sexp" in
+ let l =
+ match Colitur_kernel.Layer.load Vocab_of.rank_of_sexp path with
+ | Ok l -> l
+ | Error e -> Alcotest.failf "%s: failed to load: %s" path e
+ in
+ let annunciation_real =
+ match Colitur_kernel.Layer.find l (Slug.of_string_exn "annunciation-of-the-lord") with
+ | Some e -> { Precedence.cel = e.Colitur_kernel.Layer.cel; origin = Precedence.Sanctoral }
+ | None -> Alcotest.fail "\"annunciation-of-the-lord\" not found in the shipped calendar"
+ in
+ (* 2027: Easter 28 March, so 25 March is Holy Thursday -- inside Holy
+ Week -- and Easter+8 is 5 April, the date this rig occupies. *)
+ let origin = iso "2027-03-25" in
+ let blocked = iso "2027-04-05" in
+ let rigged d =
+ if Date.compare d blocked = 0 then
+ mk_cel ~slug:"of-w6-synthetic-blocker" ~rank:Vocab_of.Sollemnitas ()
+ else occupant d
+ in
+ let control =
+ mk ~slug:"of-w6-control" ~rank:Vocab_of.Sollemnitas ~origin:Precedence.Sanctoral () in
+ let control_target = Rite_of.Precedence_of.transfer_target control origin rigged in
+ Alcotest.(check string)
+ "control (not the Annunciation, not St Joseph): the rig really blocks -- pushed past 5 April to 6 April"
+ "2027-04-06" (Date.to_iso8601 control_target);
+ let target = Rite_of.Precedence_of.transfer_target annunciation_real origin rigged in
+ Alcotest.(check string)
+ "the REAL shipped Annunciation still lands on Easter+8 despite the block -- Rule 1, not Rule 3, fired"
+ "2027-04-05" (Date.to_iso8601 target)
+
(* W3 (of-known-wrongs, 2026-08-26). Mary, Mother of the Church (Easter+50)
and a fixed obligatory memorial (e.g. Anthony of Padua, 13 June) both
used to band at Tabula III.10 (100) whenever they coincide -- a tie
@@ -605,6 +671,9 @@ let suite =
"fix round 2: shipped All Souls beats an ordinary per-annum Sunday (2025-11-02)" `Quick
test_all_souls_beats_an_ordinary_sunday;
Alcotest.test_case
+ "W6: the REAL shipped Annunciation slug makes Rule 1 fire (not merely agree with Rule 3)" `Quick
+ test_annunciation_rule1_actually_fires;
+ Alcotest.test_case
"W3: a movable BVM obligatory memorial beats a fixed one, per the CDWDS's 24 March 2018 \
Notification" `Quick
test_movable_bvm_memorial_beats_a_fixed_one ]