1
2
3
4
5 package cldr
6
7 import (
8 "fmt"
9 "strings"
10 "testing"
11 )
12
13
14
15 type recorder struct {
16 calls []string
17 }
18
19 func (r *recorder) Reset(anchor string, before int) error {
20 if before > 5 {
21 return fmt.Errorf("before %d > 5", before)
22 }
23 r.calls = append(r.calls, fmt.Sprintf("R:%s-%d", anchor, before))
24 return nil
25 }
26
27 func (r *recorder) Insert(level int, str, context, extend string) error {
28 s := fmt.Sprintf("O:%d:%s", level, str)
29 if context != "" {
30 s += "|" + context
31 }
32 if extend != "" {
33 s += "/" + extend
34 }
35 r.calls = append(r.calls, s)
36 return nil
37 }
38
39 func (r *recorder) Index(id string) {
40 r.calls = append(r.calls, fmt.Sprintf("I:%s", id))
41 }
42
43 func (r *recorder) Error(err error) {
44 r.calls = append(r.calls, fmt.Sprintf("E:%v", err))
45 }
46
47 func TestRuleProcessor(t *testing.T) {
48 for _, tt := range []struct {
49 desc string
50 in string
51 out string
52 }{
53 {desc: "empty"},
54 {desc: "whitespace and comments only",
55 in: `
56
57
58 # adsfads
59 # adfadf
60 `,
61 },
62 {
63 desc: "reset anchor",
64 in: `
65 & a
66 &b #
67 & [ before 3 ] c
68 & [before 4] d & ee
69 & [first tertiary ignorable]
70 &'g'
71 & 'h''h'h'h'
72 &'\u0069' # LATIN SMALL LETTER I
73 `,
74 out: `
75 R:a-0
76 R:b-0
77 R:c-3
78 R:d-4
79 R:ee-0
80 R:<first tertiary ignorable/>-0
81 R:g-0
82 R:hhhh-0
83 R:i-0
84 `,
85 },
86 {
87 desc: "ordering",
88 in: `
89 & 0
90 < 1 <<''2#
91 <<< 3'3''33'3#
92 <<<<4
93 = 5 << 6 | s
94 <<<< 7 / z
95 << 8'' | s / ch
96 `,
97 out: `
98 R:0-0
99 O:1:1
100 O:2:'2
101 O:3:33333
102 O:4:4
103 O:5:5
104 O:2:6|s
105 O:4:7/z
106 O:2:8'|s/ch
107 `,
108 },
109 {
110 desc: "index",
111 in: "< '\ufdd0'A",
112 out: "I:A",
113 },
114 {
115 desc: "sequence",
116 in: `
117 & 0
118 <<* 1234
119 <* a-cde-f
120 =* q-q
121 `,
122 out: `
123 R:0-0
124 O:2:1
125 O:2:2
126 O:2:3
127 O:2:4
128 O:1:a
129 O:1:b
130 O:1:c
131 O:1:d
132 O:1:e
133 O:1:f
134 O:5:q
135 `,
136 },
137 {
138 desc: "compact",
139 in: "&B<t<<<T<s<<<S<e<<<E",
140 out: `
141 R:B-0
142 O:1:t
143 O:3:T
144 O:1:s
145 O:3:S
146 O:1:e
147 O:3:E
148 `,
149 },
150 {
151 desc: "err operator",
152 in: "a",
153 out: "E:1: illegal operator 'a'",
154 },
155 {
156 desc: "err line number",
157 in: `& a
158 << b
159 a`,
160 out: `
161 R:a-0
162 O:2:b
163 E:3: illegal operator 'a'`,
164 },
165 {
166 desc: "err empty anchor",
167 in: " & ",
168 out: "E:1: missing string",
169 },
170 {
171 desc: "err anchor invalid special 1",
172 in: " & [ foo ",
173 out: "E:1: unmatched bracket",
174 },
175 {
176 desc: "err anchor invalid special 2",
177 in: "&[",
178 out: "E:1: unmatched bracket",
179 },
180 {
181 desc: "err anchor invalid before 1",
182 in: "&[before a]",
183 out: `E:1: strconv.ParseUint: parsing "a": invalid syntax`,
184 },
185 {
186 desc: "err anchor invalid before 2",
187 in: "&[before 12]",
188 out: `E:1: strconv.ParseUint: parsing "12": value out of range`,
189 },
190 {
191 desc: "err anchor invalid before 3",
192 in: "&[before 2]",
193 out: "E:1: missing string",
194 },
195 {
196 desc: "err anchor invalid before 4",
197 in: "&[before 6] a",
198 out: "E:1: before 6 > 5",
199 },
200 {
201 desc: "err empty order",
202 in: " < ",
203 out: "E:1: missing string",
204 },
205 {
206 desc: "err empty identity",
207 in: " = ",
208 out: "E:1: missing string",
209 },
210 {
211 desc: "err empty context",
212 in: " < a | ",
213 out: "E:1: missing string after context",
214 },
215 {
216 desc: "err empty extend",
217 in: " < a / ",
218 out: "E:1: missing string after extension",
219 },
220 {
221 desc: "err empty sequence",
222 in: " <* ",
223 out: "E:1: empty sequence",
224 },
225 {
226 desc: "err sequence 1",
227 in: " <* -a",
228 out: "E:1: range without starter value",
229 },
230 {
231 desc: "err sequence 3",
232 in: " <* a-a-b",
233 out: `O:1:a
234 E:1: range without starter value
235 `,
236 },
237 {
238 desc: "err sequence 3",
239 in: " <* b-a",
240 out: `O:1:b
241 E:1: invalid range 'b'-'a'
242 `,
243 },
244 {
245 desc: "err unmatched quote",
246 in: " < 'b",
247 out: ` E:1: unmatched single quote
248 `,
249 },
250 } {
251 rec := &recorder{}
252 err := Collation{
253 Cr: []*Common{
254 {hidden: hidden{CharData: tt.in}},
255 },
256 }.Process(rec)
257 if err != nil {
258 rec.Error(err)
259 }
260 got := rec.calls
261 want := strings.Split(strings.TrimSpace(tt.out), "\n")
262 if tt.out == "" {
263 want = nil
264 }
265 if len(got) != len(want) {
266 t.Errorf("%s: nResults: got %d; want %d", tt.desc, len(got), len(want))
267 continue
268 }
269 for i, g := range got {
270 if want := strings.TrimSpace(want[i]); g != want {
271 t.Errorf("%s:%d: got %q; want %q", tt.desc, i, g, want)
272 }
273 }
274 }
275 }
276
View as plain text