]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tmsgfmt.cpp
ICU-8.11.tar.gz
[apple/icu.git] / icuSources / test / intltest / tmsgfmt.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2006, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /*
7 * File TMSGFMT.CPP
8 *
9 * Modification History:
10 *
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 ********************************************************************************
16 */
17
18 #include "unicode/utypes.h"
19
20 #if !UCONFIG_NO_FORMATTING
21
22 #include "tmsgfmt.h"
23
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"
31 #include <stdio.h>
32
33 void
34 TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
35 const char* &name, char* /*par*/) {
36 switch (index) {
37 TESTCASE(0,testBug1);
38 TESTCASE(1,testBug2);
39 TESTCASE(2,sample);
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;
59 }
60 }
61
62 void TestMessageFormat::testBug3()
63 {
64 double myNumber = -123456;
65 DecimalFormat *form = 0;
66 Locale locale[] = {
67 Locale("ar", "", ""),
68 Locale("be", "", ""),
69 Locale("bg", "", ""),
70 Locale("ca", "", ""),
71 Locale("cs", "", ""),
72 Locale("da", "", ""),
73 Locale("de", "", ""),
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", ""),
81 Locale("es", "", ""),
82 Locale("et", "", ""),
83 Locale("fi", "", ""),
84 Locale("fr", "", ""),
85 Locale("fr", "BE", ""),
86 Locale("fr", "CA", ""), // 20
87 Locale("fr", "CH", ""),
88 Locale("he", "", ""),
89 Locale("hr", "", ""),
90 Locale("hu", "", ""),
91 Locale("is", "", ""),
92 Locale("it", "", ""),
93 Locale("it", "CH", ""),
94 Locale("ja", "", ""),
95 Locale("ko", "", ""),
96 Locale("lt", "", ""), // 30
97 Locale("lv", "", ""),
98 Locale("mk", "", ""),
99 Locale("nl", "", ""),
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
116 };
117 int32_t i;
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.");
127 continue;
128 }
129 Formattable result;
130 FieldPosition pos(0);
131 buffer.remove();
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.");
140 }
141 delete form;
142 }
143 }
144
145 void TestMessageFormat::testBug1()
146 {
147 const double limit[] = {0.0, 1.0, 2.0};
148 const UnicodeString formats[] = {"0.0<=Arg<1.0",
149 "1.0<=Arg<2.0",
150 "2.0<-Arg"};
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");
157 }
158 logln(toAppendTo);
159 delete cf;
160 }
161
162 void TestMessageFormat::testBug2()
163 {
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.");
172 return;
173 }
174 logln("The output pattern is : " + fmt->toPattern(result));
175 if (pattern != result) {
176 errln("MessageFormat::toPattern() failed.");
177 }
178 delete fmt;
179 }
180
181 #if 0
182 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
183 //----------------------------------------------------
184 // console I/O
185 //----------------------------------------------------
186
187 #if U_IOSTREAM_SOURCE >= 199711
188 # include <iostream>
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);
193 #endif
194
195 #include "unicode/datefmt.h"
196 #include <stdlib.h>
197 #include <string.h>
198
199 IntlTest&
200 operator<<( IntlTest& stream,
201 const Formattable& obj)
202 {
203 static DateFormat *defDateFormat = 0;
204
205 UnicodeString buffer;
206 switch(obj.getType()) {
207 case Formattable::kDate :
208 if (defDateFormat == 0) {
209 defDateFormat = DateFormat::createInstance();
210 }
211 defDateFormat->format(obj.getDate(), buffer);
212 stream << buffer;
213 break;
214 case Formattable::kDouble :
215 char convert[20];
216 sprintf( convert, "%lf", obj.getDouble() );
217 stream << convert << "D";
218 break;
219 case Formattable::kLong :
220 stream << obj.getLong() << "L";
221 break;
222 case Formattable::kString:
223 stream << "\"" << obj.getString(buffer) << "\"";
224 break;
225 case Formattable::kArray:
226 int32_t i, count;
227 const Formattable* array;
228 array = obj.getArray(count);
229 stream << "[";
230 for (i=0; i<count; ++i) stream << array[i] << ( (i==(count-1)) ? "" : ", " );
231 stream << "]";
232 break;
233 default:
234 stream << "INVALID_Formattable";
235 }
236 return stream;
237 }
238 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
239 #endif
240
241 void TestMessageFormat::PatternTest()
242 {
243 Formattable testArgs[] = {
244 Formattable(double(1)), Formattable(double(3456)),
245 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate)
246 };
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,#,##}",
257 };
258
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,#,##}"
269 };
270
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"
281 };
282
283
284 for (int32_t i = 0; i < 9; ++i) {
285 //it_out << "\nPat in: " << testCases[i]);
286
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");
294 continue;
295 }
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);
302 }
303
304 //it_out << "Pat out: " << form->toPattern(buffer));
305 UnicodeString result;
306 int32_t count = 4;
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");
312 continue;
313 }
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] );
319 }
320
321
322 //it_out << "Result: " << result);
323 #if 0
324 /* TODO: Look at this test and see if this is still a valid test */
325 logln("---------------- test parse ----------------");
326
327 form->toPattern(buffer);
328 logln("MSG pattern for parse: " + buffer);
329
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);
337 }
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]));
343 failed = TRUE;
344 }
345 }
346 if (failed)
347 errln("MessageFormat failed test #6");
348 #endif
349 delete form;
350 }
351 }
352
353 void TestMessageFormat::sample()
354 {
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.");
362 return;
363 }
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);
372 delete form;
373 }
374
375 void TestMessageFormat::testStaticFormat()
376 {
377 UErrorCode err = U_ZERO_ERROR;
378 Formattable arguments[] = {
379 (int32_t)7,
380 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
381 "a disturbance in the Force"
382 };
383
384 UnicodeString result;
385 result = MessageFormat::format(
386 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
387 arguments,
388 3,
389 result,
390 err);
391
392 if (U_FAILURE(err)) {
393 errln("TestMessageFormat::testStaticFormat #1");
394 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err);
395 return;
396 }
397
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 );
404 }
405 }
406
407 /* When the default locale is tr, make sure that the pattern can still be parsed. */
408 void TestMessageFormat::TestTurkishCasing()
409 {
410 UErrorCode err = U_ZERO_ERROR;
411 Locale saveDefaultLocale;
412 Locale::setDefault( Locale("tr"), err );
413
414 Formattable arguments[] = {
415 (int32_t)7,
416 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
417 "a disturbance in the Force"
418 };
419
420 UnicodeString result;
421 result = MessageFormat::format(
422 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
423 arguments,
424 3,
425 result,
426 err);
427
428 if (U_FAILURE(err)) {
429 errln("TestTurkishCasing #1 with error code %s", u_errorName(err));
430 return;
431 }
432
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 );
439 }
440 Locale::setDefault( saveDefaultLocale, err );
441 }
442
443 void TestMessageFormat::testSimpleFormat(/* char* par */)
444 {
445 logln("running TestMessageFormat::testSimpleFormat");
446
447 UErrorCode err = U_ZERO_ERROR;
448
449 Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
450 Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
451 Formattable testArgs3[] = {(int32_t)12, "MyDisk"};
452
453 MessageFormat* form = new MessageFormat(
454 "The disk \"{1}\" contains {0} file(s).", err);
455
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"));
461 }
462
463 ignore.setField(FieldPosition::DONT_CARE);
464 string.remove();
465 form->format(testArgs2, 2, string, ignore, err);
466 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 1 file(s).") {
467 logln(string);
468 errln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string);
469 }
470
471 ignore.setField(FieldPosition::DONT_CARE);
472 string.remove();
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);
476 }
477
478 delete form;
479 }
480
481 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
482 {
483 logln("running TestMessageFormat::testMsgFormatChoice");
484
485 UErrorCode err = U_ZERO_ERROR;
486
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?
493
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");
500 }
501
502 ignore.setField(FieldPosition::DONT_CARE);
503 string.remove();
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");
508 }
509
510 ignore.setField(FieldPosition::DONT_CARE);
511 string.remove();
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");
516 }
517
518 delete form;
519 delete fileform;
520 }
521
522
523 //---------------------------------
524 // API Tests
525 //---------------------------------
526
527 void TestMessageFormat::testCopyConstructor()
528 {
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);
534 if ( (*x == *y) &&
535 (*x != *z) &&
536 (*y != *z) )
537 logln("First test (operator ==): Passed!");
538 else {
539 errln("TestMessageFormat::testCopyConstructor failed #1");
540 logln("First test (operator ==): Failed!");
541 }
542 if ( ((*x == *y) && (*y == *x)) &&
543 ((*x != *z) && (*z != *x)) &&
544 ((*y != *z) && (*z != *y)) )
545 logln("Second test (equals): Passed!");
546 else {
547 errln("TestMessageFormat::testCopyConstructor failed #2");
548 logln("Second test (equals): Failed!");
549 }
550
551 delete x;
552 delete y;
553 delete z;
554 }
555
556
557 void TestMessageFormat::testAssignment()
558 {
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);
563 *y = *x;
564 if ( (*x == *y) &&
565 (*x != *z) &&
566 (*y != *z) )
567 logln("First test (operator ==): Passed!");
568 else {
569 errln( "TestMessageFormat::testAssignment failed #1");
570 logln("First test (operator ==): Failed!");
571 }
572 if ( ((*x == *y) && (*y == *x)) &&
573 ((*x != *z) && (*z != *x)) &&
574 ((*y != *z) && (*z != *y)) )
575 logln("Second test (equals): Passed!");
576 else {
577 errln("TestMessageFormat::testAssignment failed #2");
578 logln("Second test (equals): Failed!");
579 }
580
581 delete x;
582 delete y;
583 delete z;
584 }
585
586 void TestMessageFormat::testClone()
587 {
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();
593 if ( (*x == *y) &&
594 (*x != *z) &&
595 (*y != *z) )
596 logln("First test (operator ==): Passed!");
597 else {
598 errln("TestMessageFormat::testClone failed #1");
599 logln("First test (operator ==): Failed!");
600 }
601 if ( ((*x == *y) && (*y == *x)) &&
602 ((*x != *z) && (*z != *x)) &&
603 ((*y != *z) && (*z != *y)) )
604 logln("Second test (equals): Passed!");
605 else {
606 errln("TestMessageFormat::testClone failed #2");
607 logln("Second test (equals): Failed!");
608 }
609
610 delete x;
611 delete y;
612 delete z;
613 }
614
615 void TestMessageFormat::testEquals()
616 {
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);
620 if (!(x == y)) {
621 errln( "TestMessageFormat::testEquals failed #1");
622 logln("First test (operator ==): Failed!");
623 }
624
625 }
626
627 void TestMessageFormat::testNotEquals()
628 {
629 UErrorCode success = U_ZERO_ERROR;
630 MessageFormat x("There are {0} files on {1}", success);
631 MessageFormat y(x);
632 y.setLocale(Locale("fr"));
633 if (!(x != y)) {
634 errln( "TestMessageFormat::testEquals failed #1");
635 logln("First test (operator !=): Failed!");
636 }
637 y = x;
638 y.applyPattern("There are {0} files on {1} the disk", success);
639 if (!(x != y)) {
640 errln( "TestMessageFormat::testEquals failed #1");
641 logln("Second test (operator !=): Failed!");
642 }
643 }
644
645
646 void TestMessageFormat::testSetLocale()
647 {
648 UErrorCode err = U_ZERO_ERROR;
649 GregorianCalendar cal(err);
650 Formattable arguments[] = {
651 456.83,
652 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
653 "deposit"
654 };
655
656 UnicodeString result;
657
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.";
672
673 MessageFormat msg( formatStr, err);
674 result = "";
675 FieldPosition pos(0);
676 result = msg.format(
677 arguments,
678 3,
679 result,
680 pos,
681 err);
682
683 logln(result);
684 if (result != compareStrEng) {
685 errln("*** MSG format err.");
686 }
687
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;
693 }
694
695 msg.setLocale(Locale::getGerman());
696
697 if (msg.getLocale() != Locale::getGerman()) {
698 errln("*** MSG getLocal err.");
699 getLocale_ok = FALSE;
700 }
701
702 msg.applyPattern( formatStr, err);
703
704 pos.setField(0);
705 result = "";
706 result = msg.format(
707 arguments,
708 3,
709 result,
710 pos,
711 err);
712
713 logln(result);
714 if (result == compareStrGer) {
715 logln("MSG setLocale tested.");
716 }else{
717 errln( "*** MSG setLocale err.");
718 }
719
720 if (getLocale_ok) {
721 logln("MSG getLocale tested.");
722 }
723 }
724
725 void TestMessageFormat::testFormat()
726 {
727 UErrorCode err = U_ZERO_ERROR;
728 GregorianCalendar cal(err);
729
730 const Formattable ftarray[] =
731 {
732 Formattable( UDate(8.71068e+011), Formattable::kIsDate )
733 };
734 const int32_t ft_cnt = sizeof(ftarray) / sizeof(Formattable);
735 Formattable ft_arr( ftarray, ft_cnt );
736
737 Formattable* fmt = new Formattable(UDate(8.71068e+011), Formattable::kIsDate);
738
739 UnicodeString result;
740
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.";
744
745 err = U_ZERO_ERROR;
746 MessageFormat msg( formatStr, err);
747 FieldPosition fp(0);
748
749 result = "";
750 fp = 0;
751 result = msg.format(
752 *fmt,
753 result,
754 //FieldPosition(0),
755 fp,
756 err);
757
758 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
759 errln("*** MSG format without expected error code.");
760 }
761 err = U_ZERO_ERROR;
762
763 result = "";
764 fp = 0;
765 result = msg.format(
766 ft_arr,
767 result,
768 //FieldPosition(0),
769 fp,
770 err);
771
772 logln("MSG format( Formattable&, ... ) expected:" + compareStr);
773 logln("MSG format( Formattable&, ... ) result:" + result);
774 if (result != compareStr) {
775 errln("*** MSG format( Formattable&, .... ) err.");
776 }else{
777 logln("MSG format( Formattable&, ... ) tested.");
778 }
779
780 delete fmt;
781
782 }
783
784 void TestMessageFormat::testParse()
785 {
786 UErrorCode err = U_ZERO_ERROR;
787 int32_t count;
788 UnicodeString msgFormatString = "{0} =sep= {1}";
789 MessageFormat msg( msgFormatString, err);
790 UnicodeString source = "abc =sep= def";
791 UnicodeString tmp1, tmp2;
792
793 Formattable* fmt_arr = msg.parse( source, count, err );
794 if (U_FAILURE(err) || (!fmt_arr)) {
795 errln("*** MSG parse (ustring, count, err) error.");
796 }else{
797 logln("MSG parse -- count: %d", count);
798 if (count != 2) {
799 errln("*** MSG parse (ustring, count, err) count err.");
800 }else{
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.");
806 }else{
807 errln("*** MSG parse (ustring, count, err) result err.");
808 }
809 }
810 }
811 delete[] fmt_arr;
812
813 ParsePosition pp(0);
814
815 fmt_arr = msg.parse( source, pp, count );
816 if ((pp == 0) || (!fmt_arr)) {
817 errln("*** MSG parse (ustring, parsepos., count) error.");
818 }else{
819 logln("MSG parse -- count: %d", count);
820 if (count != 2) {
821 errln("*** MSG parse (ustring, parsepos., count) count err.");
822 }else{
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.");
828 }else{
829 errln("*** MSG parse (ustring, parsepos., count) result err.");
830 }
831 }
832 }
833 delete[] fmt_arr;
834
835 pp = 0;
836 Formattable fmta;
837
838 msg.parseObject( source, fmta, pp );
839 if (pp == 0) {
840 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
841 }else{
842 logln("MSG parse -- count: %d", count);
843 fmta.getArray(count);
844 if (count != 2) {
845 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
846 }else{
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.");
852 }else{
853 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
854 }
855 }
856 }
857 }
858
859
860 void TestMessageFormat::testAdopt()
861 {
862 UErrorCode err = U_ZERO_ERROR;
863
864 UnicodeString formatStr("{0,date},{1},{2,number}", "");
865 UnicodeString formatStrChange("{0,number},{1,number},{2,date}", "");
866 err = U_ZERO_ERROR;
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;
874 int32_t countAct;
875 const Format* a;
876 const Format* b;
877 UnicodeString patCmp;
878 UnicodeString patAct;
879 Format** formatsToAdopt;
880
881 if (!formats || !formatsCmp || (count <= 0) || (count != countCmp)) {
882 errln("Error getting Formats");
883 return;
884 }
885
886 int32_t i;
887
888 for (i = 0; i < count; i++) {
889 a = formats[i];
890 b = formatsCmp[i];
891 if ((a != NULL) && (b != NULL)) {
892 if (*a != *b) {
893 errln("a != b");
894 return;
895 }
896 }else if ((a != NULL) || (b != NULL)) {
897 errln("(a != NULL) || (b != NULL)");
898 return;
899 }
900 }
901
902 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
903 int32_t countChg;
904 formatsChg = msg.getFormats(countChg); // tested function
905 if (!formatsChg || (countChg != count)) {
906 errln("Error getting Formats");
907 return;
908 }
909
910 UBool diff;
911 diff = TRUE;
912 for (i = 0; i < count; i++) {
913 a = formatsChg[i];
914 b = formatsCmp[i];
915 if ((a != NULL) && (b != NULL)) {
916 if (*a == *b) {
917 logln("formatsChg == formatsCmp at index %d", i);
918 diff = FALSE;
919 }
920 }
921 }
922 if (!diff) {
923 errln("*** MSG getFormats diff err.");
924 return;
925 }
926
927 logln("MSG getFormats tested.");
928
929 msg.setFormats( formatsCmp, countCmp ); //tested function
930
931 formatsAct = msg.getFormats(countAct);
932 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
933 errln("Error getting Formats");
934 return;
935 }
936
937 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
938 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
939
940 for (i = 0; i < countAct; i++) {
941 a = formatsAct[i];
942 b = formatsCmp[i];
943 if ((a != NULL) && (b != NULL)) {
944 if (*a != *b) {
945 logln("formatsAct != formatsCmp at index %d", i);
946 errln("a != b");
947 return;
948 }
949 }else if ((a != NULL) || (b != NULL)) {
950 errln("(a != NULL) || (b != NULL)");
951 return;
952 }
953 }
954 logln("MSG setFormats tested.");
955
956 //----
957
958 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
959
960 formatsToAdopt = new Format* [countCmp];
961 if (!formatsToAdopt) {
962 errln("memory allocation error");
963 return;
964 }
965
966 for (i = 0; i < countCmp; i++) {
967 if (formatsCmp[i] == NULL) {
968 formatsToAdopt[i] = NULL;
969 }else{
970 formatsToAdopt[i] = formatsCmp[i]->clone();
971 if (!formatsToAdopt[i]) {
972 errln("Can't clone format at index %d", i);
973 return;
974 }
975 }
976 }
977 msg.adoptFormats( formatsToAdopt, countCmp ); // function to test
978 delete[] formatsToAdopt;
979
980 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
981 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
982
983 formatsAct = msg.getFormats(countAct);
984 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
985 errln("Error getting Formats");
986 return;
987 }
988
989 for (i = 0; i < countAct; i++) {
990 a = formatsAct[i];
991 b = formatsCmp[i];
992 if ((a != NULL) && (b != NULL)) {
993 if (*a != *b) {
994 errln("a != b");
995 return;
996 }
997 }else if ((a != NULL) || (b != NULL)) {
998 errln("(a != NULL) || (b != NULL)");
999 return;
1000 }
1001 }
1002 logln("MSG adoptFormats tested.");
1003
1004 //---- adoptFormat
1005
1006 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1007
1008 formatsToAdopt = new Format* [countCmp];
1009 if (!formatsToAdopt) {
1010 errln("memory allocation error");
1011 return;
1012 }
1013
1014 for (i = 0; i < countCmp; i++) {
1015 if (formatsCmp[i] == NULL) {
1016 formatsToAdopt[i] = NULL;
1017 }else{
1018 formatsToAdopt[i] = formatsCmp[i]->clone();
1019 if (!formatsToAdopt[i]) {
1020 errln("Can't clone format at index %d", i);
1021 return;
1022 }
1023 }
1024 }
1025
1026 for ( i = 0; i < countCmp; i++ ) {
1027 msg.adoptFormat( i, formatsToAdopt[i] ); // function to test
1028 }
1029 delete[] formatsToAdopt; // array itself not needed in this case;
1030
1031 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1032 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1033
1034 formatsAct = msg.getFormats(countAct);
1035 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1036 errln("Error getting Formats");
1037 return;
1038 }
1039
1040 for (i = 0; i < countAct; i++) {
1041 a = formatsAct[i];
1042 b = formatsCmp[i];
1043 if ((a != NULL) && (b != NULL)) {
1044 if (*a != *b) {
1045 errln("a != b");
1046 return;
1047 }
1048 }else if ((a != NULL) || (b != NULL)) {
1049 errln("(a != NULL) || (b != NULL)");
1050 return;
1051 }
1052 }
1053 logln("MSG adoptFormat tested.");
1054 }
1055
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()
1063 {
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 );
1071
1072 MessageFormat* fmt1 = new MessageFormat( formatStr, status );
1073 MessageFormat* fmt2 = new MessageFormat( *fmt1 );
1074 MessageFormat* fmt3;
1075 MessageFormat* fmt4;
1076
1077 if (fmt1 == NULL) it_err("testCopyConstructor2: (fmt1 != NULL)");
1078
1079 result = fmt1->format( &fargs, 1, resultStr, fp, status );
1080
1081 if (fmt2 == NULL) it_err("testCopyConstructor2: (fmt2 != NULL)");
1082
1083 fmt3 = (MessageFormat*) fmt1->clone();
1084 fmt4 = (MessageFormat*) fmt2->clone();
1085
1086 if (fmt3 == NULL) it_err("testCopyConstructor2: (fmt3 != NULL)");
1087 if (fmt4 == NULL) it_err("testCopyConstructor2: (fmt4 != NULL)");
1088
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 );
1093 delete fmt1;
1094 delete fmt2;
1095 delete fmt3;
1096 delete fmt4;
1097 }
1098
1099 void TestMessageFormat::testCopyConstructor2() {
1100 _testCopyConstructor2();
1101 }
1102
1103 /**
1104 * Verify that MessageFormat accomodates more than 10 arguments and
1105 * more than 10 subformats.
1106 */
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");
1119 return;
1120 }
1121
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"),
1135 };
1136 const int32_t ARGS_LENGTH = sizeof(ARGS) / sizeof(ARGS[0]);
1137 Formattable ARGS_OBJ(ARGS, ARGS_LENGTH);
1138
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) {
1150 logln(result);
1151 } else {
1152 errln((UnicodeString)"FAIL: Got " + result +
1153 ", expected " + expected);
1154 }
1155 }
1156
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", "");
1161
1162 UErrorCode ec = U_ZERO_ERROR;
1163
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",
1168 };
1169 int32_t values_count = sizeof(values)/sizeof(values[0]);
1170
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.",
1178 };
1179 int32_t formats_count = sizeof(formats)/sizeof(formats[0]);
1180
1181 Formattable args[1];
1182
1183 NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
1184 if (U_FAILURE(ec)) {
1185 dataerrln("Error calling NumberFormat::createInstance()");
1186 return;
1187 }
1188
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] + "'");
1192
1193 for (int j = 0; j < values_count; ++j) {
1194 ec = U_ZERO_ERROR;
1195 numFmt->parse(values[j], args[0], ec);
1196 if (U_FAILURE(ec)) {
1197 errln((UnicodeString)"Failed to parse test argument " + values[j]);
1198 } else {
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));
1203
1204 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1205 int32_t count = 0;
1206 Formattable* parseResult = fmt->parse(result, count, ec);
1207 if (count != 1) {
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]));
1211 }
1212 delete []parseResult;
1213 }
1214 }
1215 }
1216 delete fmt;
1217 }
1218 delete numFmt;
1219 }
1220
1221 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1222 const char* patterns[] = { // pattern, expected pattern
1223 "'", "''",
1224 "''", "''",
1225 "'{", "'{'",
1226 "' {", "'' {",
1227 "'a", "''a",
1228 "'{'a", "'{'a",
1229 "'{a'", "'{a'",
1230 "'{}", "'{}'",
1231 "{'", "{'",
1232 "{'a", "{'a",
1233 "{'a{}'a}'a", "{'a{}'a}''a",
1234 "'}'", "'}'",
1235 "'} '{'}'", "'} '{'}''",
1236 "'} {{{''", "'} {{{'''",
1237 };
1238 int32_t pattern_count = sizeof(patterns)/sizeof(patterns[0]);
1239
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;
1246 char buf[256];
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;
1251 }
1252 sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2);
1253 errln(buf);
1254 }
1255 }
1256 }
1257
1258 #endif /* #if !UCONFIG_NO_FORMATTING */