summaryrefslogtreecommitdiff
path: root/test/test_mass_formulary.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-22 13:48:08 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-22 13:48:08 +0200
commit94ad73cf74d7f1cf02913e2f462c01028a8ef4b4 (patch)
tree6b184dc0563f8eb43867ca4f8060230f21dedc47 /test/test_mass_formulary.ml
parentff7fa965d68631b5caac771d6db3a0f2110cb5dd (diff)
downloadcolitur-94ad73cf74d7f1cf02913e2f462c01028a8ef4b4.tar.gz
colitur-94ad73cf74d7f1cf02913e2f462c01028a8ef4b4.zip
fix(kernel): Mass_formulary.t.said is honestly optional -- was false for Votive
The .mli promised said is "the slug whose Mass is said". For Votive (RG 78/309(a), the Saturday votive Mass of Our Lady) it was set to the day's own ferial slug -- whose Mass is exactly the one NOT said. A consumer joining rubrics to readings on that slug would silently get the wrong Mass: 2026-01-03 reports ef-christmas-1-saturday, which has zero entries in data/ef/lectionary.sexp, because the citations actually come from bvm_saturday_citations, a season-keyed function with no slug of its own anywhere in the shipped data. Chose the type-honest fix over the interim documentation one: said is now Slug.t option, None exactly for Votive, because there is genuinely no slug in the shipped data this field could report for that one source. Adding real ids for the five seasonal BVM Masses (the reviewer's first option) is out of scope -- a data restructuring this round explicitly does not carry. Threading the office slug through a second field was considered and rejected as redundant: the day's own office is already available on the same Liturgical_day.t via observed.slug, which every caller already has in scope regardless of via, so said does not need to duplicate it. colitur rubrics stays byte-identical: rubrics_line already has d.observed in scope and falls back to its slug when said is None, printing the exact value it always printed for a Votive row (verified directly, diffed against pre-fix output across four years). colitur day/readings are unaffected (neither reads Mass_formulary at all). colitur emit --format sexp's pretty-printed line count for 2027 moved 9011 -> 9025: every day's formulary record widened by said's own extra option wrapping, and to_string_hum wraps by column width. Cosmetic only, diffed line by line to confirm every change is this shape or a consequent wrap shift; recorded in test/cli.t alongside the 476(f) note it now sits next to.
Diffstat (limited to 'test/test_mass_formulary.ml')
-rw-r--r--test/test_mass_formulary.ml16
1 files changed, 14 insertions, 2 deletions
diff --git a/test/test_mass_formulary.ml b/test/test_mass_formulary.ml
index 824e0c7..1316e47 100644
--- a/test/test_mass_formulary.ml
+++ b/test/test_mass_formulary.ml
@@ -4,9 +4,19 @@ module Slug = Colitur_kernel.Slug
let slug s = Slug.of_string_exn s
let test_round_trips_through_sexp () =
- let f = { MF.said = slug "ef-time-after-pentecost-sunday-9"; via = MF.Preceding_sunday } in
+ let f = { MF.said = Some (slug "ef-time-after-pentecost-sunday-9"); via = MF.Preceding_sunday } in
let f' = MF.t_of_sexp (MF.sexp_of_t f) in
- Alcotest.(check string) "slug survives" (Slug.to_string f.MF.said) (Slug.to_string f'.MF.said);
+ Alcotest.(check (option string)) "slug survives"
+ (Option.map Slug.to_string f.MF.said) (Option.map Slug.to_string f'.MF.said);
+ Alcotest.(check bool) "source survives" true (f.MF.via = f'.MF.via)
+
+(* [said] is [None] exactly for {!MF.Votive} -- see the .mli's own citation.
+ Round-tripped separately so the [None] case has its own witness, not only
+ inferred from the [Some] case above. *)
+let test_none_said_round_trips_through_sexp () =
+ let f = { MF.said = None; via = MF.Votive } in
+ let f' = MF.t_of_sexp (MF.sexp_of_t f) in
+ Alcotest.(check bool) "said stays None" true (f'.MF.said = None);
Alcotest.(check bool) "source survives" true (f.MF.via = f'.MF.via)
(* [to_string] is what an ordo line shows. It names the SOURCE, not the slug,
@@ -25,5 +35,7 @@ let test_to_string_names_the_source () =
let suite =
( "Mass_formulary",
[ Alcotest.test_case "sexp round-trips" `Quick test_round_trips_through_sexp;
+ Alcotest.test_case "sexp round-trips, said = None (Votive)" `Quick
+ test_none_said_round_trips_through_sexp;
Alcotest.test_case "source_to_string names each source" `Quick
test_to_string_names_the_source ] )