1 /********************************************************************
3 * Copyright (c) 1997-2010, 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/locid.h"
25 #include "unicode/msgfmt.h"
26 #include "unicode/numfmt.h"
27 #include "unicode/choicfmt.h"
28 #include "unicode/selfmt.h"
29 #include "unicode/gregocal.h"
32 #define E_WITH_ACUTE ((char)0x00E9)
33 static const char E_ACCENTED
[]={E_WITH_ACUTE
,0};
36 TestMessageFormat::runIndexedTest(int32_t index
, UBool exec
,
37 const char* &name
, char* /*par*/) {
42 TESTCASE(3,PatternTest
);
43 TESTCASE(4,testStaticFormat
);
44 TESTCASE(5,testSimpleFormat
);
45 TESTCASE(6,testMsgFormatChoice
);
46 TESTCASE(7,testCopyConstructor
);
47 TESTCASE(8,testAssignment
);
48 TESTCASE(9,testClone
);
49 TESTCASE(10,testEquals
);
50 TESTCASE(11,testNotEquals
);
51 TESTCASE(12,testSetLocale
);
52 TESTCASE(13,testFormat
);
53 TESTCASE(14,testParse
);
54 TESTCASE(15,testAdopt
);
55 TESTCASE(16,testCopyConstructor2
);
56 TESTCASE(17,TestUnlimitedArgsAndSubformats
);
57 TESTCASE(18,TestRBNF
);
58 TESTCASE(19,TestTurkishCasing
);
59 TESTCASE(20,testAutoQuoteApostrophe
);
60 TESTCASE(21,testMsgFormatPlural
);
61 TESTCASE(22,testCoverage
);
62 TESTCASE(23,testMsgFormatSelect
);
63 default: name
= ""; break;
67 void TestMessageFormat::testBug3()
69 double myNumber
= -123456;
70 DecimalFormat
*form
= 0;
79 Locale("de", "AT", ""),
80 Locale("de", "CH", ""),
81 Locale("el", "", ""), // 10
82 Locale("en", "CA", ""),
83 Locale("en", "GB", ""),
84 Locale("en", "IE", ""),
85 Locale("en", "US", ""),
90 Locale("fr", "BE", ""),
91 Locale("fr", "CA", ""), // 20
92 Locale("fr", "CH", ""),
98 Locale("it", "CH", ""),
100 Locale("ko", "", ""),
101 Locale("lt", "", ""), // 30
102 Locale("lv", "", ""),
103 Locale("mk", "", ""),
104 Locale("nl", "", ""),
105 Locale("nl", "BE", ""),
106 Locale("no", "", ""),
107 Locale("pl", "", ""),
108 Locale("pt", "", ""),
109 Locale("ro", "", ""),
110 Locale("ru", "", ""),
111 Locale("sh", "", ""), // 40
112 Locale("sk", "", ""),
113 Locale("sl", "", ""),
114 Locale("sq", "", ""),
115 Locale("sr", "", ""),
116 Locale("sv", "", ""),
117 Locale("tr", "", ""),
118 Locale("uk", "", ""),
119 Locale("zh", "", ""),
120 Locale("zh", "TW", "") // 49
123 for (i
= 0; i
< 49; i
++) {
124 UnicodeString buffer
;
125 logln(locale
[i
].getDisplayName(buffer
));
126 UErrorCode success
= U_ZERO_ERROR
;
127 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
128 form
= (DecimalFormat
*)NumberFormat::createInstance(locale
[i
], success
);
129 if (U_FAILURE(success
)) {
130 errln("Err: Number Format ");
131 logln("Number format creation failed.");
135 FieldPosition
pos(0);
137 form
->format(myNumber
, buffer
, pos
);
138 success
= U_ZERO_ERROR
;
139 ParsePosition parsePos
;
140 form
->parse(buffer
, result
, parsePos
);
141 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result
) + UnicodeString("[supposed output for result]"));
142 if (U_FAILURE(success
)) {
143 errln("Err: Number Format parse");
144 logln("Number format parse failed.");
150 void TestMessageFormat::testBug1()
152 const double limit
[] = {0.0, 1.0, 2.0};
153 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
156 ChoiceFormat
*cf
= new ChoiceFormat(limit
, formats
, 3);
157 FieldPosition
status(0);
158 UnicodeString toAppendTo
;
159 cf
->format((int32_t)1, toAppendTo
, status
);
160 if (toAppendTo
!= "1.0<=Arg<2.0") {
161 errln("ChoiceFormat cmp in testBug1");
167 void TestMessageFormat::testBug2()
169 UErrorCode status
= U_ZERO_ERROR
;
170 UnicodeString result
;
171 // {sfb} use double format in pattern, so result will match (not strictly necessary)
172 const UnicodeString pattern
= "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
173 logln("The input pattern : " + pattern
);
174 MessageFormat
*fmt
= new MessageFormat(pattern
, status
);
175 if (U_FAILURE(status
)) {
176 errln("MessageFormat pattern creation failed.");
179 logln("The output pattern is : " + fmt
->toPattern(result
));
180 if (pattern
!= result
) {
181 errln("MessageFormat::toPattern() failed.");
187 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
188 //----------------------------------------------------
190 //----------------------------------------------------
192 #if U_IOSTREAM_SOURCE >= 199711
194 std::ostream
& operator<<(std::ostream
& stream
, const Formattable
& obj
);
195 #elif U_IOSTREAM_SOURCE >= 198506
196 # include <iostream.h>
197 ostream
& operator<<(ostream
& stream
, const Formattable
& obj
);
200 #include "unicode/datefmt.h"
205 operator<<( IntlTest
& stream
,
206 const Formattable
& obj
)
208 static DateFormat
*defDateFormat
= 0;
210 UnicodeString buffer
;
211 switch(obj
.getType()) {
212 case Formattable::kDate
:
213 if (defDateFormat
== 0) {
214 defDateFormat
= DateFormat::createInstance();
216 defDateFormat
->format(obj
.getDate(), buffer
);
219 case Formattable::kDouble
:
221 sprintf( convert
, "%lf", obj
.getDouble() );
222 stream
<< convert
<< "D";
224 case Formattable::kLong
:
225 stream
<< obj
.getLong() << "L";
227 case Formattable::kString
:
228 stream
<< "\"" << obj
.getString(buffer
) << "\"";
230 case Formattable::kArray
:
232 const Formattable
* array
;
233 array
= obj
.getArray(count
);
235 for (i
=0; i
<count
; ++i
) stream
<< array
[i
] << ( (i
==(count
-1)) ? "" : ", " );
239 stream
<< "INVALID_Formattable";
243 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
246 void TestMessageFormat::PatternTest()
248 Formattable testArgs
[] = {
249 Formattable(double(1)), Formattable(double(3456)),
250 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate
)
252 UnicodeString testCases
[] = {
253 "Quotes '', '{', 'a' {0} '{0}'",
254 "Quotes '', '{', 'a' {0,number} '{0}'",
255 "'{'1,number,'#',##} {1,number,'#',##}",
256 "There are {1} files on {2} at {3}.",
257 "On {2}, there are {1} files, with {0,number,currency}.",
258 "'{1,number,percent}', {1,number,percent},",
259 "'{1,date,full}', {1,date,full},",
260 "'{3,date,full}', {3,date,full},",
261 "'{1,number,#,##}' {1,number,#,##}",
264 UnicodeString testResultPatterns
[] = {
265 "Quotes '', '{', a {0} '{'0}",
266 "Quotes '', '{', a {0,number} '{'0}",
267 "'{'1,number,#,##} {1,number,'#'#,##}",
268 "There are {1} files on {2} at {3}.",
269 "On {2}, there are {1} files, with {0,number,currency}.",
270 "'{'1,number,percent}, {1,number,percent},",
271 "'{'1,date,full}, {1,date,full},",
272 "'{'3,date,full}, {3,date,full},",
273 "'{'1,number,#,##} {1,number,#,##}"
276 UnicodeString testResultStrings
[] = {
277 "Quotes ', {, a 1 {0}",
278 "Quotes ', {, a 1 {0}",
279 "{1,number,#,##} #34,56",
280 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
281 "On Disk, there are 3,456 files, with $1.00.",
282 "{1,number,percent}, 345,600%,",
283 "{1,date,full}, Wednesday, December 31, 1969,",
284 "{3,date,full}, Monday, January 12, 1970,",
285 "{1,number,#,##} 34,56"
289 for (int32_t i
= 0; i
< 9; ++i
) {
290 //it_out << "\nPat in: " << testCases[i]);
292 MessageFormat
*form
= 0;
293 UErrorCode success
= U_ZERO_ERROR
;
294 UnicodeString buffer
;
295 form
= new MessageFormat(testCases
[i
], Locale::getUS(), success
);
296 if (U_FAILURE(success
)) {
297 dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success
));
298 logln(((UnicodeString
)"MessageFormat for ") + testCases
[i
] + " creation failed.\n");
301 if (form
->toPattern(buffer
) != testResultPatterns
[i
]) {
302 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i
);
303 //form->toPattern(buffer);
304 errln(((UnicodeString
)" Orig: ") + testCases
[i
]);
305 errln(((UnicodeString
)" Exp: ") + testResultPatterns
[i
]);
306 errln(((UnicodeString
)" Got: ") + buffer
);
309 //it_out << "Pat out: " << form->toPattern(buffer));
310 UnicodeString result
;
312 FieldPosition
fieldpos(0);
313 form
->format(testArgs
, count
, result
, fieldpos
, success
);
314 if (U_FAILURE(success
)) {
315 dataerrln("MessageFormat failed test #3 - %s", u_errorName(success
));
316 logln("TestMessageFormat::PatternTest failed test #3");
319 if (result
!= testResultStrings
[i
]) {
320 errln("TestMessageFormat::PatternTest failed test #4");
321 logln("TestMessageFormat::PatternTest failed #4.");
322 logln(UnicodeString(" Result: ") + result
);
323 logln(UnicodeString(" Expected: ") + testResultStrings
[i
] );
327 //it_out << "Result: " << result);
329 /* TODO: Look at this test and see if this is still a valid test */
330 logln("---------------- test parse ----------------");
332 form
->toPattern(buffer
);
333 logln("MSG pattern for parse: " + buffer
);
335 int32_t parseCount
= 0;
336 Formattable
* values
= form
->parse(result
, parseCount
, success
);
337 if (U_FAILURE(success
)) {
338 errln("MessageFormat failed test #5");
339 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success
);
340 } else if (parseCount
!= count
) {
341 errln("MSG count not %d as expected. Got %d", count
, parseCount
);
343 UBool failed
= FALSE
;
344 for (int32_t j
= 0; j
< parseCount
; ++j
) {
345 if (values
== 0 || testArgs
[j
] != values
[j
]) {
346 errln(((UnicodeString
)"MSG testargs[") + j
+ "]: " + toString(testArgs
[j
]));
347 errln(((UnicodeString
)"MSG values[") + j
+ "] : " + toString(values
[j
]));
352 errln("MessageFormat failed test #6");
358 void TestMessageFormat::sample()
360 MessageFormat
*form
= 0;
361 UnicodeString buffer1
, buffer2
;
362 UErrorCode success
= U_ZERO_ERROR
;
363 form
= new MessageFormat("There are {0} files on {1}", success
);
364 if (U_FAILURE(success
)) {
365 errln("Err: Message format creation failed");
366 logln("Sample message format creation failed.");
369 UnicodeString
abc("abc");
370 UnicodeString
def("def");
371 Formattable testArgs1
[] = { abc
, def
};
372 FieldPosition
fieldpos(0);
373 assertEquals("format",
374 "There are abc files on def",
375 form
->format(testArgs1
, 2, buffer2
, fieldpos
, success
));
376 assertSuccess("format", success
);
380 void TestMessageFormat::testStaticFormat()
382 UErrorCode err
= U_ZERO_ERROR
;
383 Formattable arguments
[] = {
385 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
386 "a disturbance in the Force"
389 UnicodeString result
;
390 result
= MessageFormat::format(
391 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
397 if (U_FAILURE(err
)) {
398 dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err
));
399 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err
);
403 const UnicodeString
expected(
404 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
405 if (result
!= expected
) {
406 errln("TestMessageFormat::testStaticFormat failed on test");
407 logln( UnicodeString(" Result: ") + result
);
408 logln( UnicodeString(" Expected: ") + expected
);
412 /* When the default locale is tr, make sure that the pattern can still be parsed. */
413 void TestMessageFormat::TestTurkishCasing()
415 UErrorCode err
= U_ZERO_ERROR
;
416 Locale saveDefaultLocale
;
417 Locale::setDefault( Locale("tr"), err
);
419 Formattable arguments
[] = {
421 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
422 "a disturbance in the Force"
425 UnicodeString result
;
426 result
= MessageFormat::format(
427 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
433 if (U_FAILURE(err
)) {
434 dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err
));
438 const UnicodeString
expected(
439 "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
440 if (result
!= expected
) {
441 errln("TestTurkishCasing failed on test");
442 errln( UnicodeString(" Result: ") + result
);
443 errln( UnicodeString(" Expected: ") + expected
);
445 Locale::setDefault( saveDefaultLocale
, err
);
448 void TestMessageFormat::testSimpleFormat(/* char* par */)
450 logln("running TestMessageFormat::testSimpleFormat");
452 UErrorCode err
= U_ZERO_ERROR
;
454 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
455 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
456 Formattable testArgs3
[] = {(int32_t)12, "MyDisk"};
458 MessageFormat
* form
= new MessageFormat(
459 "The disk \"{1}\" contains {0} file(s).", err
);
461 UnicodeString string
;
462 FieldPosition
ignore(FieldPosition::DONT_CARE
);
463 form
->format(testArgs1
, 2, string
, ignore
, err
);
464 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 0 file(s).") {
465 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err
));
468 ignore
.setField(FieldPosition::DONT_CARE
);
470 form
->format(testArgs2
, 2, string
, ignore
, err
);
471 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 1 file(s).") {
473 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string
+ " - " + u_errorName(err
));
476 ignore
.setField(FieldPosition::DONT_CARE
);
478 form
->format(testArgs3
, 2, string
, ignore
, err
);
479 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 12 file(s).") {
480 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string
+ " - " + u_errorName(err
));
486 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
488 logln("running TestMessageFormat::testMsgFormatChoice");
490 UErrorCode err
= U_ZERO_ERROR
;
492 MessageFormat
* form
= new MessageFormat("The disk \"{1}\" contains {0}.", err
);
493 double filelimits
[] = {0,1,2};
494 UnicodeString filepart
[] = {"no files","one file","{0,number} files"};
495 ChoiceFormat
* fileform
= new ChoiceFormat(filelimits
, filepart
, 3);
496 form
->setFormat(1,*fileform
); // NOT zero, see below
497 //is the format adopted?
499 FieldPosition
ignore(FieldPosition::DONT_CARE
);
500 UnicodeString string
;
501 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
502 form
->format(testArgs1
, 2, string
, ignore
, err
);
503 if (string
!= "The disk \"MyDisk\" contains no files.") {
504 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
507 ignore
.setField(FieldPosition::DONT_CARE
);
509 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
510 form
->format(testArgs2
, 2, string
, ignore
, err
);
511 if (string
!= "The disk \"MyDisk\" contains one file.") {
512 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
515 ignore
.setField(FieldPosition::DONT_CARE
);
517 Formattable testArgs3
[] = {(int32_t)1273, "MyDisk"};
518 form
->format(testArgs3
, 2, string
, ignore
, err
);
519 if (string
!= "The disk \"MyDisk\" contains 1,273 files.") {
520 dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err
));
528 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
530 logln("running TestMessageFormat::testMsgFormatPlural");
532 UErrorCode err
= U_ZERO_ERROR
;
533 UnicodeString
t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
534 UnicodeString
t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
535 UnicodeString
t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
536 UnicodeString
t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
537 UnicodeString
t5("{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
538 MessageFormat
* mfNum
= new MessageFormat(t1
, Locale("fr"), err
);
539 if (U_FAILURE(err
)) {
540 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err
));
541 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
544 Formattable
testArgs1((int32_t)0);
545 FieldPosition
ignore(FieldPosition::DONT_CARE
);
546 UnicodeString numResult1
;
547 mfNum
->format(&testArgs1
, 1, numResult1
, ignore
, err
);
549 MessageFormat
* mfAlpha
= new MessageFormat(t2
, Locale("fr"), err
);
550 UnicodeString argName
[] = {UnicodeString("argument")};
551 UnicodeString argNameResult
;
552 mfAlpha
->format(argName
, &testArgs1
, 1, argNameResult
, err
);
553 if (U_FAILURE(err
)) {
554 errln("TestMessageFormat::testMsgFormatPlural #1 - argumentName");
555 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
559 if ( numResult1
!= argNameResult
){
560 errln("TestMessageFormat::testMsgFormatPlural #1");
561 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
563 if ( numResult1
!= UnicodeString("C\'est 0 fichier dans la liste.")) {
564 errln("TestMessageFormat::testMsgFormatPlural #1");
565 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
572 MessageFormat
* mfNum2
= new MessageFormat(t3
, Locale("ru"), err
);
574 Formattable
testArgs2((int32_t)4);
575 mfNum2
->format(&testArgs2
, 1, numResult1
, ignore
, err
);
576 MessageFormat
* mfAlpha2
= new MessageFormat(t4
, Locale("ru"), err
);
577 argNameResult
.remove();
578 mfAlpha2
->format(argName
, &testArgs2
, 1, argNameResult
, err
);
580 if (U_FAILURE(err
)) {
581 errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
582 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err
);
586 if ( numResult1
!= argNameResult
){
587 errln("TestMessageFormat::testMsgFormatPlural #2");
588 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
590 if ( numResult1
!= UnicodeString("There are 4,0 zavoda in the directory.")) {
591 errln("TestMessageFormat::testMsgFormatPlural #2");
592 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
600 MessageFormat
* msgFmt
= new MessageFormat(t5
, Locale("fr"), err
);
601 if (U_FAILURE(err
)) {
602 errln("TestMessageFormat::test nested PluralFormat with argumentName");
603 logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err
);
607 Formattable
testArgs3((int32_t)0);
608 argNameResult
.remove();
609 msgFmt
->format(&testArgs3
, 1, argNameResult
, ignore
, err
);
610 if (U_FAILURE(err
)) {
611 errln("TestMessageFormat::test nested PluralFormat with argumentName");
613 if ( argNameResult
!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
614 errln(UnicodeString("TestMessageFormat::test nested named PluralFormat."));
615 logln(UnicodeString("The unexpected nested named PluralFormat."));
620 void TestMessageFormat::internalFormat(MessageFormat
* msgFmt
,
621 Formattable
* args
, int32_t numOfArgs
,
622 UnicodeString expected
,char* errMsg
)
624 UnicodeString result
;
625 FieldPosition
ignore(FieldPosition::DONT_CARE
);
626 UErrorCode status
= U_ZERO_ERROR
;
628 //Format with passed arguments
629 msgFmt
->format( args
, numOfArgs
, result
, ignore
, status
);
630 if (U_FAILURE(status
)) {
631 dataerrln( "%serror while formatting with ErrorCode as %s" ,errMsg
, u_errorName(status
) );
633 //Compare expected with obtained result
634 if ( result
!= expected
) {
635 UnicodeString err
= UnicodeString(errMsg
);
636 err
+= UnicodeString(":Unexpected Result \n Expected: " + expected
+ "\n Obtained: " + result
+ "\n");
641 MessageFormat
* TestMessageFormat::internalCreate(
642 UnicodeString pattern
,Locale locale
,UErrorCode
&status
, char* errMsg
)
644 //Create the MessageFormat with simple SelectFormat
645 MessageFormat
* msgFmt
= new MessageFormat(pattern
, locale
, status
);
646 if (U_FAILURE(status
)) {
647 dataerrln( "%serror while constructing with ErrorCode as %s" ,errMsg
, u_errorName(status
) );
648 logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status
);
654 void TestMessageFormat::testMsgFormatSelect(/* char* par */)
656 logln("running TestMessageFormat::testMsgFormatSelect");
658 UErrorCode err
= U_ZERO_ERROR
;
660 UnicodeString
t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
663 //Create the MessageFormat with simple French pattern
664 MessageFormat
* msgFmt1
= internalCreate(t1
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t1");
665 if (!U_FAILURE(err
)) {
667 Formattable testArgs10
[] = {"Kirti","female"};
668 Formattable testArgs11
[] = {"Victor","other"};
669 Formattable testArgs12
[] = {"Ash","unknown"};
670 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
671 UnicodeString exp
[] = {
672 "Kirti est all\\u00E9e \\u00E0 Paris." ,
673 "Victor est all\\u00E9 \\u00E0 Paris.",
674 "Ash est all\\u00E9 \\u00E0 Paris."};
676 for( int i
=0; i
< 3; i
++){
677 internalFormat( msgFmt1
, testArgs
[i
], 2, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
682 //Quoted French Pattern
683 UnicodeString
t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
685 //Create the MessageFormat with Quoted French pattern
686 MessageFormat
* msgFmt2
= internalCreate(t2
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t2");
687 if (!U_FAILURE(err
)) {
689 Formattable testArgs10
[] = {"Kirti","female"};
690 Formattable testArgs11
[] = {"Victor","other"};
691 Formattable testArgs12
[] = {"Ash","male"};
692 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
693 UnicodeString exp
[] = {
694 "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
695 "Victor est all\\u00E9 c'est \\u00E0 Paris.",
696 "Ash est all\\u00E9 c'est \\u00E0 Paris."};
698 for( int i
=0; i
< 3; i
++){
699 internalFormat( msgFmt2
, testArgs
[i
], 2, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
705 UnicodeString
t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
707 //Create the MessageFormat with English pattern
708 MessageFormat
* msgFmt3
= internalCreate(t3
, Locale("en"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t3");
709 if (!U_FAILURE(err
)) {
711 Formattable testArgs10
[] = {"female"};
712 Formattable testArgs11
[] = {"other"};
713 Formattable testArgs12
[] = {"male"};
714 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
715 UnicodeString exp
[] = {
716 "FEMALE FR company published new books." ,
717 "FR otherValue published new books.",
718 "MALE FR company published new books."};
720 for( int i
=0; i
< 3; i
++){
721 internalFormat( msgFmt3
, testArgs
[i
], 1, exp
[i
] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
726 //Nested patterns with plural, number ,choice ,select format etc.
727 //Select Format with embedded number format
728 UnicodeString
t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
729 //Create the MessageFormat with Select Format with embedded number format (nested pattern)
730 MessageFormat
* msgFmt4
= internalCreate(t4
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t4");
731 if (!U_FAILURE(err
)) {
733 Formattable testArgs10
[] = {"Kirti","female",(int32_t)6};
734 Formattable testArgs11
[] = {"Kirti","female",100.100};
735 Formattable testArgs12
[] = {"Kirti","other",(int32_t)6};
736 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
};
737 UnicodeString exp
[] = {
738 "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
739 "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
740 "Kirti est all\\u00E9 \\u00E0 Paris."};
742 for( int i
=0; i
< 3; i
++){
743 internalFormat( msgFmt4
, testArgs
[i
], 3, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
749 //Plural format with embedded select format
750 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.");
752 //Create the MessageFormat with Plural format with embedded select format(nested pattern)
753 MessageFormat
* msgFmt5
= internalCreate(t5
.unescape(), Locale("fr"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t5");
754 if (!U_FAILURE(err
)) {
756 Formattable testArgs10
[] = {"Kirti",(int32_t)6,"female"};
757 Formattable testArgs11
[] = {"Kirti",(int32_t)1,"female"};
758 Formattable testArgs12
[] = {"Ash",(int32_t)1,"other"};
759 Formattable testArgs13
[] = {"Ash",(int32_t)5,"other"};
760 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
,testArgs13
};
761 UnicodeString exp
[] = {
762 "Kirti sont all\\u00E9es \\u00E0 Paris." ,
763 "Kirti est all\\u00E9e \\u00E0 Paris.",
764 "Ash est all\\u00E9 \\u00E0 Paris.",
765 "Ash sont all\\u00E9s \\u00E0 Paris."};
767 for( int i
=0; i
< 4; i
++){
768 internalFormat( msgFmt5
, testArgs
[i
], 3, exp
[i
].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
774 //Select, plural, and number formats heavily nested
775 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.");
776 //Create the MessageFormat with Select, plural, and number formats heavily nested
777 MessageFormat
* msgFmt6
= internalCreate(t6
, Locale("de"),err
,(char*)"From TestMessageFormat::TestSelectFormat create t6");
778 if (!U_FAILURE(err
)) {
780 Formattable testArgs10
[] = {"Kirti","other",(int32_t)1,"other"};
781 Formattable testArgs11
[] = {"Kirti","other",(int32_t)6,"other"};
782 Formattable testArgs12
[] = {"Kirti","other",(int32_t)1,"female"};
783 Formattable testArgs13
[] = {"Kirti","other",(int32_t)3,"female"};
784 Formattable testArgs14
[] = {"Kirti","female",(int32_t)1,"female"};
785 Formattable testArgs15
[] = {"Kirti","female",(int32_t)5,"female"};
786 Formattable testArgs16
[] = {"Kirti","female",(int32_t)1,"other"};
787 Formattable testArgs17
[] = {"Kirti","female",(int32_t)5,"other"};
788 Formattable testArgs18
[] = {"Kirti","mixed",(int32_t)1,"mixed"};
789 Formattable testArgs19
[] = {"Kirti","mixed",(int32_t)1,"other"};
790 Formattable testArgs20
[] = {"Kirti","female",(int32_t)1,"mixed"};
791 Formattable testArgs21
[] = {"Kirti","mixed",(int32_t)5,"mixed"};
792 Formattable testArgs22
[] = {"Kirti","mixed",(int32_t)5,"other"};
793 Formattable testArgs23
[] = {"Kirti","female",(int32_t)5,"mixed"};
794 Formattable
* testArgs
[] = {testArgs10
,testArgs11
,testArgs12
,testArgs13
,
795 testArgs14
,testArgs15
,testArgs16
,testArgs17
,
796 testArgs18
,testArgs19
,testArgs20
,testArgs21
,
797 testArgs22
,testArgs23
};
798 UnicodeString exp
[] = {
799 "Kirti und sein Freund gingen nach Paris." ,
800 "Kirti und seine 6 Freunde gingen nach Paris." ,
801 "Kirti und seine Freundin gingen nach Paris.",
802 "Kirti und seine 3 Freundinnen gingen nach Paris.",
803 "Kirti und ihre Freundin gingen nach Paris.",
804 "Kirti und ihre 5 Freundinnen gingen nach Paris.",
805 "Kirti und ihr Freund gingen nach Paris.",
806 "Kirti und ihre 5 Freunde gingen nach Paris.",
807 "Kirti und sein Freund gingen nach Paris.",
808 "Kirti und sein Freund gingen nach Paris.",
809 "Kirti und ihr Freund gingen nach Paris.",
810 "Kirti und seine 5 Freunde gingen nach Paris." ,
811 "Kirti und seine 5 Freunde gingen nach Paris." ,
812 "Kirti und ihre 5 Freunde gingen nach Paris."
815 for( int i
=0; i
< 14; i
++){
816 internalFormat( msgFmt6
, testArgs
[i
], 4, exp
[i
] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
822 //---------------------------------
824 //---------------------------------
826 void TestMessageFormat::testCopyConstructor()
828 UErrorCode success
= U_ZERO_ERROR
;
829 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
830 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
831 MessageFormat
*y
= 0;
832 y
= new MessageFormat(*x
);
836 logln("First test (operator ==): Passed!");
838 errln("TestMessageFormat::testCopyConstructor failed #1");
839 logln("First test (operator ==): Failed!");
841 if ( ((*x
== *y
) && (*y
== *x
)) &&
842 ((*x
!= *z
) && (*z
!= *x
)) &&
843 ((*y
!= *z
) && (*z
!= *y
)) )
844 logln("Second test (equals): Passed!");
846 errln("TestMessageFormat::testCopyConstructor failed #2");
847 logln("Second test (equals): Failed!");
856 void TestMessageFormat::testAssignment()
858 UErrorCode success
= U_ZERO_ERROR
;
859 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
860 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
861 MessageFormat
*y
= new MessageFormat("There are {0} files on {1} created", success
);
866 logln("First test (operator ==): Passed!");
868 errln( "TestMessageFormat::testAssignment failed #1");
869 logln("First test (operator ==): Failed!");
871 if ( ((*x
== *y
) && (*y
== *x
)) &&
872 ((*x
!= *z
) && (*z
!= *x
)) &&
873 ((*y
!= *z
) && (*z
!= *y
)) )
874 logln("Second test (equals): Passed!");
876 errln("TestMessageFormat::testAssignment failed #2");
877 logln("Second test (equals): Failed!");
885 void TestMessageFormat::testClone()
887 UErrorCode success
= U_ZERO_ERROR
;
888 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
889 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
890 MessageFormat
*y
= 0;
891 y
= (MessageFormat
*)x
->clone();
895 logln("First test (operator ==): Passed!");
897 errln("TestMessageFormat::testClone failed #1");
898 logln("First test (operator ==): Failed!");
900 if ( ((*x
== *y
) && (*y
== *x
)) &&
901 ((*x
!= *z
) && (*z
!= *x
)) &&
902 ((*y
!= *z
) && (*z
!= *y
)) )
903 logln("Second test (equals): Passed!");
905 errln("TestMessageFormat::testClone failed #2");
906 logln("Second test (equals): Failed!");
914 void TestMessageFormat::testEquals()
916 UErrorCode success
= U_ZERO_ERROR
;
917 MessageFormat
x("There are {0} files on {1}", success
);
918 MessageFormat
y("There are {0} files on {1}", success
);
920 errln( "TestMessageFormat::testEquals failed #1");
921 logln("First test (operator ==): Failed!");
926 void TestMessageFormat::testNotEquals()
928 UErrorCode success
= U_ZERO_ERROR
;
929 MessageFormat
x("There are {0} files on {1}", success
);
931 y
.setLocale(Locale("fr"));
933 errln( "TestMessageFormat::testEquals failed #1");
934 logln("First test (operator !=): Failed!");
937 y
.applyPattern("There are {0} files on {1} the disk", success
);
939 errln( "TestMessageFormat::testEquals failed #1");
940 logln("Second test (operator !=): Failed!");
945 void TestMessageFormat::testSetLocale()
947 UErrorCode err
= U_ZERO_ERROR
;
948 GregorianCalendar
cal(err
);
949 Formattable arguments
[] = {
951 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
955 UnicodeString result
;
957 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
958 UnicodeString formatStr
= "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
959 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
960 // Just use unlocalized currency symbol.
961 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
962 UnicodeString compareStrEng
= "At <time> on Aug 8, 1997, you made a deposit of ";
963 compareStrEng
+= (UChar
) 0x00a4;
964 compareStrEng
+= "456.83.";
965 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
966 // Just use unlocalized currency symbol.
967 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
968 UnicodeString compareStrGer
= "At <time> on 08.08.1997, you made a deposit of ";
969 compareStrGer
+= "456,83";
970 compareStrGer
+= (UChar
) 0x00a0;
971 compareStrGer
+= (UChar
) 0x00a4;
972 compareStrGer
+= ".";
974 MessageFormat
msg( formatStr
, err
);
976 FieldPosition
pos(0);
985 if (result
!= compareStrEng
) {
986 dataerrln("*** MSG format err. - %s", u_errorName(err
));
989 msg
.setLocale(Locale::getEnglish());
990 UBool getLocale_ok
= TRUE
;
991 if (msg
.getLocale() != Locale::getEnglish()) {
992 errln("*** MSG getLocal err.");
993 getLocale_ok
= FALSE
;
996 msg
.setLocale(Locale::getGerman());
998 if (msg
.getLocale() != Locale::getGerman()) {
999 errln("*** MSG getLocal err.");
1000 getLocale_ok
= FALSE
;
1003 msg
.applyPattern( formatStr
, err
);
1007 result
= msg
.format(
1015 if (result
== compareStrGer
) {
1016 logln("MSG setLocale tested.");
1018 dataerrln( "*** MSG setLocale err. - %s", u_errorName(err
));
1022 logln("MSG getLocale tested.");
1026 void TestMessageFormat::testFormat()
1028 UErrorCode err
= U_ZERO_ERROR
;
1029 GregorianCalendar
cal(err
);
1031 const Formattable ftarray
[] =
1033 Formattable( UDate(8.71068e+011), Formattable::kIsDate
)
1035 const int32_t ft_cnt
= sizeof(ftarray
) / sizeof(Formattable
);
1036 Formattable
ft_arr( ftarray
, ft_cnt
);
1038 Formattable
* fmt
= new Formattable(UDate(8.71068e+011), Formattable::kIsDate
);
1040 UnicodeString result
;
1042 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
1043 UnicodeString formatStr
= "On {0,date}, it began.";
1044 UnicodeString compareStr
= "On Aug 8, 1997, it began.";
1047 MessageFormat
msg( formatStr
, err
);
1048 FieldPosition
fp(0);
1052 result
= msg
.format(
1059 if (err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
1060 dataerrln("*** MSG format without expected error code. - %s", u_errorName(err
));
1066 result
= msg
.format(
1073 logln("MSG format( Formattable&, ... ) expected:" + compareStr
);
1074 logln("MSG format( Formattable&, ... ) result:" + result
);
1075 if (result
!= compareStr
) {
1076 dataerrln("*** MSG format( Formattable&, .... ) err. - %s", u_errorName(err
));
1078 logln("MSG format( Formattable&, ... ) tested.");
1085 void TestMessageFormat::testParse()
1087 UErrorCode err
= U_ZERO_ERROR
;
1089 UnicodeString msgFormatString
= "{0} =sep= {1}";
1090 MessageFormat
msg( msgFormatString
, err
);
1091 UnicodeString source
= "abc =sep= def";
1092 UnicodeString tmp1
, tmp2
;
1094 Formattable
* fmt_arr
= msg
.parse( source
, count
, err
);
1095 if (U_FAILURE(err
) || (!fmt_arr
)) {
1096 errln("*** MSG parse (ustring, count, err) error.");
1098 logln("MSG parse -- count: %d", count
);
1100 errln("*** MSG parse (ustring, count, err) count err.");
1102 if ((fmt_arr
[0].getType() == Formattable::kString
)
1103 && (fmt_arr
[1].getType() == Formattable::kString
)
1104 && (fmt_arr
[0].getString(tmp1
) == "abc")
1105 && (fmt_arr
[1].getString(tmp2
) == "def")) {
1106 logln("MSG parse (ustring, count, err) tested.");
1108 errln("*** MSG parse (ustring, count, err) result err.");
1114 ParsePosition
pp(0);
1116 fmt_arr
= msg
.parse( source
, pp
, count
);
1117 if ((pp
== 0) || (!fmt_arr
)) {
1118 errln("*** MSG parse (ustring, parsepos., count) error.");
1120 logln("MSG parse -- count: %d", count
);
1122 errln("*** MSG parse (ustring, parsepos., count) count err.");
1124 if ((fmt_arr
[0].getType() == Formattable::kString
)
1125 && (fmt_arr
[1].getType() == Formattable::kString
)
1126 && (fmt_arr
[0].getString(tmp1
) == "abc")
1127 && (fmt_arr
[1].getString(tmp2
) == "def")) {
1128 logln("MSG parse (ustring, parsepos., count) tested.");
1130 errln("*** MSG parse (ustring, parsepos., count) result err.");
1139 msg
.parseObject( source
, fmta
, pp
);
1141 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
1143 logln("MSG parse -- count: %d", count
);
1144 fmta
.getArray(count
);
1146 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
1148 if ((fmta
[0].getType() == Formattable::kString
)
1149 && (fmta
[1].getType() == Formattable::kString
)
1150 && (fmta
[0].getString(tmp1
) == "abc")
1151 && (fmta
[1].getString(tmp2
) == "def")) {
1152 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
1154 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
1161 void TestMessageFormat::testAdopt()
1163 UErrorCode err
= U_ZERO_ERROR
;
1165 UnicodeString
formatStr("{0,date},{1},{2,number}", "");
1166 UnicodeString
formatStrChange("{0,number},{1,number},{2,date}", "");
1168 MessageFormat
msg( formatStr
, err
);
1169 MessageFormat
msgCmp( formatStr
, err
);
1170 int32_t count
, countCmp
;
1171 const Format
** formats
= msg
.getFormats(count
);
1172 const Format
** formatsCmp
= msgCmp
.getFormats(countCmp
);
1173 const Format
** formatsChg
= 0;
1174 const Format
** formatsAct
= 0;
1178 UnicodeString patCmp
;
1179 UnicodeString patAct
;
1180 Format
** formatsToAdopt
;
1182 if (!formats
|| !formatsCmp
|| (count
<= 0) || (count
!= countCmp
)) {
1183 dataerrln("Error getting Formats");
1189 for (i
= 0; i
< count
; i
++) {
1192 if ((a
!= NULL
) && (b
!= NULL
)) {
1197 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1198 errln("(a != NULL) || (b != NULL)");
1203 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1205 formatsChg
= msg
.getFormats(countChg
); // tested function
1206 if (!formatsChg
|| (countChg
!= count
)) {
1207 errln("Error getting Formats");
1213 for (i
= 0; i
< count
; i
++) {
1216 if ((a
!= NULL
) && (b
!= NULL
)) {
1218 logln("formatsChg == formatsCmp at index %d", i
);
1224 errln("*** MSG getFormats diff err.");
1228 logln("MSG getFormats tested.");
1230 msg
.setFormats( formatsCmp
, countCmp
); //tested function
1232 formatsAct
= msg
.getFormats(countAct
);
1233 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1234 errln("Error getting Formats");
1238 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1239 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1241 for (i
= 0; i
< countAct
; i
++) {
1244 if ((a
!= NULL
) && (b
!= NULL
)) {
1246 logln("formatsAct != formatsCmp at index %d", i
);
1250 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1251 errln("(a != NULL) || (b != NULL)");
1255 logln("MSG setFormats tested.");
1259 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1261 formatsToAdopt
= new Format
* [countCmp
];
1262 if (!formatsToAdopt
) {
1263 errln("memory allocation error");
1267 for (i
= 0; i
< countCmp
; i
++) {
1268 if (formatsCmp
[i
] == NULL
) {
1269 formatsToAdopt
[i
] = NULL
;
1271 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1272 if (!formatsToAdopt
[i
]) {
1273 errln("Can't clone format at index %d", i
);
1278 msg
.adoptFormats( formatsToAdopt
, countCmp
); // function to test
1279 delete[] formatsToAdopt
;
1281 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1282 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1284 formatsAct
= msg
.getFormats(countAct
);
1285 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1286 errln("Error getting Formats");
1290 for (i
= 0; i
< countAct
; i
++) {
1293 if ((a
!= NULL
) && (b
!= NULL
)) {
1298 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1299 errln("(a != NULL) || (b != NULL)");
1303 logln("MSG adoptFormats tested.");
1307 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1309 formatsToAdopt
= new Format
* [countCmp
];
1310 if (!formatsToAdopt
) {
1311 errln("memory allocation error");
1315 for (i
= 0; i
< countCmp
; i
++) {
1316 if (formatsCmp
[i
] == NULL
) {
1317 formatsToAdopt
[i
] = NULL
;
1319 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1320 if (!formatsToAdopt
[i
]) {
1321 errln("Can't clone format at index %d", i
);
1327 for ( i
= 0; i
< countCmp
; i
++ ) {
1328 msg
.adoptFormat( i
, formatsToAdopt
[i
] ); // function to test
1330 delete[] formatsToAdopt
; // array itself not needed in this case;
1332 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1333 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1335 formatsAct
= msg
.getFormats(countAct
);
1336 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1337 errln("Error getting Formats");
1341 for (i
= 0; i
< countAct
; i
++) {
1344 if ((a
!= NULL
) && (b
!= NULL
)) {
1349 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1350 errln("(a != NULL) || (b != NULL)");
1354 logln("MSG adoptFormat tested.");
1357 // This test is a regression test for a fixed bug in the copy constructor.
1358 // It is kept as a global function rather than as a method since the test depends on memory values.
1359 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1360 // which is probably why it didn't show up in the regular test for the copy constructor.)
1361 // For this reason, the test isn't changed even though it contains function calls whose results are
1362 // not tested and had no problems. Actually, the test failed by *crashing*.
1363 static void _testCopyConstructor2()
1365 UErrorCode status
= U_ZERO_ERROR
;
1366 UnicodeString
formatStr("Hello World on {0,date,full}", "");
1367 UnicodeString
resultStr(" ", "");
1368 UnicodeString result
;
1369 FieldPosition
fp(0);
1370 UDate d
= Calendar::getNow();
1371 const Formattable
fargs( d
, Formattable::kIsDate
);
1373 MessageFormat
* fmt1
= new MessageFormat( formatStr
, status
);
1374 MessageFormat
* fmt2
= new MessageFormat( *fmt1
);
1375 MessageFormat
* fmt3
;
1376 MessageFormat
* fmt4
;
1378 if (fmt1
== NULL
) it_err("testCopyConstructor2: (fmt1 != NULL)");
1380 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1382 if (fmt2
== NULL
) it_err("testCopyConstructor2: (fmt2 != NULL)");
1384 fmt3
= (MessageFormat
*) fmt1
->clone();
1385 fmt4
= (MessageFormat
*) fmt2
->clone();
1387 if (fmt3
== NULL
) it_err("testCopyConstructor2: (fmt3 != NULL)");
1388 if (fmt4
== NULL
) it_err("testCopyConstructor2: (fmt4 != NULL)");
1390 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1391 result
= fmt2
->format( &fargs
, 1, resultStr
, fp
, status
);
1392 result
= fmt3
->format( &fargs
, 1, resultStr
, fp
, status
);
1393 result
= fmt4
->format( &fargs
, 1, resultStr
, fp
, status
);
1400 void TestMessageFormat::testCopyConstructor2() {
1401 _testCopyConstructor2();
1405 * Verify that MessageFormat accomodates more than 10 arguments and
1406 * more than 10 subformats.
1408 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1409 UErrorCode ec
= U_ZERO_ERROR
;
1410 const UnicodeString pattern
=
1411 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1412 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1413 "there were {1,number} werjes "
1414 "(a {3,number,percent} increase over {2,number}) "
1415 "despite the {4}''s efforts "
1416 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1417 MessageFormat
msg(pattern
, ec
);
1418 if (U_FAILURE(ec
)) {
1419 dataerrln("FAIL: constructor failed - %s", u_errorName(ec
));
1423 const Formattable ARGS
[] = {
1424 Formattable(UDate(1e13
), Formattable::kIsDate
),
1425 Formattable((int32_t)1303),
1426 Formattable((int32_t)1202),
1427 Formattable(1303.0/1202 - 1),
1428 Formattable("Glimmung"),
1429 Formattable("the printers"),
1430 Formattable("Nick"),
1431 Formattable("his father"),
1432 Formattable("his mother"),
1433 Formattable("the spiddles"),
1434 Formattable("of course"),
1435 Formattable("Horace"),
1437 const int32_t ARGS_LENGTH
= sizeof(ARGS
) / sizeof(ARGS
[0]);
1438 Formattable
ARGS_OBJ(ARGS
, ARGS_LENGTH
);
1440 UnicodeString expected
=
1441 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1442 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1443 "there were 1,303 werjes "
1444 "(a 8% increase over 1,202) "
1445 "despite the Glimmung's efforts "
1446 "and to delight of the printers, Nick, his father, "
1447 "his mother, the spiddles, and of course Horace.";
1448 UnicodeString result
;
1449 msg
.format(ARGS_OBJ
, result
, ec
);
1450 if (result
== expected
) {
1453 errln((UnicodeString
)"FAIL: Got " + result
+
1454 ", expected " + expected
);
1458 // test RBNF extensions to message format
1459 void TestMessageFormat::TestRBNF(void) {
1460 // WARNING: this depends on the RBNF formats for en_US
1461 Locale
locale("en", "US", "");
1463 UErrorCode ec
= U_ZERO_ERROR
;
1465 UnicodeString values
[] = {
1466 // decimal values do not format completely for ordinal or duration, and
1467 // do not always parse, so do not include them
1468 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1470 int32_t values_count
= sizeof(values
)/sizeof(values
[0]);
1472 UnicodeString formats
[] = {
1473 "There are {0,spellout} files to search.",
1474 "There are {0,spellout,%simplified} files to search.",
1475 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1476 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1477 "Searching this file will take {0,duration} to complete.",
1478 "Searching this file will take {0,duration,%with-words} to complete.",
1480 int32_t formats_count
= sizeof(formats
)/sizeof(formats
[0]);
1482 Formattable args
[1];
1484 NumberFormat
* numFmt
= NumberFormat::createInstance(locale
, ec
);
1485 if (U_FAILURE(ec
)) {
1486 dataerrln("Error calling NumberFormat::createInstance()");
1490 for (int i
= 0; i
< formats_count
; ++i
) {
1491 MessageFormat
* fmt
= new MessageFormat(formats
[i
], locale
, ec
);
1492 logln((UnicodeString
)"Testing format pattern: '" + formats
[i
] + "'");
1494 for (int j
= 0; j
< values_count
; ++j
) {
1496 numFmt
->parse(values
[j
], args
[0], ec
);
1497 if (U_FAILURE(ec
)) {
1498 errln((UnicodeString
)"Failed to parse test argument " + values
[j
]);
1500 FieldPosition
fp(0);
1501 UnicodeString result
;
1502 fmt
->format(args
, 1, result
, fp
, ec
);
1503 logln((UnicodeString
)"value: " + toString(args
[0]) + " --> " + result
+ UnicodeString(" ec: ") + u_errorName(ec
));
1505 if (i
!= 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1507 Formattable
* parseResult
= fmt
->parse(result
, count
, ec
);
1509 errln((UnicodeString
)"parse returned " + count
+ " args");
1510 } else if (parseResult
[0] != args
[0]) {
1511 errln((UnicodeString
)"parsed argument " + toString(parseResult
[0]) + " != " + toString(args
[0]));
1513 delete []parseResult
;
1522 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1523 const char* patterns
[] = { // pattern, expected pattern
1534 "{'a{}'a}'a", "{'a{}'a}''a",
1536 "'} '{'}'", "'} '{'}''",
1537 "'} {{{''", "'} {{{'''",
1539 int32_t pattern_count
= sizeof(patterns
)/sizeof(patterns
[0]);
1541 for (int i
= 0; i
< pattern_count
; i
+= 2) {
1542 UErrorCode status
= U_ZERO_ERROR
;
1543 UnicodeString result
= MessageFormat::autoQuoteApostrophe(patterns
[i
], status
);
1544 UnicodeString
target(patterns
[i
+1]);
1545 if (target
!= result
) {
1546 const int BUF2_LEN
= 64;
1548 char buf2
[BUF2_LEN
];
1549 int32_t len
= result
.extract(0, result
.length(), buf2
, BUF2_LEN
);
1550 if (len
>= BUF2_LEN
) {
1551 buf2
[BUF2_LEN
-1] = 0;
1553 sprintf(buf
, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i
/2, patterns
[i
], patterns
[i
+1], buf2
);
1559 void TestMessageFormat::testCoverage(void) {
1560 UErrorCode status
= U_ZERO_ERROR
;
1561 UnicodeString
testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
1562 MessageFormat
*msgfmt
= new MessageFormat(testformat
, Locale("fr"), status
);
1563 if (msgfmt
== NULL
|| U_FAILURE(status
)) {
1564 dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status
));
1567 if (!msgfmt
->usesNamedArguments()) {
1568 errln("FAIL: Unable to detect usage of named arguments.");
1570 const double limit
[] = {0.0, 1.0, 2.0};
1571 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
1574 ChoiceFormat
cf(limit
, formats
, 3);
1576 msgfmt
->setFormat("set", cf
, status
);
1578 StringEnumeration
*en
= msgfmt
->getFormatNames(status
);
1579 if (en
== NULL
|| U_FAILURE(status
)) {
1580 errln("FAIL: Unable to get format names enumeration.");
1584 count
= en
->count(status
);
1585 if (U_FAILURE(status
)) {
1586 errln("FAIL: Unable to get format name enumeration count.");
1588 for (int32_t i
= 0; i
< count
; i
++) {
1590 if (U_FAILURE(status
)) {
1591 errln("FAIL: Error enumerating through names.");
1598 msgfmt
->adoptFormat("adopt", &cf
, status
);
1603 msgfmt
= new MessageFormat("'", status
);
1604 if (msgfmt
== NULL
|| U_FAILURE(status
)) {
1605 errln("FAIL: Unable to create MessageFormat.");
1608 if (msgfmt
->usesNamedArguments()) {
1609 errln("FAIL: Unable to detect usage of named arguments.");
1612 msgfmt
->setFormat("formatName", cf
, status
);
1613 if (!U_FAILURE(status
)) {
1614 errln("FAIL: Should fail to setFormat instead of passing.");
1616 status
= U_ZERO_ERROR
;
1617 en
= msgfmt
->getFormatNames(status
);
1618 if (!U_FAILURE(status
)) {
1619 errln("FAIL: Should fail to get format names enumeration instead of passing.");
1626 #endif /* #if !UCONFIG_NO_FORMATTING */