aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 14:12:52 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 14:12:52 +0200
commitf00f7a66d073815249e94cec1b6ef10539d773e7 (patch)
tree81fe9cd2f9878c7113a9cdba658f5d646be2cb06 /test
parentd869a4410a88333d328358c723609577d32f3380 (diff)
downloadcolitur-f00f7a66d073815249e94cec1b6ef10539d773e7.tar.gz
colitur-f00f7a66d073815249e94cec1b6ef10539d773e7.zip
feat(lang): Latin temporal names from the Missal
Every entry is transcribed from the 1962 Missal's own propers headings in docs/research/LT.txt and cites where it came from; names constructed by following a neighbouring pattern are marked as such, so a reader can tell transcription from inference. The coverage test is the point of this commit. It walks every day of 2020-2045 and fails naming any slug with no Latin name -- the test that would have caught the original defect, where a printed booklet said ef-septuagesima-sunday-2 because nothing asserted that names exist. The three Triduum names reuse the exact strings temporal_ef.ml already carries, so the engine and the language file cannot disagree.
Diffstat (limited to 'test')
-rw-r--r--test/dune1
-rw-r--r--test/test_colitur.ml1
-rw-r--r--test/test_lang_coverage.ml73
3 files changed, 75 insertions, 0 deletions
diff --git a/test/dune b/test/dune
index b9cc2a7..6e2ac87 100644
--- a/test/dune
+++ b/test/dune
@@ -4,6 +4,7 @@
(deps
../data/ef/sanctoral.sexp
../data/ef/adjustments.sexp
+ ../lang/la.ini
../data/ef/expected-divergences.sexp
../data/ef/expected-divergences-missalemeum.sexp
../data/ef/lectionary.sexp
diff --git a/test/test_colitur.ml b/test/test_colitur.ml
index 1c445a6..1bdd220 100644
--- a/test/test_colitur.ml
+++ b/test/test_colitur.ml
@@ -3,6 +3,7 @@ let () =
Alcotest.run "colitur"
[ Test_date.suite; Test_computus.suite; Test_colour.suite; Test_slug.suite; Test_names.suite;
Test_lang.suite;
+ Test_lang_coverage.suite;
Test_config.suite;
Test_overlay.suite; Test_overlay_ini.suite; Test_temporal_ef.suite; Test_validate.suite; Test_precedence.suite;
Test_calendar.suite; Test_precedence_ef.suite; Test_sanctoral_ef.suite; Test_rite_ef.suite;
diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml
new file mode 100644
index 0000000..d72484f
--- /dev/null
+++ b/test/test_lang_coverage.ml
@@ -0,0 +1,73 @@
+module L = Colitur_naming.Lang
+
+let read path =
+ let ic = open_in_bin path in
+ let s = really_input_string ic (in_channel_length ic) in
+ close_in ic;
+ s
+
+let la () =
+ match L.of_string (read "../lang/la.ini") with
+ | Ok t -> t
+ | Error e -> Alcotest.failf "lang/la.ini: %s" e
+
+(* Every TEMPORAL slug the engine can emit must have a Latin name. THIS IS THE
+ TEST THAT WOULD HAVE CAUGHT THE ORIGINAL DEFECT -- a booklet printed
+ "ef-septuagesima-sunday-2" because nothing asserted coverage. It must fail
+ loudly the moment a new slug appears without a name.
+
+ RESTRICTED TO "^ef-" SLUGS FOR NOW (Task 3's own scope: la.ini's
+ [celebration] table currently carries the temporal half only). Task 4 adds
+ the sanctoral names and REMOVES this filter -- see this file's own
+ [is_temporal_slug] below, kept as one clearly-named, easy-to-find place to
+ change, rather than an inline condition. *)
+let is_temporal_slug slug = String.length slug >= 3 && String.sub slug 0 3 = "ef-"
+
+let test_every_temporal_slug_has_a_latin_name () =
+ let t = la () in
+ let layer = match Test_support.load_ef_layer () with Ok l -> l | Error e -> Alcotest.failf "%s" e in
+ let ctx = Test_support.ef_context () in
+ let missing = ref [] in
+ for y = 2020 to 2045 do
+ Array.iter
+ (fun (d : (Rite_ef.Vocab_ef.season, Rite_ef.Vocab_ef.rank) Colitur_kernel.Liturgical_day.t) ->
+ let slug =
+ Colitur_kernel.Slug.to_string
+ d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug
+ in
+ (* A miss returns the key itself, so name = slug means "no entry". *)
+ if
+ is_temporal_slug slug
+ && L.celebration t slug = slug
+ && not (List.mem slug !missing)
+ then missing := slug :: !missing)
+ (Colitur_kernel.Calendar.year ctx layer y)
+ done;
+ if !missing <> [] then
+ Alcotest.failf "%d slugs have no Latin name, e.g. %s" (List.length !missing)
+ (String.concat ", " (List.filteri (fun i _ -> i < 5) !missing))
+
+let test_vocabularies_are_complete () =
+ let t = la () in
+ List.iter
+ (fun s -> if L.season t s = s then Alcotest.failf "no Latin season name for %S" s)
+ [ "advent"; "christmastide"; "time-after-epiphany"; "septuagesima"; "lent";
+ "passiontide"; "paschaltide"; "time-after-pentecost" ];
+ List.iter
+ (fun r -> if L.rank t r = r then Alcotest.failf "no Latin rank name for %S" r)
+ [ "class-1"; "class-2"; "class-3"; "class-4" ];
+ List.iter
+ (fun c -> if L.colour t c = c then Alcotest.failf "no Latin colour name for %S" c)
+ [ "white"; "red"; "green"; "violet"; "rose"; "black" ];
+ for n = 0 to 6 do
+ if L.weekday t n = string_of_int n then Alcotest.failf "no Latin weekday for %d" n
+ done;
+ for n = 1 to 12 do
+ if L.month t n = string_of_int n then Alcotest.failf "no Latin month for %d" n
+ done
+
+let suite =
+ ( "Lang/coverage",
+ [ Alcotest.test_case "every temporal slug has a Latin name" `Slow
+ test_every_temporal_slug_has_a_latin_name;
+ Alcotest.test_case "vocabularies complete" `Quick test_vocabularies_are_complete ] )