]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
51004dcb A |
3 | /* |
4 | ******************************************************************************* | |
5 | * | |
2ca993e8 | 6 | * Copyright (C) 2012-2016, International Business Machines |
51004dcb A |
7 | * Corporation and others. All Rights Reserved. |
8 | * | |
9 | ******************************************************************************* | |
10 | * file name: listformattertest.cpp | |
f3c0d7a5 | 11 | * encoding: UTF-8 |
51004dcb A |
12 | * tab size: 8 (not used) |
13 | * indentation:4 | |
14 | * | |
15 | * created on: 2012aug27 | |
16 | * created by: Umesh P. Nair | |
17 | */ | |
18 | ||
19 | #include "listformattertest.h" | |
3d1f044b A |
20 | #include "unicode/ulistformatter.h" |
21 | #include "cmemory.h" | |
51004dcb A |
22 | #include <string.h> |
23 | ||
3d1f044b A |
24 | #if !UCONFIG_NO_FORMATTING |
25 | ||
26 | namespace { | |
27 | const char* attrString(int32_t attrId) { | |
28 | switch (attrId) { | |
29 | case ULISTFMT_LITERAL_FIELD: return "literal"; | |
30 | case ULISTFMT_ELEMENT_FIELD: return "element"; | |
31 | default: return "xxx"; | |
32 | } | |
33 | } | |
34 | } // namespace | |
35 | ||
36 | void ListFormatterTest::ExpectPositions(FieldPositionIterator& iter, | |
37 | int32_t *values, int32_t tupleCount) { | |
38 | UBool found[10]; | |
39 | FieldPosition fp; | |
40 | if (tupleCount > 10) { | |
41 | assertTrue("internal error, tupleCount too large", FALSE); | |
42 | } else { | |
43 | for (int i = 0; i < tupleCount; ++i) { | |
44 | found[i] = FALSE; | |
45 | } | |
46 | } | |
47 | while (iter.next(fp)) { | |
48 | UBool ok = FALSE; | |
49 | int32_t id = fp.getField(); | |
50 | int32_t start = fp.getBeginIndex(); | |
51 | int32_t limit = fp.getEndIndex(); | |
52 | char buf[128]; | |
53 | sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit); | |
54 | logln(buf); | |
55 | for (int i = 0; i < tupleCount; ++i) { | |
56 | if (found[i]) { | |
57 | continue; | |
58 | } | |
59 | if (values[i*3] == id && values[i*3+1] == start && values[i*3+2] == limit) { | |
60 | found[i] = ok = TRUE; | |
61 | break; | |
62 | } | |
63 | } | |
64 | assertTrue((UnicodeString)"found [" + attrString(id) + "," + start + "," + limit + "]", ok); | |
65 | } | |
66 | // check that all were found | |
67 | UBool ok = TRUE; | |
68 | for (int i = 0; i < tupleCount; ++i) { | |
69 | if (!found[i]) { | |
70 | ok = FALSE; | |
71 | assertTrue((UnicodeString) "missing [" + attrString(values[i*3]) + "," + values[i*3+1] + | |
72 | "," + values[i*3+2] + "]", found[i]); | |
73 | } | |
74 | } | |
75 | assertTrue("no expected values were missing", ok); | |
76 | } | |
77 | ||
51004dcb A |
78 | ListFormatterTest::ListFormatterTest() : |
79 | prefix("Prefix: ", -1, US_INV), | |
80 | one("Alice", -1, US_INV), two("Bob", -1, US_INV), | |
81 | three("Charlie", -1, US_INV), four("Delta", -1, US_INV) { | |
82 | } | |
83 | ||
84 | void ListFormatterTest::CheckFormatting(const ListFormatter* formatter, UnicodeString data[], int32_t dataSize, | |
3d1f044b | 85 | const UnicodeString& expected_result, const char* testName) { |
51004dcb | 86 | UnicodeString actualResult(prefix); |
3d1f044b | 87 | IcuTestErrorCode errorCode(*this, testName); |
51004dcb A |
88 | formatter->format(data, dataSize, actualResult, errorCode); |
89 | UnicodeString expectedStringWithPrefix = prefix + expected_result; | |
90 | if (expectedStringWithPrefix != actualResult) { | |
91 | errln(UnicodeString("Expected: |") + expectedStringWithPrefix + "|, Actual: |" + actualResult + "|"); | |
92 | } | |
93 | } | |
94 | ||
95 | void ListFormatterTest::CheckFourCases(const char* locale_string, UnicodeString one, UnicodeString two, | |
3d1f044b A |
96 | UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName) { |
97 | IcuTestErrorCode errorCode(*this, testName); | |
51004dcb A |
98 | LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(Locale(locale_string), errorCode)); |
99 | if (U_FAILURE(errorCode)) { | |
100 | dataerrln("ListFormatter::createInstance(Locale(\"%s\"), errorCode) failed in CheckFourCases: %s", locale_string, u_errorName(errorCode)); | |
101 | return; | |
102 | } | |
103 | UnicodeString input1[] = {one}; | |
3d1f044b | 104 | CheckFormatting(formatter.getAlias(), input1, 1, results[0], testName); |
51004dcb A |
105 | |
106 | UnicodeString input2[] = {one, two}; | |
3d1f044b | 107 | CheckFormatting(formatter.getAlias(), input2, 2, results[1], testName); |
51004dcb A |
108 | |
109 | UnicodeString input3[] = {one, two, three}; | |
3d1f044b | 110 | CheckFormatting(formatter.getAlias(), input3, 3, results[2], testName); |
51004dcb A |
111 | |
112 | UnicodeString input4[] = {one, two, three, four}; | |
3d1f044b | 113 | CheckFormatting(formatter.getAlias(), input4, 4, results[3], testName); |
51004dcb A |
114 | } |
115 | ||
116 | UBool ListFormatterTest::RecordFourCases(const Locale& locale, UnicodeString one, UnicodeString two, | |
3d1f044b A |
117 | UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName) { |
118 | IcuTestErrorCode errorCode(*this, testName); | |
51004dcb A |
119 | LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(locale, errorCode)); |
120 | if (U_FAILURE(errorCode)) { | |
121 | dataerrln("ListFormatter::createInstance(\"%s\", errorCode) failed in RecordFourCases: %s", locale.getName(), u_errorName(errorCode)); | |
122 | return FALSE; | |
123 | } | |
124 | UnicodeString input1[] = {one}; | |
125 | formatter->format(input1, 1, results[0], errorCode); | |
126 | UnicodeString input2[] = {one, two}; | |
127 | formatter->format(input2, 2, results[1], errorCode); | |
128 | UnicodeString input3[] = {one, two, three}; | |
129 | formatter->format(input3, 3, results[2], errorCode); | |
130 | UnicodeString input4[] = {one, two, three, four}; | |
131 | formatter->format(input4, 4, results[3], errorCode); | |
132 | if (U_FAILURE(errorCode)) { | |
133 | errln("RecordFourCases failed: %s", u_errorName(errorCode)); | |
134 | return FALSE; | |
135 | } | |
136 | return TRUE; | |
137 | } | |
138 | ||
139 | void ListFormatterTest::TestRoot() { | |
140 | UnicodeString results[4] = { | |
141 | one, | |
142 | one + ", " + two, | |
143 | one + ", " + two + ", " + three, | |
144 | one + ", " + two + ", " + three + ", " + four | |
145 | }; | |
146 | ||
3d1f044b | 147 | CheckFourCases("", one, two, three, four, results, "TestRoot()"); |
51004dcb A |
148 | } |
149 | ||
150 | // Bogus locale should fallback to root. | |
151 | void ListFormatterTest::TestBogus() { | |
152 | UnicodeString results[4]; | |
3d1f044b A |
153 | if (RecordFourCases(Locale::getDefault(), one, two, three, four, results, "TestBogus()")) { |
154 | CheckFourCases("ex_PY", one, two, three, four, results, "TestBogus()"); | |
51004dcb A |
155 | } |
156 | } | |
157 | ||
158 | // Formatting in English. | |
159 | // "and" is used before the last element, and all elements up to (and including) the penultimate are followed by a comma. | |
160 | void ListFormatterTest::TestEnglish() { | |
161 | UnicodeString results[4] = { | |
162 | one, | |
163 | one + " and " + two, | |
164 | one + ", " + two + ", and " + three, | |
165 | one + ", " + two + ", " + three + ", and " + four | |
166 | }; | |
167 | ||
3d1f044b | 168 | CheckFourCases("en", one, two, three, four, results, "TestEnglish()"); |
51004dcb A |
169 | } |
170 | ||
57a6839d | 171 | void ListFormatterTest::Test9946() { |
3d1f044b | 172 | IcuTestErrorCode errorCode(*this, "Test9946()"); |
57a6839d A |
173 | LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(Locale("en"), errorCode)); |
174 | if (U_FAILURE(errorCode)) { | |
175 | dataerrln( | |
176 | "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in Test9946: %s", | |
177 | u_errorName(errorCode)); | |
178 | return; | |
179 | } | |
180 | UnicodeString data[3] = {"{0}", "{1}", "{2}"}; | |
181 | UnicodeString actualResult; | |
182 | formatter->format(data, 3, actualResult, errorCode); | |
183 | if (U_FAILURE(errorCode)) { | |
184 | dataerrln( | |
185 | "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in Test9946: %s", | |
186 | u_errorName(errorCode)); | |
187 | return; | |
188 | } | |
189 | UnicodeString expected("{0}, {1}, and {2}"); | |
190 | if (expected != actualResult) { | |
191 | errln("Expected " + expected + ", got " + actualResult); | |
192 | } | |
193 | } | |
194 | ||
51004dcb A |
195 | void ListFormatterTest::TestEnglishUS() { |
196 | UnicodeString results[4] = { | |
197 | one, | |
198 | one + " and " + two, | |
199 | one + ", " + two + ", and " + three, | |
200 | one + ", " + two + ", " + three + ", and " + four | |
201 | }; | |
202 | ||
3d1f044b | 203 | CheckFourCases("en_US", one, two, three, four, results, "TestEnglishUS()"); |
51004dcb A |
204 | } |
205 | ||
f3c0d7a5 A |
206 | // Tests resource loading and inheritance when region sublocale |
207 | // has only partial data for the listPattern element (overriding | |
208 | // some of the parent data). #12994 | |
209 | void ListFormatterTest::TestEnglishGB() { | |
210 | UnicodeString results[4] = { | |
211 | one, | |
212 | one + " and " + two, | |
213 | one + ", " + two + " and " + three, | |
214 | one + ", " + two + ", " + three + " and " + four | |
215 | }; | |
216 | ||
3d1f044b A |
217 | CheckFourCases("en_GB", one, two, three, four, results, "TestEnglishGB()"); |
218 | } | |
219 | ||
220 | void ListFormatterTest::TestFieldPositionIteratorWontCrash() { | |
221 | IcuTestErrorCode errorCode(*this, "TestFieldPositionIteratorWontCrash()"); | |
222 | LocalPointer<ListFormatter> formatter( | |
223 | ListFormatter::createInstance(Locale("en"), errorCode)); | |
224 | if (U_FAILURE(errorCode)) { | |
225 | dataerrln( | |
226 | "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in " | |
227 | "TestFieldPositionIteratorWontCrash: %s", | |
228 | u_errorName(errorCode)); | |
229 | return; | |
230 | } | |
231 | UnicodeString data[3] = {"a", "bbb", "cc"}; | |
232 | UnicodeString actualResult; | |
233 | // make sure NULL as FieldPositionIterator won't caused crash. | |
234 | formatter->format(data, 3, actualResult, nullptr, errorCode); | |
235 | if (U_FAILURE(errorCode)) { | |
236 | dataerrln( | |
237 | "ListFormatter::format(data, 3, nullptr, errorCode) " | |
238 | "failed in TestFieldPositionIteratorWontCrash: %s", | |
239 | u_errorName(errorCode)); | |
240 | return; | |
241 | } | |
242 | } | |
243 | ||
244 | void ListFormatterTest::RunTestFieldPositionIteratorWithFormatter( | |
245 | ListFormatter* formatter, | |
246 | UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount, | |
247 | UnicodeString& appendTo, const char16_t *expectedFormatted, | |
248 | const char* testName) { | |
249 | IcuTestErrorCode errorCode(*this, testName); | |
250 | FieldPositionIterator iter; | |
251 | formatter->format(data, n, appendTo, &iter, errorCode); | |
252 | if (U_FAILURE(errorCode)) { | |
253 | dataerrln( | |
254 | "ListFormatter::format(data, %d, &iter, errorCode) " | |
255 | "failed in %s: %s", n, testName, u_errorName(errorCode)); | |
256 | return; | |
257 | } | |
258 | if (appendTo != expectedFormatted) { | |
259 | errln(UnicodeString("Expected: |") + expectedFormatted + "|, Actual: |" + appendTo + "|"); | |
260 | } | |
261 | ExpectPositions(iter, expected, tupleCount); | |
262 | } | |
263 | ||
264 | void ListFormatterTest::RunTestFieldPositionIteratorWithNItemsPatternShift( | |
265 | UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount, | |
266 | UnicodeString& appendTo, const char16_t *expectedFormatted, | |
267 | const char* testName) { | |
268 | IcuTestErrorCode errorCode(*this, testName); | |
269 | LocalPointer<ListFormatter> formatter( | |
270 | ListFormatter::createInstance(Locale("ur", "IN"), "unit-narrow", errorCode)); | |
271 | if (U_FAILURE(errorCode)) { | |
272 | dataerrln( | |
273 | "ListFormatter::createInstance(Locale(\"ur\", \"IN\"), \"unit-narrow\", errorCode) failed in " | |
274 | "%s: %s", testName, u_errorName(errorCode)); | |
275 | return; | |
276 | } | |
277 | RunTestFieldPositionIteratorWithFormatter( | |
278 | formatter.getAlias(), | |
279 | data, n, expected, tupleCount, appendTo, expectedFormatted, testName); | |
280 | } | |
281 | ||
282 | void ListFormatterTest::RunTestFieldPositionIteratorWithNItems( | |
283 | UnicodeString data[], int32_t n, int32_t expected[], int32_t tupleCount, | |
284 | UnicodeString& appendTo, const char16_t *expectedFormatted, | |
285 | const char* testName) { | |
286 | IcuTestErrorCode errorCode(*this, testName); | |
287 | LocalPointer<ListFormatter> formatter( | |
288 | ListFormatter::createInstance(Locale("en"), errorCode)); | |
289 | if (U_FAILURE(errorCode)) { | |
290 | dataerrln( | |
291 | "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in " | |
292 | "%s: %s", testName, u_errorName(errorCode)); | |
293 | return; | |
294 | } | |
295 | RunTestFieldPositionIteratorWithFormatter( | |
296 | formatter.getAlias(), | |
297 | data, n, expected, tupleCount, appendTo, expectedFormatted, testName); | |
298 | } | |
299 | ||
300 | void ListFormatterTest::TestFieldPositionIteratorWith3ItemsAndDataBefore() { | |
301 | // 0 1 2 | |
302 | // 0123456789012345678901234567 | |
303 | // "Hello World: a, bbb, and cc" | |
304 | UnicodeString data[3] = {"a", "bbb", "cc"}; | |
305 | int32_t expected[] = { | |
306 | ULISTFMT_ELEMENT_FIELD, 13, 14, | |
307 | ULISTFMT_LITERAL_FIELD, 14, 16, | |
308 | ULISTFMT_ELEMENT_FIELD, 16, 19, | |
309 | ULISTFMT_LITERAL_FIELD, 19, 25, | |
310 | ULISTFMT_ELEMENT_FIELD, 25, 27 | |
311 | }; | |
312 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
313 | UnicodeString appendTo(u"Hello World: "); | |
314 | RunTestFieldPositionIteratorWithNItems( | |
315 | data, 3, expected, tupleCount, appendTo, | |
316 | u"Hello World: a, bbb, and cc", | |
317 | "TestFieldPositionIteratorWith3ItemsAndDataBefore"); | |
318 | } | |
319 | ||
320 | void ListFormatterTest::TestFieldPositionIteratorWith3Items() { | |
321 | // 0 1 | |
322 | // 012345678901234 | |
323 | // "a, bbb, and cc" | |
324 | UnicodeString data[3] = {"a", "bbb", "cc"}; | |
325 | int32_t expected[] = { | |
326 | ULISTFMT_ELEMENT_FIELD, 0, 1, | |
327 | ULISTFMT_LITERAL_FIELD, 1, 3, | |
328 | ULISTFMT_ELEMENT_FIELD, 3, 6, | |
329 | ULISTFMT_LITERAL_FIELD, 6, 12, | |
330 | ULISTFMT_ELEMENT_FIELD, 12, 14 | |
331 | }; | |
332 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
333 | UnicodeString appendTo; | |
334 | RunTestFieldPositionIteratorWithNItems( | |
335 | data, 3, expected, tupleCount, appendTo, | |
336 | u"a, bbb, and cc", | |
337 | "TestFieldPositionIteratorWith3Items"); | |
338 | } | |
339 | ||
340 | void ListFormatterTest::TestFieldPositionIteratorWith3ItemsPatternShift() { | |
341 | // 0 1 | |
342 | // 012345678901234 | |
343 | // "cc bbb a" | |
344 | UnicodeString data[3] = {"a", "bbb", "cc"}; | |
345 | int32_t expected[] = { | |
346 | ULISTFMT_ELEMENT_FIELD, 7, 8, | |
347 | ULISTFMT_LITERAL_FIELD, 6, 7, | |
348 | ULISTFMT_ELEMENT_FIELD, 3, 6, | |
349 | ULISTFMT_LITERAL_FIELD, 2, 3, | |
350 | ULISTFMT_ELEMENT_FIELD, 0, 2 | |
351 | }; | |
352 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
353 | UnicodeString appendTo; | |
354 | RunTestFieldPositionIteratorWithNItemsPatternShift( | |
355 | data, 3, expected, tupleCount, appendTo, | |
356 | u"cc bbb a", | |
357 | "TestFieldPositionIteratorWith3ItemsPatternShift"); | |
358 | } | |
359 | ||
360 | void ListFormatterTest::TestFieldPositionIteratorWith2ItemsAndDataBefore() { | |
361 | // 0 1 | |
362 | // 0123456789012345 | |
363 | // "Foo: bbb and cc" | |
364 | UnicodeString data[2] = {"bbb", "cc"}; | |
365 | int32_t expected[] = { | |
366 | ULISTFMT_ELEMENT_FIELD, 5, 8, | |
367 | ULISTFMT_LITERAL_FIELD, 8, 13, | |
368 | ULISTFMT_ELEMENT_FIELD, 13, 15 | |
369 | }; | |
370 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
371 | UnicodeString appendTo("Foo: "); | |
372 | RunTestFieldPositionIteratorWithNItems( | |
373 | data, 2, expected, tupleCount, appendTo, | |
374 | u"Foo: bbb and cc", | |
375 | "TestFieldPositionIteratorWith2ItemsAndDataBefore"); | |
376 | } | |
377 | ||
378 | void ListFormatterTest::TestFieldPositionIteratorWith2Items() { | |
379 | // 0 1 | |
380 | // 01234567890 | |
381 | // "bbb and cc" | |
382 | UnicodeString data[2] = {"bbb", "cc"}; | |
383 | int32_t expected[] = { | |
384 | ULISTFMT_ELEMENT_FIELD, 0, 3, | |
385 | ULISTFMT_LITERAL_FIELD, 3, 8, | |
386 | ULISTFMT_ELEMENT_FIELD, 8, 10 | |
387 | }; | |
388 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
389 | UnicodeString appendTo; | |
390 | RunTestFieldPositionIteratorWithNItems( | |
391 | data, 2, expected, tupleCount, appendTo, | |
392 | u"bbb and cc", | |
393 | "TestFieldPositionIteratorWith2Items"); | |
394 | } | |
395 | ||
396 | void ListFormatterTest::TestFieldPositionIteratorWith2ItemsPatternShift() { | |
397 | // 0 1 | |
398 | // 01234567890 | |
399 | // "cc bbb" | |
400 | UnicodeString data[2] = {"bbb", "cc"}; | |
401 | int32_t expected[] = { | |
402 | ULISTFMT_ELEMENT_FIELD, 3, 6, | |
403 | ULISTFMT_LITERAL_FIELD, 2, 3, | |
404 | ULISTFMT_ELEMENT_FIELD, 0, 2 | |
405 | }; | |
406 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
407 | UnicodeString appendTo; | |
408 | RunTestFieldPositionIteratorWithNItemsPatternShift( | |
409 | data, 2, expected, tupleCount, appendTo, | |
410 | u"cc bbb", | |
411 | "TestFieldPositionIteratorWith2ItemsPatternShift"); | |
412 | } | |
413 | ||
414 | void ListFormatterTest::TestFieldPositionIteratorWith1ItemAndDataBefore() { | |
415 | // 012345678 | |
416 | // "Hello cc" | |
417 | UnicodeString data[1] = {"cc"}; | |
418 | int32_t expected[] = { | |
419 | ULISTFMT_ELEMENT_FIELD, 6, 8 | |
420 | }; | |
421 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
422 | UnicodeString appendTo("Hello "); | |
423 | RunTestFieldPositionIteratorWithNItems( | |
424 | data, 1, expected, tupleCount, appendTo, | |
425 | u"Hello cc", | |
426 | "TestFieldPositionIteratorWith1ItemAndDataBefore"); | |
427 | } | |
428 | ||
429 | void ListFormatterTest::TestFieldPositionIteratorWith1Item() { | |
430 | // 012 | |
431 | // "cc" | |
432 | UnicodeString data[1] = {"cc"}; | |
433 | int32_t expected[] = { | |
434 | ULISTFMT_ELEMENT_FIELD, 0, 2 | |
435 | }; | |
436 | int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); | |
437 | UnicodeString appendTo; | |
438 | RunTestFieldPositionIteratorWithNItems( | |
439 | data, 1, expected, tupleCount, appendTo, | |
440 | u"cc", | |
441 | "TestFieldPositionIteratorWith1Item"); | |
f3c0d7a5 A |
442 | } |
443 | ||
444 | // Tests resource loading and inheritance when region sublocale | |
445 | // has only partial data for the listPattern element (overriding | |
446 | // some of the parent data). #12994 | |
447 | void ListFormatterTest::TestNynorsk() { | |
448 | UnicodeString results[4] = { | |
449 | one, | |
450 | one + " og " + two, | |
451 | one + ", " + two + " og " + three, | |
452 | one + ", " + two + ", " + three + " og " + four | |
453 | }; | |
454 | ||
3d1f044b | 455 | CheckFourCases("nn", one, two, three, four, results, "TestNynorsk()"); |
f3c0d7a5 A |
456 | } |
457 | ||
458 | // Tests resource loading and inheritance when region sublocale | |
459 | // has only partial data for the listPattern element (overriding | |
460 | // some of the parent data). #12994 | |
461 | void ListFormatterTest::TestChineseTradHK() { | |
462 | UnicodeString and_string = UnicodeString("\\u53CA", -1, US_INV).unescape(); | |
463 | UnicodeString comma_string = UnicodeString("\\u3001", -1, US_INV).unescape(); | |
464 | UnicodeString results[4] = { | |
465 | one, | |
466 | one + and_string + two, | |
467 | one + comma_string + two + and_string + three, | |
468 | one + comma_string + two + comma_string + three + and_string + four | |
469 | }; | |
470 | ||
3d1f044b | 471 | CheckFourCases("zh_Hant_HK", one, two, three, four, results, "TestChineseTradHK()"); |
f3c0d7a5 A |
472 | } |
473 | ||
51004dcb A |
474 | // Formatting in Russian. |
475 | // "\\u0438" is used before the last element, and all elements up to (but not including) the penultimate are followed by a comma. | |
476 | void ListFormatterTest::TestRussian() { | |
477 | UnicodeString and_string = UnicodeString(" \\u0438 ", -1, US_INV).unescape(); | |
478 | UnicodeString results[4] = { | |
479 | one, | |
480 | one + and_string + two, | |
481 | one + ", " + two + and_string + three, | |
482 | one + ", " + two + ", " + three + and_string + four | |
483 | }; | |
484 | ||
3d1f044b | 485 | CheckFourCases("ru", one, two, three, four, results, "TestRussian()"); |
51004dcb A |
486 | } |
487 | ||
488 | // Formatting in Malayalam. | |
489 | // For two elements, "\\u0d15\\u0d42\\u0d1f\\u0d3e\\u0d24\\u0d46" is inserted in between. | |
490 | // For more than two elements, comma is inserted between all elements up to (and including) the penultimate, | |
491 | // and the word \\u0d0e\\u0d28\\u0d4d\\u0d28\\u0d3f\\u0d35 is inserted in the end. | |
492 | void ListFormatterTest::TestMalayalam() { | |
493 | UnicodeString pair_string = UnicodeString(" \\u0d15\\u0d42\\u0d1f\\u0d3e\\u0d24\\u0d46 ", -1, US_INV).unescape(); | |
494 | UnicodeString total_string = UnicodeString(" \\u0d0e\\u0d28\\u0d4d\\u0d28\\u0d3f\\u0d35", -1, US_INV).unescape(); | |
495 | UnicodeString results[4] = { | |
496 | one, | |
497 | one + pair_string + two, | |
498 | one + ", " + two + ", " + three + total_string, | |
499 | one + ", " + two + ", " + three + ", " + four + total_string | |
500 | }; | |
501 | ||
3d1f044b | 502 | CheckFourCases("ml", one, two, three, four, results, "TestMalayalam()"); |
51004dcb A |
503 | } |
504 | ||
505 | // Formatting in Zulu. | |
506 | // "and" is used before the last element, and all elements up to (and including) the penultimate are followed by a comma. | |
507 | void ListFormatterTest::TestZulu() { | |
508 | UnicodeString results[4] = { | |
509 | one, | |
f3c0d7a5 | 510 | one + " ne-" + two, |
b331163b A |
511 | one + ", " + two + ", ne-" + three, |
512 | one + ", " + two + ", " + three + ", ne-" + four | |
51004dcb A |
513 | }; |
514 | ||
3d1f044b | 515 | CheckFourCases("zu", one, two, three, four, results, "TestZulu()"); |
51004dcb A |
516 | } |
517 | ||
518 | void ListFormatterTest::TestOutOfOrderPatterns() { | |
519 | UnicodeString results[4] = { | |
520 | one, | |
521 | two + " after " + one, | |
522 | three + " in the last after " + two + " after the first " + one, | |
523 | four + " in the last after " + three + " after " + two + " after the first " + one | |
524 | }; | |
525 | ||
3d1f044b | 526 | IcuTestErrorCode errorCode(*this, "TestOutOfOrderPatterns()"); |
51004dcb A |
527 | ListFormatData data("{1} after {0}", "{1} after the first {0}", |
528 | "{1} after {0}", "{1} in the last after {0}"); | |
2ca993e8 | 529 | ListFormatter formatter(data, errorCode); |
51004dcb A |
530 | |
531 | UnicodeString input1[] = {one}; | |
3d1f044b | 532 | CheckFormatting(&formatter, input1, 1, results[0], "TestOutOfOrderPatterns()"); |
51004dcb A |
533 | |
534 | UnicodeString input2[] = {one, two}; | |
3d1f044b | 535 | CheckFormatting(&formatter, input2, 2, results[1], "TestOutOfOrderPatterns()"); |
51004dcb A |
536 | |
537 | UnicodeString input3[] = {one, two, three}; | |
3d1f044b | 538 | CheckFormatting(&formatter, input3, 3, results[2], "TestOutOfOrderPatterns()"); |
51004dcb A |
539 | |
540 | UnicodeString input4[] = {one, two, three, four}; | |
3d1f044b A |
541 | CheckFormatting(&formatter, input4, 4, results[3], "TestOutOfOrderPatterns()"); |
542 | } | |
543 | ||
544 | void ListFormatterTest::TestFormattedValue() { | |
545 | IcuTestErrorCode status(*this, "TestFormattedValue"); | |
546 | LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", status)); | |
547 | if (status.errIfFailureAndReset()) { return; } | |
548 | ||
549 | { | |
550 | const char16_t* message = u"Field position test 1"; | |
551 | const char16_t* expectedString = u"hello, wonderful, and world"; | |
552 | const UnicodeString inputs[] = { | |
553 | u"hello", | |
554 | u"wonderful", | |
555 | u"world" | |
556 | }; | |
557 | FormattedList result = fmt->formatStringsToValue(inputs, UPRV_LENGTHOF(inputs), status); | |
558 | static const UFieldPositionWithCategory expectedFieldPositions[] = { | |
559 | // field, begin index, end index | |
560 | {UFIELD_CATEGORY_LIST_SPAN, 0, 0, 5}, | |
561 | {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 5}, | |
562 | {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 5, 7}, | |
563 | {UFIELD_CATEGORY_LIST_SPAN, 1, 7, 16}, | |
564 | {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 7, 16}, | |
565 | {UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 22}, | |
566 | {UFIELD_CATEGORY_LIST_SPAN, 2, 22, 27}, | |
567 | {UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 22, 27}}; | |
568 | checkMixedFormattedValue( | |
569 | message, | |
570 | result, | |
571 | expectedString, | |
572 | expectedFieldPositions, | |
573 | UPRV_LENGTHOF(expectedFieldPositions)); | |
574 | } | |
575 | } | |
576 | ||
577 | void ListFormatterTest::DoTheRealListStyleTesting(Locale locale, | |
578 | UnicodeString items[], int itemCount, | |
579 | const char* style, const char* expected, IcuTestErrorCode status) { | |
580 | ||
581 | LocalPointer<ListFormatter> formatter( | |
582 | ListFormatter::createInstance(locale, style, status)); | |
583 | ||
584 | UnicodeString actualResult; | |
585 | formatter->format(items, itemCount, actualResult, status); | |
586 | assertEquals(style, UnicodeString(expected), actualResult); | |
587 | } | |
588 | ||
589 | void ListFormatterTest::TestDifferentStyles() { | |
590 | Locale locale("fr"); | |
591 | UnicodeString input[4] = { u"rouge", u"jaune", u"bleu", u"vert" }; | |
592 | IcuTestErrorCode status(*this, "TestDifferentStyles()"); | |
593 | ||
594 | DoTheRealListStyleTesting(locale, input, 4, "standard", "rouge, jaune, bleu et vert", status); | |
595 | DoTheRealListStyleTesting(locale, input, 4, "or", "rouge, jaune, bleu ou vert", status); | |
596 | DoTheRealListStyleTesting(locale, input, 4, "unit", "rouge, jaune, bleu et vert", status); | |
597 | DoTheRealListStyleTesting(locale, input, 4, "unit-narrow", "rouge jaune bleu vert", status); | |
598 | DoTheRealListStyleTesting(locale, input, 4, "unit-short", "rouge, jaune, bleu et vert", status); | |
599 | } | |
600 | ||
601 | void ListFormatterTest::TestBadStylesFail() { | |
602 | Locale locale("fr"); | |
603 | const char * badStyles[4] = { "", "duration", "duration-short", "something-clearly-wrong" }; | |
604 | IcuTestErrorCode status(*this, "TestBadStylesFail()"); | |
605 | ||
606 | for (int i = 0; i < 4; ++i) { | |
607 | LocalPointer<ListFormatter> formatter(ListFormatter::createInstance(locale, badStyles[i], status)); | |
608 | if (!status.expectErrorAndReset(U_MISSING_RESOURCE_ERROR, "style \"%s\"", badStyles[i])) { | |
609 | // Do nothing, expectErrorAndReset already reports the error | |
610 | } | |
611 | } | |
51004dcb A |
612 | } |
613 | ||
614 | void ListFormatterTest::runIndexedTest(int32_t index, UBool exec, | |
615 | const char* &name, char* /*par */) { | |
616 | switch(index) { | |
617 | case 0: name = "TestRoot"; if (exec) TestRoot(); break; | |
618 | case 1: name = "TestBogus"; if (exec) TestBogus(); break; | |
619 | case 2: name = "TestEnglish"; if (exec) TestEnglish(); break; | |
620 | case 3: name = "TestEnglishUS"; if (exec) TestEnglishUS(); break; | |
621 | case 4: name = "TestRussian"; if (exec) TestRussian(); break; | |
622 | case 5: name = "TestMalayalam"; if (exec) TestMalayalam(); break; | |
623 | case 6: name = "TestZulu"; if (exec) TestZulu(); break; | |
624 | case 7: name = "TestOutOfOrderPatterns"; if (exec) TestOutOfOrderPatterns(); break; | |
57a6839d | 625 | case 8: name = "Test9946"; if (exec) Test9946(); break; |
f3c0d7a5 A |
626 | case 9: name = "TestEnglishGB"; if (exec) TestEnglishGB(); break; |
627 | case 10: name = "TestNynorsk"; if (exec) TestNynorsk(); break; | |
628 | case 11: name = "TestChineseTradHK"; if (exec) TestChineseTradHK(); break; | |
3d1f044b A |
629 | case 12: name = "TestFieldPositionIteratorWontCrash"; |
630 | if (exec) TestFieldPositionIteratorWontCrash(); | |
631 | break; | |
632 | case 13: name = "TestFieldPositionIteratorWith1Item"; | |
633 | if (exec) TestFieldPositionIteratorWith1Item(); | |
634 | break; | |
635 | case 14: name = "TestFieldPositionIteratorWith1ItemAndDataBefore"; | |
636 | if (exec) TestFieldPositionIteratorWith1ItemAndDataBefore(); | |
637 | break; | |
638 | case 15: name = "TestFieldPositionIteratorWith2Items"; | |
639 | if (exec) TestFieldPositionIteratorWith2Items(); | |
640 | break; | |
641 | case 16: name = "TestFieldPositionIteratorWith2ItemsAndDataBefore"; | |
642 | if (exec) TestFieldPositionIteratorWith2ItemsAndDataBefore(); | |
643 | break; | |
644 | case 17: name = "TestFieldPositionIteratorWith2ItemsPatternShift"; | |
645 | if (exec) TestFieldPositionIteratorWith2ItemsPatternShift(); | |
646 | break; | |
647 | case 18: name = "TestFieldPositionIteratorWith3Items"; | |
648 | if (exec) TestFieldPositionIteratorWith3Items(); | |
649 | break; | |
650 | case 19: name = "TestFieldPositionIteratorWith3ItemsAndDataBefore"; | |
651 | if (exec) TestFieldPositionIteratorWith3ItemsAndDataBefore(); | |
652 | break; | |
653 | case 20: name = "TestFieldPositionIteratorWith3ItemsPatternShift"; | |
654 | if (exec) TestFieldPositionIteratorWith3ItemsPatternShift(); | |
655 | break; | |
656 | case 21: name = "TestFormattedValue"; | |
657 | if (exec) TestFormattedValue(); | |
658 | break; | |
659 | case 22: name = "TestDifferentStyles"; | |
660 | if (exec) TestDifferentStyles(); | |
661 | break; | |
662 | case 23: name = "TestBadStylesFail"; | |
663 | if (exec) TestBadStylesFail(); | |
664 | break; | |
51004dcb A |
665 | default: name = ""; break; |
666 | } | |
667 | } | |
3d1f044b A |
668 | |
669 | #endif /* #if !UCONFIG_NO_FORMATTING */ |