1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2012-2016, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
10 * file name: listformattertest.cpp
12 * tab size: 8 (not used)
15 * created on: 2012aug27
16 * created by: Umesh P. Nair
19 #include "listformattertest.h"
20 #include "unicode/ulistformatter.h"
24 #if !UCONFIG_NO_FORMATTING
26 void ListFormatterTest::runIndexedTest(int32_t index
, UBool exec
,
27 const char* &name
, char* /*par */) {
29 TESTCASE_AUTO(TestRoot
);
30 TESTCASE_AUTO(TestBogus
);
31 TESTCASE_AUTO(TestEnglish
);
32 TESTCASE_AUTO(TestEnglishUS
);
33 TESTCASE_AUTO(TestRussian
);
34 TESTCASE_AUTO(TestMalayalam
);
35 TESTCASE_AUTO(TestZulu
);
36 TESTCASE_AUTO(TestOutOfOrderPatterns
);
37 TESTCASE_AUTO(Test9946
);
38 TESTCASE_AUTO(TestEnglishGB
);
39 TESTCASE_AUTO(TestNynorsk
);
40 TESTCASE_AUTO(TestChineseTradHK
);
41 TESTCASE_AUTO(TestFieldPositionIteratorWontCrash
);
42 TESTCASE_AUTO(TestFieldPositionIteratorWith1Item
);
43 TESTCASE_AUTO(TestFieldPositionIteratorWith1ItemAndDataBefore
);
44 TESTCASE_AUTO(TestFieldPositionIteratorWith2Items
);
45 TESTCASE_AUTO(TestFieldPositionIteratorWith2ItemsAndDataBefore
);
46 TESTCASE_AUTO(TestFieldPositionIteratorWith2ItemsPatternShift
);
47 TESTCASE_AUTO(TestFieldPositionIteratorWith3Items
);
48 TESTCASE_AUTO(TestFieldPositionIteratorWith3ItemsAndDataBefore
);
49 TESTCASE_AUTO(TestFieldPositionIteratorWith3ItemsPatternShift
);
50 TESTCASE_AUTO(TestFormattedValue
);
51 TESTCASE_AUTO(TestDifferentStyles
);
52 TESTCASE_AUTO(TestBadStylesFail
);
53 TESTCASE_AUTO(TestCreateStyled
);
54 TESTCASE_AUTO(TestContextual
);
59 const char* attrString(int32_t attrId
) {
61 case ULISTFMT_LITERAL_FIELD
: return "literal";
62 case ULISTFMT_ELEMENT_FIELD
: return "element";
63 default: return "xxx";
68 void ListFormatterTest::ExpectPositions(FieldPositionIterator
& iter
,
69 int32_t *values
, int32_t tupleCount
) {
72 if (tupleCount
> 10) {
73 assertTrue("internal error, tupleCount too large", FALSE
);
75 for (int i
= 0; i
< tupleCount
; ++i
) {
79 while (iter
.next(fp
)) {
81 int32_t id
= fp
.getField();
82 int32_t start
= fp
.getBeginIndex();
83 int32_t limit
= fp
.getEndIndex();
85 sprintf(buf
, "%24s %3d %3d %3d", attrString(id
), id
, start
, limit
);
87 for (int i
= 0; i
< tupleCount
; ++i
) {
91 if (values
[i
*3] == id
&& values
[i
*3+1] == start
&& values
[i
*3+2] == limit
) {
96 assertTrue((UnicodeString
)"found [" + attrString(id
) + "," + start
+ "," + limit
+ "]", ok
);
98 // check that all were found
100 for (int i
= 0; i
< tupleCount
; ++i
) {
103 assertTrue((UnicodeString
) "missing [" + attrString(values
[i
*3]) + "," + values
[i
*3+1] +
104 "," + values
[i
*3+2] + "]", found
[i
]);
107 assertTrue("no expected values were missing", ok
);
110 ListFormatterTest::ListFormatterTest() :
111 prefix("Prefix: ", -1, US_INV
),
112 one("Alice", -1, US_INV
), two("Bob", -1, US_INV
),
113 three("Charlie", -1, US_INV
), four("Delta", -1, US_INV
) {
116 void ListFormatterTest::CheckFormatting(const ListFormatter
* formatter
, UnicodeString data
[], int32_t dataSize
,
117 const UnicodeString
& expected_result
, const char* testName
) {
118 UnicodeString
actualResult(prefix
);
119 IcuTestErrorCode
errorCode(*this, testName
);
120 formatter
->format(data
, dataSize
, actualResult
, errorCode
);
121 UnicodeString expectedStringWithPrefix
= prefix
+ expected_result
;
122 if (expectedStringWithPrefix
!= actualResult
) {
123 errln(UnicodeString("Expected: |") + expectedStringWithPrefix
+ "|, Actual: |" + actualResult
+ "|");
127 void ListFormatterTest::CheckFourCases(const char* locale_string
, UnicodeString one
, UnicodeString two
,
128 UnicodeString three
, UnicodeString four
, UnicodeString results
[4], const char* testName
) {
129 IcuTestErrorCode
errorCode(*this, testName
);
130 LocalPointer
<ListFormatter
> formatter(ListFormatter::createInstance(Locale(locale_string
), errorCode
));
131 if (U_FAILURE(errorCode
)) {
132 dataerrln("ListFormatter::createInstance(Locale(\"%s\"), errorCode) failed in CheckFourCases: %s", locale_string
, u_errorName(errorCode
));
135 UnicodeString input1
[] = {one
};
136 CheckFormatting(formatter
.getAlias(), input1
, 1, results
[0], testName
);
138 UnicodeString input2
[] = {one
, two
};
139 CheckFormatting(formatter
.getAlias(), input2
, 2, results
[1], testName
);
141 UnicodeString input3
[] = {one
, two
, three
};
142 CheckFormatting(formatter
.getAlias(), input3
, 3, results
[2], testName
);
144 UnicodeString input4
[] = {one
, two
, three
, four
};
145 CheckFormatting(formatter
.getAlias(), input4
, 4, results
[3], testName
);
148 UBool
ListFormatterTest::RecordFourCases(const Locale
& locale
, UnicodeString one
, UnicodeString two
,
149 UnicodeString three
, UnicodeString four
, UnicodeString results
[4], const char* testName
) {
150 IcuTestErrorCode
errorCode(*this, testName
);
151 LocalPointer
<ListFormatter
> formatter(ListFormatter::createInstance(locale
, errorCode
));
152 if (U_FAILURE(errorCode
)) {
153 dataerrln("ListFormatter::createInstance(\"%s\", errorCode) failed in RecordFourCases: %s", locale
.getName(), u_errorName(errorCode
));
156 UnicodeString input1
[] = {one
};
157 formatter
->format(input1
, 1, results
[0], errorCode
);
158 UnicodeString input2
[] = {one
, two
};
159 formatter
->format(input2
, 2, results
[1], errorCode
);
160 UnicodeString input3
[] = {one
, two
, three
};
161 formatter
->format(input3
, 3, results
[2], errorCode
);
162 UnicodeString input4
[] = {one
, two
, three
, four
};
163 formatter
->format(input4
, 4, results
[3], errorCode
);
164 if (U_FAILURE(errorCode
)) {
165 errln("RecordFourCases failed: %s", u_errorName(errorCode
));
171 void ListFormatterTest::TestRoot() {
172 UnicodeString results
[4] = {
175 one
+ ", " + two
+ ", " + three
,
176 one
+ ", " + two
+ ", " + three
+ ", " + four
179 CheckFourCases("", one
, two
, three
, four
, results
, "TestRoot()");
182 // Bogus locale should fallback to root.
183 void ListFormatterTest::TestBogus() {
184 UnicodeString results
[4];
185 if (RecordFourCases(Locale::getDefault(), one
, two
, three
, four
, results
, "TestBogus()")) {
186 CheckFourCases("ex_PY", one
, two
, three
, four
, results
, "TestBogus()");
190 // Formatting in English.
191 // "and" is used before the last element, and all elements up to (and including) the penultimate are followed by a comma.
192 void ListFormatterTest::TestEnglish() {
193 UnicodeString results
[4] = {
196 one
+ ", " + two
+ ", and " + three
,
197 one
+ ", " + two
+ ", " + three
+ ", and " + four
200 CheckFourCases("en", one
, two
, three
, four
, results
, "TestEnglish()");
203 void ListFormatterTest::Test9946() {
204 IcuTestErrorCode
errorCode(*this, "Test9946()");
205 LocalPointer
<ListFormatter
> formatter(ListFormatter::createInstance(Locale("en"), errorCode
));
206 if (U_FAILURE(errorCode
)) {
208 "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in Test9946: %s",
209 u_errorName(errorCode
));
212 UnicodeString data
[3] = {"{0}", "{1}", "{2}"};
213 UnicodeString actualResult
;
214 formatter
->format(data
, 3, actualResult
, errorCode
);
215 if (U_FAILURE(errorCode
)) {
217 "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in Test9946: %s",
218 u_errorName(errorCode
));
221 UnicodeString
expected("{0}, {1}, and {2}");
222 if (expected
!= actualResult
) {
223 errln("Expected " + expected
+ ", got " + actualResult
);
227 void ListFormatterTest::TestEnglishUS() {
228 UnicodeString results
[4] = {
231 one
+ ", " + two
+ ", and " + three
,
232 one
+ ", " + two
+ ", " + three
+ ", and " + four
235 CheckFourCases("en_US", one
, two
, three
, four
, results
, "TestEnglishUS()");
238 // Tests resource loading and inheritance when region sublocale
239 // has only partial data for the listPattern element (overriding
240 // some of the parent data). #12994
241 void ListFormatterTest::TestEnglishGB() {
242 UnicodeString results
[4] = {
245 one
+ ", " + two
+ " and " + three
,
246 one
+ ", " + two
+ ", " + three
+ " and " + four
249 CheckFourCases("en_GB", one
, two
, three
, four
, results
, "TestEnglishGB()");
252 void ListFormatterTest::TestFieldPositionIteratorWontCrash() {
253 IcuTestErrorCode
errorCode(*this, "TestFieldPositionIteratorWontCrash()");
254 LocalPointer
<ListFormatter
> formatter(
255 ListFormatter::createInstance(Locale("en"), errorCode
));
256 if (U_FAILURE(errorCode
)) {
258 "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in "
259 "TestFieldPositionIteratorWontCrash: %s",
260 u_errorName(errorCode
));
263 UnicodeString data
[3] = {"a", "bbb", "cc"};
264 UnicodeString actualResult
;
265 // make sure NULL as FieldPositionIterator won't caused crash.
266 formatter
->format(data
, 3, actualResult
, nullptr, errorCode
);
267 if (U_FAILURE(errorCode
)) {
269 "ListFormatter::format(data, 3, nullptr, errorCode) "
270 "failed in TestFieldPositionIteratorWontCrash: %s",
271 u_errorName(errorCode
));
276 void ListFormatterTest::RunTestFieldPositionIteratorWithFormatter(
277 ListFormatter
* formatter
,
278 UnicodeString data
[], int32_t n
, int32_t expected
[], int32_t tupleCount
,
279 UnicodeString
& appendTo
, const char16_t *expectedFormatted
,
280 const char* testName
) {
281 IcuTestErrorCode
errorCode(*this, testName
);
282 FieldPositionIterator iter
;
283 formatter
->format(data
, n
, appendTo
, &iter
, errorCode
);
284 if (U_FAILURE(errorCode
)) {
286 "ListFormatter::format(data, %d, &iter, errorCode) "
287 "failed in %s: %s", n
, testName
, u_errorName(errorCode
));
290 if (appendTo
!= expectedFormatted
) {
291 errln(UnicodeString("Expected: |") + expectedFormatted
+ "|, Actual: |" + appendTo
+ "|");
293 ExpectPositions(iter
, expected
, tupleCount
);
296 void ListFormatterTest::RunTestFieldPositionIteratorWithNItemsPatternShift(
297 UnicodeString data
[], int32_t n
, int32_t expected
[], int32_t tupleCount
,
298 UnicodeString
& appendTo
, const char16_t *expectedFormatted
,
299 const char* testName
) {
300 IcuTestErrorCode
errorCode(*this, testName
);
301 LocalPointer
<ListFormatter
> formatter(
302 ListFormatter::createInstance(Locale("ur", "IN"), "unit-narrow", errorCode
));
303 if (U_FAILURE(errorCode
)) {
305 "ListFormatter::createInstance(Locale(\"ur\", \"IN\"), \"unit-narrow\", errorCode) failed in "
306 "%s: %s", testName
, u_errorName(errorCode
));
309 RunTestFieldPositionIteratorWithFormatter(
310 formatter
.getAlias(),
311 data
, n
, expected
, tupleCount
, appendTo
, expectedFormatted
, testName
);
314 void ListFormatterTest::RunTestFieldPositionIteratorWithNItems(
315 UnicodeString data
[], int32_t n
, int32_t expected
[], int32_t tupleCount
,
316 UnicodeString
& appendTo
, const char16_t *expectedFormatted
,
317 const char* testName
) {
318 IcuTestErrorCode
errorCode(*this, testName
);
319 LocalPointer
<ListFormatter
> formatter(
320 ListFormatter::createInstance(Locale("en"), errorCode
));
321 if (U_FAILURE(errorCode
)) {
323 "ListFormatter::createInstance(Locale(\"en\"), errorCode) failed in "
324 "%s: %s", testName
, u_errorName(errorCode
));
327 RunTestFieldPositionIteratorWithFormatter(
328 formatter
.getAlias(),
329 data
, n
, expected
, tupleCount
, appendTo
, expectedFormatted
, testName
);
332 void ListFormatterTest::TestFieldPositionIteratorWith3ItemsAndDataBefore() {
334 // 0123456789012345678901234567
335 // "Hello World: a, bbb, and cc"
336 UnicodeString data
[3] = {"a", "bbb", "cc"};
337 int32_t expected
[] = {
338 ULISTFMT_ELEMENT_FIELD
, 13, 14,
339 ULISTFMT_LITERAL_FIELD
, 14, 16,
340 ULISTFMT_ELEMENT_FIELD
, 16, 19,
341 ULISTFMT_LITERAL_FIELD
, 19, 25,
342 ULISTFMT_ELEMENT_FIELD
, 25, 27
344 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
345 UnicodeString
appendTo(u
"Hello World: ");
346 RunTestFieldPositionIteratorWithNItems(
347 data
, 3, expected
, tupleCount
, appendTo
,
348 u
"Hello World: a, bbb, and cc",
349 "TestFieldPositionIteratorWith3ItemsAndDataBefore");
352 void ListFormatterTest::TestFieldPositionIteratorWith3Items() {
356 UnicodeString data
[3] = {"a", "bbb", "cc"};
357 int32_t expected
[] = {
358 ULISTFMT_ELEMENT_FIELD
, 0, 1,
359 ULISTFMT_LITERAL_FIELD
, 1, 3,
360 ULISTFMT_ELEMENT_FIELD
, 3, 6,
361 ULISTFMT_LITERAL_FIELD
, 6, 12,
362 ULISTFMT_ELEMENT_FIELD
, 12, 14
364 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
365 UnicodeString appendTo
;
366 RunTestFieldPositionIteratorWithNItems(
367 data
, 3, expected
, tupleCount
, appendTo
,
369 "TestFieldPositionIteratorWith3Items");
372 void ListFormatterTest::TestFieldPositionIteratorWith3ItemsPatternShift() {
376 UnicodeString data
[3] = {"a", "bbb", "cc"};
377 int32_t expected
[] = {
378 ULISTFMT_ELEMENT_FIELD
, 7, 8,
379 ULISTFMT_LITERAL_FIELD
, 6, 7,
380 ULISTFMT_ELEMENT_FIELD
, 3, 6,
381 ULISTFMT_LITERAL_FIELD
, 2, 3,
382 ULISTFMT_ELEMENT_FIELD
, 0, 2
384 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
385 UnicodeString appendTo
;
386 RunTestFieldPositionIteratorWithNItemsPatternShift(
387 data
, 3, expected
, tupleCount
, appendTo
,
389 "TestFieldPositionIteratorWith3ItemsPatternShift");
392 void ListFormatterTest::TestFieldPositionIteratorWith2ItemsAndDataBefore() {
396 UnicodeString data
[2] = {"bbb", "cc"};
397 int32_t expected
[] = {
398 ULISTFMT_ELEMENT_FIELD
, 5, 8,
399 ULISTFMT_LITERAL_FIELD
, 8, 13,
400 ULISTFMT_ELEMENT_FIELD
, 13, 15
402 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
403 UnicodeString
appendTo("Foo: ");
404 RunTestFieldPositionIteratorWithNItems(
405 data
, 2, expected
, tupleCount
, appendTo
,
407 "TestFieldPositionIteratorWith2ItemsAndDataBefore");
410 void ListFormatterTest::TestFieldPositionIteratorWith2Items() {
414 UnicodeString data
[2] = {"bbb", "cc"};
415 int32_t expected
[] = {
416 ULISTFMT_ELEMENT_FIELD
, 0, 3,
417 ULISTFMT_LITERAL_FIELD
, 3, 8,
418 ULISTFMT_ELEMENT_FIELD
, 8, 10
420 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
421 UnicodeString appendTo
;
422 RunTestFieldPositionIteratorWithNItems(
423 data
, 2, expected
, tupleCount
, appendTo
,
425 "TestFieldPositionIteratorWith2Items");
428 void ListFormatterTest::TestFieldPositionIteratorWith2ItemsPatternShift() {
432 UnicodeString data
[2] = {"bbb", "cc"};
433 int32_t expected
[] = {
434 ULISTFMT_ELEMENT_FIELD
, 3, 6,
435 ULISTFMT_LITERAL_FIELD
, 2, 3,
436 ULISTFMT_ELEMENT_FIELD
, 0, 2
438 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
439 UnicodeString appendTo
;
440 RunTestFieldPositionIteratorWithNItemsPatternShift(
441 data
, 2, expected
, tupleCount
, appendTo
,
443 "TestFieldPositionIteratorWith2ItemsPatternShift");
446 void ListFormatterTest::TestFieldPositionIteratorWith1ItemAndDataBefore() {
449 UnicodeString data
[1] = {"cc"};
450 int32_t expected
[] = {
451 ULISTFMT_ELEMENT_FIELD
, 6, 8
453 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
454 UnicodeString
appendTo("Hello ");
455 RunTestFieldPositionIteratorWithNItems(
456 data
, 1, expected
, tupleCount
, appendTo
,
458 "TestFieldPositionIteratorWith1ItemAndDataBefore");
461 void ListFormatterTest::TestFieldPositionIteratorWith1Item() {
464 UnicodeString data
[1] = {"cc"};
465 int32_t expected
[] = {
466 ULISTFMT_ELEMENT_FIELD
, 0, 2
468 int32_t tupleCount
= sizeof(expected
)/(3 * sizeof(*expected
));
469 UnicodeString appendTo
;
470 RunTestFieldPositionIteratorWithNItems(
471 data
, 1, expected
, tupleCount
, appendTo
,
473 "TestFieldPositionIteratorWith1Item");
476 // Tests resource loading and inheritance when region sublocale
477 // has only partial data for the listPattern element (overriding
478 // some of the parent data). #12994
479 void ListFormatterTest::TestNynorsk() {
480 UnicodeString results
[4] = {
483 one
+ ", " + two
+ " og " + three
,
484 one
+ ", " + two
+ ", " + three
+ " og " + four
487 CheckFourCases("nn", one
, two
, three
, four
, results
, "TestNynorsk()");
490 // Tests resource loading and inheritance when region sublocale
491 // has only partial data for the listPattern element (overriding
492 // some of the parent data). #12994
493 void ListFormatterTest::TestChineseTradHK() {
494 UnicodeString and_string
= UnicodeString("\\u53CA", -1, US_INV
).unescape();
495 UnicodeString comma_string
= UnicodeString("\\u3001", -1, US_INV
).unescape();
496 UnicodeString results
[4] = {
498 one
+ and_string
+ two
,
499 one
+ comma_string
+ two
+ and_string
+ three
,
500 one
+ comma_string
+ two
+ comma_string
+ three
+ and_string
+ four
503 CheckFourCases("zh_Hant_HK", one
, two
, three
, four
, results
, "TestChineseTradHK()");
506 // Formatting in Russian.
507 // "\\u0438" is used before the last element, and all elements up to (but not including) the penultimate are followed by a comma.
508 void ListFormatterTest::TestRussian() {
509 UnicodeString and_string
= UnicodeString(" \\u0438 ", -1, US_INV
).unescape();
510 UnicodeString results
[4] = {
512 one
+ and_string
+ two
,
513 one
+ ", " + two
+ and_string
+ three
,
514 one
+ ", " + two
+ ", " + three
+ and_string
+ four
517 CheckFourCases("ru", one
, two
, three
, four
, results
, "TestRussian()");
520 // Formatting in Malayalam.
521 // For two elements, "\\u0d15\\u0d42\\u0d1f\\u0d3e\\u0d24\\u0d46" is inserted in between.
522 // For more than two elements, comma is inserted between all elements up to (and including) the penultimate,
523 // and the word \\u0d0e\\u0d28\\u0d4d\\u0d28\\u0d3f\\u0d35 is inserted in the end.
524 void ListFormatterTest::TestMalayalam() {
525 UnicodeString pair_string
= UnicodeString(" \\u0d15\\u0d42\\u0d1f\\u0d3e\\u0d24\\u0d46 ", -1, US_INV
).unescape();
526 UnicodeString total_string
= UnicodeString(" \\u0d0e\\u0d28\\u0d4d\\u0d28\\u0d3f\\u0d35", -1, US_INV
).unescape();
527 UnicodeString results
[4] = {
529 one
+ pair_string
+ two
,
530 one
+ ", " + two
+ ", " + three
+ total_string
,
531 one
+ ", " + two
+ ", " + three
+ ", " + four
+ total_string
534 CheckFourCases("ml", one
, two
, three
, four
, results
, "TestMalayalam()");
537 // Formatting in Zulu.
538 // "and" is used before the last element, and all elements up to (and including) the penultimate are followed by a comma.
539 void ListFormatterTest::TestZulu() {
540 UnicodeString results
[4] = {
543 one
+ ", " + two
+ ", ne-" + three
,
544 one
+ ", " + two
+ ", " + three
+ ", ne-" + four
547 CheckFourCases("zu", one
, two
, three
, four
, results
, "TestZulu()");
550 void ListFormatterTest::TestOutOfOrderPatterns() {
551 UnicodeString results
[4] = {
553 two
+ " after " + one
,
554 three
+ " in the last after " + two
+ " after the first " + one
,
555 four
+ " in the last after " + three
+ " after " + two
+ " after the first " + one
558 IcuTestErrorCode
errorCode(*this, "TestOutOfOrderPatterns()");
560 ListFormatData
data("{1} after {0}", "{1} after the first {0}",
561 "{1} after {0}", "{1} in the last after {0}", locale
);
562 ListFormatter
formatter(data
, errorCode
);
564 UnicodeString input1
[] = {one
};
565 CheckFormatting(&formatter
, input1
, 1, results
[0], "TestOutOfOrderPatterns()");
567 UnicodeString input2
[] = {one
, two
};
568 CheckFormatting(&formatter
, input2
, 2, results
[1], "TestOutOfOrderPatterns()");
570 UnicodeString input3
[] = {one
, two
, three
};
571 CheckFormatting(&formatter
, input3
, 3, results
[2], "TestOutOfOrderPatterns()");
573 UnicodeString input4
[] = {one
, two
, three
, four
};
574 CheckFormatting(&formatter
, input4
, 4, results
[3], "TestOutOfOrderPatterns()");
577 void ListFormatterTest::TestFormattedValue() {
578 IcuTestErrorCode
status(*this, "TestFormattedValue");
579 LocalPointer
<ListFormatter
> fmt(ListFormatter::createInstance("en", status
));
580 if (status
.errIfFailureAndReset()) { return; }
583 const char16_t* message
= u
"Field position test 1";
584 const char16_t* expectedString
= u
"hello, wonderful, and world";
585 const UnicodeString inputs
[] = {
590 FormattedList result
= fmt
->formatStringsToValue(inputs
, UPRV_LENGTHOF(inputs
), status
);
591 static const UFieldPositionWithCategory expectedFieldPositions
[] = {
592 // field, begin index, end index
593 {UFIELD_CATEGORY_LIST_SPAN
, 0, 0, 5},
594 {UFIELD_CATEGORY_LIST
, ULISTFMT_ELEMENT_FIELD
, 0, 5},
595 {UFIELD_CATEGORY_LIST
, ULISTFMT_LITERAL_FIELD
, 5, 7},
596 {UFIELD_CATEGORY_LIST_SPAN
, 1, 7, 16},
597 {UFIELD_CATEGORY_LIST
, ULISTFMT_ELEMENT_FIELD
, 7, 16},
598 {UFIELD_CATEGORY_LIST
, ULISTFMT_LITERAL_FIELD
, 16, 22},
599 {UFIELD_CATEGORY_LIST_SPAN
, 2, 22, 27},
600 {UFIELD_CATEGORY_LIST
, ULISTFMT_ELEMENT_FIELD
, 22, 27}};
601 checkMixedFormattedValue(
605 expectedFieldPositions
,
606 UPRV_LENGTHOF(expectedFieldPositions
));
610 void ListFormatterTest::DoTheRealListStyleTesting(Locale locale
,
611 UnicodeString items
[], int itemCount
,
612 const char* style
, const char* expected
, IcuTestErrorCode status
) {
614 LocalPointer
<ListFormatter
> formatter(
615 ListFormatter::createInstance(locale
, style
, status
));
617 UnicodeString actualResult
;
618 formatter
->format(items
, itemCount
, actualResult
, status
);
619 assertEquals(style
, UnicodeString(expected
), actualResult
);
622 void ListFormatterTest::TestDifferentStyles() {
624 UnicodeString input
[4] = { u
"rouge", u
"jaune", u
"bleu", u
"vert" };
625 IcuTestErrorCode
status(*this, "TestDifferentStyles()");
627 DoTheRealListStyleTesting(locale
, input
, 4, "standard", "rouge, jaune, bleu et vert", status
);
628 DoTheRealListStyleTesting(locale
, input
, 4, "or", "rouge, jaune, bleu ou vert", status
);
629 DoTheRealListStyleTesting(locale
, input
, 4, "unit", "rouge, jaune, bleu et vert", status
);
630 DoTheRealListStyleTesting(locale
, input
, 4, "unit-narrow", "rouge jaune bleu vert", status
);
631 DoTheRealListStyleTesting(locale
, input
, 4, "unit-short", "rouge, jaune, bleu et vert", status
);
634 void ListFormatterTest::TestBadStylesFail() {
636 const char * badStyles
[4] = { "", "duration", "duration-short", "something-clearly-wrong" };
637 IcuTestErrorCode
status(*this, "TestBadStylesFail()");
639 for (int i
= 0; i
< 4; ++i
) {
640 LocalPointer
<ListFormatter
> formatter(ListFormatter::createInstance(locale
, badStyles
[i
], status
));
641 if (!status
.expectErrorAndReset(U_MISSING_RESOURCE_ERROR
, "style \"%s\"", badStyles
[i
])) {
642 // Do nothing, expectErrorAndReset already reports the error
647 void ListFormatterTest::TestCreateStyled() {
648 IcuTestErrorCode
status(*this, "TestCreateStyled");
649 // Locale en has interesting data
652 UListFormatterType type
;
653 UListFormatterWidth width
;
654 const char16_t* expected3
;
655 const char16_t* expected2
;
656 const char16_t* expected1
;
658 { "pt", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_WIDE
, u
"A, B e C", u
"A e B", u
"A" },
659 { "pt", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_SHORT
, u
"A, B e C", u
"A e B", u
"A" },
660 { "pt", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_NARROW
, u
"A, B, C", u
"A, B", u
"A" },
661 { "pt", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_WIDE
, u
"A, B ou C", u
"A ou B", u
"A" },
662 { "pt", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_SHORT
, u
"A, B ou C", u
"A ou B", u
"A" },
663 { "pt", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_NARROW
, u
"A, B ou C", u
"A ou B", u
"A" },
664 { "pt", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_WIDE
, u
"A, B e C", u
"A e B", u
"A" },
665 { "pt", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_SHORT
, u
"A, B e C", u
"A e B", u
"A" },
666 { "pt", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_NARROW
, u
"A B C", u
"A B", u
"A" },
667 { "en", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_WIDE
, u
"A, B, and C", u
"A and B", u
"A" },
668 { "en", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_SHORT
, u
"A, B, & C", u
"A & B", u
"A" },
669 { "en", ULISTFMT_TYPE_AND
, ULISTFMT_WIDTH_NARROW
, u
"A, B, C", u
"A, B", u
"A" },
670 { "en", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_WIDE
, u
"A, B, or C", u
"A or B", u
"A" },
671 { "en", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_SHORT
, u
"A, B, or C", u
"A or B", u
"A" },
672 { "en", ULISTFMT_TYPE_OR
, ULISTFMT_WIDTH_NARROW
, u
"A, B, or C", u
"A or B", u
"A" },
673 { "en", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_WIDE
, u
"A, B, C", u
"A, B", u
"A" },
674 { "en", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_SHORT
, u
"A, B, C", u
"A, B", u
"A" },
675 { "en", ULISTFMT_TYPE_UNITS
, ULISTFMT_WIDTH_NARROW
, u
"A B C", u
"A B", u
"A" },
677 for (auto cas
: cases
) {
678 LocalPointer
<ListFormatter
> fmt(
679 ListFormatter::createInstance(cas
.locale
, cas
.type
, cas
.width
, status
),
681 if (status
.errIfFailureAndReset()) {
684 UnicodeString message
= UnicodeString(u
"TestCreateStyled loc=")
685 + cas
.locale
+ u
" type="
686 + Int64ToUnicodeString(cas
.type
) + u
" width="
687 + Int64ToUnicodeString(cas
.width
);
688 const UnicodeString inputs3
[] = {
693 FormattedList result
= fmt
->formatStringsToValue(inputs3
, UPRV_LENGTHOF(inputs3
), status
);
694 assertEquals(message
, cas
.expected3
, result
.toTempString(status
));
695 const UnicodeString inputs2
[] = {
699 result
= fmt
->formatStringsToValue(inputs2
, UPRV_LENGTHOF(inputs2
), status
);
700 assertEquals(message
, cas
.expected2
, result
.toTempString(status
));
701 const UnicodeString inputs1
[] = {
704 result
= fmt
->formatStringsToValue(inputs1
, UPRV_LENGTHOF(inputs1
), status
);
705 assertEquals(message
, cas
.expected1
, result
.toTempString(status
));
709 void ListFormatterTest::TestContextual() {
710 IcuTestErrorCode
status(*this, "TestContextual");
711 std::vector
<std::string
> es
= { "es", "es_419" , "es_PY", "es_DO" };
712 std::vector
<std::string
> he
= { "he", "he_IL", "iw", "iw_IL" };
713 std::vector
<std::string
> th
= { "th", "th_TH" };
714 UListFormatterWidth widths
[] = {
715 ULISTFMT_WIDTH_WIDE
, ULISTFMT_WIDTH_SHORT
, ULISTFMT_WIDTH_NARROW
718 std::vector
<std::string
> locales
;
719 UListFormatterType type
;
720 const char16_t* expected
;
721 const char16_t* data1
;
722 const char16_t* data2
;
723 const char16_t* data3
;
725 { es
, ULISTFMT_TYPE_AND
, u
"fascinante e increíblemente",
726 u
"fascinante", u
"increíblemente", nullptr },
727 { es
, ULISTFMT_TYPE_AND
, u
"Comunicaciones Industriales e IIoT",
728 u
"Comunicaciones Industriales", u
"IIoT", nullptr },
729 { es
, ULISTFMT_TYPE_AND
, u
"España e Italia", u
"España", u
"Italia", nullptr },
730 { es
, ULISTFMT_TYPE_AND
, u
"hijas intrépidas e hijos solidarios",
731 u
"hijas intrépidas", u
"hijos solidarios", nullptr },
732 { es
, ULISTFMT_TYPE_AND
, u
"a un hombre e hirieron a otro",
733 u
"a un hombre", u
"hirieron a otro", nullptr },
734 { es
, ULISTFMT_TYPE_AND
, u
"hija e hijo", u
"hija", u
"hijo", nullptr },
735 { es
, ULISTFMT_TYPE_AND
, u
"esposa, hija e hijo", u
"esposa", u
"hija", u
"hijo" },
737 { es
, ULISTFMT_TYPE_AND
, u
"oro y hierro", u
"oro", u
"hierro", nullptr },
738 { es
, ULISTFMT_TYPE_AND
, u
"agua y hielo", u
"agua", u
"hielo", nullptr },
739 { es
, ULISTFMT_TYPE_AND
, u
"colágeno y hialurónico", u
"colágeno", u
"hialurónico", nullptr },
741 { es
, ULISTFMT_TYPE_OR
, u
"desierto u oasis", u
"desierto", u
"oasis", nullptr },
742 { es
, ULISTFMT_TYPE_OR
, u
"oasis, desierto u océano", u
"oasis", u
"desierto", u
"océano" },
743 { es
, ULISTFMT_TYPE_OR
, u
"7 u 8", u
"7", u
"8", nullptr },
744 { es
, ULISTFMT_TYPE_OR
, u
"7 u 80", u
"7", u
"80", nullptr },
745 { es
, ULISTFMT_TYPE_OR
, u
"7 u 800", u
"7", u
"800", nullptr },
746 { es
, ULISTFMT_TYPE_OR
, u
"6, 7 u 8", u
"6", u
"7", u
"8" },
747 { es
, ULISTFMT_TYPE_OR
, u
"10 u 11", u
"10", u
"11", nullptr },
748 { es
, ULISTFMT_TYPE_OR
, u
"10 o 111", u
"10", u
"111", nullptr },
749 { es
, ULISTFMT_TYPE_OR
, u
"10 o 11.2", u
"10", u
"11.2", nullptr },
750 { es
, ULISTFMT_TYPE_OR
, u
"9, 10 u 11", u
"9", u
"10", u
"11" },
752 { he
, ULISTFMT_TYPE_AND
, u
"a, b ו-c", u
"a", u
"b", u
"c" },
753 { he
, ULISTFMT_TYPE_AND
, u
"a ו-b", u
"a", u
"b", nullptr },
754 { he
, ULISTFMT_TYPE_AND
, u
"1, 2 ו-3", u
"1", u
"2", u
"3" },
755 { he
, ULISTFMT_TYPE_AND
, u
"1 ו-2", u
"1", u
"2", nullptr },
756 { he
, ULISTFMT_TYPE_AND
, u
"אהבה ומקווה", u
"אהבה", u
"מקווה", nullptr },
757 { he
, ULISTFMT_TYPE_AND
, u
"אהבה, מקווה ואמונה", u
"אהבה", u
"מקווה", u
"אמונה" },
760 { th
, ULISTFMT_TYPE_AND
, u
"ข้อความธรรมดาและ 1 ภาพ", u
"ข้อความธรรมดา", u
"1 ภาพ", nullptr },
761 { th
, ULISTFMT_TYPE_AND
, u
"ข้อความธรรมดาและข้อความธรรมดา", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา", nullptr },
762 { th
, ULISTFMT_TYPE_AND
, u
"0 และ 1 ภาพ", u
"0", u
"1 ภาพ", nullptr },
763 { th
, ULISTFMT_TYPE_AND
, u
"0 และข้อความธรรมดา", u
"0", u
"ข้อความธรรมดา", nullptr },
764 { th
, ULISTFMT_TYPE_AND
, u
"ข้อความธรรมดา ข้อความธรรมดา และข้อความธรรมดา", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา" },
765 { th
, ULISTFMT_TYPE_AND
, u
"ข้อความธรรมดา ข้อความธรรมดา และ 1 ภาพ", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา", u
"1 ภาพ" },
766 { th
, ULISTFMT_TYPE_OR
, u
"ข้อความธรรมดา หรือ 1 ภาพ", u
"ข้อความธรรมดา", u
"1 ภาพ", nullptr },
767 { th
, ULISTFMT_TYPE_OR
, u
"ข้อความธรรมดา หรือ ข้อความธรรมดา", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา", nullptr },
768 { th
, ULISTFMT_TYPE_OR
, u
"ข้อความธรรมดา, ข้อความธรรมดา หรือ 1 ภาพ", u
"ข้อความธรรมดา", u
"ข้อความธรรมดา", u
"1 ภาพ" },
770 for (auto width
: widths
) {
771 for (auto cas
: cases
) {
772 for (auto locale
: cas
.locales
) {
773 if ((locale
== "th" || locale
== "th_TH") && cas
.type
== ULISTFMT_TYPE_OR
&& (width
== ULISTFMT_WIDTH_SHORT
|| width
== ULISTFMT_WIDTH_NARROW
)) {
774 // this test was written to assume all the widths product the same result, but that isn't
775 // true of the Thai "or" formats, so we skip the short and narrow Thai "or" formats (which
776 // work the same way as the "and" formats)
780 LocalPointer
<ListFormatter
> fmt(
781 ListFormatter::createInstance(locale
.c_str(), cas
.type
, width
, status
),
783 if (status
.errIfFailureAndReset()) {
786 UnicodeString message
= UnicodeString(u
"TestContextual loc=")
787 + locale
.c_str() + u
" type="
788 + Int64ToUnicodeString(cas
.type
) + u
" width="
789 + Int64ToUnicodeString(width
);
790 if (cas
.data3
== nullptr) {
791 const UnicodeString inputs2
[] = { cas
.data1
, cas
.data2
};
792 FormattedList result
= fmt
->formatStringsToValue(inputs2
, UPRV_LENGTHOF(inputs2
), status
);
793 assertEquals(message
, cas
.expected
, result
.toTempString(status
));
795 const UnicodeString inputs3
[] = { cas
.data1
, cas
.data2
, cas
.data3
};
796 FormattedList result
= fmt
->formatStringsToValue(inputs3
, UPRV_LENGTHOF(inputs3
), status
);
797 assertEquals(message
, cas
.expected
, result
.toTempString(status
));
804 #endif /* #if !UCONFIG_NO_FORMATTING */