• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 *******************************************************************************
5 *
6 *   Copyright (C) 2012-2016, International Business Machines
7 *   Corporation and others.  All Rights Reserved.
8 *
9 *******************************************************************************
10 *   file name:  listformattertest.cpp
11 *   encoding:   UTF-8
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"
20 #include "unicode/ulistformatter.h"
21 #include "cmemory.h"
22 #include <string.h>
23 
24 #if !UCONFIG_NO_FORMATTING
25 
26 namespace {
attrString(int32_t attrId)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 
ExpectPositions(FieldPositionIterator & iter,int32_t * values,int32_t tupleCount)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 
ListFormatterTest()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 
CheckFormatting(const ListFormatter * formatter,UnicodeString data[],int32_t dataSize,const UnicodeString & expected_result,const char * testName)84 void ListFormatterTest::CheckFormatting(const ListFormatter* formatter, UnicodeString data[], int32_t dataSize,
85                                         const UnicodeString& expected_result, const char* testName) {
86     UnicodeString actualResult(prefix);
87     IcuTestErrorCode errorCode(*this, testName);
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 
CheckFourCases(const char * locale_string,UnicodeString one,UnicodeString two,UnicodeString three,UnicodeString four,UnicodeString results[4],const char * testName)95 void ListFormatterTest::CheckFourCases(const char* locale_string, UnicodeString one, UnicodeString two,
96         UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName) {
97     IcuTestErrorCode errorCode(*this, testName);
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};
104     CheckFormatting(formatter.getAlias(), input1, 1, results[0], testName);
105 
106     UnicodeString input2[] = {one, two};
107     CheckFormatting(formatter.getAlias(), input2, 2, results[1], testName);
108 
109     UnicodeString input3[] = {one, two, three};
110     CheckFormatting(formatter.getAlias(), input3, 3, results[2], testName);
111 
112     UnicodeString input4[] = {one, two, three, four};
113     CheckFormatting(formatter.getAlias(), input4, 4, results[3], testName);
114 }
115 
RecordFourCases(const Locale & locale,UnicodeString one,UnicodeString two,UnicodeString three,UnicodeString four,UnicodeString results[4],const char * testName)116 UBool ListFormatterTest::RecordFourCases(const Locale& locale, UnicodeString one, UnicodeString two,
117         UnicodeString three, UnicodeString four, UnicodeString results[4], const char* testName)  {
118     IcuTestErrorCode errorCode(*this, testName);
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 
TestRoot()139 void ListFormatterTest::TestRoot() {
140     UnicodeString results[4] = {
141         one,
142         one + ", " + two,
143         one + ", " + two + ", " + three,
144         one + ", " + two + ", " + three + ", " + four
145     };
146 
147     CheckFourCases("", one, two, three, four, results, "TestRoot()");
148 }
149 
150 // Bogus locale should fallback to root.
TestBogus()151 void ListFormatterTest::TestBogus() {
152     UnicodeString results[4];
153     if (RecordFourCases(Locale::getDefault(), one, two, three, four, results, "TestBogus()")) {
154       CheckFourCases("ex_PY", one, two, three, four, results, "TestBogus()");
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.
TestEnglish()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 
168     CheckFourCases("en", one, two, three, four, results, "TestEnglish()");
169 }
170 
Test9946()171 void ListFormatterTest::Test9946() {
172     IcuTestErrorCode errorCode(*this, "Test9946()");
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 
TestEnglishUS()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 
203     CheckFourCases("en_US", one, two, three, four, results, "TestEnglishUS()");
204 }
205 
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
TestEnglishGB()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 
217     CheckFourCases("en_GB", one, two, three, four, results, "TestEnglishGB()");
218 }
219 
TestFieldPositionIteratorWontCrash()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 
RunTestFieldPositionIteratorWithFormatter(ListFormatter * formatter,UnicodeString data[],int32_t n,int32_t expected[],int32_t tupleCount,UnicodeString & appendTo,const char16_t * expectedFormatted,const char * testName)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 
RunTestFieldPositionIteratorWithNItemsPatternShift(UnicodeString data[],int32_t n,int32_t expected[],int32_t tupleCount,UnicodeString & appendTo,const char16_t * expectedFormatted,const char * testName)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 
RunTestFieldPositionIteratorWithNItems(UnicodeString data[],int32_t n,int32_t expected[],int32_t tupleCount,UnicodeString & appendTo,const char16_t * expectedFormatted,const char * testName)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 
TestFieldPositionIteratorWith3ItemsAndDataBefore()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 
TestFieldPositionIteratorWith3Items()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 
TestFieldPositionIteratorWith3ItemsPatternShift()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 
TestFieldPositionIteratorWith2ItemsAndDataBefore()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 
TestFieldPositionIteratorWith2Items()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 
TestFieldPositionIteratorWith2ItemsPatternShift()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 
TestFieldPositionIteratorWith1ItemAndDataBefore()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 
TestFieldPositionIteratorWith1Item()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");
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
TestNynorsk()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 
455     CheckFourCases("nn", one, two, three, four, results, "TestNynorsk()");
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
TestChineseTradHK()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 
471     CheckFourCases("zh_Hant_HK", one, two, three, four, results, "TestChineseTradHK()");
472 }
473 
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.
TestRussian()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 
485     CheckFourCases("ru", one, two, three, four, results, "TestRussian()");
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.
TestMalayalam()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 
502     CheckFourCases("ml", one, two, three, four, results, "TestMalayalam()");
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.
TestZulu()507 void ListFormatterTest::TestZulu() {
508     UnicodeString results[4] = {
509         one,
510         one + " ne-" + two,
511         one + ", " + two + ", ne-" + three,
512         one + ", " + two + ", " + three + ", ne-" + four
513     };
514 
515     CheckFourCases("zu", one, two, three, four, results, "TestZulu()");
516 }
517 
TestOutOfOrderPatterns()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 
526     IcuTestErrorCode errorCode(*this, "TestOutOfOrderPatterns()");
527     ListFormatData data("{1} after {0}", "{1} after the first {0}",
528                         "{1} after {0}", "{1} in the last after {0}");
529     ListFormatter formatter(data, errorCode);
530 
531     UnicodeString input1[] = {one};
532     CheckFormatting(&formatter, input1, 1, results[0], "TestOutOfOrderPatterns()");
533 
534     UnicodeString input2[] = {one, two};
535     CheckFormatting(&formatter, input2, 2, results[1], "TestOutOfOrderPatterns()");
536 
537     UnicodeString input3[] = {one, two, three};
538     CheckFormatting(&formatter, input3, 3, results[2], "TestOutOfOrderPatterns()");
539 
540     UnicodeString input4[] = {one, two, three, four};
541     CheckFormatting(&formatter, input4, 4, results[3], "TestOutOfOrderPatterns()");
542 }
543 
TestFormattedValue()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 
DoTheRealListStyleTesting(Locale locale,UnicodeString items[],int itemCount,const char * style,const char * expected,IcuTestErrorCode status)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 
TestDifferentStyles()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 
TestBadStylesFail()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     }
612 }
613 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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;
625         case 8: name = "Test9946"; if (exec) Test9946(); break;
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;
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;
665         default: name = ""; break;
666     }
667 }
668 
669 #endif /* #if !UCONFIG_NO_FORMATTING */
670