diff options
Diffstat (limited to 'test/test_lang_coverage.ml')
| -rw-r--r-- | test/test_lang_coverage.ml | 71 |
1 files changed, 51 insertions, 20 deletions
diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml index d72484f..96a3383 100644 --- a/test/test_lang_coverage.ml +++ b/test/test_lang_coverage.ml @@ -11,19 +11,17 @@ let la () = | 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. +(* Every slug the engine can emit -- temporal ("^ef-") AND sanctoral (a fixed + saint's day) alike -- 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 () = + Task 3 restricted this to "^ef-" slugs only (la.ini's [celebration] table + carried the temporal half alone at the time); Task 4 added the sanctoral + half and REMOVED that filter -- every slug is now in scope, with no + exceptions. *) +let test_every_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 @@ -36,11 +34,8 @@ let test_every_temporal_slug_has_a_latin_name () = 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) + if 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 @@ -66,8 +61,44 @@ let test_vocabularies_are_complete () = if L.month t n = string_of_int n then Alcotest.failf "no Latin month for %d" n done +(* lang/en.ini is DELIBERATELY partial (see its own header note): it declares + [meta] fallback = la, so a slug it does not carry itself should still + resolve through the chain to la.ini's name rather than degrade to the bare + slug -- that is what makes an incomplete translation shippable from its + first line. This test proves the CHAIN MECHANISM itself, independent of + how complete lang/en.ini happens to be today: a from-scratch table with NO + [celebration] entries at all, chained to the real la.ini, must still + resolve a real la.ini key -- so the test cannot be defeated simply by + en.ini becoming more complete over time. It also sanity-checks the real + shipped file: that it parses, declares the right fallback code, and that + at least one of its own entries resolves directly (not merely through the + chain). *) +let test_en_falls_back_to_latin () = + let en = + match L.of_string (read "../lang/en.ini") with + | Ok t -> t + | Error e -> Alcotest.failf "lang/en.ini: %s" e + in + Alcotest.(check string) "declares la fallback" "la" + (Option.value (L.fallback_code en) ~default:"NONE"); + (* The real shipped file: at least one of its own entries resolves without + needing the chain at all. *) + Alcotest.(check bool) "en.ini names ef-epiphany directly" true + (L.celebration en "ef-epiphany" <> "ef-epiphany"); + (* The mechanism, isolated from today's en.ini coverage: an EMPTY table + (no [celebration] section) chained to la.ini must still resolve a real + la.ini-only key through the fallback. *) + let empty = + match L.of_string "[meta]\nlang = en\nfallback = la\n" with + | Ok t -> t + | Error e -> Alcotest.failf "synthetic empty en table: %s" e + in + let chained = L.with_fallback empty (la ()) in + Alcotest.(check bool) "empty table falls back to la.ini for a real slug" true + (L.celebration chained "hilary" <> "hilary") + 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 ] ) + [ Alcotest.test_case "every slug has a Latin name" `Slow test_every_slug_has_a_latin_name; + Alcotest.test_case "vocabularies complete" `Quick test_vocabularies_are_complete; + Alcotest.test_case "en.ini falls back to Latin" `Quick test_en_falls_back_to_latin ] ) |
