aboutsummaryrefslogtreecommitdiff
path: root/test/test_rite_ef.ml
blob: 7b6071858d9b88e70e36215633d45d7f28d0edda (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(* Coordinator review (Task 11 fix round): integration tests wiring
   [Rite_ef.context] together with the REAL data/ef/sanctoral.sexp +
   data/ef/adjustments.sexp through [Colitur_kernel.Calendar] -- the same
   pipeline `colitur day` uses, proven here at the OCaml level. *)

module Cal = Colitur_kernel.Calendar
module Layer = Colitur_kernel.Layer
module Overlay = Colitur_kernel.Overlay
module LD = Colitur_kernel.Liturgical_day
module Slug = Colitur_kernel.Slug
module Date = Colitur_kernel.Date
module Date_spec = Colitur_kernel.Date_spec
module Cel = Colitur_kernel.Celebration
module Colour = Colitur_kernel.Colour
module V = Rite_ef.Vocab_ef

(* Relative to this test's own build directory (_build/default/test/), same
   convention test_sanctoral_ef.ml uses -- test/dune declares both as deps
   of the (test ...) stanza. *)
let sanctoral_path = "../data/ef/sanctoral.sexp"
let adjustments_path = "../data/ef/adjustments.sexp"

let real_layer () =
  let layer =
    match Layer.load V.rank_of_sexp sanctoral_path with
    | Ok l -> l
    | Error e -> Alcotest.failf "%s: failed to load: %s" sanctoral_path e
  in
  let overlay =
    match Overlay.load V.rank_of_sexp adjustments_path with
    | Ok o -> o
    | Error e -> Alcotest.failf "%s: failed to load: %s" adjustments_path e
  in
  let layer, diagnostics = Overlay.apply layer overlay in
  Alcotest.(check (list string)) "the committed overlay applies cleanly, no diagnostics" []
    (List.map Overlay.diagnostic_to_string diagnostics);
  layer

let slug_of (c : V.rank Cel.t) = Slug.to_string c.Cel.slug

(* Coordinator review, finding 2, reproduced through the project's OWN
   extension path (an overlay), the same way the reviewer found it: adding
   an I-class feast on 25 December (competing against, and losing to, the
   real Nativity) forces an RG 96 search starting 26 December -- which, with
   the real sanctoral data (Stephen/John/the Innocents, all II class) plus
   the temporal cycle's own Nativity-octave-day entries (29-31 Dec, also II
   class), is blocking every single day through 31 December 9999. Before the
   domain-ceiling fix this raised (Computus: year 10000 out of range);
   confirmed by mutation-testing at the precedence_ef.ml unit level (see the
   task report) -- this is the same defect reproduced end to end, through
   Calendar, with real data, exactly as the review found it. *)
let test_transfer_search_does_not_raise_at_domain_ceiling () =
  let layer = real_layer () in
  let impeding_entry : V.rank Layer.entry =
    { Layer.date = (match Date_spec.fixed ~month:12 ~day:25 with Ok d -> d | Error e -> failwith e);
      cel =
        Cel.make ~slug:(Slug.of_string_exn "test-domain-ceiling-impeder") ~rank:V.Class1
          ~colour:Colour.White ~layer:Rite_ef.Precedence_ef.universal_layer () }
  in
  let overlay : V.rank Overlay.t =
    { Overlay.id = "test-domain-ceiling"; directives = [ Overlay.Add impeding_entry ] }
  in
  let layer, _diagnostics = Overlay.apply layer overlay in
  (* Must not raise -- the whole point of the fix. *)
  let days = Cal.year Rite_ef.context layer 9999 in
  Alcotest.(check bool) "year 9999 resolves without raising, even with an impeded Christmas Day"
    true (Array.length days > 0);
  let impeder_placed_or_recorded =
    Array.to_list days
    |> List.exists (fun d ->
           slug_of d.LD.observed = "test-domain-ceiling-impeder"
           || List.exists (fun (c, _) -> slug_of c = "test-domain-ceiling-impeder") d.LD.omitted)
  in
  Alcotest.(check bool) "the impeding candidate is accounted for (observed somewhere, or omitted \
                         with a recorded reason) -- never silently dropped"
    true impeder_placed_or_recorded

let suite =
  ( "Rite_ef (real data: overlay-in-effect, domain-ceiling)",
    [ Alcotest.test_case "RG96 search does not raise at the domain ceiling (real data)" `Quick
        test_transfer_search_does_not_raise_at_domain_ceiling ] )