1 /********************************************************************
3 * Copyright (c) 1997-2004, 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"
33 TestMessageFormat::runIndexedTest(int32_t index
, UBool exec
,
34 const char* &name
, char* /*par*/) {
39 TESTCASE(3,PatternTest
);
40 TESTCASE(4,testStaticFormat
);
41 TESTCASE(5,testSimpleFormat
);
42 TESTCASE(6,testMsgFormatChoice
);
43 TESTCASE(7,testCopyConstructor
);
44 TESTCASE(8,testAssignment
);
45 TESTCASE(9,testClone
);
46 TESTCASE(10,testEquals
);
47 TESTCASE(11,testNotEquals
);
48 TESTCASE(12,testSetLocale
);
49 TESTCASE(13,testFormat
);
50 TESTCASE(14,testParse
);
51 TESTCASE(15,testAdopt
);
52 TESTCASE(16,testCopyConstructor2
);
53 TESTCASE(17,TestUnlimitedArgsAndSubformats
);
54 TESTCASE(18,TestRBNF
);
55 default: name
= ""; break;
59 void TestMessageFormat::testBug3()
61 double myNumber
= -123456;
62 DecimalFormat
*form
= 0;
71 Locale("de", "AT", ""),
72 Locale("de", "CH", ""),
73 Locale("el", "", ""), // 10
74 Locale("en", "CA", ""),
75 Locale("en", "GB", ""),
76 Locale("en", "IE", ""),
77 Locale("en", "US", ""),
82 Locale("fr", "BE", ""),
83 Locale("fr", "CA", ""), // 20
84 Locale("fr", "CH", ""),
90 Locale("it", "CH", ""),
93 Locale("lt", "", ""), // 30
97 Locale("nl", "BE", ""),
100 Locale("pt", "", ""),
101 Locale("ro", "", ""),
102 Locale("ru", "", ""),
103 Locale("sh", "", ""), // 40
104 Locale("sk", "", ""),
105 Locale("sl", "", ""),
106 Locale("sq", "", ""),
107 Locale("sr", "", ""),
108 Locale("sv", "", ""),
109 Locale("tr", "", ""),
110 Locale("uk", "", ""),
111 Locale("zh", "", ""),
112 Locale("zh", "TW", "") // 49
115 for (i
= 0; i
< 49; i
++) {
116 UnicodeString buffer
;
117 logln(locale
[i
].getDisplayName(buffer
));
118 UErrorCode success
= U_ZERO_ERROR
;
119 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
120 form
= (DecimalFormat
*)NumberFormat::createInstance(locale
[i
], success
);
121 if (U_FAILURE(success
)) {
122 errln("Err: Number Format ");
123 logln("Number format creation failed.");
127 FieldPosition
pos(0);
129 form
->format(myNumber
, buffer
, pos
);
130 success
= U_ZERO_ERROR
;
131 ParsePosition parsePos
;
132 form
->parse(buffer
, result
, parsePos
);
133 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result
) + UnicodeString("[supposed output for result]"));
134 if (U_FAILURE(success
)) {
135 errln("Err: Number Format parse");
136 logln("Number format parse failed.");
142 void TestMessageFormat::testBug1()
144 const double limit
[] = {0.0, 1.0, 2.0};
145 const UnicodeString formats
[] = {"0.0<=Arg<1.0",
148 ChoiceFormat
*cf
= new ChoiceFormat(limit
, formats
, 3);
149 FieldPosition
status(0);
150 UnicodeString toAppendTo
;
151 cf
->format((int32_t)1, toAppendTo
, status
);
152 if (toAppendTo
!= "1.0<=Arg<2.0") {
153 errln("ChoiceFormat cmp in testBug1");
159 void TestMessageFormat::testBug2()
161 UErrorCode status
= U_ZERO_ERROR
;
162 UnicodeString result
;
163 // {sfb} use double format in pattern, so result will match (not strictly necessary)
164 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}. ";
165 logln("The input pattern : " + pattern
);
166 MessageFormat
*fmt
= new MessageFormat(pattern
, status
);
167 if (U_FAILURE(status
)) {
168 errln("MessageFormat pattern creation failed.");
171 logln("The output pattern is : " + fmt
->toPattern(result
));
172 if (pattern
!= result
) {
173 errln("MessageFormat::toPattern() failed.");
179 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
180 //----------------------------------------------------
182 //----------------------------------------------------
184 #if U_IOSTREAM_SOURCE >= 199711
186 std::ostream
& operator<<(std::ostream
& stream
, const Formattable
& obj
);
187 #elif U_IOSTREAM_SOURCE >= 198506
188 # include <iostream.h>
189 ostream
& operator<<(ostream
& stream
, const Formattable
& obj
);
192 #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
);
406 void TestMessageFormat::testSimpleFormat(/* char* par */)
408 logln("running TestMessageFormat::testSimpleFormat");
410 UErrorCode err
= U_ZERO_ERROR
;
412 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
413 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
414 Formattable testArgs3
[] = {(int32_t)12, "MyDisk"};
416 MessageFormat
* form
= new MessageFormat(
417 "The disk \"{1}\" contains {0} file(s).", err
);
419 UnicodeString string
;
420 FieldPosition
ignore(FieldPosition::DONT_CARE
);
421 form
->format(testArgs1
, 2, string
, ignore
, err
);
422 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 0 file(s).") {
423 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1"));
426 ignore
.setField(FieldPosition::DONT_CARE
);
428 form
->format(testArgs2
, 2, string
, ignore
, err
);
429 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 1 file(s).") {
431 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string
);
434 ignore
.setField(FieldPosition::DONT_CARE
);
436 form
->format(testArgs3
, 2, string
, ignore
, err
);
437 if (U_FAILURE(err
) || string
!= "The disk \"MyDisk\" contains 12 file(s).") {
438 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string
);
444 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
446 logln("running TestMessageFormat::testMsgFormatChoice");
448 UErrorCode err
= U_ZERO_ERROR
;
450 MessageFormat
* form
= new MessageFormat("The disk \"{1}\" contains {0}.", err
);
451 double filelimits
[] = {0,1,2};
452 UnicodeString filepart
[] = {"no files","one file","{0,number} files"};
453 ChoiceFormat
* fileform
= new ChoiceFormat(filelimits
, filepart
, 3);
454 form
->setFormat(1,*fileform
); // NOT zero, see below
455 //is the format adopted?
457 FieldPosition
ignore(FieldPosition::DONT_CARE
);
458 UnicodeString string
;
459 Formattable testArgs1
[] = {(int32_t)0, "MyDisk"};
460 form
->format(testArgs1
, 2, string
, ignore
, err
);
461 if (string
!= "The disk \"MyDisk\" contains no files.") {
462 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
465 ignore
.setField(FieldPosition::DONT_CARE
);
467 Formattable testArgs2
[] = {(int32_t)1, "MyDisk"};
468 form
->format(testArgs2
, 2, string
, ignore
, err
);
469 if (string
!= "The disk \"MyDisk\" contains one file.") {
470 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
473 ignore
.setField(FieldPosition::DONT_CARE
);
475 Formattable testArgs3
[] = {(int32_t)1273, "MyDisk"};
476 form
->format(testArgs3
, 2, string
, ignore
, err
);
477 if (string
!= "The disk \"MyDisk\" contains 1,273 files.") {
478 errln("TestMessageFormat::testMsgFormatChoice failed on test #3");
486 //---------------------------------
488 //---------------------------------
490 void TestMessageFormat::testCopyConstructor()
492 UErrorCode success
= U_ZERO_ERROR
;
493 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
494 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
495 MessageFormat
*y
= 0;
496 y
= new MessageFormat(*x
);
500 logln("First test (operator ==): Passed!");
502 errln("TestMessageFormat::testCopyConstructor failed #1");
503 logln("First test (operator ==): Failed!");
505 if ( ((*x
== *y
) && (*y
== *x
)) &&
506 ((*x
!= *z
) && (*z
!= *x
)) &&
507 ((*y
!= *z
) && (*z
!= *y
)) )
508 logln("Second test (equals): Passed!");
510 errln("TestMessageFormat::testCopyConstructor failed #2");
511 logln("Second test (equals): Failed!");
520 void TestMessageFormat::testAssignment()
522 UErrorCode success
= U_ZERO_ERROR
;
523 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
524 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
525 MessageFormat
*y
= new MessageFormat("There are {0} files on {1} created", success
);
530 logln("First test (operator ==): Passed!");
532 errln( "TestMessageFormat::testAssignment failed #1");
533 logln("First test (operator ==): Failed!");
535 if ( ((*x
== *y
) && (*y
== *x
)) &&
536 ((*x
!= *z
) && (*z
!= *x
)) &&
537 ((*y
!= *z
) && (*z
!= *y
)) )
538 logln("Second test (equals): Passed!");
540 errln("TestMessageFormat::testAssignment failed #2");
541 logln("Second test (equals): Failed!");
549 void TestMessageFormat::testClone()
551 UErrorCode success
= U_ZERO_ERROR
;
552 MessageFormat
*x
= new MessageFormat("There are {0} files on {1}", success
);
553 MessageFormat
*z
= new MessageFormat("There are {0} files on {1} created", success
);
554 MessageFormat
*y
= 0;
555 y
= (MessageFormat
*)x
->clone();
559 logln("First test (operator ==): Passed!");
561 errln("TestMessageFormat::testClone failed #1");
562 logln("First test (operator ==): Failed!");
564 if ( ((*x
== *y
) && (*y
== *x
)) &&
565 ((*x
!= *z
) && (*z
!= *x
)) &&
566 ((*y
!= *z
) && (*z
!= *y
)) )
567 logln("Second test (equals): Passed!");
569 errln("TestMessageFormat::testClone failed #2");
570 logln("Second test (equals): Failed!");
578 void TestMessageFormat::testEquals()
580 UErrorCode success
= U_ZERO_ERROR
;
581 MessageFormat
x("There are {0} files on {1}", success
);
582 MessageFormat
y("There are {0} files on {1}", success
);
584 errln( "TestMessageFormat::testEquals failed #1");
585 logln("First test (operator ==): Failed!");
590 void TestMessageFormat::testNotEquals()
592 UErrorCode success
= U_ZERO_ERROR
;
593 MessageFormat
x("There are {0} files on {1}", success
);
595 y
.setLocale(Locale("fr"));
597 errln( "TestMessageFormat::testEquals failed #1");
598 logln("First test (operator !=): Failed!");
601 y
.applyPattern("There are {0} files on {1} the disk", success
);
603 errln( "TestMessageFormat::testEquals failed #1");
604 logln("Second test (operator !=): Failed!");
609 void TestMessageFormat::testSetLocale()
611 UErrorCode err
= U_ZERO_ERROR
;
612 GregorianCalendar
cal(err
);
613 Formattable arguments
[] = {
615 Formattable(UDate(8.71068e+011), Formattable::kIsDate
),
619 UnicodeString result
;
621 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
622 UnicodeString formatStr
= "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
623 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
624 // Just use unlocalized currency symbol.
625 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
626 UnicodeString compareStrEng
= "At <time> on Aug 8, 1997, you made a deposit of ";
627 compareStrEng
+= (UChar
) 0x00a4;
628 compareStrEng
+= "456.83.";
629 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
630 // Just use unlocalized currency symbol.
631 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
632 UnicodeString compareStrGer
= "At <time> on 08.08.1997, you made a deposit of ";
633 compareStrGer
+= (UChar
) 0x00a4;
634 compareStrGer
+= " 456,83.";
636 MessageFormat
msg( formatStr
, err
);
638 FieldPosition
pos(0);
647 if (result
!= compareStrEng
) {
648 errln("*** MSG format err.");
651 msg
.setLocale(Locale::getEnglish());
652 UBool getLocale_ok
= TRUE
;
653 if (msg
.getLocale() != Locale::getEnglish()) {
654 errln("*** MSG getLocal err.");
655 getLocale_ok
= FALSE
;
658 msg
.setLocale(Locale::getGerman());
660 if (msg
.getLocale() != Locale::getGerman()) {
661 errln("*** MSG getLocal err.");
662 getLocale_ok
= FALSE
;
665 msg
.applyPattern( formatStr
, err
);
677 if (result
== compareStrGer
) {
678 logln("MSG setLocale tested.");
680 errln( "*** MSG setLocale err.");
684 logln("MSG getLocale tested.");
688 void TestMessageFormat::testFormat()
690 UErrorCode err
= U_ZERO_ERROR
;
691 GregorianCalendar
cal(err
);
693 const Formattable ftarray
[] =
695 Formattable( UDate(8.71068e+011), Formattable::kIsDate
)
697 const int32_t ft_cnt
= sizeof(ftarray
) / sizeof(Formattable
);
698 Formattable
ft_arr( ftarray
, ft_cnt
);
700 Formattable
* fmt
= new Formattable(UDate(8.71068e+011), Formattable::kIsDate
);
702 UnicodeString result
;
704 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
705 UnicodeString formatStr
= "On {0,date}, it began.";
706 UnicodeString compareStr
= "On Aug 8, 1997, it began.";
709 MessageFormat
msg( formatStr
, err
);
721 if (err
!= U_ILLEGAL_ARGUMENT_ERROR
) {
722 errln("*** MSG format without expected error code.");
735 logln("MSG format( Formattable&, ... ) expected:" + compareStr
);
736 logln("MSG format( Formattable&, ... ) result:" + result
);
737 if (result
!= compareStr
) {
738 errln("*** MSG format( Formattable&, .... ) err.");
740 logln("MSG format( Formattable&, ... ) tested.");
747 void TestMessageFormat::testParse()
749 UErrorCode err
= U_ZERO_ERROR
;
751 UnicodeString msgFormatString
= "{0} =sep= {1}";
752 MessageFormat
msg( msgFormatString
, err
);
753 UnicodeString source
= "abc =sep= def";
754 UnicodeString tmp1
, tmp2
;
756 Formattable
* fmt_arr
= msg
.parse( source
, count
, err
);
757 if (U_FAILURE(err
) || (!fmt_arr
)) {
758 errln("*** MSG parse (ustring, count, err) error.");
760 logln("MSG parse -- count: %d", count
);
762 errln("*** MSG parse (ustring, count, err) count err.");
764 if ((fmt_arr
[0].getType() == Formattable::kString
)
765 && (fmt_arr
[1].getType() == Formattable::kString
)
766 && (fmt_arr
[0].getString(tmp1
) == "abc")
767 && (fmt_arr
[1].getString(tmp2
) == "def")) {
768 logln("MSG parse (ustring, count, err) tested.");
770 errln("*** MSG parse (ustring, count, err) result err.");
778 fmt_arr
= msg
.parse( source
, pp
, count
);
779 if ((pp
== 0) || (!fmt_arr
)) {
780 errln("*** MSG parse (ustring, parsepos., count) error.");
782 logln("MSG parse -- count: %d", count
);
784 errln("*** MSG parse (ustring, parsepos., count) count err.");
786 if ((fmt_arr
[0].getType() == Formattable::kString
)
787 && (fmt_arr
[1].getType() == Formattable::kString
)
788 && (fmt_arr
[0].getString(tmp1
) == "abc")
789 && (fmt_arr
[1].getString(tmp2
) == "def")) {
790 logln("MSG parse (ustring, parsepos., count) tested.");
792 errln("*** MSG parse (ustring, parsepos., count) result err.");
801 msg
.parseObject( source
, fmta
, pp
);
803 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
805 logln("MSG parse -- count: %d", count
);
806 fmta
.getArray(count
);
808 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
810 if ((fmta
[0].getType() == Formattable::kString
)
811 && (fmta
[1].getType() == Formattable::kString
)
812 && (fmta
[0].getString(tmp1
) == "abc")
813 && (fmta
[1].getString(tmp2
) == "def")) {
814 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
816 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
823 void TestMessageFormat::testAdopt()
825 UErrorCode err
= U_ZERO_ERROR
;
827 UnicodeString
formatStr("{0,date},{1},{2,number}", "");
828 UnicodeString
formatStrChange("{0,number},{1,number},{2,date}", "");
830 MessageFormat
msg( formatStr
, err
);
831 MessageFormat
msgCmp( formatStr
, err
);
832 int32_t count
, countCmp
;
833 const Format
** formats
= msg
.getFormats(count
);
834 const Format
** formatsCmp
= msgCmp
.getFormats(countCmp
);
835 const Format
** formatsChg
= 0;
836 const Format
** formatsAct
= 0;
840 UnicodeString patCmp
;
841 UnicodeString patAct
;
842 Format
** formatsToAdopt
;
844 if (!formats
|| !formatsCmp
|| (count
<= 0) || (count
!= countCmp
)) {
845 errln("Error getting Formats");
851 for (i
= 0; i
< count
; i
++) {
854 if ((a
!= NULL
) && (b
!= NULL
)) {
859 }else if ((a
!= NULL
) || (b
!= NULL
)) {
860 errln("(a != NULL) || (b != NULL)");
865 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
867 formatsChg
= msg
.getFormats(countChg
); // tested function
868 if (!formatsChg
|| (countChg
!= count
)) {
869 errln("Error getting Formats");
875 for (i
= 0; i
< count
; i
++) {
878 if ((a
!= NULL
) && (b
!= NULL
)) {
880 logln("formatsChg == formatsCmp at index %d", i
);
886 errln("*** MSG getFormats diff err.");
890 logln("MSG getFormats tested.");
892 msg
.setFormats( formatsCmp
, countCmp
); //tested function
894 formatsAct
= msg
.getFormats(countAct
);
895 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
896 errln("Error getting Formats");
900 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
901 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
903 for (i
= 0; i
< countAct
; i
++) {
906 if ((a
!= NULL
) && (b
!= NULL
)) {
908 logln("formatsAct != formatsCmp at index %d", i
);
912 }else if ((a
!= NULL
) || (b
!= NULL
)) {
913 errln("(a != NULL) || (b != NULL)");
917 logln("MSG setFormats tested.");
921 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
923 formatsToAdopt
= new Format
* [countCmp
];
924 if (!formatsToAdopt
) {
925 errln("memory allocation error");
929 for (i
= 0; i
< countCmp
; i
++) {
930 if (formatsCmp
[i
] == NULL
) {
931 formatsToAdopt
[i
] = NULL
;
933 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
934 if (!formatsToAdopt
[i
]) {
935 errln("Can't clone format at index %d", i
);
940 msg
.adoptFormats( formatsToAdopt
, countCmp
); // function to test
941 delete[] formatsToAdopt
;
943 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
944 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
946 formatsAct
= msg
.getFormats(countAct
);
947 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
948 errln("Error getting Formats");
952 for (i
= 0; i
< countAct
; i
++) {
955 if ((a
!= NULL
) && (b
!= NULL
)) {
960 }else if ((a
!= NULL
) || (b
!= NULL
)) {
961 errln("(a != NULL) || (b != NULL)");
965 logln("MSG adoptFormats tested.");
969 msg
.applyPattern( formatStrChange
, err
); //set msg formats to something different
971 formatsToAdopt
= new Format
* [countCmp
];
972 if (!formatsToAdopt
) {
973 errln("memory allocation error");
977 for (i
= 0; i
< countCmp
; i
++) {
978 if (formatsCmp
[i
] == NULL
) {
979 formatsToAdopt
[i
] = NULL
;
981 formatsToAdopt
[i
] = formatsCmp
[i
]->clone();
982 if (!formatsToAdopt
[i
]) {
983 errln("Can't clone format at index %d", i
);
989 for ( i
= 0; i
< countCmp
; i
++ ) {
990 msg
.adoptFormat( i
, formatsToAdopt
[i
] ); // function to test
992 delete[] formatsToAdopt
; // array itself not needed in this case;
994 assertEquals("msgCmp.toPattern()", formatStr
, msgCmp
.toPattern(patCmp
.remove()));
995 assertEquals("msg.toPattern()", formatStr
, msg
.toPattern(patAct
.remove()));
997 formatsAct
= msg
.getFormats(countAct
);
998 if (!formatsAct
|| (countAct
<=0) || (countAct
!= countCmp
)) {
999 errln("Error getting Formats");
1003 for (i
= 0; i
< countAct
; i
++) {
1006 if ((a
!= NULL
) && (b
!= NULL
)) {
1011 }else if ((a
!= NULL
) || (b
!= NULL
)) {
1012 errln("(a != NULL) || (b != NULL)");
1016 logln("MSG adoptFormat tested.");
1019 // This test is a regression test for a fixed bug in the copy constructor.
1020 // It is kept as a global function rather than as a method since the test depends on memory values.
1021 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1022 // which is probably why it didn't show up in the regular test for the copy constructor.)
1023 // For this reason, the test isn't changed even though it contains function calls whose results are
1024 // not tested and had no problems. Actually, the test failed by *crashing*.
1025 static void _testCopyConstructor2()
1027 UErrorCode status
= U_ZERO_ERROR
;
1028 UnicodeString
formatStr("Hello World on {0,date,full}", "");
1029 UnicodeString
resultStr(" ", "");
1030 UnicodeString result
;
1031 FieldPosition
fp(0);
1032 UDate d
= Calendar::getNow();
1033 const Formattable
fargs( d
, Formattable::kIsDate
);
1035 MessageFormat
* fmt1
= new MessageFormat( formatStr
, status
);
1036 MessageFormat
* fmt2
= new MessageFormat( *fmt1
);
1037 MessageFormat
* fmt3
;
1038 MessageFormat
* fmt4
;
1040 if (fmt1
== NULL
) it_err("testCopyConstructor2: (fmt1 != NULL)");
1042 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1044 if (fmt2
== NULL
) it_err("testCopyConstructor2: (fmt2 != NULL)");
1046 fmt3
= (MessageFormat
*) fmt1
->clone();
1047 fmt4
= (MessageFormat
*) fmt2
->clone();
1049 if (fmt3
== NULL
) it_err("testCopyConstructor2: (fmt3 != NULL)");
1050 if (fmt4
== NULL
) it_err("testCopyConstructor2: (fmt4 != NULL)");
1052 result
= fmt1
->format( &fargs
, 1, resultStr
, fp
, status
);
1053 result
= fmt2
->format( &fargs
, 1, resultStr
, fp
, status
);
1054 result
= fmt3
->format( &fargs
, 1, resultStr
, fp
, status
);
1055 result
= fmt4
->format( &fargs
, 1, resultStr
, fp
, status
);
1062 void TestMessageFormat::testCopyConstructor2() {
1063 _testCopyConstructor2();
1067 * Verify that MessageFormat accomodates more than 10 arguments and
1068 * more than 10 subformats.
1070 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1071 UErrorCode ec
= U_ZERO_ERROR
;
1072 const UnicodeString pattern
=
1073 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1074 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1075 "there were {1,number} werjes "
1076 "(a {3,number,percent} increase over {2,number}) "
1077 "despite the {4}''s efforts "
1078 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1079 MessageFormat
msg(pattern
, ec
);
1080 if (U_FAILURE(ec
)) {
1081 errln("FAIL: constructor failed");
1085 const Formattable ARGS
[] = {
1086 Formattable(UDate(1e13
), Formattable::kIsDate
),
1087 Formattable((int32_t)1303),
1088 Formattable((int32_t)1202),
1089 Formattable(1303.0/1202 - 1),
1090 Formattable("Glimmung"),
1091 Formattable("the printers"),
1092 Formattable("Nick"),
1093 Formattable("his father"),
1094 Formattable("his mother"),
1095 Formattable("the spiddles"),
1096 Formattable("of course"),
1097 Formattable("Horace"),
1099 const int32_t ARGS_LENGTH
= sizeof(ARGS
) / sizeof(ARGS
[0]);
1100 Formattable
ARGS_OBJ(ARGS
, ARGS_LENGTH
);
1102 UnicodeString expected
=
1103 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1104 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1105 "there were 1,303 werjes "
1106 "(a 8% increase over 1,202) "
1107 "despite the Glimmung's efforts "
1108 "and to delight of the printers, Nick, his father, "
1109 "his mother, the spiddles, and of course Horace.";
1110 UnicodeString result
;
1111 msg
.format(ARGS_OBJ
, result
, ec
);
1112 if (result
== expected
) {
1115 errln((UnicodeString
)"FAIL: Got " + result
+
1116 ", expected " + expected
);
1120 // test RBNF extensions to message format
1121 void TestMessageFormat::TestRBNF(void) {
1122 // WARNING: this depends on the RBNF formats for en_US
1123 Locale
locale("en", "US", "");
1125 UErrorCode ec
= U_ZERO_ERROR
;
1127 UnicodeString values
[] = {
1128 // decimal values do not format completely for ordinal or duration, and
1129 // do not always parse, so do not include them
1130 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1132 int32_t values_count
= sizeof(values
)/sizeof(values
[0]);
1134 UnicodeString formats
[] = {
1135 "There are {0,spellout} files to search.",
1136 "There are {0,spellout,%simplified} files to search.",
1137 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1138 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1139 "Searching this file will take {0,duration} to complete.",
1140 "Searching this file will take {0,duration,%with-words} to complete.",
1142 int32_t formats_count
= sizeof(formats
)/sizeof(formats
[0]);
1144 Formattable args
[1];
1146 NumberFormat
* numFmt
= NumberFormat::createInstance(locale
, ec
);
1147 for (int i
= 0; i
< formats_count
; ++i
) {
1148 MessageFormat
* fmt
= new MessageFormat(formats
[i
], locale
, ec
);
1149 logln((UnicodeString
)"Testing format pattern: '" + formats
[i
] + "'");
1150 for (int j
= 0; j
< values_count
; ++j
) {
1152 numFmt
->parse(values
[j
], args
[0], ec
);
1153 if (U_FAILURE(ec
)) {
1154 errln((UnicodeString
)"Failed to parse test argument " + values
[j
]);
1156 FieldPosition
fp(0);
1157 UnicodeString result
;
1158 fmt
->format(args
, 1, result
, fp
, ec
);
1159 logln((UnicodeString
)"value: " + toString(args
[0]) + " --> " + result
+ UnicodeString(" ec: ") + u_errorName(ec
));
1161 if (i
!= 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1163 Formattable
* parseResult
= fmt
->parse(result
, count
, ec
);
1165 errln((UnicodeString
)"parse returned " + count
+ " args");
1166 } else if (parseResult
[0] != args
[0]) {
1167 errln((UnicodeString
)"parsed argument " + toString(parseResult
[0]) + " != " + toString(args
[0]));
1169 delete []parseResult
;
1178 #endif /* #if !UCONFIG_NO_FORMATTING */