blob: b54e85ba63c6679b9cc6aa02039a03dfca65ff4c (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
module L = Colitur_naming.Lang
let ok = function Ok x -> x | Error e -> Alcotest.failf "parse: %s" e
let sample =
"[meta]\n\
lang = xx\n\
fallback = la\n\
[celebration]\n\
ef-lent-3-monday = Feria II hebdomadae III Quadragesimae\n\
francis-de-sales = S. Francisci Salesii\n\
[weekday]\n\
sunday = Dominica\n\
monday = Feria II\n\
[month]\n\
1 = Ianuarius\n\
[season]\n\
lent = Quadragesima\n\
[rank]\n\
class-1 = I classis\n\
[colour]\n\
white = albus\n\
[term]\n\
epistle = Epistola\n"
let test_meta () =
let t = ok (L.of_string sample) in
Alcotest.(check string) "code" "xx" (L.code t);
Alcotest.(check (option string)) "fallback" (Some "la") (L.fallback_code t)
let test_lookups () =
let t = ok (L.of_string sample) in
Alcotest.(check string) "celebration" "Feria II hebdomadae III Quadragesimae"
(L.celebration t "ef-lent-3-monday");
Alcotest.(check string) "weekday 0 is Sunday" "Dominica" (L.weekday t 0);
Alcotest.(check string) "month 1" "Ianuarius" (L.month t 1);
Alcotest.(check string) "season" "Quadragesima" (L.season t "lent");
Alcotest.(check string) "rank" "I classis" (L.rank t "class-1");
Alcotest.(check string) "colour" "albus" (L.colour t "white");
Alcotest.(check string) "term" "Epistola" (L.term t "epistle")
(* THE load-bearing property: a missing key degrades to the key itself, never to
empty. A partial translation must be usable from its first line, and an
untranslated day must still say something a reader can act on. *)
let test_missing_degrades_to_key () =
let t = ok (L.of_string sample) in
Alcotest.(check string) "unknown celebration" "ef-advent-1-monday"
(L.celebration t "ef-advent-1-monday");
Alcotest.(check string) "unknown colour" "rose" (L.colour t "rose");
Alcotest.(check string) "unknown term" "gospel" (L.term t "gospel")
let test_fallback_chain () =
let base = ok (L.of_string "[meta]\nlang = la\n[celebration]\na = ALPHA\nb = BETA\n") in
let over = ok (L.of_string "[meta]\nlang = xx\nfallback = la\n[celebration]\nb = BETA-XX\n") in
let t = L.with_fallback over base in
Alcotest.(check string) "own key wins" "BETA-XX" (L.celebration t "b");
Alcotest.(check string) "falls back" "ALPHA" (L.celebration t "a");
Alcotest.(check string) "neither: the key" "c" (L.celebration t "c")
(* --raw must be a real identity table, not a special case threaded through every
call site: one table the whole program can pass around. *)
let test_raw_is_identity () =
Alcotest.(check string) "celebration" "ef-epiphany" (L.celebration L.raw "ef-epiphany");
Alcotest.(check string) "colour" "white" (L.colour L.raw "white");
Alcotest.(check string) "weekday" "0" (L.weekday L.raw 0)
let test_malformed_is_error_not_crash () =
match L.of_string "[celebration\nbroken" with
| Error _ -> ()
| Ok _ -> Alcotest.fail "a malformed language file must be an Error, never accepted"
let test_missing_meta_lang_is_error () =
match L.of_string "[celebration]\na = B\n" with
| Error _ -> ()
| Ok _ -> Alcotest.fail "a language file with no [meta] lang must be an Error"
(* F1 regression: a hand-edited language file WILL grow duplicate [section]
headers as contributors append entries over time (Tasks 3/4's 595-entry
la.ini). Both blocks' keys must resolve -- silently dropping the second
block is a data-loss footgun that surfaces as a false "missing name"
report far from its real cause. *)
let test_duplicate_sections_all_merge () =
let t =
ok
(L.of_string
"[meta]\nlang = la\n[celebration]\na = ALPHA\n[weekday]\nsunday = Dominica\n\
[celebration]\nb = BETA\n")
in
Alcotest.(check string) "first block's key" "ALPHA" (L.celebration t "a");
Alcotest.(check string) "second block's key" "BETA" (L.celebration t "b")
let test_duplicate_key_across_sections_last_wins () =
let t =
ok
(L.of_string
"[meta]\nlang = la\n[celebration]\na = FIRST\n[celebration]\na = SECOND\n")
in
Alcotest.(check string) "later block's value wins" "SECOND" (L.celebration t "a")
let test_duplicate_key_within_section_last_wins () =
let t = ok (L.of_string "[meta]\nlang = la\n[celebration]\na = FIRST\na = SECOND\n") in
Alcotest.(check string) "later line's value wins" "SECOND" (L.celebration t "a")
let suite =
( "Lang",
[ Alcotest.test_case "meta" `Quick test_meta;
Alcotest.test_case "lookups" `Quick test_lookups;
Alcotest.test_case "missing degrades to key" `Quick test_missing_degrades_to_key;
Alcotest.test_case "fallback chain" `Quick test_fallback_chain;
Alcotest.test_case "raw is identity" `Quick test_raw_is_identity;
Alcotest.test_case "malformed is error" `Quick test_malformed_is_error_not_crash;
Alcotest.test_case "missing meta lang is error" `Quick test_missing_meta_lang_is_error;
Alcotest.test_case "duplicate sections all merge" `Quick test_duplicate_sections_all_merge;
Alcotest.test_case "duplicate key across sections: last wins" `Quick
test_duplicate_key_across_sections_last_wins;
Alcotest.test_case "duplicate key within section: last wins" `Quick
test_duplicate_key_within_section_last_wins ] )
|