summaryrefslogtreecommitdiff
path: root/test/test_lectionary_ef.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-24 16:29:23 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-24 16:29:23 +0200
commit8a5da8756cf6b57aa36c01b71ce893f7967d3a29 (patch)
tree10873a692400fa25ce54c67ac9fc34d46af86272 /test/test_lectionary_ef.ml
parent4f87cbde4ee79ac96aa7ebfed105b3a5ec02be43 (diff)
parent73b15551804bb63ee0081005e2869d36afb54be2 (diff)
downloadcolitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.tar.gz
colitur-8a5da8756cf6b57aa36c01b71ce893f7967d3a29.zip
merge: celebrant Mass rubrics, and four rubrical corrections
colitur now prints what a real ordo prints for the Mass: which formulary is said and how it was reached, the Gloria, the Creed, the preface, and the commemorations with their Low-Mass/sung distinction. colitur rubrics joins day and readings. Four defects were found and fixed on the way, each by an external witness rather than by inspection: the Creed said at Requiem Masses (RG 476(f)), the missing bissextile shift of St Matthias and St Gabriel (2 041 leap years), Rogation Monday and Tuesday coloured violet in Paschaltide (RG 119(b)), and the ferias after the Ascension resuming the wrong Sunday's Mass rather than the Ascension's. Validation gained a sixth layer and then some: the preface is checked against three independent publishers over seven witness-years (FIUV, three LMS editions, three extraordinaryform.org editions), none of which shares the Divinum Officium -> missalemeum -> lectio lineage the older layers all descend from.
Diffstat (limited to 'test/test_lectionary_ef.ml')
-rw-r--r--test/test_lectionary_ef.ml91
1 files changed, 89 insertions, 2 deletions
diff --git a/test/test_lectionary_ef.ml b/test/test_lectionary_ef.ml
index d56d187..3e0880e 100644
--- a/test/test_lectionary_ef.ml
+++ b/test/test_lectionary_ef.ml
@@ -467,7 +467,7 @@ let test_step4_unreachable_commons_still_resolve () =
let for_saint s = Lectionary_ef.commons_for ~commons (Slug.of_string_exn s) in
let refs_of = function
| None -> [ "<no common>" ]
- | Some cs -> List.map (fun c -> c.Citation.reference) cs
+ | Some (_id, cs) -> List.map (fun c -> c.Citation.reference) cs
in
Alcotest.(check (list string))
"St Benedict (21 March), Common of Abbots"
@@ -580,6 +580,89 @@ let test_commons_load_rejects_bad_data () =
(Slug.of_string_exn "benedict")
= None)
+(* ---------------------------------------------------------------------- *)
+(* The formulary itself (Task 2): each step of the chain now reports HOW *)
+(* it resolved, not only what it resolved. One day per step, plus the RG *)
+(* 309(a) votive branch (fix round 1) -- the same dates this file already *)
+(* uses (and hand-verifies) elsewhere for the citations those days carry, *)
+(* so no new date needs independent checking. *)
+(* ---------------------------------------------------------------------- *)
+
+let formulary_cases =
+ [ (* step 1: a saint with his own proper -- same date as
+ [test_step1_proper_beats_any_common_john_of_god]. *)
+ (2038, 3, 8, Some "john-of-god", Colitur_kernel.Mass_formulary.Proper);
+ (* step 2: the day's own temporal slug -- same date as
+ [test_step2_lenten_feria_has_its_own], Monday of Lent I. *)
+ (2026, 2, 23, Some "ef-lent-1-monday", Colitur_kernel.Mass_formulary.Own_slug);
+ (* step 3: a feria resuming the preceding Sunday. The task brief's own
+ snippet pinned this date against week 9 ("ef-time-after-pentecost-
+ sunday-9"); running the real resolver against 2026 shows 3 August
+ 2026 is Monday of week 10, resuming 2 August's "...sunday-10" --
+ corrected per the brief's own "find the dates by running the current
+ binary if they drift" instruction. *)
+ (2026, 8, 3, Some "ef-time-after-pentecost-sunday-10",
+ Colitur_kernel.Mass_formulary.Preceding_sunday);
+ (* step 4: a saint sent to a Common -- same date as
+ [test_step4_commons_perpetua_and_felicity]; [said] is the Common's
+ OWN id (data/ef/commons.sexp), not the saint's slug. *)
+ (2038, 3, 6, Some "common-of-non-virgins-1", Colitur_kernel.Mass_formulary.Common);
+ (* Fix round 1 (coordinator review): the RG 309(a)/RG 78 Saturday votive
+ Mass of Our Lady, structurally reached between steps 4 and 2 (see
+ [readings]' own implementation comment) but tagged [Votive], not
+ [Own_slug] -- RG 431(e) ("in Missis votivis IV classis ... de B.
+ Maria Virg. quae in sabbato celebrantur") classifies this Mass, in
+ the Missal's own words, as a "Missa votiva", said in place of the
+ day's own office's Mass while the office (RG 78) itself is kept.
+ (CORRECTED, fix round 2: this previously also claimed the Latin Mass
+ Society Ordo witnesses the tag by printing "V" as an abbreviation for
+ "votive" on this day -- that was the coordinator's own misreading;
+ the Ordo's "I"-"V" are roman numerals naming which of the Missal's
+ five SEASONAL Masses is said, not the Mass's kind -- see
+ [readings]' own implementation comment for the full account.) 1 August
+ 2026 verified directly against the real resolver (`colitur day
+ 2026`), not trusted from a supplied date, given this session's own
+ drifted-pin history: a IV-class Saturday, "Officium sanctae Mariae in
+ sabbato", temporal slug [ef-time-after-pentecost-9-saturday].
+ (CORRECTED, whole-branch review fix round: [said] used to be
+ claimed "unaffected by the retag" and pinned to that same reused
+ ferial slug -- that was the defect this round fixed. [said] is
+ [None] here: the shipped data names no slug for the votive Mass
+ actually said, only for the office it replaces. The office slug
+ itself is checked separately, below, via [observed.slug], not
+ through [said] -- see {!Colitur_kernel.Mass_formulary.t}'s own
+ citation for why the two are no longer conflated.) *)
+ (2026, 8, 1, None, Colitur_kernel.Mass_formulary.Votive) ]
+
+let test_formulary_reports_its_source () =
+ List.iter
+ (fun (y, m, d, expected_slug, expected_via) ->
+ let day = day y m d in
+ match day.Colitur_kernel.Liturgical_day.formulary with
+ | None -> Alcotest.failf "%04d-%02d-%02d: no formulary" y m d
+ | Some f ->
+ Alcotest.(check (option string))
+ (Printf.sprintf "%04d-%02d-%02d slug" y m d)
+ expected_slug
+ (Option.map Colitur_kernel.Slug.to_string f.Colitur_kernel.Mass_formulary.said);
+ Alcotest.(check string)
+ (Printf.sprintf "%04d-%02d-%02d source" y m d)
+ (Colitur_kernel.Mass_formulary.source_to_string expected_via)
+ (Colitur_kernel.Mass_formulary.source_to_string
+ f.Colitur_kernel.Mass_formulary.via))
+ formulary_cases
+
+(* [said = None] on the Votive day above does not mean the office is lost --
+ {!Colitur_kernel.Mass_formulary.t}'s own citation says a caller reads it
+ off [observed.slug] instead, on the very same {!Colitur_kernel.
+ Liturgical_day.t}. Checked directly, not merely asserted: the same
+ 1 August 2026 date, same expected slug the old (pre-fix) [said] field
+ used to carry. *)
+let test_votive_office_slug_still_available_via_observed () =
+ let d = day 2026 8 1 in
+ Alcotest.(check string) "2026-08-01 observed slug" "ef-time-after-pentecost-9-saturday"
+ (Colitur_kernel.Slug.to_string d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug)
+
let suite =
[ ("step 1: sanctoral proper", `Quick, test_step1_sanctoral_proper);
("step 2: own temporal proper", `Quick, test_step2_lenten_feria_has_its_own);
@@ -618,4 +701,8 @@ let suite =
("the five propers no real year reaches are present", `Quick,
test_step4_unreachable_propers_are_present);
("Commons.load rejects the four silent-degradation defects", `Quick,
- test_commons_load_rejects_bad_data) ]
+ test_commons_load_rejects_bad_data);
+ ("the formulary reports its own source, one day per step", `Quick,
+ test_formulary_reports_its_source);
+ ("the Votive office slug is still available via observed, not said", `Quick,
+ test_votive_office_slug_still_available_via_observed) ]