1 /********************************************************************
2 * Copyright (c) 1997-2008, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 ********************************************************************
7 * Modification History:
9 * Date Name Description
10 * 03/24/97 helena Converted from Java.
11 * 07/11/97 helena Updated to work on AIX.
12 * 08/04/97 jfitz Updated to intltest
13 *******************************************************************/
15 #include "unicode/utypes.h"
17 #if !UCONFIG_NO_FORMATTING
21 #include "unicode/format.h"
22 #include "unicode/decimfmt.h"
23 #include "unicode/locid.h"
24 #include "unicode/msgfmt.h"
25 #include "unicode/numfmt.h"
26 #include "unicode/choicfmt.h"
27 #include "unicode/gregocal.h"
31 TestMessageFormat::runIndexedTest(int32_t index
, UBool exec
,
32 const char* &name
, char* /*par*/) {
37 TESTCASE(3,PatternTest
);
38 TESTCASE(4,testStaticFormat
);
39 TESTCASE(5,testSimpleFormat
);
40 TESTCASE(6,testMsgFormatChoice
);
41 TESTCASE(7,testCopyConstructor
);
42 TESTCASE(8,testAssignment
);
43 TESTCASE(9,testClone
);
44 TESTCASE(10,testEquals
);
45 TESTCASE(11,testNotEquals
);
46 TESTCASE(12,testSetLocale
);
47 TESTCASE(13,testFormat
);
48 TESTCASE(14,testParse
);
49 TESTCASE(15,testAdopt
);
50 TESTCASE(16,testCopyConstructor2
);
51 TESTCASE(17,TestUnlimitedArgsAndSubformats
);
52 TESTCASE(18,TestRBNF
);
53 TESTCASE(19,TestTurkishCasing
);
54 TESTCASE(20,testAutoQuoteApostrophe
);
55 TESTCASE(21,testMsgFormatPlural
);
56 default: name
= ""; break;
60 void TestMessageFormat::testBug3()
62 double myNumber
= -123456;
63 DecimalFormat
*form
= 0;
72 Locale("de", "AT", ""),
73 Locale("de", "CH", ""),
74 Locale("el", "", ""), // 10
75 Locale("en", "CA", ""),
76 Locale("en", "GB", ""),
77 Locale("en", "IE", ""),
78 Locale("en", "US", ""),
83 Locale("fr", "BE", ""),
84 Locale("fr", "CA", ""), // 20
85 Locale("fr", "CH", ""),
91 Locale("it", "CH", ""),
94 Locale("lt", "", ""), // 30
98 Locale("nl", "BE", ""),
100 Locale("pl", "", ""),
101 Locale("pt", "", ""),
102 Locale("ro", "", ""),
103 Locale("ru", "", ""),
104 Locale("sh", "", ""), // 40
105 Locale("sk", "", ""),
106 Locale("sl", "", ""),
107 Locale("sq", "", ""),
108 Locale("sr", "", ""),
109 Locale("sv", "", ""),
110 Locale("tr", "", ""),
111 Locale("uk", "", ""),
112 Locale("zh", "", ""),
113 Locale("zh", "TW", "") // 49
116 for (i
= 0; i
< 49; i
++) {
117 UnicodeString buffer
;
118 logln(locale
[i
].getDisplayName(buffer
));
119 UErrorCode success
= U_ZERO_ERROR
;
120 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
121 form
= (DecimalFormat
*)NumberFormat::createInstance(locale
[i
], success
);
122 if (U_FAILURE(success
)) {
123 errln("Err: Number Format ");
124 logln("Number format creation failed.");
128 FieldPosition
pos(0);
130 form
->format(myNumber
, buffer
, pos
);
131 success
= U_ZERO_ERROR
;
132 ParsePosition parsePos
;
133 form
->parse(buffer
, result
, parsePos
);
134 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result
) + UnicodeString("[supposed output for result]"));
135 if (U_FAILURE(success
)) {
136 errln("Err: Number Format parse");
137 logln("Number format parse failed.");
143 void TestMessageFormat::testBug1()
145 const double limit
[] = {0.0, 1.0, 2.0};
146 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
149 ChoiceFormat
*cf
= new ChoiceFormat(limit
, formats
, 3);
150 FieldPosition
status(0);
151 UnicodeString toAppendTo
;
152 cf
->format((int32_t)1, toAppendTo
, status
);
153 if (toAppendTo
!= "1.0<=Arg<2.0") {
154 errln("ChoiceFormat cmp in testBug1");
160 void TestMessageFormat::testBug2()
162 UErrorCode status
= U_ZERO_ERROR
;
163 UnicodeString result
;
164 // {sfb} use double format in pattern, so result will match (not strictly necessary)
165 const UnicodeString pattern
= "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
166 logln("The input pattern : " + pattern
);
167 MessageFormat
*fmt
= new MessageFormat(pattern
, status
);
168 if (U_FAILURE(status
)) {
169 errln("MessageFormat pattern creation failed.");
172 logln("The output pattern is : " + fmt
->toPattern(result
));
173 if (pattern
!= result
) {
174 errln("MessageFormat::toPattern() failed.");
180 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
181 //----------------------------------------------------
183 //----------------------------------------------------
185 #if U_IOSTREAM_SOURCE >= 199711
187 std::ostream
& operator<<(std::ostream
& stream
, const Formattable
& obj
);
188 #elif U_IOSTREAM_SOURCE >= 198506
189 # include <iostream.h>
190 ostream
& operator<<(ostream
& stream
, const Formattable
& obj
);
193 #include "unicode/datefmt.h"
198 operator<<( IntlTest
& stream
,
199 const Formattable
& obj
)
201 static DateFormat
*defDateFormat
= 0;
203 UnicodeString buffer
;
204 switch(obj
.getType()) {
205 case Formattable::kDate
:
206 if (defDateFormat
== 0) {
207 defDateFormat
= DateFormat::createInstance();
209 defDateFormat
->format(obj
.getDate(), buffer
);
212 case Formattable::kDouble
:
214 sprintf( convert
, "%lf", obj
.getDouble() );
215 stream
<< convert
<< "D";
217 case Formattable::kLong
:
218 stream
<< obj
.getLong() << "L";
220 case Formattable::kString
:
221 stream
<< "\"" << obj
.getString(buffer
) << "\"";
223 case Formattable::kArray
:
225 const Formattable
* array
;
226 array
= obj
.getArray(count
);
228 for (i
=0; i
<count
; ++i
) stream
<< array
[i
] << ( (i
==(count
-1)) ? "" : ", " );
232 stream
<< "INVALID_Formattable";
236 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
239 void TestMessageFormat::PatternTest()
241 Formattable testArgs
[] = {
242 Formattable(double(1)), Formattable(double(3456)),
243 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate
)
245 UnicodeString testCases
[] = {
246 "Quotes '', '{', 'a' {0} '{0}'",
247 "Quotes '', '{', 'a' {0,number} '{0}'",
248 "'{'1,number,'#',##} {1,number,'#',##}",
249 "There are {1} files on {2} at {3}.",
250 "On {2}, there are {1} files, with {0,number,currency}.",
251 "'{1,number,percent}', {1,number,percent},",
252 "'{1,date,full}', {1,date,full},",
253 "'{3,date,full}', {3,date,full},",
254 "'{1,number,#,##}' {1,number,#,##}",
257 UnicodeString testResultPatterns
[] = {
258 "Quotes '', '{', a {0} '{'0}",
259 "Quotes '', '{', a {0,number} '{'0}",
260 "'{'1,number,#,##} {1,number,'#'#,##}",
261 "There are {1} files on {2} at {3}.",
262 "On {2}, there are {1} files, with {0,number,currency}.",
263 "'{'1,number,percent}, {1,number,percent},",
264 "'{'1,date,full}, {1,date,full},",
265 "'{'3,date,full}, {3,date,full},",
266 "'{'1,number,#,##} {1,number,#,##}"
269 UnicodeString testResultStrings
[] = {
270 "Quotes ', {, a 1 {0}",
271 "Quotes ', {, a 1 {0}",
272 "{1,number,#,##} #34,56",
273 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
274 "On Disk, there are 3,456 files, with $1.00.",
275 "{1,number,percent}, 345,600%,",
276 "{1,date,full}, Wednesday, December 31, 1969,",
277 "{3,date,full}, Monday, January 12, 1970,",
278 "{1,number,#,##} 34,56"
282 for (int32_t i
= 0; i
< 9; ++i
) {
283 //it_out << "\nPat in: " << testCases[i]);
285 MessageFormat
*form
= 0;
286 UErrorCode success
= U_ZERO_ERROR
;
287 UnicodeString buffer
;
288 form
= new MessageFormat(testCases
[i
], Locale::getUS(), success
);
289 if (U_FAILURE(success
)) {
290 errln("MessageFormat creation failed.#1");
291 logln(((UnicodeString
)"MessageFormat for ") + testCases
[i
] + " creation failed.\n");
294 if (form
->toPattern(buffer
) != testResultPatterns
[i
]) {
295 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i
);
296 //form->toPattern(buffer);
297 errln(((UnicodeString
)" Orig: ") + testCases
[i
]);
298 errln(((UnicodeString
)" Exp: ") + testResultPatterns
[i
]);
299 errln(((UnicodeString
)" Got: ") + buffer
);
302 //it_out << "Pat out: " << form->toPattern(buffer));
303 UnicodeString result
;
305 FieldPosition
fieldpos(0);
306 form
->format(testArgs
, count
, result
, fieldpos
, success
);
307 if (U_FAILURE(success
)) {
308 errln("MessageFormat failed test #3");
309 logln("TestMessageFormat::PatternTest failed test #3");
312 if (result
!= testResultStrings
[i
]) {
313 errln("TestMessageFormat::PatternTest failed test #4");
314 logln("TestMessageFormat::PatternTest failed #4.");
315 logln(UnicodeString(" Result: ") + result
);
316 logln(UnicodeString(" Expected: ") + testResultStrings
[i
] );
320 //it_out << "Result: " << result);
322 /* TODO: Look at this test and see if this is still a valid test */
323 logln("---------------- test parse ----------------");
325 form
->toPattern(buffer
);
326 logln("MSG pattern for parse: " + buffer
);
328 int32_t parseCount
= 0;
329 Formattable
* values
= form
->parse(result
, parseCount
, success
);
330 if (U_FAILURE(success
)) {
331 errln("MessageFormat failed test #5");
332 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success
);
333 } else if (parseCount
!= count
) {
334 errln("MSG count not %d as expected. Got %d", count
, parseCount
);
336 UBool failed
= FALSE
;
337 for (int32_t j
= 0; j
< parseCount
; ++j
) {
338 if (values
== 0 || testArgs
[j
] != values
[j
]) {
339 errln(((UnicodeString
)"MSG testargs[") + j
+ "]: " + toString(testArgs
[j
]));
340 errln(((UnicodeString
)"MSG values[") + j
+ "] : " + toString(values
[j
]));
345 errln("MessageFormat failed test #6");
351 void TestMessageFormat::sample()
353 MessageFormat
*form
= 0;
354 UnicodeString buffer1
, buffer2
;
355 UErrorCode success
= U_ZERO_ERROR
;
356 form
= new MessageFormat("There are {0} files on {1}", success
);
357 if (U_FAILURE(success
)) {
358 errln("Err: Message format creation failed");
359 logln("Sample message format creation failed.");
362 UnicodeString
abc("abc");
363 UnicodeString
def("def");
364 Formattable testArgs1
[] = { abc
, def
};
365 FieldPosition
fieldpos(0);
366 assertEquals("format",
367 "There are abc files on def",
368 form
->format(testArgs1
, 2, buffer2
, fieldpos
, success
));
369 assertSuccess("format", success
);
373 void TestMessageFormat::testStaticFormat()
375 UErrorCode err
= U_ZERO_ERROR
;
376 Formattable arguments
[] = {
378 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
379 "a disturbance in the Force"
382 UnicodeString result
;
383 result
= MessageFormat::format(
384 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
390 if (U_FAILURE(err
)) {
391 errln("TestMessageFormat::testStaticFormat #1");
392 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err
);
396 const UnicodeString
expected(
397 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
398 if (result
!= expected
) {
399 errln("TestMessageFormat::testStaticFormat failed on test");
400 logln( UnicodeString(" Result: ") + result
);
401 logln( UnicodeString(" Expected: ") + expected
);
405 /* When the default locale is tr, make sure that the pattern can still be parsed. */
406 void TestMessageFormat::TestTurkishCasing()
408 UErrorCode err
= U_ZERO_ERROR
;
409 Locale saveDefaultLocale
;
410 Locale::setDefault( Locale("tr"), err
);
412 Formattable arguments
[] = {
414 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
415 "a disturbance in the Force"
418 UnicodeString result
;
419 result
= MessageFormat::format(
420 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
426 if (U_FAILURE(err
)) {
427 errln("TestTurkishCasing #1 with error code %s", u_errorName(err
));
431 const UnicodeString
expected(
432 "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
433 if (result
!= expected
) {
434 errln("TestTurkishCasing failed on test");
435 errln( UnicodeString(" Result: ") + result
);
436 errln( UnicodeString(" Expected: ") + expected
);
438 Locale::setDefault( saveDefaultLocale
, err
);
441 void TestMessageFormat::testSimpleFormat(/* char* par */)
443 logln("running TestMessageFormat::testSimpleFormat");
445 UErrorCode err
= U_ZERO_ERROR
;
447 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
448 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
449 Formattable testArgs3
[] = {(int32_t)12, "MyDisk"};
451 MessageFormat
* form
= new MessageFormat(
452 "The disk \"{1}\" contains {0} file(s).", err
);
454 UnicodeString string
;
455 FieldPosition
ignore(FieldPosition::DONT_CARE
);
456 form
->format(testArgs1
, 2, string
, ignore
, err
);
457 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 0 file(s).") {
458 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1"));
461 ignore
.setField(FieldPosition::DONT_CARE
);
463 form
->format(testArgs2
, 2, string
, ignore
, err
);
464 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 1 file(s).") {
466 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string
);
469 ignore
.setField(FieldPosition::DONT_CARE
);
471 form
->format(testArgs3
, 2, string
, ignore
, err
);
472 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 12 file(s).") {
473 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string
);
479 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
481 logln("running TestMessageFormat::testMsgFormatChoice");
483 UErrorCode err
= U_ZERO_ERROR
;
485 MessageFormat
* form
= new MessageFormat("The disk \"{1}\" contains {0}.", err
);
486 double filelimits
[] = {0,1,2};
487 UnicodeString filepart
[] = {"no files","one file","{0,number} files"};
488 ChoiceFormat
* fileform
= new ChoiceFormat(filelimits
, filepart
, 3);
489 form
->setFormat(1,*fileform
); // NOT zero, see below
490 //is the format adopted?
492 FieldPosition
ignore(FieldPosition::DONT_CARE
);
493 UnicodeString string
;
494 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
495 form
->format(testArgs1
, 2, string
, ignore
, err
);
496 if (string
!= "The disk \"MyDisk\" contains no files.") {
497 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
500 ignore
.setField(FieldPosition::DONT_CARE
);
502 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
503 form
->format(testArgs2
, 2, string
, ignore
, err
);
504 if (string
!= "The disk \"MyDisk\" contains one file.") {
505 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
508 ignore
.setField(FieldPosition::DONT_CARE
);
510 Formattable testArgs3
[] = {(int32_t)1273, "MyDisk"};
511 form
->format(testArgs3
, 2, string
, ignore
, err
);
512 if (string
!= "The disk \"MyDisk\" contains 1,273 files.") {
513 errln("TestMessageFormat::testMsgFormatChoice failed on test #3");
521 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
523 logln("running TestMessageFormat::testMsgFormatPlural");
525 UErrorCode err
= U_ZERO_ERROR
;
526 UnicodeString
t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
527 UnicodeString
t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
528 UnicodeString
t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
529 UnicodeString
t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
530 UnicodeString
t5("{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
531 MessageFormat
* mfNum
= new MessageFormat(t1
, Locale("fr"), err
);
532 if (U_FAILURE(err
)) {
533 errln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex");
534 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
537 Formattable
testArgs1((int32_t)0);
538 FieldPosition
ignore(FieldPosition::DONT_CARE
);
539 UnicodeString numResult1
;
540 mfNum
->format(&testArgs1
, 1, numResult1
, ignore
, err
);
542 MessageFormat
* mfAlpha
= new MessageFormat(t2
, Locale("fr"), err
);
543 UnicodeString argName
[] = {UnicodeString("argument")};
544 UnicodeString argNameResult
;
545 mfAlpha
->format(argName
, &testArgs1
, 1, argNameResult
, err
);
546 if (U_FAILURE(err
)) {
547 errln("TestMessageFormat::testMsgFormatPlural #1 - argumentName");
548 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err
);
552 if ( numResult1
!= argNameResult
){
553 errln("TestMessageFormat::testMsgFormatPlural #1");
554 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
556 if ( numResult1
!= UnicodeString("C\'est 0 fichier dans la liste.")) {
557 errln("TestMessageFormat::testMsgFormatPlural #1");
558 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
565 MessageFormat
* mfNum2
= new MessageFormat(t3
, Locale("ru"), err
);
567 Formattable
testArgs2((int32_t)4);
568 mfNum2
->format(&testArgs2
, 1, numResult1
, ignore
, err
);
569 MessageFormat
* mfAlpha2
= new MessageFormat(t4
, Locale("ru"), err
);
570 argNameResult
.remove();
571 mfAlpha2
->format(argName
, &testArgs2
, 1, argNameResult
, err
);
573 if (U_FAILURE(err
)) {
574 errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
575 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err
);
579 if ( numResult1
!= argNameResult
){
580 errln("TestMessageFormat::testMsgFormatPlural #2");
581 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
583 if ( numResult1
!= UnicodeString("There are 4,0 zavoda in the directory.")) {
584 errln("TestMessageFormat::testMsgFormatPlural #2");
585 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
593 MessageFormat
* msgFmt
= new MessageFormat(t5
, Locale("fr"), err
);
594 if (U_FAILURE(err
)) {
595 errln("TestMessageFormat::test nested PluralFormat with argumentName");
596 logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err
);
600 Formattable
testArgs3((int32_t)0);
601 argNameResult
.remove();
602 msgFmt
->format(&testArgs3
, 1, argNameResult
, ignore
, err
);
603 if (U_FAILURE(err
)) {
604 errln("TestMessageFormat::test nested PluralFormat with argumentName");
606 if ( argNameResult
!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
607 errln(UnicodeString("TestMessageFormat::test nested named PluralFormat."));
608 logln(UnicodeString("The unexpected nested named PluralFormat."));
614 //---------------------------------
616 //---------------------------------
618 void TestMessageFormat::testCopyConstructor()
620 UErrorCode success
= U_ZERO_ERROR
;
621 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
622 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
623 MessageFormat
*y
= 0;
624 y
= new MessageFormat(*x
);
628 logln("First test (operator ==): Passed!");
630 errln("TestMessageFormat::testCopyConstructor failed #1");
631 logln("First test (operator ==): Failed!");
633 if ( ((*x
== *y
) && (*y
== *x
)) &&
634 ((*x
!= *z
) && (*z
!= *x
)) &&
635 ((*y
!= *z
) && (*z
!= *y
)) )
636 logln("Second test (equals): Passed!");
638 errln("TestMessageFormat::testCopyConstructor failed #2");
639 logln("Second test (equals): Failed!");
648 void TestMessageFormat::testAssignment()
650 UErrorCode success
= U_ZERO_ERROR
;
651 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
652 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
653 MessageFormat
*y
= new MessageFormat("There are {0} files on {1} created", success
);
658 logln("First test (operator ==): Passed!");
660 errln( "TestMessageFormat::testAssignment failed #1");
661 logln("First test (operator ==): Failed!");
663 if ( ((*x
== *y
) && (*y
== *x
)) &&
664 ((*x
!= *z
) && (*z
!= *x
)) &&
665 ((*y
!= *z
) && (*z
!= *y
)) )
666 logln("Second test (equals): Passed!");
668 errln("TestMessageFormat::testAssignment failed #2");
669 logln("Second test (equals): Failed!");
677 void TestMessageFormat::testClone()
679 UErrorCode success
= U_ZERO_ERROR
;
680 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
681 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
682 MessageFormat
*y
= 0;
683 y
= (MessageFormat
*)x
->clone();
687 logln("First test (operator ==): Passed!");
689 errln("TestMessageFormat::testClone failed #1");
690 logln("First test (operator ==): Failed!");
692 if ( ((*x
== *y
) && (*y
== *x
)) &&
693 ((*x
!= *z
) && (*z
!= *x
)) &&
694 ((*y
!= *z
) && (*z
!= *y
)) )
695 logln("Second test (equals): Passed!");
697 errln("TestMessageFormat::testClone failed #2");
698 logln("Second test (equals): Failed!");
706 void TestMessageFormat::testEquals()
708 UErrorCode success
= U_ZERO_ERROR
;
709 MessageFormat
x("There are {0} files on {1}", success
);
710 MessageFormat
y("There are {0} files on {1}", success
);
712 errln( "TestMessageFormat::testEquals failed #1");
713 logln("First test (operator ==): Failed!");
718 void TestMessageFormat::testNotEquals()
720 UErrorCode success
= U_ZERO_ERROR
;
721 MessageFormat
x("There are {0} files on {1}", success
);
723 y
.setLocale(Locale("fr"));
725 errln( "TestMessageFormat::testEquals failed #1");
726 logln("First test (operator !=): Failed!");
729 y
.applyPattern("There are {0} files on {1} the disk", success
);
731 errln( "TestMessageFormat::testEquals failed #1");
732 logln("Second test (operator !=): Failed!");
737 void TestMessageFormat::testSetLocale()
739 UErrorCode err
= U_ZERO_ERROR
;
740 GregorianCalendar
cal(err
);
741 Formattable arguments
[] = {
743 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
747 UnicodeString result
;
749 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
750 UnicodeString formatStr
= "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
751 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
752 // Just use unlocalized currency symbol.
753 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
754 UnicodeString compareStrEng
= "At <time> on Aug 8, 1997, you made a deposit of ";
755 compareStrEng
+= (UChar
) 0x00a4;
756 compareStrEng
+= "456.83.";
757 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
758 // Just use unlocalized currency symbol.
759 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
760 UnicodeString compareStrGer
= "At <time> on 08.08.1997, you made a deposit of ";
761 compareStrGer
+= "456,83";
762 compareStrGer
+= (UChar
) 0x00a0;
763 compareStrGer
+= (UChar
) 0x00a4;
764 compareStrGer
+= ".";
766 MessageFormat
msg( formatStr
, err
);
768 FieldPosition
pos(0);
777 if (result
!= compareStrEng
) {
778 errln("*** MSG format err.");
781 msg
.setLocale(Locale::getEnglish());
782 UBool getLocale_ok
= TRUE
;
783 if (msg
.getLocale() != Locale::getEnglish()) {
784 errln("*** MSG getLocal err.");
785 getLocale_ok
= FALSE
;
788 msg
.setLocale(Locale::getGerman());
790 if (msg
.getLocale() != Locale::getGerman()) {
791 errln("*** MSG getLocal err.");
792 getLocale_ok
= FALSE
;
795 msg
.applyPattern( formatStr
, err
);
807 if (result
== compareStrGer
) {
808 logln("MSG setLocale tested.");
810 errln( "*** MSG setLocale err.");
814 logln("MSG getLocale tested.");
818 void TestMessageFormat::testFormat()
820 UErrorCode err
= U_ZERO_ERROR
;
821 GregorianCalendar
cal(err
);
823 const Formattable ftarray
[] =
825 Formattable( UDate(8.71068e+011), Formattable::kIsDate
)
827 const int32_t ft_cnt
= sizeof(ftarray
) / sizeof(Formattable
);
828 Formattable
ft_arr( ftarray
, ft_cnt
);
830 Formattable
* fmt
= new Formattable(UDate(8.71068e+011), Formattable::kIsDate
);
832 UnicodeString result
;
834 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
835 UnicodeString formatStr
= "On {0,date}, it began.";
836 UnicodeString compareStr
= "On Aug 8, 1997, it began.";
839 MessageFormat
msg( formatStr
, err
);
851 if (err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
852 errln("*** MSG format without expected error code.");
865 logln("MSG format( Formattable&, ... ) expected:" + compareStr
);
866 logln("MSG format( Formattable&, ... ) result:" + result
);
867 if (result
!= compareStr
) {
868 errln("*** MSG format( Formattable&, .... ) err.");
870 logln("MSG format( Formattable&, ... ) tested.");
877 void TestMessageFormat::testParse()
879 UErrorCode err
= U_ZERO_ERROR
;
881 UnicodeString msgFormatString
= "{0} =sep= {1}";
882 MessageFormat
msg( msgFormatString
, err
);
883 UnicodeString source
= "abc =sep= def";
884 UnicodeString tmp1
, tmp2
;
886 Formattable
* fmt_arr
= msg
.parse( source
, count
, err
);
887 if (U_FAILURE(err
) || (!fmt_arr
)) {
888 errln("*** MSG parse (ustring, count, err) error.");
890 logln("MSG parse -- count: %d", count
);
892 errln("*** MSG parse (ustring, count, err) count err.");
894 if ((fmt_arr
[0].getType() == Formattable::kString
)
895 && (fmt_arr
[1].getType() == Formattable::kString
)
896 && (fmt_arr
[0].getString(tmp1
) == "abc")
897 && (fmt_arr
[1].getString(tmp2
) == "def")) {
898 logln("MSG parse (ustring, count, err) tested.");
900 errln("*** MSG parse (ustring, count, err) result err.");
908 fmt_arr
= msg
.parse( source
, pp
, count
);
909 if ((pp
== 0) || (!fmt_arr
)) {
910 errln("*** MSG parse (ustring, parsepos., count) error.");
912 logln("MSG parse -- count: %d", count
);
914 errln("*** MSG parse (ustring, parsepos., count) count err.");
916 if ((fmt_arr
[0].getType() == Formattable::kString
)
917 && (fmt_arr
[1].getType() == Formattable::kString
)
918 && (fmt_arr
[0].getString(tmp1
) == "abc")
919 && (fmt_arr
[1].getString(tmp2
) == "def")) {
920 logln("MSG parse (ustring, parsepos., count) tested.");
922 errln("*** MSG parse (ustring, parsepos., count) result err.");
931 msg
.parseObject( source
, fmta
, pp
);
933 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
935 logln("MSG parse -- count: %d", count
);
936 fmta
.getArray(count
);
938 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
940 if ((fmta
[0].getType() == Formattable::kString
)
941 && (fmta
[1].getType() == Formattable::kString
)
942 && (fmta
[0].getString(tmp1
) == "abc")
943 && (fmta
[1].getString(tmp2
) == "def")) {
944 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
946 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
953 void TestMessageFormat::testAdopt()
955 UErrorCode err
= U_ZERO_ERROR
;
957 UnicodeString
formatStr("{0,date},{1},{2,number}", "");
958 UnicodeString
formatStrChange("{0,number},{1,number},{2,date}", "");
960 MessageFormat
msg( formatStr
, err
);
961 MessageFormat
msgCmp( formatStr
, err
);
962 int32_t count
, countCmp
;
963 const Format
** formats
= msg
.getFormats(count
);
964 const Format
** formatsCmp
= msgCmp
.getFormats(countCmp
);
965 const Format
** formatsChg
= 0;
966 const Format
** formatsAct
= 0;
970 UnicodeString patCmp
;
971 UnicodeString patAct
;
972 Format
** formatsToAdopt
;
974 if (!formats
|| !formatsCmp
|| (count
<= 0) || (count
!= countCmp
)) {
975 errln("Error getting Formats");
981 for (i
= 0; i
< count
; i
++) {
984 if ((a
!= NULL
) && (b
!= NULL
)) {
989 }else if ((a
!= NULL
) || (b
!= NULL
)) {
990 errln("(a != NULL) || (b != NULL)");
995 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
997 formatsChg
= msg
.getFormats(countChg
); // tested function
998 if (!formatsChg
|| (countChg
!= count
)) {
999 errln("Error getting Formats");
1005 for (i
= 0; i
< count
; i
++) {
1008 if ((a
!= NULL
) && (b
!= NULL
)) {
1010 logln("formatsChg == formatsCmp at index %d", i
);
1016 errln("*** MSG getFormats diff err.");
1020 logln("MSG getFormats tested.");
1022 msg
.setFormats( formatsCmp
, countCmp
); //tested function
1024 formatsAct
= msg
.getFormats(countAct
);
1025 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1026 errln("Error getting Formats");
1030 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1031 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1033 for (i
= 0; i
< countAct
; i
++) {
1036 if ((a
!= NULL
) && (b
!= NULL
)) {
1038 logln("formatsAct != formatsCmp at index %d", i
);
1042 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1043 errln("(a != NULL) || (b != NULL)");
1047 logln("MSG setFormats tested.");
1051 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1053 formatsToAdopt
= new Format
* [countCmp
];
1054 if (!formatsToAdopt
) {
1055 errln("memory allocation error");
1059 for (i
= 0; i
< countCmp
; i
++) {
1060 if (formatsCmp
[i
] == NULL
) {
1061 formatsToAdopt
[i
] = NULL
;
1063 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1064 if (!formatsToAdopt
[i
]) {
1065 errln("Can't clone format at index %d", i
);
1070 msg
.adoptFormats( formatsToAdopt
, countCmp
); // function to test
1071 delete[] formatsToAdopt
;
1073 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1074 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1076 formatsAct
= msg
.getFormats(countAct
);
1077 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1078 errln("Error getting Formats");
1082 for (i
= 0; i
< countAct
; i
++) {
1085 if ((a
!= NULL
) && (b
!= NULL
)) {
1090 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1091 errln("(a != NULL) || (b != NULL)");
1095 logln("MSG adoptFormats tested.");
1099 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1101 formatsToAdopt
= new Format
* [countCmp
];
1102 if (!formatsToAdopt
) {
1103 errln("memory allocation error");
1107 for (i
= 0; i
< countCmp
; i
++) {
1108 if (formatsCmp
[i
] == NULL
) {
1109 formatsToAdopt
[i
] = NULL
;
1111 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1112 if (!formatsToAdopt
[i
]) {
1113 errln("Can't clone format at index %d", i
);
1119 for ( i
= 0; i
< countCmp
; i
++ ) {
1120 msg
.adoptFormat( i
, formatsToAdopt
[i
] ); // function to test
1122 delete[] formatsToAdopt
; // array itself not needed in this case;
1124 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1125 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1127 formatsAct
= msg
.getFormats(countAct
);
1128 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1129 errln("Error getting Formats");
1133 for (i
= 0; i
< countAct
; i
++) {
1136 if ((a
!= NULL
) && (b
!= NULL
)) {
1141 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1142 errln("(a != NULL) || (b != NULL)");
1146 logln("MSG adoptFormat tested.");
1149 // This test is a regression test for a fixed bug in the copy constructor.
1150 // It is kept as a global function rather than as a method since the test depends on memory values.
1151 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1152 // which is probably why it didn't show up in the regular test for the copy constructor.)
1153 // For this reason, the test isn't changed even though it contains function calls whose results are
1154 // not tested and had no problems. Actually, the test failed by *crashing*.
1155 static void _testCopyConstructor2()
1157 UErrorCode status
= U_ZERO_ERROR
;
1158 UnicodeString
formatStr("Hello World on {0,date,full}", "");
1159 UnicodeString
resultStr(" ", "");
1160 UnicodeString result
;
1161 FieldPosition
fp(0);
1162 UDate d
= Calendar::getNow();
1163 const Formattable
fargs( d
, Formattable::kIsDate
);
1165 MessageFormat
* fmt1
= new MessageFormat( formatStr
, status
);
1166 MessageFormat
* fmt2
= new MessageFormat( *fmt1
);
1167 MessageFormat
* fmt3
;
1168 MessageFormat
* fmt4
;
1170 if (fmt1
== NULL
) it_err("testCopyConstructor2: (fmt1 != NULL)");
1172 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1174 if (fmt2
== NULL
) it_err("testCopyConstructor2: (fmt2 != NULL)");
1176 fmt3
= (MessageFormat
*) fmt1
->clone();
1177 fmt4
= (MessageFormat
*) fmt2
->clone();
1179 if (fmt3
== NULL
) it_err("testCopyConstructor2: (fmt3 != NULL)");
1180 if (fmt4
== NULL
) it_err("testCopyConstructor2: (fmt4 != NULL)");
1182 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1183 result
= fmt2
->format( &fargs
, 1, resultStr
, fp
, status
);
1184 result
= fmt3
->format( &fargs
, 1, resultStr
, fp
, status
);
1185 result
= fmt4
->format( &fargs
, 1, resultStr
, fp
, status
);
1192 void TestMessageFormat::testCopyConstructor2() {
1193 _testCopyConstructor2();
1197 * Verify that MessageFormat accomodates more than 10 arguments and
1198 * more than 10 subformats.
1200 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1201 UErrorCode ec
= U_ZERO_ERROR
;
1202 const UnicodeString pattern
=
1203 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1204 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1205 "there were {1,number} werjes "
1206 "(a {3,number,percent} increase over {2,number}) "
1207 "despite the {4}''s efforts "
1208 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1209 MessageFormat
msg(pattern
, ec
);
1210 if (U_FAILURE(ec
)) {
1211 errln("FAIL: constructor failed");
1215 const Formattable ARGS
[] = {
1216 Formattable(UDate(1e13
), Formattable::kIsDate
),
1217 Formattable((int32_t)1303),
1218 Formattable((int32_t)1202),
1219 Formattable(1303.0/1202 - 1),
1220 Formattable("Glimmung"),
1221 Formattable("the printers"),
1222 Formattable("Nick"),
1223 Formattable("his father"),
1224 Formattable("his mother"),
1225 Formattable("the spiddles"),
1226 Formattable("of course"),
1227 Formattable("Horace"),
1229 const int32_t ARGS_LENGTH
= sizeof(ARGS
) / sizeof(ARGS
[0]);
1230 Formattable
ARGS_OBJ(ARGS
, ARGS_LENGTH
);
1232 UnicodeString expected
=
1233 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1234 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1235 "there were 1,303 werjes "
1236 "(a 8% increase over 1,202) "
1237 "despite the Glimmung's efforts "
1238 "and to delight of the printers, Nick, his father, "
1239 "his mother, the spiddles, and of course Horace.";
1240 UnicodeString result
;
1241 msg
.format(ARGS_OBJ
, result
, ec
);
1242 if (result
== expected
) {
1245 errln((UnicodeString
)"FAIL: Got " + result
+
1246 ", expected " + expected
);
1250 // test RBNF extensions to message format
1251 void TestMessageFormat::TestRBNF(void) {
1252 // WARNING: this depends on the RBNF formats for en_US
1253 Locale
locale("en", "US", "");
1255 UErrorCode ec
= U_ZERO_ERROR
;
1257 UnicodeString values
[] = {
1258 // decimal values do not format completely for ordinal or duration, and
1259 // do not always parse, so do not include them
1260 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1262 int32_t values_count
= sizeof(values
)/sizeof(values
[0]);
1264 UnicodeString formats
[] = {
1265 "There are {0,spellout} files to search.",
1266 "There are {0,spellout,%simplified} files to search.",
1267 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1268 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1269 "Searching this file will take {0,duration} to complete.",
1270 "Searching this file will take {0,duration,%with-words} to complete.",
1272 int32_t formats_count
= sizeof(formats
)/sizeof(formats
[0]);
1274 Formattable args
[1];
1276 NumberFormat
* numFmt
= NumberFormat::createInstance(locale
, ec
);
1277 if (U_FAILURE(ec
)) {
1278 dataerrln("Error calling NumberFormat::createInstance()");
1282 for (int i
= 0; i
< formats_count
; ++i
) {
1283 MessageFormat
* fmt
= new MessageFormat(formats
[i
], locale
, ec
);
1284 logln((UnicodeString
)"Testing format pattern: '" + formats
[i
] + "'");
1286 for (int j
= 0; j
< values_count
; ++j
) {
1288 numFmt
->parse(values
[j
], args
[0], ec
);
1289 if (U_FAILURE(ec
)) {
1290 errln((UnicodeString
)"Failed to parse test argument " + values
[j
]);
1292 FieldPosition
fp(0);
1293 UnicodeString result
;
1294 fmt
->format(args
, 1, result
, fp
, ec
);
1295 logln((UnicodeString
)"value: " + toString(args
[0]) + " --> " + result
+ UnicodeString(" ec: ") + u_errorName(ec
));
1297 if (i
!= 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1299 Formattable
* parseResult
= fmt
->parse(result
, count
, ec
);
1301 errln((UnicodeString
)"parse returned " + count
+ " args");
1302 } else if (parseResult
[0] != args
[0]) {
1303 errln((UnicodeString
)"parsed argument " + toString(parseResult
[0]) + " != " + toString(args
[0]));
1305 delete []parseResult
;
1314 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1315 const char* patterns
[] = { // pattern, expected pattern
1326 "{'a{}'a}'a", "{'a{}'a}''a",
1328 "'} '{'}'", "'} '{'}''",
1329 "'} {{{''", "'} {{{'''",
1331 int32_t pattern_count
= sizeof(patterns
)/sizeof(patterns
[0]);
1333 for (int i
= 0; i
< pattern_count
; i
+= 2) {
1334 UErrorCode status
= U_ZERO_ERROR
;
1335 UnicodeString result
= MessageFormat::autoQuoteApostrophe(patterns
[i
], status
);
1336 UnicodeString
target(patterns
[i
+1]);
1337 if (target
!= result
) {
1338 const int BUF2_LEN
= 64;
1340 char buf2
[BUF2_LEN
];
1341 int32_t len
= result
.extract(0, result
.length(), buf2
, BUF2_LEN
);
1342 if (len
>= BUF2_LEN
) {
1343 buf2
[BUF2_LEN
-1] = 0;
1345 sprintf(buf
, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i
/2, patterns
[i
], patterns
[i
+1], buf2
);
1351 #endif /* #if !UCONFIG_NO_FORMATTING */