1 /********************************************************************
3 * Copyright (c) 1997-2013, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************
8 * Modification History:
10 * Date Name Description
11 * 03/24/97 helena Converted from Java.
12 * 07/11/97 helena Updated to work on AIX.
13 * 08/04/97 jfitz Updated to intltest
14 *******************************************************************/
16 #include "unicode/utypes.h"
18 #if !UCONFIG_NO_FORMATTING
22 #include "unicode/format.h"
23 #include "unicode/decimfmt.h"
24 #include "unicode/localpointer.h"
25 #include "unicode/locid.h"
26 #include "unicode/msgfmt.h"
27 #include "unicode/numfmt.h"
28 #include "unicode/choicfmt.h"
29 #include "unicode/messagepattern.h"
30 #include "unicode/selfmt.h"
31 #include "unicode/gregocal.h"
34 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
37 TestMessageFormat::runIndexedTest(int32_t index
, UBool exec
,
38 const char* &name
, char* /*par*/) {
40 TESTCASE_AUTO(testBug1
);
41 TESTCASE_AUTO(testBug2
);
42 TESTCASE_AUTO(sample
);
43 TESTCASE_AUTO(PatternTest
);
44 TESTCASE_AUTO(testStaticFormat
);
45 TESTCASE_AUTO(testSimpleFormat
);
46 TESTCASE_AUTO(testMsgFormatChoice
);
47 TESTCASE_AUTO(testCopyConstructor
);
48 TESTCASE_AUTO(testAssignment
);
49 TESTCASE_AUTO(testClone
);
50 TESTCASE_AUTO(testEquals
);
51 TESTCASE_AUTO(testNotEquals
);
52 TESTCASE_AUTO(testSetLocale
);
53 TESTCASE_AUTO(testFormat
);
54 TESTCASE_AUTO(testParse
);
55 TESTCASE_AUTO(testAdopt
);
56 TESTCASE_AUTO(testCopyConstructor2
);
57 TESTCASE_AUTO(TestUnlimitedArgsAndSubformats
);
58 TESTCASE_AUTO(TestRBNF
);
59 TESTCASE_AUTO(TestTurkishCasing
);
60 TESTCASE_AUTO(testAutoQuoteApostrophe
);
61 TESTCASE_AUTO(testMsgFormatPlural
);
62 TESTCASE_AUTO(testMsgFormatSelect
);
63 TESTCASE_AUTO(testApostropheInPluralAndSelect
);
64 TESTCASE_AUTO(TestApostropheMode
);
65 TESTCASE_AUTO(TestCompatibleApostrophe
);
66 TESTCASE_AUTO(testCoverage
);
67 TESTCASE_AUTO(testGetFormatNames
);
68 TESTCASE_AUTO(TestTrimArgumentName
);
69 TESTCASE_AUTO(TestSelectOrdinal
);
70 TESTCASE_AUTO(TestDecimals
);
74 void TestMessageFormat::testBug3()
76 double myNumber
= -123456;
77 DecimalFormat
*form
= 0;
86 Locale("de", "AT", ""),
87 Locale("de", "CH", ""),
88 Locale("el", "", ""), // 10
89 Locale("en", "CA", ""),
90 Locale("en", "GB", ""),
91 Locale("en", "IE", ""),
92 Locale("en", "US", ""),
97 Locale("fr", "BE", ""),
98 Locale("fr", "CA", ""), // 20
99 Locale("fr", "CH", ""),
100 Locale("he", "", ""),
101 Locale("hr", "", ""),
102 Locale("hu", "", ""),
103 Locale("is", "", ""),
104 Locale("it", "", ""),
105 Locale("it", "CH", ""),
106 Locale("ja", "", ""),
107 Locale("ko", "", ""),
108 Locale("lt", "", ""), // 30
109 Locale("lv", "", ""),
110 Locale("mk", "", ""),
111 Locale("nl", "", ""),
112 Locale("nl", "BE", ""),
113 Locale("no", "", ""),
114 Locale("pl", "", ""),
115 Locale("pt", "", ""),
116 Locale("ro", "", ""),
117 Locale("ru", "", ""),
118 Locale("sh", "", ""), // 40
119 Locale("sk", "", ""),
120 Locale("sl", "", ""),
121 Locale("sq", "", ""),
122 Locale("sr", "", ""),
123 Locale("sv", "", ""),
124 Locale("tr", "", ""),
125 Locale("uk", "", ""),
126 Locale("zh", "", ""),
127 Locale("zh", "TW", "") // 49
130 for (i
= 0; i
< 49; i
++) {
131 UnicodeString buffer
;
132 logln(locale
[i
].getDisplayName(buffer
));
133 UErrorCode success
= U_ZERO_ERROR
;
134 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
135 form
= (DecimalFormat
*)NumberFormat::createInstance(locale
[i
], success
);
136 if (U_FAILURE(success
)) {
137 errln("Err: Number Format ");
138 logln("Number format creation failed.");
142 FieldPosition
pos(0);
144 form
->format(myNumber
, buffer
, pos
);
145 success
= U_ZERO_ERROR
;
146 ParsePosition parsePos
;
147 form
->parse(buffer
, result
, parsePos
);
148 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result
) + UnicodeString("[supposed output for result]"));
149 if (U_FAILURE(success
)) {
150 errln("Err: Number Format parse");
151 logln("Number format parse failed.");
157 void TestMessageFormat::testBug1()
159 const double limit
[] = {0.0, 1.0, 2.0};
160 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
163 ChoiceFormat
*cf
= new ChoiceFormat(limit
, formats
, 3);
164 FieldPosition
status(0);
165 UnicodeString toAppendTo
;
166 cf
->format((int32_t)1, toAppendTo
, status
);
167 if (toAppendTo
!= "1.0<=Arg<2.0") {
168 errln("ChoiceFormat cmp in testBug1");
174 void TestMessageFormat::testBug2()
176 UErrorCode status
= U_ZERO_ERROR
;
177 UnicodeString result
;
178 // {sfb} use double format in pattern, so result will match (not strictly necessary)
179 const UnicodeString pattern
= "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
180 logln("The input pattern : " + pattern
);
181 MessageFormat
*fmt
= new MessageFormat(pattern
, status
);
182 if (U_FAILURE(status
)) {
183 dataerrln("MessageFormat pattern creation failed. - %s", u_errorName(status
));
186 logln("The output pattern is : " + fmt
->toPattern(result
));
187 if (pattern
!= result
) {
188 errln("MessageFormat::toPattern() failed.");
194 #if defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711
195 //----------------------------------------------------
197 //----------------------------------------------------
200 std::ostream
& operator<<(std::ostream
& stream
, const Formattable
& obj
);
202 #include "unicode/datefmt.h"
207 operator<<( IntlTest
& stream
,
208 const Formattable
& obj
)
210 static DateFormat
*defDateFormat
= 0;
212 UnicodeString buffer
;
213 switch(obj
.getType()) {
214 case Formattable::kDate
:
215 if (defDateFormat
== 0) {
216 defDateFormat
= DateFormat::createInstance();
218 defDateFormat
->format(obj
.getDate(), buffer
);
221 case Formattable::kDouble
:
223 sprintf( convert
, "%lf", obj
.getDouble() );
224 stream
<< convert
<< "D";
226 case Formattable::kLong
:
227 stream
<< obj
.getLong() << "L";
229 case Formattable::kString
:
230 stream
<< "\"" << obj
.getString(buffer
) << "\"";
232 case Formattable::kArray
:
234 const Formattable
* array
;
235 array
= obj
.getArray(count
);
237 for (i
=0; i
<count
; ++i
) stream
<< array
[i
] << ( (i
==(count
-1)) ? "" : ", " );
241 stream
<< "INVALID_Formattable";
245 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE >= 199711 */
248 void TestMessageFormat::PatternTest()
250 Formattable testArgs
[] = {
251 Formattable(double(1)), Formattable(double(3456)),
252 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate
)
254 UnicodeString testCases
[] = {
255 "Quotes '', '{', 'a' {0} '{0}'",
256 "Quotes '', '{', 'a' {0,number} '{0}'",
257 "'{'1,number,'#',##} {1,number,'#',##}",
258 "There are {1} files on {2} at {3}.",
259 "On {2}, there are {1} files, with {0,number,currency}.",
260 "'{1,number,percent}', {1,number,percent},",
261 "'{1,date,full}', {1,date,full},",
262 "'{3,date,full}', {3,date,full},",
263 "'{1,number,#,##}' {1,number,#,##}",
266 // ICU 4.8 returns the original pattern (testCases),
267 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
268 /*UnicodeString testResultPatterns[] = {
269 "Quotes '', '{', a {0} '{'0}",
270 "Quotes '', '{', a {0,number} '{'0}",
271 "'{'1,number,#,##} {1,number,'#'#,##}",
272 "There are {1} files on {2} at {3}.",
273 "On {2}, there are {1} files, with {0,number,currency}.",
274 "'{'1,number,percent}, {1,number,percent},",
275 "'{'1,date,full}, {1,date,full},",
276 "'{'3,date,full}, {3,date,full},",
277 "'{'1,number,#,##} {1,number,#,##}"
280 UnicodeString testResultStrings
[] = {
281 "Quotes ', {, 'a' 1 {0}",
282 "Quotes ', {, 'a' 1 {0}",
283 "{1,number,'#',##} #34,56",
284 "There are 3,456 files on Disk at 1/12/70, 5:46 AM.",
285 "On Disk, there are 3,456 files, with $1.00.",
286 "{1,number,percent}, 345,600%,",
287 "{1,date,full}, Wednesday, December 31, 1969,",
288 "{3,date,full}, Monday, January 12, 1970,",
289 "{1,number,#,##} 34,56"
293 for (int32_t i
= 0; i
< 9; ++i
) {
294 //it_out << "\nPat in: " << testCases[i]);
296 MessageFormat
*form
= 0;
297 UErrorCode success
= U_ZERO_ERROR
;
298 UnicodeString buffer
;
299 form
= new MessageFormat(testCases
[i
], Locale::getUS(), success
);
300 if (U_FAILURE(success
)) {
301 dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success
));
302 logln(((UnicodeString
)"MessageFormat for ") + testCases
[i
] + " creation failed.\n");
305 // ICU 4.8 returns the original pattern (testCases),
306 // rather than toPattern() reconstituting a new, equivalent pattern string (testResultPatterns).
307 if (form
->toPattern(buffer
) != testCases
[i
]) {
308 // Note: An alternative test would be to build MessagePattern objects for
309 // both the input and output patterns and compare them, taking SKIP_SYNTAX etc.
311 // (Too much trouble...)
312 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i
);
313 //form->toPattern(buffer);
314 errln(((UnicodeString
)" Orig: ") + testCases
[i
]);
315 errln(((UnicodeString
)" Exp: ") + testCases
[i
]);
316 errln(((UnicodeString
)" Got: ") + buffer
);
319 //it_out << "Pat out: " << form->toPattern(buffer));
320 UnicodeString result
;
322 FieldPosition
fieldpos(0);
323 form
->format(testArgs
, count
, result
, fieldpos
, success
);
324 if (U_FAILURE(success
)) {
325 dataerrln("MessageFormat failed test #3 - %s", u_errorName(success
));
326 logln("TestMessageFormat::PatternTest failed test #3");
329 if (result
!= testResultStrings
[i
]) {
330 errln("TestMessageFormat::PatternTest failed test #4");
331 logln("TestMessageFormat::PatternTest failed #4.");
332 logln(UnicodeString(" Result: ") + result
);
333 logln(UnicodeString(" Expected: ") + testResultStrings
[i
] );
337 //it_out << "Result: " << result);
339 /* TODO: Look at this test and see if this is still a valid test */
340 logln("---------------- test parse ----------------");
342 form
->toPattern(buffer
);
343 logln("MSG pattern for parse: " + buffer
);
345 int32_t parseCount
= 0;
346 Formattable
* values
= form
->parse(result
, parseCount
, success
);
347 if (U_FAILURE(success
)) {
348 errln("MessageFormat failed test #5");
349 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success
);
350 } else if (parseCount
!= count
) {
351 errln("MSG count not %d as expected. Got %d", count
, parseCount
);
353 UBool failed
= FALSE
;
354 for (int32_t j
= 0; j
< parseCount
; ++j
) {
355 if (values
== 0 || testArgs
[j
] != values
[j
]) {
356 errln(((UnicodeString
)"MSG testargs[") + j
+ "]: " + toString(testArgs
[j
]));
357 errln(((UnicodeString
)"MSG values[") + j
+ "] : " + toString(values
[j
]));
362 errln("MessageFormat failed test #6");
368 void TestMessageFormat::sample()
370 MessageFormat
*form
= 0;
371 UnicodeString buffer1
, buffer2
;
372 UErrorCode success
= U_ZERO_ERROR
;
373 form
= new MessageFormat("There are {0} files on {1}", success
);
374 if (U_FAILURE(success
)) {
375 errln("Err: Message format creation failed");
376 logln("Sample message format creation failed.");
379 UnicodeString
abc("abc");
380 UnicodeString
def("def");
381 Formattable testArgs1
[] = { abc
, def
};
382 FieldPosition
fieldpos(0);
383 assertEquals("format",
384 "There are abc files on def",
385 form
->format(testArgs1
, 2, buffer2
, fieldpos
, success
));
386 assertSuccess("format", success
);
390 void TestMessageFormat::testStaticFormat()
392 UErrorCode err
= U_ZERO_ERROR
;
393 Formattable arguments
[] = {
395 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
396 "a disturbance in the Force"
399 UnicodeString result
;
400 result
= MessageFormat::format(
401 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
407 if (U_FAILURE(err
)) {
408 dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err
));
409 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err
);
413 const UnicodeString
expected(
414 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
415 if (result
!= expected
) {
416 errln("TestMessageFormat::testStaticFormat failed on test");
417 logln( UnicodeString(" Result: ") + result
);
418 logln( UnicodeString(" Expected: ") + expected
);
422 /* When the default locale is tr, make sure that the pattern can still be parsed. */
423 void TestMessageFormat::TestTurkishCasing()
425 UErrorCode err
= U_ZERO_ERROR
;
426 Locale saveDefaultLocale
;
427 Locale::setDefault( Locale("tr"), err
);
429 Formattable arguments
[] = {
431 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
432 "a disturbance in the Force"
435 UnicodeString result
;
436 result
= MessageFormat::format(
437 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
443 if (U_FAILURE(err
)) {
444 dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err
));
448 const UnicodeString
expected(
449 "At 12:20:00 on 8.08.1997, there was a disturbance in the Force on planet 7.", "");
450 if (result
!= expected
) {
451 errln("TestTurkishCasing failed on test");
452 errln( UnicodeString(" Result: ") + result
);
453 errln( UnicodeString(" Expected: ") + expected
);
455 Locale::setDefault( saveDefaultLocale
, err
);
458 void TestMessageFormat::testSimpleFormat(/* char* par */)
460 logln("running TestMessageFormat::testSimpleFormat");
462 UErrorCode err
= U_ZERO_ERROR
;
464 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
465 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
466 Formattable testArgs3
[] = {(int32_t)12, "MyDisk"};
468 MessageFormat
* form
= new MessageFormat(
469 "The disk \"{1}\" contains {0} file(s).", err
);
471 UnicodeString string
;
472 FieldPosition
ignore(FieldPosition::DONT_CARE
);
473 form
->format(testArgs1
, 2, string
, ignore
, err
);
474 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 0 file(s).") {
475 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err
));
478 ignore
.setField(FieldPosition::DONT_CARE
);
480 form
->format(testArgs2
, 2, string
, ignore
, err
);
481 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 1 file(s).") {
483 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string
+ " - " + u_errorName(err
));
486 ignore
.setField(FieldPosition::DONT_CARE
);
488 form
->format(testArgs3
, 2, string
, ignore
, err
);
489 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 12 file(s).") {
490 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string
+ " - " + u_errorName(err
));
496 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
498 logln("running TestMessageFormat::testMsgFormatChoice");
500 UErrorCode err
= U_ZERO_ERROR
;
502 MessageFormat
* form
= new MessageFormat("The disk \"{1}\" contains {0}.", err
);
503 double filelimits
[] = {0,1,2};
504 UnicodeString filepart
[] = {"no files","one file","{0,number} files"};
505 ChoiceFormat
* fileform
= new ChoiceFormat(filelimits
, filepart
, 3);
506 form
->setFormat(1,*fileform
); // NOT zero, see below
507 //is the format adopted?
509 FieldPosition
ignore(FieldPosition::DONT_CARE
);
510 UnicodeString string
;
511 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
512 form
->format(testArgs1
, 2, string
, ignore
, err
);
513 if (string
!= "The disk \"MyDisk\" contains no files.") {
514 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
517 ignore
.setField(FieldPosition::DONT_CARE
);
519 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
520 form
->format(testArgs2
, 2, string
, ignore
, err
);
521 if (string
!= "The disk \"MyDisk\" contains one file.") {
522 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
525 ignore
.setField(FieldPosition::DONT_CARE
);
527 Formattable testArgs3
[] = {(int32_t)1273, "MyDisk"};
528 form
->format(testArgs3
, 2, string
, ignore
, err
);
529 if (string
!= "The disk \"MyDisk\" contains 1,273 files.") {
530 dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err
));
538 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
540 logln("running TestMessageFormat::testMsgFormatPlural");
542 UErrorCode err
= U_ZERO_ERROR
;
543 UnicodeString
t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
544 UnicodeString
t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
545 UnicodeString
t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
546 UnicodeString
t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
547 UnicodeString
t5("{0, plural, one {{0, number,C''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
548 MessageFormat
* mfNum
= new MessageFormat(t1
, Locale("fr"), err
);
549 if (U_FAILURE(err
)) {
550 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err
));
551 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
554 Formattable
testArgs1((int32_t)0);
555 FieldPosition
ignore(FieldPosition::DONT_CARE
);
556 UnicodeString numResult1
;
557 mfNum
->format(&testArgs1
, 1, numResult1
, ignore
, err
);
559 MessageFormat
* mfAlpha
= new MessageFormat(t2
, Locale("fr"), err
);
560 UnicodeString argName
[] = {UnicodeString("argument")};
561 UnicodeString argNameResult
;
562 mfAlpha
->format(argName
, &testArgs1
, 1, argNameResult
, err
);
563 if (U_FAILURE(err
)) {
564 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentName - %s", u_errorName(err
));
565 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
569 if ( numResult1
!= argNameResult
){
570 errln("TestMessageFormat::testMsgFormatPlural #1");
571 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
573 if ( numResult1
!= UnicodeString("C\'est 0 fichier dans la liste.")) {
574 errln("TestMessageFormat::testMsgFormatPlural #1");
575 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
582 MessageFormat
* mfNum2
= new MessageFormat(t3
, Locale("uk"), err
);
584 Formattable
testArgs2((int32_t)4);
585 mfNum2
->format(&testArgs2
, 1, numResult1
, ignore
, err
);
586 MessageFormat
* mfAlpha2
= new MessageFormat(t4
, Locale("uk"), err
);
587 argNameResult
.remove();
588 mfAlpha2
->format(argName
, &testArgs2
, 1, argNameResult
, err
);
590 if (U_FAILURE(err
)) {
591 errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
592 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err
);
596 if ( numResult1
!= argNameResult
){
597 errln("TestMessageFormat::testMsgFormatPlural #2");
598 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
600 if ( numResult1
!= UnicodeString("There are 4,0 zavoda in the directory.")) {
601 errln("TestMessageFormat::testMsgFormatPlural #2");
602 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
610 MessageFormat
* msgFmt
= new MessageFormat(t5
, Locale("fr"), err
);
611 if (U_FAILURE(err
)) {
612 errln("TestMessageFormat::test nested PluralFormat with argumentName");
613 logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err
);
617 Formattable
testArgs3((int32_t)0);
618 argNameResult
.remove();
619 msgFmt
->format(&testArgs3
, 1, argNameResult
, ignore
, err
);
620 if (U_FAILURE(err
)) {
621 errln("TestMessageFormat::test nested PluralFormat with argumentName");
623 if ( argNameResult
!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
624 errln(UnicodeString("TestMessageFormat::test nested named PluralFormat: ") + argNameResult
);
625 logln(UnicodeString("The unexpected nested named PluralFormat."));
630 void TestMessageFormat::testApostropheInPluralAndSelect() {
631 UErrorCode errorCode
= U_ZERO_ERROR
;
632 MessageFormat
msgFmt(UNICODE_STRING_SIMPLE(
633 "abc_{0,plural,other{#'#'#'{'#''}}_def_{1,select,other{sel'}'ect''}}_xyz"),
634 Locale::getEnglish(),
636 if (U_FAILURE(errorCode
)) {
637 errln("MessageFormat constructor failed - %s\n", u_errorName(errorCode
));
640 UnicodeString expected
= UNICODE_STRING_SIMPLE("abc_3#3{3'_def_sel}ect'_xyz");
641 Formattable args
[] = { (int32_t)3, UNICODE_STRING_SIMPLE("x") };
643 &msgFmt
, args
, 2, expected
,
644 "MessageFormat with apostrophes in plural/select arguments failed:\n");
647 void TestMessageFormat::internalFormat(MessageFormat
* msgFmt
,
648 Formattable
* args
, int32_t numOfArgs
,
649 UnicodeString expected
, const char* errMsg
)
651 UnicodeString result
;
652 FieldPosition
ignore(FieldPosition::DONT_CARE
);
653 UErrorCode status
= U_ZERO_ERROR
;
655 //Format with passed arguments
656 msgFmt
->format( args
, numOfArgs
, result
, ignore
, status
);
657 if (U_FAILURE(status
)) {
658 dataerrln( "%s error while formatting with ErrorCode as %s" ,errMsg
, u_errorName(status
) );
660 //Compare expected with obtained result
661 if ( result
!= expected
) {
662 UnicodeString err
= UnicodeString(errMsg
);
663 err
+= UnicodeString(":Unexpected Result \n Expected: " + expected
+ "\n Obtained: " + result
+ "\n");
668 MessageFormat
* TestMessageFormat::internalCreate(
669 UnicodeString pattern
,Locale locale
,UErrorCode
&status
, char* errMsg
)
671 //Create the MessageFormat with simple SelectFormat
672 MessageFormat
* msgFmt
= new MessageFormat(pattern
, locale
, status
);
673 if (U_FAILURE(status
)) {
674 dataerrln( "%s error while constructing with ErrorCode as %s" ,errMsg
, u_errorName(status
) );
675 logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status
);
681 void TestMessageFormat::testMsgFormatSelect(/* char* par */)
683 logln("running TestMessageFormat::testMsgFormatSelect");
685 UErrorCode err
= U_ZERO_ERROR
;
687 UnicodeString
t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
690 //Create the MessageFormat with simple French pattern
691 MessageFormat
* msgFmt1
= internalCreate(t1
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t1");
692 if (!U_FAILURE(err
)) {
694 Formattable testArgs10
[] = {"Kirti","female"};
695 Formattable testArgs11
[] = {"Victor","other"};
696 Formattable testArgs12
[] = {"Ash","unknown"};
697 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
698 UnicodeString exp
[] = {
699 "Kirti est all\\u00E9e \\u00E0 Paris." ,
700 "Victor est all\\u00E9 \\u00E0 Paris.",
701 "Ash est all\\u00E9 \\u00E0 Paris."};
703 for( int i
=0; i
< 3; i
++){
704 internalFormat( msgFmt1
, testArgs
[i
], 2, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
709 //Quoted French Pattern
710 UnicodeString
t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
712 //Create the MessageFormat with Quoted French pattern
713 MessageFormat
* msgFmt2
= internalCreate(t2
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t2");
714 if (!U_FAILURE(err
)) {
716 Formattable testArgs10
[] = {"Kirti","female"};
717 Formattable testArgs11
[] = {"Victor","other"};
718 Formattable testArgs12
[] = {"Ash","male"};
719 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
720 UnicodeString exp
[] = {
721 "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
722 "Victor est all\\u00E9 c'est \\u00E0 Paris.",
723 "Ash est all\\u00E9 c'est \\u00E0 Paris."};
725 for( int i
=0; i
< 3; i
++){
726 internalFormat( msgFmt2
, testArgs
[i
], 2, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
732 UnicodeString
t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
734 //Create the MessageFormat with English pattern
735 MessageFormat
* msgFmt3
= internalCreate(t3
, Locale("en"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t3");
736 if (!U_FAILURE(err
)) {
738 Formattable testArgs10
[] = {"female"};
739 Formattable testArgs11
[] = {"other"};
740 Formattable testArgs12
[] = {"male"};
741 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
742 UnicodeString exp
[] = {
743 "FEMALE FR company published new books." ,
744 "FR otherValue published new books.",
745 "MALE FR company published new books."};
747 for( int i
=0; i
< 3; i
++){
748 internalFormat( msgFmt3
, testArgs
[i
], 1, exp
[i
] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
753 //Nested patterns with plural, number ,choice ,select format etc.
754 //Select Format with embedded number format
755 UnicodeString
t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
757 //Create the MessageFormat with Select Format with embedded number format (nested pattern)
758 MessageFormat
* msgFmt4
= internalCreate(t4
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t4");
759 if (!U_FAILURE(err
)) {
761 Formattable testArgs10
[] = {"Kirti","female",(int32_t)6};
762 Formattable testArgs11
[] = {"Kirti","female",100.100};
763 Formattable testArgs12
[] = {"Kirti","other",(int32_t)6};
764 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
765 UnicodeString exp
[] = {
766 "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
767 "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
768 "Kirti est all\\u00E9 \\u00E0 Paris."};
770 for( int i
=0; i
< 3; i
++){
771 internalFormat( msgFmt4
, testArgs
[i
], 3, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
776 //Plural format with embedded select format
777 UnicodeString
t5("{0} {1, plural, one {est {2, select, female {all\\u00E9e} other {all\\u00E9}}} other {sont {2, select, female {all\\u00E9es} other {all\\u00E9s}}}} \\u00E0 Paris.");
779 //Create the MessageFormat with Plural format with embedded select format(nested pattern)
780 MessageFormat
* msgFmt5
= internalCreate(t5
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t5");
781 if (!U_FAILURE(err
)) {
783 Formattable testArgs10
[] = {"Kirti",(int32_t)6,"female"};
784 Formattable testArgs11
[] = {"Kirti",(int32_t)1,"female"};
785 Formattable testArgs12
[] = {"Ash",(int32_t)1,"other"};
786 Formattable testArgs13
[] = {"Ash",(int32_t)5,"other"};
787 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
,testArgs13
};
788 UnicodeString exp
[] = {
789 "Kirti sont all\\u00E9es \\u00E0 Paris." ,
790 "Kirti est all\\u00E9e \\u00E0 Paris.",
791 "Ash est all\\u00E9 \\u00E0 Paris.",
792 "Ash sont all\\u00E9s \\u00E0 Paris."};
794 for( int i
=0; i
< 4; i
++){
795 internalFormat( msgFmt5
, testArgs
[i
], 3, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
801 //Select, plural, and number formats heavily nested
802 UnicodeString
t6("{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris.");
803 //Create the MessageFormat with Select, plural, and number formats heavily nested
804 MessageFormat
* msgFmt6
= internalCreate(t6
, Locale("de"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t6");
805 if (!U_FAILURE(err
)) {
807 Formattable testArgs10
[] = {"Kirti","other",(int32_t)1,"other"};
808 Formattable testArgs11
[] = {"Kirti","other",(int32_t)6,"other"};
809 Formattable testArgs12
[] = {"Kirti","other",(int32_t)1,"female"};
810 Formattable testArgs13
[] = {"Kirti","other",(int32_t)3,"female"};
811 Formattable testArgs14
[] = {"Kirti","female",(int32_t)1,"female"};
812 Formattable testArgs15
[] = {"Kirti","female",(int32_t)5,"female"};
813 Formattable testArgs16
[] = {"Kirti","female",(int32_t)1,"other"};
814 Formattable testArgs17
[] = {"Kirti","female",(int32_t)5,"other"};
815 Formattable testArgs18
[] = {"Kirti","mixed",(int32_t)1,"mixed"};
816 Formattable testArgs19
[] = {"Kirti","mixed",(int32_t)1,"other"};
817 Formattable testArgs20
[] = {"Kirti","female",(int32_t)1,"mixed"};
818 Formattable testArgs21
[] = {"Kirti","mixed",(int32_t)5,"mixed"};
819 Formattable testArgs22
[] = {"Kirti","mixed",(int32_t)5,"other"};
820 Formattable testArgs23
[] = {"Kirti","female",(int32_t)5,"mixed"};
821 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
,testArgs13
,
822 testArgs14
,testArgs15
,testArgs16
,testArgs17
,
823 testArgs18
,testArgs19
,testArgs20
,testArgs21
,
824 testArgs22
,testArgs23
};
825 UnicodeString exp
[] = {
826 "Kirti und sein Freund gingen nach Paris." ,
827 "Kirti und seine 6 Freunde gingen nach Paris." ,
828 "Kirti und seine Freundin gingen nach Paris.",
829 "Kirti und seine 3 Freundinnen gingen nach Paris.",
830 "Kirti und ihre Freundin gingen nach Paris.",
831 "Kirti und ihre 5 Freundinnen gingen nach Paris.",
832 "Kirti und ihr Freund gingen nach Paris.",
833 "Kirti und ihre 5 Freunde gingen nach Paris.",
834 "Kirti und sein Freund gingen nach Paris.",
835 "Kirti und sein Freund gingen nach Paris.",
836 "Kirti und ihr Freund gingen nach Paris.",
837 "Kirti und seine 5 Freunde gingen nach Paris." ,
838 "Kirti und seine 5 Freunde gingen nach Paris." ,
839 "Kirti und ihre 5 Freunde gingen nach Paris."
842 for( int i
=0; i
< 14; i
++){
843 internalFormat( msgFmt6
, testArgs
[i
], 4, exp
[i
] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
849 //---------------------------------
851 //---------------------------------
853 void TestMessageFormat::testCopyConstructor()
855 UErrorCode success
= U_ZERO_ERROR
;
856 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
857 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
858 MessageFormat
*y
= 0;
859 y
= new MessageFormat(*x
);
863 logln("First test (operator ==): Passed!");
865 errln("TestMessageFormat::testCopyConstructor failed #1");
866 logln("First test (operator ==): Failed!");
868 if ( ((*x
== *y
) && (*y
== *x
)) &&
869 ((*x
!= *z
) && (*z
!= *x
)) &&
870 ((*y
!= *z
) && (*z
!= *y
)) )
871 logln("Second test (equals): Passed!");
873 errln("TestMessageFormat::testCopyConstructor failed #2");
874 logln("Second test (equals): Failed!");
883 void TestMessageFormat::testAssignment()
885 UErrorCode success
= U_ZERO_ERROR
;
886 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
887 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
888 MessageFormat
*y
= new MessageFormat("There are {0} files on {1} created", success
);
893 logln("First test (operator ==): Passed!");
895 errln( "TestMessageFormat::testAssignment failed #1");
896 logln("First test (operator ==): Failed!");
898 if ( ((*x
== *y
) && (*y
== *x
)) &&
899 ((*x
!= *z
) && (*z
!= *x
)) &&
900 ((*y
!= *z
) && (*z
!= *y
)) )
901 logln("Second test (equals): Passed!");
903 errln("TestMessageFormat::testAssignment failed #2");
904 logln("Second test (equals): Failed!");
912 void TestMessageFormat::testClone()
914 UErrorCode success
= U_ZERO_ERROR
;
915 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
916 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
917 MessageFormat
*y
= 0;
918 y
= (MessageFormat
*)x
->clone();
922 logln("First test (operator ==): Passed!");
924 errln("TestMessageFormat::testClone failed #1");
925 logln("First test (operator ==): Failed!");
927 if ( ((*x
== *y
) && (*y
== *x
)) &&
928 ((*x
!= *z
) && (*z
!= *x
)) &&
929 ((*y
!= *z
) && (*z
!= *y
)) )
930 logln("Second test (equals): Passed!");
932 errln("TestMessageFormat::testClone failed #2");
933 logln("Second test (equals): Failed!");
941 void TestMessageFormat::testEquals()
943 UErrorCode success
= U_ZERO_ERROR
;
944 MessageFormat
x("There are {0} files on {1}", success
);
945 MessageFormat
y("There are {0} files on {1}", success
);
947 errln( "TestMessageFormat::testEquals failed #1");
948 logln("First test (operator ==): Failed!");
953 void TestMessageFormat::testNotEquals()
955 UErrorCode success
= U_ZERO_ERROR
;
956 MessageFormat
x("There are {0} files on {1}", success
);
958 y
.setLocale(Locale("fr"));
960 errln( "TestMessageFormat::testEquals failed #1");
961 logln("First test (operator !=): Failed!");
964 y
.applyPattern("There are {0} files on {1} the disk", success
);
966 errln( "TestMessageFormat::testEquals failed #1");
967 logln("Second test (operator !=): Failed!");
972 void TestMessageFormat::testSetLocale()
974 UErrorCode err
= U_ZERO_ERROR
;
975 GregorianCalendar
cal(err
);
976 Formattable arguments
[] = {
978 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
982 UnicodeString result
;
984 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
985 UnicodeString formatStr
= "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
986 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
987 // Just use unlocalized currency symbol.
988 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
989 UnicodeString compareStrEng
= "At <time> on Aug 8, 1997, you made a deposit of ";
990 compareStrEng
+= (UChar
) 0x00a4;
991 compareStrEng
+= "456.83.";
992 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
993 // Just use unlocalized currency symbol.
994 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
995 UnicodeString compareStrGer
= "At <time> on 08.08.1997, you made a deposit of ";
996 compareStrGer
+= "456,83";
997 compareStrGer
+= (UChar
) 0x00a0;
998 compareStrGer
+= (UChar
) 0x00a4;
999 compareStrGer
+= ".";
1001 MessageFormat
msg( formatStr
, err
);
1003 FieldPosition
pos(0);
1004 result
= msg
.format(
1012 if (result
!= compareStrEng
) {
1013 dataerrln("*** MSG format err. - %s", u_errorName(err
));
1016 msg
.setLocale(Locale::getEnglish());
1017 UBool getLocale_ok
= TRUE
;
1018 if (msg
.getLocale() != Locale::getEnglish()) {
1019 errln("*** MSG getLocal err.");
1020 getLocale_ok
= FALSE
;
1023 msg
.setLocale(Locale::getGerman());
1025 if (msg
.getLocale() != Locale::getGerman()) {
1026 errln("*** MSG getLocal err.");
1027 getLocale_ok
= FALSE
;
1030 msg
.applyPattern( formatStr
, err
);
1034 result
= msg
.format(
1042 if (result
== compareStrGer
) {
1043 logln("MSG setLocale tested.");
1045 dataerrln( "*** MSG setLocale err. - %s", u_errorName(err
));
1049 logln("MSG getLocale tested.");
1053 void TestMessageFormat::testFormat()
1055 UErrorCode err
= U_ZERO_ERROR
;
1056 GregorianCalendar
cal(err
);
1058 const Formattable ftarray
[] =
1060 Formattable( UDate(8.71068e+011), Formattable::kIsDate
)
1062 const int32_t ft_cnt
= sizeof(ftarray
) / sizeof(Formattable
);
1063 Formattable
ft_arr( ftarray
, ft_cnt
);
1065 Formattable
* fmt
= new Formattable(UDate(8.71068e+011), Formattable::kIsDate
);
1067 UnicodeString result
;
1069 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
1070 UnicodeString formatStr
= "On {0,date}, it began.";
1071 UnicodeString compareStr
= "On Aug 8, 1997, it began.";
1074 MessageFormat
msg( formatStr
, err
);
1075 FieldPosition
fp(0);
1079 result
= msg
.format(
1086 if (err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1087 dataerrln("*** MSG format without expected error code. - %s", u_errorName(err
));
1093 result
= msg
.format(
1100 logln("MSG format( Formattable&, ... ) expected:" + compareStr
);
1101 logln("MSG format( Formattable&, ... ) result:" + result
);
1102 if (result
!= compareStr
) {
1103 dataerrln("*** MSG format( Formattable&, .... ) err. - %s", u_errorName(err
));
1105 logln("MSG format( Formattable&, ... ) tested.");
1112 void TestMessageFormat::testParse()
1114 UErrorCode err
= U_ZERO_ERROR
;
1116 UnicodeString msgFormatString
= "{0} =sep= {1}";
1117 MessageFormat
msg( msgFormatString
, err
);
1118 UnicodeString source
= "abc =sep= def";
1119 UnicodeString tmp1
, tmp2
;
1121 Formattable
* fmt_arr
= msg
.parse( source
, count
, err
);
1122 if (U_FAILURE(err
) || (!fmt_arr
)) {
1123 errln("*** MSG parse (ustring, count, err) error.");
1125 logln("MSG parse -- count: %d", count
);
1127 errln("*** MSG parse (ustring, count, err) count err.");
1129 if ((fmt_arr
[0].getType() == Formattable::kString
)
1130 && (fmt_arr
[1].getType() == Formattable::kString
)
1131 && (fmt_arr
[0].getString(tmp1
) == "abc")
1132 && (fmt_arr
[1].getString(tmp2
) == "def")) {
1133 logln("MSG parse (ustring, count, err) tested.");
1135 errln("*** MSG parse (ustring, count, err) result err.");
1141 ParsePosition
pp(0);
1143 fmt_arr
= msg
.parse( source
, pp
, count
);
1144 if ((pp
== 0) || (!fmt_arr
)) {
1145 errln("*** MSG parse (ustring, parsepos., count) error.");
1147 logln("MSG parse -- count: %d", count
);
1149 errln("*** MSG parse (ustring, parsepos., count) count err.");
1151 if ((fmt_arr
[0].getType() == Formattable::kString
)
1152 && (fmt_arr
[1].getType() == Formattable::kString
)
1153 && (fmt_arr
[0].getString(tmp1
) == "abc")
1154 && (fmt_arr
[1].getString(tmp2
) == "def")) {
1155 logln("MSG parse (ustring, parsepos., count) tested.");
1157 errln("*** MSG parse (ustring, parsepos., count) result err.");
1166 msg
.parseObject( source
, fmta
, pp
);
1168 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
1170 logln("MSG parse -- count: %d", count
);
1171 fmta
.getArray(count
);
1173 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
1175 if ((fmta
[0].getType() == Formattable::kString
)
1176 && (fmta
[1].getType() == Formattable::kString
)
1177 && (fmta
[0].getString(tmp1
) == "abc")
1178 && (fmta
[1].getString(tmp2
) == "def")) {
1179 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
1181 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
1188 void TestMessageFormat::testAdopt()
1190 UErrorCode err
= U_ZERO_ERROR
;
1192 UnicodeString
formatStr("{0,date},{1},{2,number}", "");
1193 UnicodeString
formatStrChange("{0,number},{1,number},{2,date}", "");
1195 MessageFormat
msg( formatStr
, err
);
1196 MessageFormat
msgCmp( formatStr
, err
);
1197 if (U_FAILURE(err
)) {
1198 dataerrln("Unable to instantiate MessageFormat - %s", u_errorName(err
));
1201 int32_t count
, countCmp
;
1202 const Format
** formats
= msg
.getFormats(count
);
1203 const Format
** formatsCmp
= msgCmp
.getFormats(countCmp
);
1204 const Format
** formatsChg
= 0;
1205 const Format
** formatsAct
= 0;
1209 UnicodeString patCmp
;
1210 UnicodeString patAct
;
1211 Format
** formatsToAdopt
;
1213 if (!formats
|| !formatsCmp
|| (count
<= 0) || (count
!= countCmp
)) {
1214 dataerrln("Error getting Formats");
1220 for (i
= 0; i
< count
; i
++) {
1223 if ((a
!= NULL
) && (b
!= NULL
)) {
1228 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1229 errln("(a != NULL) || (b != NULL)");
1234 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1236 formatsChg
= msg
.getFormats(countChg
); // tested function
1237 if (!formatsChg
|| (countChg
!= count
)) {
1238 errln("Error getting Formats");
1244 for (i
= 0; i
< count
; i
++) {
1247 if ((a
!= NULL
) && (b
!= NULL
)) {
1249 logln("formatsChg == formatsCmp at index %d", i
);
1255 errln("*** MSG getFormats diff err.");
1259 logln("MSG getFormats tested.");
1261 msg
.setFormats( formatsCmp
, countCmp
); //tested function
1263 formatsAct
= msg
.getFormats(countAct
);
1264 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1265 errln("Error getting Formats");
1269 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1270 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1271 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1272 msg
.toPattern(patCmp
.remove());
1273 if (!patCmp
.isBogus()) {
1274 errln("msg.setFormat().toPattern() succeeds.");
1277 for (i
= 0; i
< countAct
; i
++) {
1280 if ((a
!= NULL
) && (b
!= NULL
)) {
1282 logln("formatsAct != formatsCmp at index %d", i
);
1286 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1287 errln("(a != NULL) || (b != NULL)");
1291 logln("MSG setFormats tested.");
1295 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1297 formatsToAdopt
= new Format
* [countCmp
];
1298 if (!formatsToAdopt
) {
1299 errln("memory allocation error");
1303 for (i
= 0; i
< countCmp
; i
++) {
1304 if (formatsCmp
[i
] == NULL
) {
1305 formatsToAdopt
[i
] = NULL
;
1307 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1308 if (!formatsToAdopt
[i
]) {
1309 errln("Can't clone format at index %d", i
);
1314 msg
.adoptFormats( formatsToAdopt
, countCmp
); // function to test
1315 delete[] formatsToAdopt
;
1317 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1318 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1319 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1321 formatsAct
= msg
.getFormats(countAct
);
1322 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1323 errln("Error getting Formats");
1327 for (i
= 0; i
< countAct
; i
++) {
1330 if ((a
!= NULL
) && (b
!= NULL
)) {
1335 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1336 errln("(a != NULL) || (b != NULL)");
1340 logln("MSG adoptFormats tested.");
1344 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1346 formatsToAdopt
= new Format
* [countCmp
];
1347 if (!formatsToAdopt
) {
1348 errln("memory allocation error");
1352 for (i
= 0; i
< countCmp
; i
++) {
1353 if (formatsCmp
[i
] == NULL
) {
1354 formatsToAdopt
[i
] = NULL
;
1356 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1357 if (!formatsToAdopt
[i
]) {
1358 errln("Can't clone format at index %d", i
);
1364 for ( i
= 0; i
< countCmp
; i
++ ) {
1365 msg
.adoptFormat( i
, formatsToAdopt
[i
] ); // function to test
1367 delete[] formatsToAdopt
; // array itself not needed in this case;
1369 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1370 // ICU 4.8 does not support toPattern() when there are custom formats (from setFormat() etc.).
1371 // assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1373 formatsAct
= msg
.getFormats(countAct
);
1374 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1375 errln("Error getting Formats");
1379 for (i
= 0; i
< countAct
; i
++) {
1382 if ((a
!= NULL
) && (b
!= NULL
)) {
1387 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1388 errln("(a != NULL) || (b != NULL)");
1392 logln("MSG adoptFormat tested.");
1395 // This test is a regression test for a fixed bug in the copy constructor.
1396 // It is kept as a global function rather than as a method since the test depends on memory values.
1397 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1398 // which is probably why it didn't show up in the regular test for the copy constructor.)
1399 // For this reason, the test isn't changed even though it contains function calls whose results are
1400 // not tested and had no problems. Actually, the test failed by *crashing*.
1401 static void _testCopyConstructor2()
1403 UErrorCode status
= U_ZERO_ERROR
;
1404 UnicodeString
formatStr("Hello World on {0,date,full}", "");
1405 UnicodeString
resultStr(" ", "");
1406 UnicodeString result
;
1407 FieldPosition
fp(0);
1408 UDate d
= Calendar::getNow();
1409 const Formattable
fargs( d
, Formattable::kIsDate
);
1411 MessageFormat
* fmt1
= new MessageFormat( formatStr
, status
);
1412 MessageFormat
* fmt2
= NULL
;
1413 MessageFormat
* fmt3
= NULL
;
1414 MessageFormat
* fmt4
= NULL
;
1417 it_err("testCopyConstructor2: (fmt1 != NULL)");
1421 fmt2
= new MessageFormat( *fmt1
);
1422 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1425 it_err("testCopyConstructor2: (fmt2 != NULL)");
1429 fmt3
= (MessageFormat
*) fmt1
->clone();
1430 fmt4
= (MessageFormat
*) fmt2
->clone();
1433 it_err("testCopyConstructor2: (fmt3 != NULL)");
1437 it_err("testCopyConstructor2: (fmt4 != NULL)");
1441 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1442 result
= fmt2
->format( &fargs
, 1, resultStr
, fp
, status
);
1443 result
= fmt3
->format( &fargs
, 1, resultStr
, fp
, status
);
1444 result
= fmt4
->format( &fargs
, 1, resultStr
, fp
, status
);
1453 void TestMessageFormat::testCopyConstructor2() {
1454 _testCopyConstructor2();
1458 * Verify that MessageFormat accomodates more than 10 arguments and
1459 * more than 10 subformats.
1461 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1462 UErrorCode ec
= U_ZERO_ERROR
;
1463 const UnicodeString pattern
=
1464 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1465 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1466 "there were {1,number} werjes "
1467 "(a {3,number,percent} increase over {2,number}) "
1468 "despite the {4}''s efforts "
1469 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1470 MessageFormat
msg(pattern
, ec
);
1471 if (U_FAILURE(ec
)) {
1472 dataerrln("FAIL: constructor failed - %s", u_errorName(ec
));
1476 const Formattable ARGS
[] = {
1477 Formattable(UDate(1e13
), Formattable::kIsDate
),
1478 Formattable((int32_t)1303),
1479 Formattable((int32_t)1202),
1480 Formattable(1303.0/1202 - 1),
1481 Formattable("Glimmung"),
1482 Formattable("the printers"),
1483 Formattable("Nick"),
1484 Formattable("his father"),
1485 Formattable("his mother"),
1486 Formattable("the spiddles"),
1487 Formattable("of course"),
1488 Formattable("Horace"),
1490 const int32_t ARGS_LENGTH
= sizeof(ARGS
) / sizeof(ARGS
[0]);
1491 Formattable
ARGS_OBJ(ARGS
, ARGS_LENGTH
);
1493 UnicodeString expected
=
1494 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1495 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1496 "there were 1,303 werjes "
1497 "(a 8% increase over 1,202) "
1498 "despite the Glimmung's efforts "
1499 "and to delight of the printers, Nick, his father, "
1500 "his mother, the spiddles, and of course Horace.";
1501 UnicodeString result
;
1502 msg
.format(ARGS_OBJ
, result
, ec
);
1503 if (result
== expected
) {
1506 errln((UnicodeString
)"FAIL: Got " + result
+
1507 ", expected " + expected
);
1511 // test RBNF extensions to message format
1512 void TestMessageFormat::TestRBNF(void) {
1513 // WARNING: this depends on the RBNF formats for en_US
1514 Locale
locale("en", "US", "");
1516 UErrorCode ec
= U_ZERO_ERROR
;
1518 UnicodeString values
[] = {
1519 // decimal values do not format completely for ordinal or duration, and
1520 // do not always parse, so do not include them
1521 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1523 int32_t values_count
= sizeof(values
)/sizeof(values
[0]);
1525 UnicodeString formats
[] = {
1526 "There are {0,spellout} files to search.",
1527 "There are {0,spellout,%simplified} files to search.",
1528 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1529 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1530 "Searching this file will take {0,duration} to complete.",
1531 "Searching this file will take {0,duration,%with-words} to complete.",
1533 int32_t formats_count
= sizeof(formats
)/sizeof(formats
[0]);
1535 Formattable args
[1];
1537 NumberFormat
* numFmt
= NumberFormat::createInstance(locale
, ec
);
1538 if (U_FAILURE(ec
)) {
1539 dataerrln("Error calling NumberFormat::createInstance()");
1543 for (int i
= 0; i
< formats_count
; ++i
) {
1544 MessageFormat
* fmt
= new MessageFormat(formats
[i
], locale
, ec
);
1545 logln((UnicodeString
)"Testing format pattern: '" + formats
[i
] + "'");
1547 for (int j
= 0; j
< values_count
; ++j
) {
1549 numFmt
->parse(values
[j
], args
[0], ec
);
1550 if (U_FAILURE(ec
)) {
1551 errln((UnicodeString
)"Failed to parse test argument " + values
[j
]);
1553 FieldPosition
fp(0);
1554 UnicodeString result
;
1555 fmt
->format(args
, 1, result
, fp
, ec
);
1556 logln((UnicodeString
)"value: " + toString(args
[0]) + " --> " + result
+ UnicodeString(" ec: ") + u_errorName(ec
));
1558 if (i
!= 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1560 Formattable
* parseResult
= fmt
->parse(result
, count
, ec
);
1562 errln((UnicodeString
)"parse returned " + count
+ " args");
1563 } else if (parseResult
[0] != args
[0]) {
1564 errln((UnicodeString
)"parsed argument " + toString(parseResult
[0]) + " != " + toString(args
[0]));
1566 delete []parseResult
;
1575 UnicodeString
TestMessageFormat::GetPatternAndSkipSyntax(const MessagePattern
& pattern
) {
1576 UnicodeString
us(pattern
.getPatternString());
1577 int count
= pattern
.countParts();
1578 for (int i
= count
; i
> 0;) {
1579 const MessagePattern::Part
& part
= pattern
.getPart(--i
);
1580 if (part
.getType() == UMSGPAT_PART_TYPE_SKIP_SYNTAX
) {
1581 us
.remove(part
.getIndex(), part
.getLimit() - part
.getIndex());
1587 void TestMessageFormat::TestApostropheMode() {
1588 UErrorCode status
= U_ZERO_ERROR
;
1589 MessagePattern
*ado_mp
= new MessagePattern(UMSGPAT_APOS_DOUBLE_OPTIONAL
, status
);
1590 MessagePattern
*adr_mp
= new MessagePattern(UMSGPAT_APOS_DOUBLE_REQUIRED
, status
);
1591 if (ado_mp
->getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL
) {
1592 errln("wrong value from ado_mp->getApostropheMode().");
1594 if (adr_mp
->getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED
) {
1595 errln("wrong value from adr_mp->getApostropheMode().");
1599 UnicodeString tuples
[] = {
1601 // DOUBLE_OPTIONAL pattern
1602 // DOUBLE_REQUIRED pattern (empty=same as DOUBLE_OPTIONAL)
1603 "I see {many}", "I see '{many}'", "",
1604 "I said {'Wow!'}", "I said '{''Wow!''}'", "",
1605 "I dont know", "I dont know", "I don't know",
1606 "I don't know", "I don't know", "I don''t know",
1607 "I don't know", "I don''t know", "I don''t know"
1609 int32_t tuples_count
= LENGTHOF(tuples
);
1611 for (int i
= 0; i
< tuples_count
; i
+= 3) {
1612 UnicodeString
& desired
= tuples
[i
];
1613 UnicodeString
& ado_pattern
= tuples
[i
+ 1];
1614 UErrorCode status
= U_ZERO_ERROR
;
1615 assertEquals("DOUBLE_OPTIONAL failure",
1617 GetPatternAndSkipSyntax(ado_mp
->parse(ado_pattern
, NULL
, status
)));
1618 UnicodeString
& adr_pattern
= tuples
[i
+ 2].isEmpty() ? ado_pattern
: tuples
[i
+ 2];
1619 assertEquals("DOUBLE_REQUIRED failure", desired
,
1620 GetPatternAndSkipSyntax(adr_mp
->parse(adr_pattern
, NULL
, status
)));
1627 // Compare behavior of DOUBLE_OPTIONAL (new default) and DOUBLE_REQUIRED JDK-compatibility mode.
1628 void TestMessageFormat::TestCompatibleApostrophe() {
1629 // Message with choice argument which does not contain another argument.
1630 // The JDK performs only one apostrophe-quoting pass on this pattern.
1631 UnicodeString pattern
= "ab{0,choice,0#1'2''3'''4''''.}yz";
1633 UErrorCode ec
= U_ZERO_ERROR
;
1634 MessageFormat
compMsg("", Locale::getUS(), ec
);
1635 compMsg
.applyPattern(pattern
, UMSGPAT_APOS_DOUBLE_REQUIRED
, NULL
, ec
);
1636 if (compMsg
.getApostropheMode() != UMSGPAT_APOS_DOUBLE_REQUIRED
) {
1637 errln("wrong value from compMsg.getApostropheMode().");
1640 MessageFormat
icuMsg("", Locale::getUS(), ec
);
1641 icuMsg
.applyPattern(pattern
, UMSGPAT_APOS_DOUBLE_OPTIONAL
, NULL
, ec
);
1642 if (icuMsg
.getApostropheMode() != UMSGPAT_APOS_DOUBLE_OPTIONAL
) {
1643 errln("wrong value from icuMsg.getApostropheMode().");
1646 Formattable zero0
[] = { (int32_t)0 };
1647 FieldPosition
fieldpos(0);
1648 UnicodeString buffer1
, buffer2
;
1649 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1651 compMsg
.format(zero0
, 1, buffer1
, fieldpos
, ec
));
1652 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1654 icuMsg
.format(zero0
, 1, buffer2
, fieldpos
, ec
));
1656 // Message with choice argument which contains a nested simple argument.
1657 // The DOUBLE_REQUIRED version performs two apostrophe-quoting passes.
1660 pattern
= "ab{0,choice,0#1'2''3'''4''''.{0,number,'#x'}}yz";
1661 compMsg
.applyPattern(pattern
, ec
);
1662 icuMsg
.applyPattern(pattern
, ec
);
1663 if (U_FAILURE(ec
)) {
1664 dataerrln("Unable to applyPattern - %s", u_errorName(ec
));
1666 assertEquals("incompatible ICU MessageFormat compatibility-apostrophe behavior",
1668 compMsg
.format(zero0
, 1, buffer1
, fieldpos
, ec
));
1669 assertEquals("unexpected ICU MessageFormat double-apostrophe-optional behavior",
1670 "ab1'2'3''4''.#x0yz",
1671 icuMsg
.format(zero0
, 1, buffer2
, fieldpos
, ec
));
1674 // This part is copied over from Java tests but cannot be properly tested here
1675 // because we do not have a live reference implementation with JDK behavior.
1676 // The JDK ChoiceFormat itself always performs one apostrophe-quoting pass.
1678 ChoiceFormat choice = new ChoiceFormat("0#1'2''3'''4''''.");
1679 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1682 choice.applyPattern("0#1'2''3'''4''''.{0,number,'#x'}");
1683 assertEquals("unexpected JDK ChoiceFormat apostrophe behavior",
1684 "12'3'4''.{0,number,#x}",
1689 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1690 const char* patterns
[] = { // pattern, expected pattern
1701 "{'a{}'a}'a", "{'a{}'a}''a",
1703 "'} '{'}'", "'} '{'}''",
1704 "'} {{{''", "'} {{{'''",
1706 int32_t pattern_count
= sizeof(patterns
)/sizeof(patterns
[0]);
1708 for (int i
= 0; i
< pattern_count
; i
+= 2) {
1709 UErrorCode status
= U_ZERO_ERROR
;
1710 UnicodeString result
= MessageFormat::autoQuoteApostrophe(patterns
[i
], status
);
1711 UnicodeString
target(patterns
[i
+1]);
1712 if (target
!= result
) {
1713 const int BUF2_LEN
= 64;
1715 char buf2
[BUF2_LEN
];
1716 int32_t len
= result
.extract(0, result
.length(), buf2
, BUF2_LEN
);
1717 if (len
>= BUF2_LEN
) {
1718 buf2
[BUF2_LEN
-1] = 0;
1720 sprintf(buf
, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i
/2, patterns
[i
], patterns
[i
+1], buf2
);
1726 void TestMessageFormat::testCoverage(void) {
1727 UErrorCode status
= U_ZERO_ERROR
;
1728 UnicodeString
testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
1729 MessageFormat
*msgfmt
= new MessageFormat(testformat
, Locale("fr"), status
);
1730 if (msgfmt
== NULL
|| U_FAILURE(status
)) {
1731 dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status
));
1734 if (!msgfmt
->usesNamedArguments()) {
1735 errln("FAIL: Unable to detect usage of named arguments.");
1737 const double limit
[] = {0.0, 1.0, 2.0};
1738 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
1741 ChoiceFormat
cf(limit
, formats
, 3);
1743 msgfmt
->setFormat("set", cf
, status
);
1745 StringEnumeration
*en
= msgfmt
->getFormatNames(status
);
1746 if (en
== NULL
|| U_FAILURE(status
)) {
1747 errln("FAIL: Unable to get format names enumeration.");
1751 count
= en
->count(status
);
1752 if (U_FAILURE(status
)) {
1753 errln("FAIL: Unable to get format name enumeration count.");
1755 for (int32_t i
= 0; i
< count
; i
++) {
1757 if (U_FAILURE(status
)) {
1758 errln("FAIL: Error enumerating through names.");
1765 // adoptFormat() takes ownership of the input Format object.
1766 // We need to clone the stack-allocated cf so that we do not attempt to delete cf.
1767 Format
*cfClone
= cf
.clone();
1768 msgfmt
->adoptFormat("adopt", cfClone
, status
);
1773 msgfmt
= new MessageFormat("'", status
);
1774 if (msgfmt
== NULL
|| U_FAILURE(status
)) {
1775 errln("FAIL: Unable to create MessageFormat.");
1778 if (msgfmt
->usesNamedArguments()) {
1779 errln("FAIL: Unable to detect usage of named arguments.");
1782 // Starting with ICU 4.8, we support setFormat(name, ...) and getFormatNames()
1783 // on a MessageFormat without named arguments.
1784 msgfmt
->setFormat("formatName", cf
, status
);
1785 if (U_FAILURE(status
)) {
1786 errln("FAIL: Should work to setFormat(name, ...) regardless of pattern.");
1788 status
= U_ZERO_ERROR
;
1789 en
= msgfmt
->getFormatNames(status
);
1790 if (U_FAILURE(status
)) {
1791 errln("FAIL: Should work to get format names enumeration regardless of pattern.");
1798 void TestMessageFormat::testGetFormatNames() {
1799 IcuTestErrorCode
errorCode(*this, "testGetFormatNames");
1800 MessageFormat
msgfmt("Hello, {alice,number} {oops,date,full} {zip,spellout} World.", Locale::getRoot(), errorCode
);
1801 if(errorCode
.logDataIfFailureAndReset("MessageFormat() failed")) {
1804 LocalPointer
<StringEnumeration
> names(msgfmt
.getFormatNames(errorCode
));
1805 if(errorCode
.logIfFailureAndReset("msgfmt.getFormatNames() failed")) {
1808 const UnicodeString
*name
;
1809 name
= names
->snext(errorCode
);
1810 if (name
== NULL
|| errorCode
.isFailure()) {
1811 errln("msgfmt.getFormatNames()[0] failed: %s", errorCode
.errorName());
1815 if (!assertEquals("msgfmt.getFormatNames()[0]", UNICODE_STRING_SIMPLE("alice"), *name
)) {
1818 name
= names
->snext(errorCode
);
1819 if (name
== NULL
|| errorCode
.isFailure()) {
1820 errln("msgfmt.getFormatNames()[1] failed: %s", errorCode
.errorName());
1824 if (!assertEquals("msgfmt.getFormatNames()[1]", UNICODE_STRING_SIMPLE("oops"), *name
)) {
1827 name
= names
->snext(errorCode
);
1828 if (name
== NULL
|| errorCode
.isFailure()) {
1829 errln("msgfmt.getFormatNames()[2] failed: %s", errorCode
.errorName());
1833 if (!assertEquals("msgfmt.getFormatNames()[2]", UNICODE_STRING_SIMPLE("zip"), *name
)) {
1836 name
= names
->snext(errorCode
);
1838 errln(UnicodeString("msgfmt.getFormatNames()[3] should be NULL but is: ") + *name
);
1843 void TestMessageFormat::TestTrimArgumentName() {
1844 // ICU 4.8 allows and ignores white space around argument names and numbers.
1845 IcuTestErrorCode
errorCode(*this, "TestTrimArgumentName");
1846 MessageFormat
m("a { 0 , number , '#,#'#.0 } z", Locale::getEnglish(), errorCode
);
1847 if (errorCode
.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
1850 Formattable args
[1] = { (int32_t)2 };
1851 FieldPosition
ignore(0);
1852 UnicodeString result
;
1853 assertEquals("trim-numbered-arg format() failed", "a #,#2.0 z",
1854 m
.format(args
, 1, result
, ignore
, errorCode
));
1856 m
.applyPattern("x { _oOo_ , number , integer } y", errorCode
);
1857 UnicodeString argName
= UNICODE_STRING_SIMPLE("_oOo_");
1860 assertEquals("trim-named-arg format() failed", "x 3 y",
1861 m
.format(&argName
, args
, 1, result
, errorCode
));
1864 void TestMessageFormat::TestSelectOrdinal() {
1865 IcuTestErrorCode
errorCode(*this, "TestSelectOrdinal");
1866 // Test plural & ordinal together,
1867 // to make sure that we get the correct cached PluralSelector for each.
1869 "{0,plural,one{1 file}other{# files}}, "
1870 "{0,selectordinal,one{#st file}two{#nd file}few{#rd file}other{#th file}}",
1871 Locale::getEnglish(), errorCode
);
1872 if (errorCode
.logDataIfFailureAndReset("Unable to instantiate MessageFormat")) {
1875 Formattable args
[1] = { (int32_t)21 };
1876 FieldPosition
ignore(0);
1877 UnicodeString result
;
1878 assertEquals("plural-and-ordinal format(21) failed", "21 files, 21st file",
1879 m
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1882 assertEquals("plural-and-ordinal format(2) failed", "2 files, 2nd file",
1883 m
.format(args
, 1, result
.remove(), ignore
, errorCode
), TRUE
);
1886 assertEquals("plural-and-ordinal format(1) failed", "1 file, 1st file",
1887 m
.format(args
, 1, result
.remove(), ignore
, errorCode
), TRUE
);
1890 assertEquals("plural-and-ordinal format(3) failed", "3 files, 3rd file",
1891 m
.format(args
, 1, result
.remove(), ignore
, errorCode
), TRUE
);
1893 errorCode
.logDataIfFailureAndReset("");
1896 void TestMessageFormat::TestDecimals() {
1897 IcuTestErrorCode
errorCode(*this, "TestDecimals");
1898 // Simple number replacement.
1900 "{0,plural,one{one meter}other{# meters}}",
1901 Locale::getEnglish(), errorCode
);
1902 Formattable args
[1] = { (int32_t)1 };
1903 FieldPosition ignore
;
1904 UnicodeString result
;
1905 assertEquals("simple format(1)", "one meter",
1906 m
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1908 args
[0] = (double)1.5;
1910 assertEquals("simple format(1.5)", "1.5 meters",
1911 m
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1913 // Simple but explicit.
1915 "{0,plural,one{one meter}other{{0} meters}}",
1916 Locale::getEnglish(), errorCode
);
1917 args
[0] = (int32_t)1;
1919 assertEquals("explicit format(1)", "one meter",
1920 m0
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1922 args
[0] = (double)1.5;
1924 assertEquals("explicit format(1.5)", "1.5 meters",
1925 m0
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1927 // With offset and specific simple format with optional decimals.
1929 "{0,plural,offset:1 one{another meter}other{{0,number,00.#} meters}}",
1930 Locale::getEnglish(), errorCode
);
1931 args
[0] = (int32_t)1;
1933 assertEquals("offset format(1)", "01 meters",
1934 m1
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1936 args
[0] = (int32_t)2;
1938 assertEquals("offset format(1)", "another meter",
1939 m1
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1941 args
[0] = (double)2.5;
1943 assertEquals("offset format(1)", "02.5 meters",
1944 m1
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1946 // With offset and specific simple format with forced decimals.
1948 "{0,plural,offset:1 one{another meter}other{{0,number,0.0} meters}}",
1949 Locale::getEnglish(), errorCode
);
1950 args
[0] = (int32_t)1;
1952 assertEquals("offset-decimals format(1)", "1.0 meters",
1953 m2
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1955 args
[0] = (int32_t)2;
1957 assertEquals("offset-decimals format(1)", "2.0 meters",
1958 m2
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1960 args
[0] = (double)2.5;
1962 assertEquals("offset-decimals format(1)", "2.5 meters",
1963 m2
.format(args
, 1, result
, ignore
, errorCode
), TRUE
);
1967 #endif /* #if !UCONFIG_NO_FORMATTING */