diff options
Diffstat (limited to 'test/test_lang_coverage.ml')
| -rw-r--r-- | test/test_lang_coverage.ml | 111 |
1 files changed, 110 insertions, 1 deletions
diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml index d41f7e7..01aa9b7 100644 --- a/test/test_lang_coverage.ml +++ b/test/test_lang_coverage.ml @@ -295,6 +295,113 @@ let test_en_falls_back_to_latin () = Alcotest.(check bool) "empty table falls back to la.ini for a real slug" true (L.celebration chained "hilary" <> "hilary") +(* ------------------------------------------------------------------ *) +(* Fix wave I1 (final-review.md, 2026-08-25-colitur-of-phases-3-5): *) +(* --rite of used to resolve every displayed name through lang/la.ini, *) +(* EF's own independently-cited 1962-vocabulary table, keyed on slug. *) +(* 18 of 222 shipped OF sanctoral slugs happen to collide with an EF *) +(* slug there and all 18 printed the WRONG (1962) title -- e.g. *) +(* "S. Marthae Virg." (a title the 1969 reform deleted, and which also *) +(* silently overrode amendment 011's own rename) instead of *) +(* calendar-2002.sexp's own "Ss. Marthae, Mariae et Lazari". The other *) +(* 204 had no entry there at all and degraded to a bare slug, so none *) +(* of the 208 hand-verified titles Task 1 transcribed (cited against *) +(* the 2002 Missal) was ever reachable. *) +(* *) +(* bin/main.ml's [observed_name_of] now prefers the observed *) +(* celebration's OWN {!Colitur_kernel.Celebration.names}, falling back *) +(* to the lang table only on a miss. That priority order is duplicated *) +(* here -- bin/ and test/ are separate dune stanzas that do not share *) +(* code, the same reasoning test_support.ml's own header gives for why *) +(* it duplicates bin/main.ml's EF loaders rather than requiring them -- *) +(* and checked against every entry the REAL, assembled OF layer *) +(* actually carries (calendar-2002.sexp + all 13 amendments), not a *) +(* synthetic fixture. Walking {!Colitur_kernel.Layer.t.entries} directly *) +(* rather than a resolved calendar year: several of the 18 real *) +(* collisions (e.g. Margaret of Scotland, 16 November) never win the *) +(* alphabetical tie-break against a same-day rival in ANY year and so *) +(* are never the OBSERVED day at all -- the collision in the DATA is *) +(* real and load-bearing regardless (a future tie-break or Calendar *) +(* change could make her win one), so this test does not depend on *) +(* which slugs happen to be observed in any particular year range. *) +let of_base_path = "../data/of/calendar-2002.sexp" +let of_amendments_dir = "../data/of/amendments/" +let of_amendment_files = + [ "001-padre-pio.sexp"; "002-juan-diego-cuauhtlatoatzin.sexp"; "003-our-lady-of-guadalupe.sexp"; + "004-john-xxiii-john-paul-ii.sexp"; "005-mary-magdalene-rank.sexp"; "006-mary-mother-of-the-church.sexp"; + "007-paul-vi.sexp"; "008-our-lady-of-loreto.sexp"; "009-faustina-kowalska.sexp"; + "010-narek-avila-hildegard.sexp"; "011-martha-mary-lazarus.sexp"; "012-teresa-of-calcutta.sexp"; + "013-john-henry-newman.sexp" ] + +let of_layer () = + match Colitur_kernel.Layer.load Rite_of.Vocab_of.rank_of_sexp of_base_path with + | Error e -> Alcotest.failf "%s: %s" of_base_path e + | Ok base -> + let overlays = + List.map + (fun name -> + let path = of_amendments_dir ^ name in + match Colitur_kernel.Overlay.load Rite_of.Vocab_of.rank_of_sexp path with + | Ok o -> o + | Error e -> Alcotest.failf "%s: %s" path e) + of_amendment_files + in + let layer, diagnostics = Colitur_kernel.Overlay.merge base overlays in + if diagnostics <> [] then Alcotest.failf "unexpected OF amendment diagnostics on the shipped data"; + layer + +let la_lang = Colitur_kernel.Lang.of_string_exn "la" + +(* [observed_name_of]'s own resolution order (bin/main.ml), duplicated + rather than called -- see this section's own header. *) +let resolve_like_cli t (cel : Rite_of.Vocab_of.rank Colitur_kernel.Celebration.t) slug_s = + match Colitur_kernel.Names.find cel.Colitur_kernel.Celebration.names la_lang with + | Some n -> n + | None -> L.celebration t slug_s + +let test_of_names_win_over_ef_lang_table () = + let t = la () in + let layer = of_layer () in + let collisions = ref [] in + List.iter + (fun (e : _ Colitur_kernel.Layer.entry) -> + let cel = e.Colitur_kernel.Layer.cel in + let slug_s = Colitur_kernel.Slug.to_string cel.Colitur_kernel.Celebration.slug in + (* A miss returns the key itself (lang.mli's own TOTAL-lookup + contract): [L.celebration t slug_s <> slug_s] means la.ini really + does carry an entry for this OF slug -- a genuine collision, not + a hypothetical one. *) + if L.celebration t slug_s <> slug_s then collisions := slug_s :: !collisions) + layer.Colitur_kernel.Layer.entries; + (* Not asserting the collision count -- two independently-authored + vocabularies sharing a slug is expected (the whole reason this fix + exists) and not itself a defect; what matters, and what regresses + silently if [observed_name_of]'s priority order is ever reverted, is + what happens on EVERY one of them: *) + if !collisions = [] then + Alcotest.fail + "expected at least one real OF/EF slug collision (e.g. \"martha\") -- if this is now empty, \ + either lang/la.ini or calendar-2002.sexp changed and this test's own premise needs re-checking, \ + not silently passing on zero cases"; + List.iter + (fun slug_s -> + match Colitur_kernel.Layer.find layer (Colitur_kernel.Slug.of_string_exn slug_s) with + | None -> Alcotest.failf "%s: found in entries but not via Layer.find" slug_s + | Some (e : _ Colitur_kernel.Layer.entry) -> ( + let cel = e.Colitur_kernel.Layer.cel in + match Colitur_kernel.Names.find cel.Colitur_kernel.Celebration.names la_lang with + | None -> + Alcotest.failf + "%s: collides with lang/la.ini and calendar-2002.sexp carries NO own `la` name for it \ + -- would silently print EF's 1962 title (%s)" + slug_s (L.celebration t slug_s) + | Some own_name -> + Alcotest.(check string) + (Printf.sprintf "%s: resolves to the OF's own transcribed name, not lang/la.ini's EF one" + slug_s) + own_name (resolve_like_cli t cel slug_s))) + !collisions + let suite = ( "Lang/coverage", [ Alcotest.test_case "every slug has a Latin name" `Slow test_every_slug_has_a_latin_name; @@ -307,4 +414,6 @@ let suite = test_no_two_books_share_a_name; Alcotest.test_case "shipped styles round-trip" `Quick test_shipped_styles_round_trip; - Alcotest.test_case "en.ini falls back to Latin" `Quick test_en_falls_back_to_latin ] ) + Alcotest.test_case "en.ini falls back to Latin" `Quick test_en_falls_back_to_latin; + Alcotest.test_case "OF names win over lang/la.ini on every real slug collision" `Quick + test_of_names_win_over_ef_lang_table ] ) |
