diff options
Diffstat (limited to 'test/test_rite_ef.ml')
| -rw-r--r-- | test/test_rite_ef.ml | 53 |
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 |
