aboutsummaryrefslogtreecommitdiff
path: root/test/test_rite_ef.ml
diff options
context:
space:
mode:
Diffstat (limited to 'test/test_rite_ef.ml')
-rw-r--r--test/test_rite_ef.ml53
1 files changed, 50 insertions, 3 deletions
diff --git a/test/test_rite_ef.ml b/test/test_rite_ef.ml
index 9a1e6d5..6cd8709 100644
--- a/test/test_rite_ef.ml
+++ b/test/test_rite_ef.ml
@@ -233,6 +233,21 @@ let sample_years =
let rec range a b = if a > b then [] else a :: range (a + 1) b in
range 2005 2050
+(* ef-major-litanies task: [major-litanies] (RG 80, Precedence_ef's own
+ [major_litanies_slug]) is a DELIBERATE, cited exception to this
+ property, not a bug to catch -- RG 80's own text sends the Major
+ Litanies to "the following Tuesday" unconditionally in a transfer year,
+ which is always Easter+2, squarely inside [Easter, Easter+7]
+ (precedence_ef.ml's own [transfer_target] Litanies branch has the full
+ citation and the "why not the general RG96 search" argument). Every
+ OTHER slug this rite ever transfers is still held to the original
+ property below: RG 96's general walk (and its own named Annunciation
+ exception) is what this property actually protects, and neither of
+ those two mechanisms is exempted here -- only this one rite-cited,
+ hand-verified exception, matched by NAME so a future regression in some
+ OTHER slug cannot silently hide behind this exemption. *)
+let is_major_litanies_slug slug = String.equal slug PE.major_litanies_slug
+
(* Property 1: no day in the resolved output, across the whole sample, is
EVER a transfer's landing point inside [Easter, Easter+7] -- checked two
ways. [transferred_out]'s own recorded target is what [transfer_target]
@@ -248,7 +263,7 @@ let test_no_transfer_lands_in_easter_octave () =
Array.iter
(fun (d : (V.season, V.rank) LD.t) ->
(match d.LD.transferred_in with
- | Some c when in_easter_octave d.LD.date ->
+ | Some c when in_easter_octave d.LD.date && not (is_major_litanies_slug (slug_of c)) ->
violations :=
(Printf.sprintf "%s transferred_in on %s (Easter+%d)" (slug_of c)
(Date.to_iso8601 d.LD.date) (easter_offset d.LD.date))
@@ -256,7 +271,7 @@ let test_no_transfer_lands_in_easter_octave () =
| _ -> ());
List.iter
(fun (c, target) ->
- if in_easter_octave target then
+ if in_easter_octave target && not (is_major_litanies_slug (slug_of c)) then
violations :=
Printf.sprintf "%s transferred_out from %s to %s (Easter+%d)" (slug_of c)
(Date.to_iso8601 d.LD.date) (Date.to_iso8601 target) (easter_offset target)
@@ -265,7 +280,37 @@ let test_no_transfer_lands_in_easter_octave () =
days)
sample_years;
Alcotest.(check (list string))
- "no day in [Easter, Easter+7] is ever a transfer's target, 2005-2050" [] (List.rev !violations)
+ "no day (other than the RG80-cited Major Litanies exception) in [Easter, Easter+7] is ever a transfer's \
+ target, 2005-2050" []
+ (List.rev !violations)
+
+(* The positive contrast to the property above: RG 80's own exception DOES
+ fire, exactly twice in the 2005-2050 sample (register: 194/8417 domain-
+ wide trigger years; this task's own report has the full count), both
+ landing on Easter+2 as RG 80's text requires -- proving the exemption
+ above is not merely masking an absent case. 2011 (Easter Monday = 25
+ April, Easter = 24 April) and 2038 (Easter Sunday = 25 April) are this
+ file's own worked examples (precedence_ef.ml's [major_litanies_slug]
+ citation). *)
+let test_major_litanies_transfers_inside_easter_octave_exactly_when_rg80_requires () =
+ let layer = real_layer () in
+ let landings = ref [] in
+ List.iter
+ (fun y ->
+ let days = Cal.year Rite_ef.context layer y in
+ Array.iter
+ (fun (d : (V.season, V.rank) LD.t) ->
+ List.iter
+ (fun (c, target) ->
+ if is_major_litanies_slug (slug_of c) then
+ landings := (Date.to_iso8601 d.LD.date, Date.to_iso8601 target) :: !landings)
+ d.LD.transferred_out)
+ days)
+ sample_years;
+ Alcotest.(check (list (pair string string)))
+ "RG80 fires exactly twice in 2005-2050, both landing on Easter+2"
+ [ ("2011-04-25", "2011-04-26"); ("2038-04-25", "2038-04-27") ]
+ (List.rev !landings)
(* Property 2, and the LIVE case: [PE.transfer_target] called directly, with
an origin that genuinely starts the search INSIDE Holy Week -- Holy
@@ -381,6 +426,8 @@ let suite =
test_transfer_search_does_not_raise_at_domain_ceiling;
Alcotest.test_case "no transfer ever lands inside [Easter, Easter+7], 2005-2050" `Quick
test_no_transfer_lands_in_easter_octave;
+ Alcotest.test_case "RG80: the Major Litanies DO transfer inside the octave, exactly twice in 2005-2050"
+ `Quick test_major_litanies_transfers_inside_easter_octave_exactly_when_rg80_requires;
Alcotest.test_case "transfer_target skips the whole Easter octave from inside Holy Week" `Quick
test_transfer_target_skips_the_whole_easter_octave;
Alcotest.test_case "the search genuinely enters the window (not vacuous)" `Quick