1 /********************************************************************
3 * Copyright (c) 1997-2006, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
9 * Modification History:
11 * Date Name Description
12 * 03/24/97 helena Converted from Java.
13 * 07/11/97 helena Updated to work on AIX.
14 * 08/04/97 jfitz Updated to intltest
15 ********************************************************************************
18 #include "unicode/utypes.h"
20 #if !UCONFIG_NO_FORMATTING
24 #include "unicode/format.h"
25 #include "unicode/decimfmt.h"
26 #include "unicode/locid.h"
27 #include "unicode/msgfmt.h"
28 #include "unicode/numfmt.h"
29 #include "unicode/choicfmt.h"
30 #include "unicode/gregocal.h"
34 TestMessageFormat::runIndexedTest(int32_t index
, UBool exec
,
35 const char* &name
, char* /*par*/) {
40 TESTCASE(3,PatternTest
);
41 TESTCASE(4,testStaticFormat
);
42 TESTCASE(5,testSimpleFormat
);
43 TESTCASE(6,testMsgFormatChoice
);
44 TESTCASE(7,testCopyConstructor
);
45 TESTCASE(8,testAssignment
);
46 TESTCASE(9,testClone
);
47 TESTCASE(10,testEquals
);
48 TESTCASE(11,testNotEquals
);
49 TESTCASE(12,testSetLocale
);
50 TESTCASE(13,testFormat
);
51 TESTCASE(14,testParse
);
52 TESTCASE(15,testAdopt
);
53 TESTCASE(16,testCopyConstructor2
);
54 TESTCASE(17,TestUnlimitedArgsAndSubformats
);
55 TESTCASE(18,TestRBNF
);
56 TESTCASE(19,TestTurkishCasing
);
57 TESTCASE(20,testAutoQuoteApostrophe
);
58 default: name
= ""; break;
62 void TestMessageFormat::testBug3()
64 double myNumber
= -123456;
65 DecimalFormat
*form
= 0;
74 Locale("de", "AT", ""),
75 Locale("de", "CH", ""),
76 Locale("el", "", ""), // 10
77 Locale("en", "CA", ""),
78 Locale("en", "GB", ""),
79 Locale("en", "IE", ""),
80 Locale("en", "US", ""),
85 Locale("fr", "BE", ""),
86 Locale("fr", "CA", ""), // 20
87 Locale("fr", "CH", ""),
93 Locale("it", "CH", ""),
96 Locale("lt", "", ""), // 30
100 Locale("nl", "BE", ""),
101 Locale("no", "", ""),
102 Locale("pl", "", ""),
103 Locale("pt", "", ""),
104 Locale("ro", "", ""),
105 Locale("ru", "", ""),
106 Locale("sh", "", ""), // 40
107 Locale("sk", "", ""),
108 Locale("sl", "", ""),
109 Locale("sq", "", ""),
110 Locale("sr", "", ""),
111 Locale("sv", "", ""),
112 Locale("tr", "", ""),
113 Locale("uk", "", ""),
114 Locale("zh", "", ""),
115 Locale("zh", "TW", "") // 49
118 for (i
= 0; i
< 49; i
++) {
119 UnicodeString buffer
;
120 logln(locale
[i
].getDisplayName(buffer
));
121 UErrorCode success
= U_ZERO_ERROR
;
122 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
123 form
= (DecimalFormat
*)NumberFormat::createInstance(locale
[i
], success
);
124 if (U_FAILURE(success
)) {
125 errln("Err: Number Format ");
126 logln("Number format creation failed.");
130 FieldPosition
pos(0);
132 form
->format(myNumber
, buffer
, pos
);
133 success
= U_ZERO_ERROR
;
134 ParsePosition parsePos
;
135 form
->parse(buffer
, result
, parsePos
);
136 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result
) + UnicodeString("[supposed output for result]"));
137 if (U_FAILURE(success
)) {
138 errln("Err: Number Format parse");
139 logln("Number format parse failed.");
145 void TestMessageFormat::testBug1()
147 const double limit
[] = {0.0, 1.0, 2.0};
148 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
151 ChoiceFormat
*cf
= new ChoiceFormat(limit
, formats
, 3);
152 FieldPosition
status(0);
153 UnicodeString toAppendTo
;
154 cf
->format((int32_t)1, toAppendTo
, status
);
155 if (toAppendTo
!= "1.0<=Arg<2.0") {
156 errln("ChoiceFormat cmp in testBug1");
162 void TestMessageFormat::testBug2()
164 UErrorCode status
= U_ZERO_ERROR
;
165 UnicodeString result
;
166 // {sfb} use double format in pattern, so result will match (not strictly necessary)
167 const UnicodeString pattern
= "There {0,choice,0.0#are no files|1.0#is one file|1.0<are {0, number} files} on disk {1}. ";
168 logln("The input pattern : " + pattern
);
169 MessageFormat
*fmt
= new MessageFormat(pattern
, status
);
170 if (U_FAILURE(status
)) {
171 errln("MessageFormat pattern creation failed.");
174 logln("The output pattern is : " + fmt
->toPattern(result
));
175 if (pattern
!= result
) {
176 errln("MessageFormat::toPattern() failed.");
182 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
183 //----------------------------------------------------
185 //----------------------------------------------------
187 #if U_IOSTREAM_SOURCE >= 199711
189 std::ostream
& operator<<(std::ostream
& stream
, const Formattable
& obj
);
190 #elif U_IOSTREAM_SOURCE >= 198506
191 # include <iostream.h>
192 ostream
& operator<<(ostream
& stream
, const Formattable
& obj
);
195 #include "unicode/datefmt.h"
200 operator<<( IntlTest
& stream
,
201 const Formattable
& obj
)
203 static DateFormat
*defDateFormat
= 0;
205 UnicodeString buffer
;
206 switch(obj
.getType()) {
207 case Formattable::kDate
:
208 if (defDateFormat
== 0) {
209 defDateFormat
= DateFormat::createInstance();
211 defDateFormat
->format(obj
.getDate(), buffer
);
214 case Formattable::kDouble
:
216 sprintf( convert
, "%lf", obj
.getDouble() );
217 stream
<< convert
<< "D";
219 case Formattable::kLong
:
220 stream
<< obj
.getLong() << "L";
222 case Formattable::kString
:
223 stream
<< "\"" << obj
.getString(buffer
) << "\"";
225 case Formattable::kArray
:
227 const Formattable
* array
;
228 array
= obj
.getArray(count
);
230 for (i
=0; i
<count
; ++i
) stream
<< array
[i
] << ( (i
==(count
-1)) ? "" : ", " );
234 stream
<< "INVALID_Formattable";
238 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
241 void TestMessageFormat::PatternTest()
243 Formattable testArgs
[] = {
244 Formattable(double(1)), Formattable(double(3456)),
245 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate
)
247 UnicodeString testCases
[] = {
248 "Quotes '', '{', 'a' {0} '{0}'",
249 "Quotes '', '{', 'a' {0,number} '{0}'",
250 "'{'1,number,'#',##} {1,number,'#',##}",
251 "There are {1} files on {2} at {3}.",
252 "On {2}, there are {1} files, with {0,number,currency}.",
253 "'{1,number,percent}', {1,number,percent},",
254 "'{1,date,full}', {1,date,full},",
255 "'{3,date,full}', {3,date,full},",
256 "'{1,number,#,##}' {1,number,#,##}",
259 UnicodeString testResultPatterns
[] = {
260 "Quotes '', '{', a {0} '{'0}",
261 "Quotes '', '{', a {0,number} '{'0}",
262 "'{'1,number,#,##} {1,number,'#'#,##}",
263 "There are {1} files on {2} at {3}.",
264 "On {2}, there are {1} files, with {0,number,currency}.",
265 "'{'1,number,percent}, {1,number,percent},",
266 "'{'1,date,full}, {1,date,full},",
267 "'{'3,date,full}, {3,date,full},",
268 "'{'1,number,#,##} {1,number,#,##}"
271 UnicodeString testResultStrings
[] = {
272 "Quotes ', {, a 1 {0}",
273 "Quotes ', {, a 1 {0}",
274 "{1,number,#,##} #34,56",
275 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
276 "On Disk, there are 3,456 files, with $1.00.",
277 "{1,number,percent}, 345,600%,",
278 "{1,date,full}, Wednesday, December 31, 1969,",
279 "{3,date,full}, Monday, January 12, 1970,",
280 "{1,number,#,##} 34,56"
284 for (int32_t i
= 0; i
< 9; ++i
) {
285 //it_out << "\nPat in: " << testCases[i]);
287 MessageFormat
*form
= 0;
288 UErrorCode success
= U_ZERO_ERROR
;
289 UnicodeString buffer
;
290 form
= new MessageFormat(testCases
[i
], Locale::getUS(), success
);
291 if (U_FAILURE(success
)) {
292 errln("MessageFormat creation failed.#1");
293 logln(((UnicodeString
)"MessageFormat for ") + testCases
[i
] + " creation failed.\n");
296 if (form
->toPattern(buffer
) != testResultPatterns
[i
]) {
297 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i
);
298 //form->toPattern(buffer);
299 errln(((UnicodeString
)" Orig: ") + testCases
[i
]);
300 errln(((UnicodeString
)" Exp: ") + testResultPatterns
[i
]);
301 errln(((UnicodeString
)" Got: ") + buffer
);
304 //it_out << "Pat out: " << form->toPattern(buffer));
305 UnicodeString result
;
307 FieldPosition
fieldpos(0);
308 form
->format(testArgs
, count
, result
, fieldpos
, success
);
309 if (U_FAILURE(success
)) {
310 errln("MessageFormat failed test #3");
311 logln("TestMessageFormat::PatternTest failed test #3");
314 if (result
!= testResultStrings
[i
]) {
315 errln("TestMessageFormat::PatternTest failed test #4");
316 logln("TestMessageFormat::PatternTest failed #4.");
317 logln(UnicodeString(" Result: ") + result
);
318 logln(UnicodeString(" Expected: ") + testResultStrings
[i
] );
322 //it_out << "Result: " << result);
324 /* TODO: Look at this test and see if this is still a valid test */
325 logln("---------------- test parse ----------------");
327 form
->toPattern(buffer
);
328 logln("MSG pattern for parse: " + buffer
);
330 int32_t parseCount
= 0;
331 Formattable
* values
= form
->parse(result
, parseCount
, success
);
332 if (U_FAILURE(success
)) {
333 errln("MessageFormat failed test #5");
334 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success
);
335 } else if (parseCount
!= count
) {
336 errln("MSG count not %d as expected. Got %d", count
, parseCount
);
338 UBool failed
= FALSE
;
339 for (int32_t j
= 0; j
< parseCount
; ++j
) {
340 if (values
== 0 || testArgs
[j
] != values
[j
]) {
341 errln(((UnicodeString
)"MSG testargs[") + j
+ "]: " + toString(testArgs
[j
]));
342 errln(((UnicodeString
)"MSG values[") + j
+ "] : " + toString(values
[j
]));
347 errln("MessageFormat failed test #6");
353 void TestMessageFormat::sample()
355 MessageFormat
*form
= 0;
356 UnicodeString buffer1
, buffer2
;
357 UErrorCode success
= U_ZERO_ERROR
;
358 form
= new MessageFormat("There are {0} files on {1}", success
);
359 if (U_FAILURE(success
)) {
360 errln("Err: Message format creation failed");
361 logln("Sample message format creation failed.");
364 UnicodeString
abc("abc");
365 UnicodeString
def("def");
366 Formattable testArgs1
[] = { abc
, def
};
367 FieldPosition
fieldpos(0);
368 assertEquals("format",
369 "There are abc files on def",
370 form
->format(testArgs1
, 2, buffer2
, fieldpos
, success
));
371 assertSuccess("format", success
);
375 void TestMessageFormat::testStaticFormat()
377 UErrorCode err
= U_ZERO_ERROR
;
378 Formattable arguments
[] = {
380 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
381 "a disturbance in the Force"
384 UnicodeString result
;
385 result
= MessageFormat::format(
386 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
392 if (U_FAILURE(err
)) {
393 errln("TestMessageFormat::testStaticFormat #1");
394 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err
);
398 const UnicodeString
expected(
399 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
400 if (result
!= expected
) {
401 errln("TestMessageFormat::testStaticFormat failed on test");
402 logln( UnicodeString(" Result: ") + result
);
403 logln( UnicodeString(" Expected: ") + expected
);
407 /* When the default locale is tr, make sure that the pattern can still be parsed. */
408 void TestMessageFormat::TestTurkishCasing()
410 UErrorCode err
= U_ZERO_ERROR
;
411 Locale saveDefaultLocale
;
412 Locale::setDefault( Locale("tr"), err
);
414 Formattable arguments
[] = {
416 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
417 "a disturbance in the Force"
420 UnicodeString result
;
421 result
= MessageFormat::format(
422 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
428 if (U_FAILURE(err
)) {
429 errln("TestTurkishCasing #1 with error code %s", u_errorName(err
));
433 const UnicodeString
expected(
434 "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
435 if (result
!= expected
) {
436 errln("TestTurkishCasing failed on test");
437 errln( UnicodeString(" Result: ") + result
);
438 errln( UnicodeString(" Expected: ") + expected
);
440 Locale::setDefault( saveDefaultLocale
, err
);
443 void TestMessageFormat::testSimpleFormat(/* char* par */)
445 logln("running TestMessageFormat::testSimpleFormat");
447 UErrorCode err
= U_ZERO_ERROR
;
449 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
450 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
451 Formattable testArgs3
[] = {(int32_t)12, "MyDisk"};
453 MessageFormat
* form
= new MessageFormat(
454 "The disk \"{1}\" contains {0} file(s).", err
);
456 UnicodeString string
;
457 FieldPosition
ignore(FieldPosition::DONT_CARE
);
458 form
->format(testArgs1
, 2, string
, ignore
, err
);
459 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 0 file(s).") {
460 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1"));
463 ignore
.setField(FieldPosition::DONT_CARE
);
465 form
->format(testArgs2
, 2, string
, ignore
, err
);
466 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 1 file(s).") {
468 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string
);
471 ignore
.setField(FieldPosition::DONT_CARE
);
473 form
->format(testArgs3
, 2, string
, ignore
, err
);
474 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 12 file(s).") {
475 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string
);
481 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
483 logln("running TestMessageFormat::testMsgFormatChoice");
485 UErrorCode err
= U_ZERO_ERROR
;
487 MessageFormat
* form
= new MessageFormat("The disk \"{1}\" contains {0}.", err
);
488 double filelimits
[] = {0,1,2};
489 UnicodeString filepart
[] = {"no files","one file","{0,number} files"};
490 ChoiceFormat
* fileform
= new ChoiceFormat(filelimits
, filepart
, 3);
491 form
->setFormat(1,*fileform
); // NOT zero, see below
492 //is the format adopted?
494 FieldPosition
ignore(FieldPosition::DONT_CARE
);
495 UnicodeString string
;
496 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
497 form
->format(testArgs1
, 2, string
, ignore
, err
);
498 if (string
!= "The disk \"MyDisk\" contains no files.") {
499 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
502 ignore
.setField(FieldPosition::DONT_CARE
);
504 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
505 form
->format(testArgs2
, 2, string
, ignore
, err
);
506 if (string
!= "The disk \"MyDisk\" contains one file.") {
507 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
510 ignore
.setField(FieldPosition::DONT_CARE
);
512 Formattable testArgs3
[] = {(int32_t)1273, "MyDisk"};
513 form
->format(testArgs3
, 2, string
, ignore
, err
);
514 if (string
!= "The disk \"MyDisk\" contains 1,273 files.") {
515 errln("TestMessageFormat::testMsgFormatChoice failed on test #3");
523 //---------------------------------
525 //---------------------------------
527 void TestMessageFormat::testCopyConstructor()
529 UErrorCode success
= U_ZERO_ERROR
;
530 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
531 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
532 MessageFormat
*y
= 0;
533 y
= new MessageFormat(*x
);
537 logln("First test (operator ==): Passed!");
539 errln("TestMessageFormat::testCopyConstructor failed #1");
540 logln("First test (operator ==): Failed!");
542 if ( ((*x
== *y
) && (*y
== *x
)) &&
543 ((*x
!= *z
) && (*z
!= *x
)) &&
544 ((*y
!= *z
) && (*z
!= *y
)) )
545 logln("Second test (equals): Passed!");
547 errln("TestMessageFormat::testCopyConstructor failed #2");
548 logln("Second test (equals): Failed!");
557 void TestMessageFormat::testAssignment()
559 UErrorCode success
= U_ZERO_ERROR
;
560 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
561 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
562 MessageFormat
*y
= new MessageFormat("There are {0} files on {1} created", success
);
567 logln("First test (operator ==): Passed!");
569 errln( "TestMessageFormat::testAssignment failed #1");
570 logln("First test (operator ==): Failed!");
572 if ( ((*x
== *y
) && (*y
== *x
)) &&
573 ((*x
!= *z
) && (*z
!= *x
)) &&
574 ((*y
!= *z
) && (*z
!= *y
)) )
575 logln("Second test (equals): Passed!");
577 errln("TestMessageFormat::testAssignment failed #2");
578 logln("Second test (equals): Failed!");
586 void TestMessageFormat::testClone()
588 UErrorCode success
= U_ZERO_ERROR
;
589 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
590 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
591 MessageFormat
*y
= 0;
592 y
= (MessageFormat
*)x
->clone();
596 logln("First test (operator ==): Passed!");
598 errln("TestMessageFormat::testClone failed #1");
599 logln("First test (operator ==): Failed!");
601 if ( ((*x
== *y
) && (*y
== *x
)) &&
602 ((*x
!= *z
) && (*z
!= *x
)) &&
603 ((*y
!= *z
) && (*z
!= *y
)) )
604 logln("Second test (equals): Passed!");
606 errln("TestMessageFormat::testClone failed #2");
607 logln("Second test (equals): Failed!");
615 void TestMessageFormat::testEquals()
617 UErrorCode success
= U_ZERO_ERROR
;
618 MessageFormat
x("There are {0} files on {1}", success
);
619 MessageFormat
y("There are {0} files on {1}", success
);
621 errln( "TestMessageFormat::testEquals failed #1");
622 logln("First test (operator ==): Failed!");
627 void TestMessageFormat::testNotEquals()
629 UErrorCode success
= U_ZERO_ERROR
;
630 MessageFormat
x("There are {0} files on {1}", success
);
632 y
.setLocale(Locale("fr"));
634 errln( "TestMessageFormat::testEquals failed #1");
635 logln("First test (operator !=): Failed!");
638 y
.applyPattern("There are {0} files on {1} the disk", success
);
640 errln( "TestMessageFormat::testEquals failed #1");
641 logln("Second test (operator !=): Failed!");
646 void TestMessageFormat::testSetLocale()
648 UErrorCode err
= U_ZERO_ERROR
;
649 GregorianCalendar
cal(err
);
650 Formattable arguments
[] = {
652 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
656 UnicodeString result
;
658 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
659 UnicodeString formatStr
= "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
660 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
661 // Just use unlocalized currency symbol.
662 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
663 UnicodeString compareStrEng
= "At <time> on Aug 8, 1997, you made a deposit of ";
664 compareStrEng
+= (UChar
) 0x00a4;
665 compareStrEng
+= "456.83.";
666 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
667 // Just use unlocalized currency symbol.
668 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
669 UnicodeString compareStrGer
= "At <time> on 08.08.1997, you made a deposit of ";
670 compareStrGer
+= (UChar
) 0x00a4;
671 compareStrGer
+= " 456,83.";
673 MessageFormat
msg( formatStr
, err
);
675 FieldPosition
pos(0);
684 if (result
!= compareStrEng
) {
685 errln("*** MSG format err.");
688 msg
.setLocale(Locale::getEnglish());
689 UBool getLocale_ok
= TRUE
;
690 if (msg
.getLocale() != Locale::getEnglish()) {
691 errln("*** MSG getLocal err.");
692 getLocale_ok
= FALSE
;
695 msg
.setLocale(Locale::getGerman());
697 if (msg
.getLocale() != Locale::getGerman()) {
698 errln("*** MSG getLocal err.");
699 getLocale_ok
= FALSE
;
702 msg
.applyPattern( formatStr
, err
);
714 if (result
== compareStrGer
) {
715 logln("MSG setLocale tested.");
717 errln( "*** MSG setLocale err.");
721 logln("MSG getLocale tested.");
725 void TestMessageFormat::testFormat()
727 UErrorCode err
= U_ZERO_ERROR
;
728 GregorianCalendar
cal(err
);
730 const Formattable ftarray
[] =
732 Formattable( UDate(8.71068e+011), Formattable::kIsDate
)
734 const int32_t ft_cnt
= sizeof(ftarray
) / sizeof(Formattable
);
735 Formattable
ft_arr( ftarray
, ft_cnt
);
737 Formattable
* fmt
= new Formattable(UDate(8.71068e+011), Formattable::kIsDate
);
739 UnicodeString result
;
741 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
742 UnicodeString formatStr
= "On {0,date}, it began.";
743 UnicodeString compareStr
= "On Aug 8, 1997, it began.";
746 MessageFormat
msg( formatStr
, err
);
758 if (err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
759 errln("*** MSG format without expected error code.");
772 logln("MSG format( Formattable&, ... ) expected:" + compareStr
);
773 logln("MSG format( Formattable&, ... ) result:" + result
);
774 if (result
!= compareStr
) {
775 errln("*** MSG format( Formattable&, .... ) err.");
777 logln("MSG format( Formattable&, ... ) tested.");
784 void TestMessageFormat::testParse()
786 UErrorCode err
= U_ZERO_ERROR
;
788 UnicodeString msgFormatString
= "{0} =sep= {1}";
789 MessageFormat
msg( msgFormatString
, err
);
790 UnicodeString source
= "abc =sep= def";
791 UnicodeString tmp1
, tmp2
;
793 Formattable
* fmt_arr
= msg
.parse( source
, count
, err
);
794 if (U_FAILURE(err
) || (!fmt_arr
)) {
795 errln("*** MSG parse (ustring, count, err) error.");
797 logln("MSG parse -- count: %d", count
);
799 errln("*** MSG parse (ustring, count, err) count err.");
801 if ((fmt_arr
[0].getType() == Formattable::kString
)
802 && (fmt_arr
[1].getType() == Formattable::kString
)
803 && (fmt_arr
[0].getString(tmp1
) == "abc")
804 && (fmt_arr
[1].getString(tmp2
) == "def")) {
805 logln("MSG parse (ustring, count, err) tested.");
807 errln("*** MSG parse (ustring, count, err) result err.");
815 fmt_arr
= msg
.parse( source
, pp
, count
);
816 if ((pp
== 0) || (!fmt_arr
)) {
817 errln("*** MSG parse (ustring, parsepos., count) error.");
819 logln("MSG parse -- count: %d", count
);
821 errln("*** MSG parse (ustring, parsepos., count) count err.");
823 if ((fmt_arr
[0].getType() == Formattable::kString
)
824 && (fmt_arr
[1].getType() == Formattable::kString
)
825 && (fmt_arr
[0].getString(tmp1
) == "abc")
826 && (fmt_arr
[1].getString(tmp2
) == "def")) {
827 logln("MSG parse (ustring, parsepos., count) tested.");
829 errln("*** MSG parse (ustring, parsepos., count) result err.");
838 msg
.parseObject( source
, fmta
, pp
);
840 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
842 logln("MSG parse -- count: %d", count
);
843 fmta
.getArray(count
);
845 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
847 if ((fmta
[0].getType() == Formattable::kString
)
848 && (fmta
[1].getType() == Formattable::kString
)
849 && (fmta
[0].getString(tmp1
) == "abc")
850 && (fmta
[1].getString(tmp2
) == "def")) {
851 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
853 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
860 void TestMessageFormat::testAdopt()
862 UErrorCode err
= U_ZERO_ERROR
;
864 UnicodeString
formatStr("{0,date},{1},{2,number}", "");
865 UnicodeString
formatStrChange("{0,number},{1,number},{2,date}", "");
867 MessageFormat
msg( formatStr
, err
);
868 MessageFormat
msgCmp( formatStr
, err
);
869 int32_t count
, countCmp
;
870 const Format
** formats
= msg
.getFormats(count
);
871 const Format
** formatsCmp
= msgCmp
.getFormats(countCmp
);
872 const Format
** formatsChg
= 0;
873 const Format
** formatsAct
= 0;
877 UnicodeString patCmp
;
878 UnicodeString patAct
;
879 Format
** formatsToAdopt
;
881 if (!formats
|| !formatsCmp
|| (count
<= 0) || (count
!= countCmp
)) {
882 errln("Error getting Formats");
888 for (i
= 0; i
< count
; i
++) {
891 if ((a
!= NULL
) && (b
!= NULL
)) {
896 }else if ((a
!= NULL
) || (b
!= NULL
)) {
897 errln("(a != NULL) || (b != NULL)");
902 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
904 formatsChg
= msg
.getFormats(countChg
); // tested function
905 if (!formatsChg
|| (countChg
!= count
)) {
906 errln("Error getting Formats");
912 for (i
= 0; i
< count
; i
++) {
915 if ((a
!= NULL
) && (b
!= NULL
)) {
917 logln("formatsChg == formatsCmp at index %d", i
);
923 errln("*** MSG getFormats diff err.");
927 logln("MSG getFormats tested.");
929 msg
.setFormats( formatsCmp
, countCmp
); //tested function
931 formatsAct
= msg
.getFormats(countAct
);
932 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
933 errln("Error getting Formats");
937 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
938 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
940 for (i
= 0; i
< countAct
; i
++) {
943 if ((a
!= NULL
) && (b
!= NULL
)) {
945 logln("formatsAct != formatsCmp at index %d", i
);
949 }else if ((a
!= NULL
) || (b
!= NULL
)) {
950 errln("(a != NULL) || (b != NULL)");
954 logln("MSG setFormats tested.");
958 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
960 formatsToAdopt
= new Format
* [countCmp
];
961 if (!formatsToAdopt
) {
962 errln("memory allocation error");
966 for (i
= 0; i
< countCmp
; i
++) {
967 if (formatsCmp
[i
] == NULL
) {
968 formatsToAdopt
[i
] = NULL
;
970 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
971 if (!formatsToAdopt
[i
]) {
972 errln("Can't clone format at index %d", i
);
977 msg
.adoptFormats( formatsToAdopt
, countCmp
); // function to test
978 delete[] formatsToAdopt
;
980 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
981 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
983 formatsAct
= msg
.getFormats(countAct
);
984 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
985 errln("Error getting Formats");
989 for (i
= 0; i
< countAct
; i
++) {
992 if ((a
!= NULL
) && (b
!= NULL
)) {
997 }else if ((a
!= NULL
) || (b
!= NULL
)) {
998 errln("(a != NULL) || (b != NULL)");
1002 logln("MSG adoptFormats tested.");
1006 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
1008 formatsToAdopt
= new Format
* [countCmp
];
1009 if (!formatsToAdopt
) {
1010 errln("memory allocation error");
1014 for (i
= 0; i
< countCmp
; i
++) {
1015 if (formatsCmp
[i
] == NULL
) {
1016 formatsToAdopt
[i
] = NULL
;
1018 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
1019 if (!formatsToAdopt
[i
]) {
1020 errln("Can't clone format at index %d", i
);
1026 for ( i
= 0; i
< countCmp
; i
++ ) {
1027 msg
.adoptFormat( i
, formatsToAdopt
[i
] ); // function to test
1029 delete[] formatsToAdopt
; // array itself not needed in this case;
1031 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
1032 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
1034 formatsAct
= msg
.getFormats(countAct
);
1035 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
1036 errln("Error getting Formats");
1040 for (i
= 0; i
< countAct
; i
++) {
1043 if ((a
!= NULL
) && (b
!= NULL
)) {
1048 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1049 errln("(a != NULL) || (b != NULL)");
1053 logln("MSG adoptFormat tested.");
1056 // This test is a regression test for a fixed bug in the copy constructor.
1057 // It is kept as a global function rather than as a method since the test depends on memory values.
1058 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1059 // which is probably why it didn't show up in the regular test for the copy constructor.)
1060 // For this reason, the test isn't changed even though it contains function calls whose results are
1061 // not tested and had no problems. Actually, the test failed by *crashing*.
1062 static void _testCopyConstructor2()
1064 UErrorCode status
= U_ZERO_ERROR
;
1065 UnicodeString
formatStr("Hello World on {0,date,full}", "");
1066 UnicodeString
resultStr(" ", "");
1067 UnicodeString result
;
1068 FieldPosition
fp(0);
1069 UDate d
= Calendar::getNow();
1070 const Formattable
fargs( d
, Formattable::kIsDate
);
1072 MessageFormat
* fmt1
= new MessageFormat( formatStr
, status
);
1073 MessageFormat
* fmt2
= new MessageFormat( *fmt1
);
1074 MessageFormat
* fmt3
;
1075 MessageFormat
* fmt4
;
1077 if (fmt1
== NULL
) it_err("testCopyConstructor2: (fmt1 != NULL)");
1079 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1081 if (fmt2
== NULL
) it_err("testCopyConstructor2: (fmt2 != NULL)");
1083 fmt3
= (MessageFormat
*) fmt1
->clone();
1084 fmt4
= (MessageFormat
*) fmt2
->clone();
1086 if (fmt3
== NULL
) it_err("testCopyConstructor2: (fmt3 != NULL)");
1087 if (fmt4
== NULL
) it_err("testCopyConstructor2: (fmt4 != NULL)");
1089 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1090 result
= fmt2
->format( &fargs
, 1, resultStr
, fp
, status
);
1091 result
= fmt3
->format( &fargs
, 1, resultStr
, fp
, status
);
1092 result
= fmt4
->format( &fargs
, 1, resultStr
, fp
, status
);
1099 void TestMessageFormat::testCopyConstructor2() {
1100 _testCopyConstructor2();
1104 * Verify that MessageFormat accomodates more than 10 arguments and
1105 * more than 10 subformats.
1107 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1108 UErrorCode ec
= U_ZERO_ERROR
;
1109 const UnicodeString pattern
=
1110 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1111 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1112 "there were {1,number} werjes "
1113 "(a {3,number,percent} increase over {2,number}) "
1114 "despite the {4}''s efforts "
1115 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1116 MessageFormat
msg(pattern
, ec
);
1117 if (U_FAILURE(ec
)) {
1118 errln("FAIL: constructor failed");
1122 const Formattable ARGS
[] = {
1123 Formattable(UDate(1e13
), Formattable::kIsDate
),
1124 Formattable((int32_t)1303),
1125 Formattable((int32_t)1202),
1126 Formattable(1303.0/1202 - 1),
1127 Formattable("Glimmung"),
1128 Formattable("the printers"),
1129 Formattable("Nick"),
1130 Formattable("his father"),
1131 Formattable("his mother"),
1132 Formattable("the spiddles"),
1133 Formattable("of course"),
1134 Formattable("Horace"),
1136 const int32_t ARGS_LENGTH
= sizeof(ARGS
) / sizeof(ARGS
[0]);
1137 Formattable
ARGS_OBJ(ARGS
, ARGS_LENGTH
);
1139 UnicodeString expected
=
1140 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1141 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1142 "there were 1,303 werjes "
1143 "(a 8% increase over 1,202) "
1144 "despite the Glimmung's efforts "
1145 "and to delight of the printers, Nick, his father, "
1146 "his mother, the spiddles, and of course Horace.";
1147 UnicodeString result
;
1148 msg
.format(ARGS_OBJ
, result
, ec
);
1149 if (result
== expected
) {
1152 errln((UnicodeString
)"FAIL: Got " + result
+
1153 ", expected " + expected
);
1157 // test RBNF extensions to message format
1158 void TestMessageFormat::TestRBNF(void) {
1159 // WARNING: this depends on the RBNF formats for en_US
1160 Locale
locale("en", "US", "");
1162 UErrorCode ec
= U_ZERO_ERROR
;
1164 UnicodeString values
[] = {
1165 // decimal values do not format completely for ordinal or duration, and
1166 // do not always parse, so do not include them
1167 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1169 int32_t values_count
= sizeof(values
)/sizeof(values
[0]);
1171 UnicodeString formats
[] = {
1172 "There are {0,spellout} files to search.",
1173 "There are {0,spellout,%simplified} files to search.",
1174 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1175 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1176 "Searching this file will take {0,duration} to complete.",
1177 "Searching this file will take {0,duration,%with-words} to complete.",
1179 int32_t formats_count
= sizeof(formats
)/sizeof(formats
[0]);
1181 Formattable args
[1];
1183 NumberFormat
* numFmt
= NumberFormat::createInstance(locale
, ec
);
1184 if (U_FAILURE(ec
)) {
1185 dataerrln("Error calling NumberFormat::createInstance()");
1189 for (int i
= 0; i
< formats_count
; ++i
) {
1190 MessageFormat
* fmt
= new MessageFormat(formats
[i
], locale
, ec
);
1191 logln((UnicodeString
)"Testing format pattern: '" + formats
[i
] + "'");
1193 for (int j
= 0; j
< values_count
; ++j
) {
1195 numFmt
->parse(values
[j
], args
[0], ec
);
1196 if (U_FAILURE(ec
)) {
1197 errln((UnicodeString
)"Failed to parse test argument " + values
[j
]);
1199 FieldPosition
fp(0);
1200 UnicodeString result
;
1201 fmt
->format(args
, 1, result
, fp
, ec
);
1202 logln((UnicodeString
)"value: " + toString(args
[0]) + " --> " + result
+ UnicodeString(" ec: ") + u_errorName(ec
));
1204 if (i
!= 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1206 Formattable
* parseResult
= fmt
->parse(result
, count
, ec
);
1208 errln((UnicodeString
)"parse returned " + count
+ " args");
1209 } else if (parseResult
[0] != args
[0]) {
1210 errln((UnicodeString
)"parsed argument " + toString(parseResult
[0]) + " != " + toString(args
[0]));
1212 delete []parseResult
;
1221 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1222 const char* patterns
[] = { // pattern, expected pattern
1233 "{'a{}'a}'a", "{'a{}'a}''a",
1235 "'} '{'}'", "'} '{'}''",
1236 "'} {{{''", "'} {{{'''",
1238 int32_t pattern_count
= sizeof(patterns
)/sizeof(patterns
[0]);
1240 for (int i
= 0; i
< pattern_count
; i
+= 2) {
1241 UErrorCode status
= U_ZERO_ERROR
;
1242 UnicodeString result
= MessageFormat::autoQuoteApostrophe(patterns
[i
], status
);
1243 UnicodeString
target(patterns
[i
+1]);
1244 if (target
!= result
) {
1245 const int BUF2_LEN
= 64;
1247 char buf2
[BUF2_LEN
];
1248 int32_t len
= result
.extract(0, result
.length(), buf2
, BUF2_LEN
);
1249 if (len
>= BUF2_LEN
) {
1250 buf2
[BUF2_LEN
-1] = 0;
1252 sprintf(buf
, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i
/2, patterns
[i
], patterns
[i
+1], buf2
);
1258 #endif /* #if !UCONFIG_NO_FORMATTING */