1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2010, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************
6 * File TMSGFMT.CPP
7 *
8 * Modification History:
9 *
10 * Date Name Description
11 * 03/24/97 helena Converted from Java.
12 * 07/11/97 helena Updated to work on AIX.
13 * 08/04/97 jfitz Updated to intltest
14 *******************************************************************/
15
16 #include "unicode/utypes.h"
17
18 #if !UCONFIG_NO_FORMATTING
19
20 #include "tmsgfmt.h"
21
22 #include "unicode/format.h"
23 #include "unicode/decimfmt.h"
24 #include "unicode/locid.h"
25 #include "unicode/msgfmt.h"
26 #include "unicode/numfmt.h"
27 #include "unicode/choicfmt.h"
28 #include "unicode/selfmt.h"
29 #include "unicode/gregocal.h"
30 #include <stdio.h>
31
32 #define E_WITH_ACUTE ((char)0x00E9)
33 static const char E_ACCENTED[]={E_WITH_ACUTE,0};
34
35 void
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)36 TestMessageFormat::runIndexedTest(int32_t index, UBool exec,
37 const char* &name, char* /*par*/) {
38 switch (index) {
39 TESTCASE(0,testBug1);
40 TESTCASE(1,testBug2);
41 TESTCASE(2,sample);
42 TESTCASE(3,PatternTest);
43 TESTCASE(4,testStaticFormat);
44 TESTCASE(5,testSimpleFormat);
45 TESTCASE(6,testMsgFormatChoice);
46 TESTCASE(7,testCopyConstructor);
47 TESTCASE(8,testAssignment);
48 TESTCASE(9,testClone);
49 TESTCASE(10,testEquals);
50 TESTCASE(11,testNotEquals);
51 TESTCASE(12,testSetLocale);
52 TESTCASE(13,testFormat);
53 TESTCASE(14,testParse);
54 TESTCASE(15,testAdopt);
55 TESTCASE(16,testCopyConstructor2);
56 TESTCASE(17,TestUnlimitedArgsAndSubformats);
57 TESTCASE(18,TestRBNF);
58 TESTCASE(19,TestTurkishCasing);
59 TESTCASE(20,testAutoQuoteApostrophe);
60 TESTCASE(21,testMsgFormatPlural);
61 TESTCASE(22,testCoverage);
62 TESTCASE(23,testMsgFormatSelect);
63 default: name = ""; break;
64 }
65 }
66
testBug3()67 void TestMessageFormat::testBug3()
68 {
69 double myNumber = -123456;
70 DecimalFormat *form = 0;
71 Locale locale[] = {
72 Locale("ar", "", ""),
73 Locale("be", "", ""),
74 Locale("bg", "", ""),
75 Locale("ca", "", ""),
76 Locale("cs", "", ""),
77 Locale("da", "", ""),
78 Locale("de", "", ""),
79 Locale("de", "AT", ""),
80 Locale("de", "CH", ""),
81 Locale("el", "", ""), // 10
82 Locale("en", "CA", ""),
83 Locale("en", "GB", ""),
84 Locale("en", "IE", ""),
85 Locale("en", "US", ""),
86 Locale("es", "", ""),
87 Locale("et", "", ""),
88 Locale("fi", "", ""),
89 Locale("fr", "", ""),
90 Locale("fr", "BE", ""),
91 Locale("fr", "CA", ""), // 20
92 Locale("fr", "CH", ""),
93 Locale("he", "", ""),
94 Locale("hr", "", ""),
95 Locale("hu", "", ""),
96 Locale("is", "", ""),
97 Locale("it", "", ""),
98 Locale("it", "CH", ""),
99 Locale("ja", "", ""),
100 Locale("ko", "", ""),
101 Locale("lt", "", ""), // 30
102 Locale("lv", "", ""),
103 Locale("mk", "", ""),
104 Locale("nl", "", ""),
105 Locale("nl", "BE", ""),
106 Locale("no", "", ""),
107 Locale("pl", "", ""),
108 Locale("pt", "", ""),
109 Locale("ro", "", ""),
110 Locale("ru", "", ""),
111 Locale("sh", "", ""), // 40
112 Locale("sk", "", ""),
113 Locale("sl", "", ""),
114 Locale("sq", "", ""),
115 Locale("sr", "", ""),
116 Locale("sv", "", ""),
117 Locale("tr", "", ""),
118 Locale("uk", "", ""),
119 Locale("zh", "", ""),
120 Locale("zh", "TW", "") // 49
121 };
122 int32_t i;
123 for (i= 0; i < 49; i++) {
124 UnicodeString buffer;
125 logln(locale[i].getDisplayName(buffer));
126 UErrorCode success = U_ZERO_ERROR;
127 // form = (DecimalFormat*)NumberFormat::createCurrencyInstance(locale[i], success);
128 form = (DecimalFormat*)NumberFormat::createInstance(locale[i], success);
129 if (U_FAILURE(success)) {
130 errln("Err: Number Format ");
131 logln("Number format creation failed.");
132 continue;
133 }
134 Formattable result;
135 FieldPosition pos(0);
136 buffer.remove();
137 form->format(myNumber, buffer, pos);
138 success = U_ZERO_ERROR;
139 ParsePosition parsePos;
140 form->parse(buffer, result, parsePos);
141 logln(UnicodeString(" -> ") /* + << dec*/ + toString(result) + UnicodeString("[supposed output for result]"));
142 if (U_FAILURE(success)) {
143 errln("Err: Number Format parse");
144 logln("Number format parse failed.");
145 }
146 delete form;
147 }
148 }
149
testBug1()150 void TestMessageFormat::testBug1()
151 {
152 const double limit[] = {0.0, 1.0, 2.0};
153 const UnicodeString formats[] = {"0.0<=Arg<1.0",
154 "1.0<=Arg<2.0",
155 "2.0<-Arg"};
156 ChoiceFormat *cf = new ChoiceFormat(limit, formats, 3);
157 FieldPosition status(0);
158 UnicodeString toAppendTo;
159 cf->format((int32_t)1, toAppendTo, status);
160 if (toAppendTo != "1.0<=Arg<2.0") {
161 errln("ChoiceFormat cmp in testBug1");
162 }
163 logln(toAppendTo);
164 delete cf;
165 }
166
testBug2()167 void TestMessageFormat::testBug2()
168 {
169 UErrorCode status = U_ZERO_ERROR;
170 UnicodeString result;
171 // {sfb} use double format in pattern, so result will match (not strictly necessary)
172 const UnicodeString pattern = "There {0,choice,0#are no files|1#is one file|1<are {0, number} files} on disk {1}. ";
173 logln("The input pattern : " + pattern);
174 MessageFormat *fmt = new MessageFormat(pattern, status);
175 if (U_FAILURE(status)) {
176 errln("MessageFormat pattern creation failed.");
177 return;
178 }
179 logln("The output pattern is : " + fmt->toPattern(result));
180 if (pattern != result) {
181 errln("MessageFormat::toPattern() failed.");
182 }
183 delete fmt;
184 }
185
186 #if 0
187 #if defined(_DEBUG) && U_IOSTREAM_SOURCE!=0
188 //----------------------------------------------------
189 // console I/O
190 //----------------------------------------------------
191
192 #if U_IOSTREAM_SOURCE >= 199711
193 # include <iostream>
194 std::ostream& operator<<(std::ostream& stream, const Formattable& obj);
195 #elif U_IOSTREAM_SOURCE >= 198506
196 # include <iostream.h>
197 ostream& operator<<(ostream& stream, const Formattable& obj);
198 #endif
199
200 #include "unicode/datefmt.h"
201 #include <stdlib.h>
202 #include <string.h>
203
204 IntlTest&
205 operator<<( IntlTest& stream,
206 const Formattable& obj)
207 {
208 static DateFormat *defDateFormat = 0;
209
210 UnicodeString buffer;
211 switch(obj.getType()) {
212 case Formattable::kDate :
213 if (defDateFormat == 0) {
214 defDateFormat = DateFormat::createInstance();
215 }
216 defDateFormat->format(obj.getDate(), buffer);
217 stream << buffer;
218 break;
219 case Formattable::kDouble :
220 char convert[20];
221 sprintf( convert, "%lf", obj.getDouble() );
222 stream << convert << "D";
223 break;
224 case Formattable::kLong :
225 stream << obj.getLong() << "L";
226 break;
227 case Formattable::kString:
228 stream << "\"" << obj.getString(buffer) << "\"";
229 break;
230 case Formattable::kArray:
231 int32_t i, count;
232 const Formattable* array;
233 array = obj.getArray(count);
234 stream << "[";
235 for (i=0; i<count; ++i) stream << array[i] << ( (i==(count-1)) ? "" : ", " );
236 stream << "]";
237 break;
238 default:
239 stream << "INVALID_Formattable";
240 }
241 return stream;
242 }
243 #endif /* defined(_DEBUG) && U_IOSTREAM_SOURCE!=0 */
244 #endif
245
PatternTest()246 void TestMessageFormat::PatternTest()
247 {
248 Formattable testArgs[] = {
249 Formattable(double(1)), Formattable(double(3456)),
250 Formattable("Disk"), Formattable(UDate((int32_t)1000000000L), Formattable::kIsDate)
251 };
252 UnicodeString testCases[] = {
253 "Quotes '', '{', 'a' {0} '{0}'",
254 "Quotes '', '{', 'a' {0,number} '{0}'",
255 "'{'1,number,'#',##} {1,number,'#',##}",
256 "There are {1} files on {2} at {3}.",
257 "On {2}, there are {1} files, with {0,number,currency}.",
258 "'{1,number,percent}', {1,number,percent},",
259 "'{1,date,full}', {1,date,full},",
260 "'{3,date,full}', {3,date,full},",
261 "'{1,number,#,##}' {1,number,#,##}",
262 };
263
264 UnicodeString testResultPatterns[] = {
265 "Quotes '', '{', a {0} '{'0}",
266 "Quotes '', '{', a {0,number} '{'0}",
267 "'{'1,number,#,##} {1,number,'#'#,##}",
268 "There are {1} files on {2} at {3}.",
269 "On {2}, there are {1} files, with {0,number,currency}.",
270 "'{'1,number,percent}, {1,number,percent},",
271 "'{'1,date,full}, {1,date,full},",
272 "'{'3,date,full}, {3,date,full},",
273 "'{'1,number,#,##} {1,number,#,##}"
274 };
275
276 UnicodeString testResultStrings[] = {
277 "Quotes ', {, a 1 {0}",
278 "Quotes ', {, a 1 {0}",
279 "{1,number,#,##} #34,56",
280 "There are 3,456 files on Disk at 1/12/70 5:46 AM.",
281 "On Disk, there are 3,456 files, with $1.00.",
282 "{1,number,percent}, 345,600%,",
283 "{1,date,full}, Wednesday, December 31, 1969,",
284 "{3,date,full}, Monday, January 12, 1970,",
285 "{1,number,#,##} 34,56"
286 };
287
288
289 for (int32_t i = 0; i < 9; ++i) {
290 //it_out << "\nPat in: " << testCases[i]);
291
292 MessageFormat *form = 0;
293 UErrorCode success = U_ZERO_ERROR;
294 UnicodeString buffer;
295 form = new MessageFormat(testCases[i], Locale::getUS(), success);
296 if (U_FAILURE(success)) {
297 dataerrln("MessageFormat creation failed.#1 - %s", u_errorName(success));
298 logln(((UnicodeString)"MessageFormat for ") + testCases[i] + " creation failed.\n");
299 continue;
300 }
301 if (form->toPattern(buffer) != testResultPatterns[i]) {
302 errln(UnicodeString("TestMessageFormat::PatternTest failed test #2, i = ") + i);
303 //form->toPattern(buffer);
304 errln(((UnicodeString)" Orig: ") + testCases[i]);
305 errln(((UnicodeString)" Exp: ") + testResultPatterns[i]);
306 errln(((UnicodeString)" Got: ") + buffer);
307 }
308
309 //it_out << "Pat out: " << form->toPattern(buffer));
310 UnicodeString result;
311 int32_t count = 4;
312 FieldPosition fieldpos(0);
313 form->format(testArgs, count, result, fieldpos, success);
314 if (U_FAILURE(success)) {
315 dataerrln("MessageFormat failed test #3 - %s", u_errorName(success));
316 logln("TestMessageFormat::PatternTest failed test #3");
317 continue;
318 }
319 if (result != testResultStrings[i]) {
320 errln("TestMessageFormat::PatternTest failed test #4");
321 logln("TestMessageFormat::PatternTest failed #4.");
322 logln(UnicodeString(" Result: ") + result );
323 logln(UnicodeString(" Expected: ") + testResultStrings[i] );
324 }
325
326
327 //it_out << "Result: " << result);
328 #if 0
329 /* TODO: Look at this test and see if this is still a valid test */
330 logln("---------------- test parse ----------------");
331
332 form->toPattern(buffer);
333 logln("MSG pattern for parse: " + buffer);
334
335 int32_t parseCount = 0;
336 Formattable* values = form->parse(result, parseCount, success);
337 if (U_FAILURE(success)) {
338 errln("MessageFormat failed test #5");
339 logln(UnicodeString("MessageFormat failed test #5 with error code ")+(int32_t)success);
340 } else if (parseCount != count) {
341 errln("MSG count not %d as expected. Got %d", count, parseCount);
342 }
343 UBool failed = FALSE;
344 for (int32_t j = 0; j < parseCount; ++j) {
345 if (values == 0 || testArgs[j] != values[j]) {
346 errln(((UnicodeString)"MSG testargs[") + j + "]: " + toString(testArgs[j]));
347 errln(((UnicodeString)"MSG values[") + j + "] : " + toString(values[j]));
348 failed = TRUE;
349 }
350 }
351 if (failed)
352 errln("MessageFormat failed test #6");
353 #endif
354 delete form;
355 }
356 }
357
sample()358 void TestMessageFormat::sample()
359 {
360 MessageFormat *form = 0;
361 UnicodeString buffer1, buffer2;
362 UErrorCode success = U_ZERO_ERROR;
363 form = new MessageFormat("There are {0} files on {1}", success);
364 if (U_FAILURE(success)) {
365 errln("Err: Message format creation failed");
366 logln("Sample message format creation failed.");
367 return;
368 }
369 UnicodeString abc("abc");
370 UnicodeString def("def");
371 Formattable testArgs1[] = { abc, def };
372 FieldPosition fieldpos(0);
373 assertEquals("format",
374 "There are abc files on def",
375 form->format(testArgs1, 2, buffer2, fieldpos, success));
376 assertSuccess("format", success);
377 delete form;
378 }
379
testStaticFormat()380 void TestMessageFormat::testStaticFormat()
381 {
382 UErrorCode err = U_ZERO_ERROR;
383 Formattable arguments[] = {
384 (int32_t)7,
385 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
386 "a disturbance in the Force"
387 };
388
389 UnicodeString result;
390 result = MessageFormat::format(
391 "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
392 arguments,
393 3,
394 result,
395 err);
396
397 if (U_FAILURE(err)) {
398 dataerrln("TestMessageFormat::testStaticFormat #1 - %s", u_errorName(err));
399 logln(UnicodeString("TestMessageFormat::testStaticFormat failed test #1 with error code ")+(int32_t)err);
400 return;
401 }
402
403 const UnicodeString expected(
404 "At 12:20:00 PM on Aug 8, 1997, there was a disturbance in the Force on planet 7.", "");
405 if (result != expected) {
406 errln("TestMessageFormat::testStaticFormat failed on test");
407 logln( UnicodeString(" Result: ") + result );
408 logln( UnicodeString(" Expected: ") + expected );
409 }
410 }
411
412 /* When the default locale is tr, make sure that the pattern can still be parsed. */
TestTurkishCasing()413 void TestMessageFormat::TestTurkishCasing()
414 {
415 UErrorCode err = U_ZERO_ERROR;
416 Locale saveDefaultLocale;
417 Locale::setDefault( Locale("tr"), err );
418
419 Formattable arguments[] = {
420 (int32_t)7,
421 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
422 "a disturbance in the Force"
423 };
424
425 UnicodeString result;
426 result = MessageFormat::format(
427 "At {1,TIME} on {1,DATE,SHORT}, there was {2} on planet {0,NUMBER,INTEGER}.",
428 arguments,
429 3,
430 result,
431 err);
432
433 if (U_FAILURE(err)) {
434 dataerrln("TestTurkishCasing #1 with error code %s", u_errorName(err));
435 return;
436 }
437
438 const UnicodeString expected(
439 "At 12:20:00 on 08.08.1997, there was a disturbance in the Force on planet 7.", "");
440 if (result != expected) {
441 errln("TestTurkishCasing failed on test");
442 errln( UnicodeString(" Result: ") + result );
443 errln( UnicodeString(" Expected: ") + expected );
444 }
445 Locale::setDefault( saveDefaultLocale, err );
446 }
447
testSimpleFormat()448 void TestMessageFormat::testSimpleFormat(/* char* par */)
449 {
450 logln("running TestMessageFormat::testSimpleFormat");
451
452 UErrorCode err = U_ZERO_ERROR;
453
454 Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
455 Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
456 Formattable testArgs3[] = {(int32_t)12, "MyDisk"};
457
458 MessageFormat* form = new MessageFormat(
459 "The disk \"{1}\" contains {0} file(s).", err);
460
461 UnicodeString string;
462 FieldPosition ignore(FieldPosition::DONT_CARE);
463 form->format(testArgs1, 2, string, ignore, err);
464 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 0 file(s).") {
465 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #1 - ") + u_errorName(err));
466 }
467
468 ignore.setField(FieldPosition::DONT_CARE);
469 string.remove();
470 form->format(testArgs2, 2, string, ignore, err);
471 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 1 file(s).") {
472 logln(string);
473 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #2")+string + " - " + u_errorName(err));
474 }
475
476 ignore.setField(FieldPosition::DONT_CARE);
477 string.remove();
478 form->format(testArgs3, 2, string, ignore, err);
479 if (U_FAILURE(err) || string != "The disk \"MyDisk\" contains 12 file(s).") {
480 dataerrln(UnicodeString("TestMessageFormat::testSimpleFormat failed on test #3")+string + " - " + u_errorName(err));
481 }
482
483 delete form;
484 }
485
testMsgFormatChoice()486 void TestMessageFormat::testMsgFormatChoice(/* char* par */)
487 {
488 logln("running TestMessageFormat::testMsgFormatChoice");
489
490 UErrorCode err = U_ZERO_ERROR;
491
492 MessageFormat* form = new MessageFormat("The disk \"{1}\" contains {0}.", err);
493 double filelimits[] = {0,1,2};
494 UnicodeString filepart[] = {"no files","one file","{0,number} files"};
495 ChoiceFormat* fileform = new ChoiceFormat(filelimits, filepart, 3);
496 form->setFormat(1,*fileform); // NOT zero, see below
497 //is the format adopted?
498
499 FieldPosition ignore(FieldPosition::DONT_CARE);
500 UnicodeString string;
501 Formattable testArgs1[] = {(int32_t)0, "MyDisk"};
502 form->format(testArgs1, 2, string, ignore, err);
503 if (string != "The disk \"MyDisk\" contains no files.") {
504 errln("TestMessageFormat::testMsgFormatChoice failed on test #1");
505 }
506
507 ignore.setField(FieldPosition::DONT_CARE);
508 string.remove();
509 Formattable testArgs2[] = {(int32_t)1, "MyDisk"};
510 form->format(testArgs2, 2, string, ignore, err);
511 if (string != "The disk \"MyDisk\" contains one file.") {
512 errln("TestMessageFormat::testMsgFormatChoice failed on test #2");
513 }
514
515 ignore.setField(FieldPosition::DONT_CARE);
516 string.remove();
517 Formattable testArgs3[] = {(int32_t)1273, "MyDisk"};
518 form->format(testArgs3, 2, string, ignore, err);
519 if (string != "The disk \"MyDisk\" contains 1,273 files.") {
520 dataerrln("TestMessageFormat::testMsgFormatChoice failed on test #3 - %s", u_errorName(err));
521 }
522
523 delete form;
524 delete fileform;
525 }
526
527
testMsgFormatPlural()528 void TestMessageFormat::testMsgFormatPlural(/* char* par */)
529 {
530 logln("running TestMessageFormat::testMsgFormatPlural");
531
532 UErrorCode err = U_ZERO_ERROR;
533 UnicodeString t1("{0, plural, one{C''est # fichier} other{Ce sont # fichiers}} dans la liste.");
534 UnicodeString t2("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
535 UnicodeString t3("There {0, plural, one{is # zavod}few{are {0, number,###.0} zavoda} other{are # zavodov}} in the directory.");
536 UnicodeString t4("There {argument, plural, one{is # zavod}few{are {argument, number,###.0} zavoda} other{are #zavodov}} in the directory.");
537 UnicodeString t5("{0, plural, one {{0, number,C''''est #,##0.0# fichier}} other {Ce sont # fichiers}} dans la liste.");
538 MessageFormat* mfNum = new MessageFormat(t1, Locale("fr"), err);
539 if (U_FAILURE(err)) {
540 dataerrln("TestMessageFormat::testMsgFormatPlural #1 - argumentIndex - %s", u_errorName(err));
541 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
542 return;
543 }
544 Formattable testArgs1((int32_t)0);
545 FieldPosition ignore(FieldPosition::DONT_CARE);
546 UnicodeString numResult1;
547 mfNum->format(&testArgs1, 1, numResult1, ignore, err);
548
549 MessageFormat* mfAlpha = new MessageFormat(t2, Locale("fr"), err);
550 UnicodeString argName[] = {UnicodeString("argument")};
551 UnicodeString argNameResult;
552 mfAlpha->format(argName, &testArgs1, 1, argNameResult, err);
553 if (U_FAILURE(err)) {
554 errln("TestMessageFormat::testMsgFormatPlural #1 - argumentName");
555 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #1 with error code ")+(int32_t)err);
556 delete mfNum;
557 return;
558 }
559 if ( numResult1 != argNameResult){
560 errln("TestMessageFormat::testMsgFormatPlural #1");
561 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
562 }
563 if ( numResult1 != UnicodeString("C\'est 0 fichier dans la liste.")) {
564 errln("TestMessageFormat::testMsgFormatPlural #1");
565 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
566 }
567 err = U_ZERO_ERROR;
568
569 delete mfNum;
570 delete mfAlpha;
571
572 MessageFormat* mfNum2 = new MessageFormat(t3, Locale("ru"), err);
573 numResult1.remove();
574 Formattable testArgs2((int32_t)4);
575 mfNum2->format(&testArgs2, 1, numResult1, ignore, err);
576 MessageFormat* mfAlpha2 = new MessageFormat(t4, Locale("ru"), err);
577 argNameResult.remove();
578 mfAlpha2->format(argName, &testArgs2, 1, argNameResult, err);
579
580 if (U_FAILURE(err)) {
581 errln("TestMessageFormat::testMsgFormatPlural #2 - argumentName");
582 logln(UnicodeString("TestMessageFormat::testMsgFormatPlural #2 with error code ")+(int32_t)err);
583 delete mfNum2;
584 return;
585 }
586 if ( numResult1 != argNameResult){
587 errln("TestMessageFormat::testMsgFormatPlural #2");
588 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
589 }
590 if ( numResult1 != UnicodeString("There are 4,0 zavoda in the directory.")) {
591 errln("TestMessageFormat::testMsgFormatPlural #2");
592 logln(UnicodeString("The results of argumentName and argumentIndex are not the same."));
593 }
594
595 delete mfNum2;
596 delete mfAlpha2;
597
598 // nested formats
599 err = U_ZERO_ERROR;
600 MessageFormat* msgFmt = new MessageFormat(t5, Locale("fr"), err);
601 if (U_FAILURE(err)) {
602 errln("TestMessageFormat::test nested PluralFormat with argumentName");
603 logln(UnicodeString("TestMessageFormat::test nested PluralFormat with error code ")+(int32_t)err);
604 delete msgFmt;
605 return;
606 }
607 Formattable testArgs3((int32_t)0);
608 argNameResult.remove();
609 msgFmt->format(&testArgs3, 1, argNameResult, ignore, err);
610 if (U_FAILURE(err)) {
611 errln("TestMessageFormat::test nested PluralFormat with argumentName");
612 }
613 if ( argNameResult!= UnicodeString("C'est 0,0 fichier dans la liste.")) {
614 errln(UnicodeString("TestMessageFormat::test nested named PluralFormat."));
615 logln(UnicodeString("The unexpected nested named PluralFormat."));
616 }
617 delete msgFmt;
618 }
619
internalFormat(MessageFormat * msgFmt,Formattable * args,int32_t numOfArgs,UnicodeString expected,char * errMsg)620 void TestMessageFormat::internalFormat(MessageFormat* msgFmt ,
621 Formattable* args , int32_t numOfArgs ,
622 UnicodeString expected ,char* errMsg)
623 {
624 UnicodeString result;
625 FieldPosition ignore(FieldPosition::DONT_CARE);
626 UErrorCode status = U_ZERO_ERROR;
627
628 //Format with passed arguments
629 msgFmt->format( args , numOfArgs , result, ignore, status);
630 if (U_FAILURE(status)) {
631 dataerrln( "%serror while formatting with ErrorCode as %s" ,errMsg, u_errorName(status) );
632 }
633 //Compare expected with obtained result
634 if ( result!= expected ) {
635 UnicodeString err = UnicodeString(errMsg);
636 err+= UnicodeString(":Unexpected Result \n Expected: " + expected + "\n Obtained: " + result + "\n");
637 dataerrln(err);
638 }
639 }
640
internalCreate(UnicodeString pattern,Locale locale,UErrorCode & status,char * errMsg)641 MessageFormat* TestMessageFormat::internalCreate(
642 UnicodeString pattern ,Locale locale ,UErrorCode &status , char* errMsg)
643 {
644 //Create the MessageFormat with simple SelectFormat
645 MessageFormat* msgFmt = new MessageFormat(pattern, locale, status);
646 if (U_FAILURE(status)) {
647 dataerrln( "%serror while constructing with ErrorCode as %s" ,errMsg, u_errorName(status) );
648 logln(UnicodeString("TestMessageFormat::testMsgFormatSelect #1 with error code ")+(int32_t)status);
649 return NULL;
650 }
651 return msgFmt;
652 }
653
testMsgFormatSelect()654 void TestMessageFormat::testMsgFormatSelect(/* char* par */)
655 {
656 logln("running TestMessageFormat::testMsgFormatSelect");
657
658 UErrorCode err = U_ZERO_ERROR;
659 //French Pattern
660 UnicodeString t1("{0} est {1, select, female {all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
661
662 err = U_ZERO_ERROR;
663 //Create the MessageFormat with simple French pattern
664 MessageFormat* msgFmt1 = internalCreate(t1.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t1");
665 if (!U_FAILURE(err)) {
666 //Arguments
667 Formattable testArgs10[] = {"Kirti","female"};
668 Formattable testArgs11[] = {"Victor","other"};
669 Formattable testArgs12[] = {"Ash","unknown"};
670 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
671 UnicodeString exp[] = {
672 "Kirti est all\\u00E9e \\u00E0 Paris." ,
673 "Victor est all\\u00E9 \\u00E0 Paris.",
674 "Ash est all\\u00E9 \\u00E0 Paris."};
675 //Format
676 for( int i=0; i< 3; i++){
677 internalFormat( msgFmt1 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t1");
678 }
679 }
680 delete msgFmt1;
681
682 //Quoted French Pattern
683 UnicodeString t2("{0} est {1, select, female {all\\u00E9e c''est} other {all\\u00E9 c''est}} \\u00E0 Paris.");
684 err = U_ZERO_ERROR;
685 //Create the MessageFormat with Quoted French pattern
686 MessageFormat* msgFmt2 = internalCreate(t2.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t2");
687 if (!U_FAILURE(err)) {
688 //Arguments
689 Formattable testArgs10[] = {"Kirti","female"};
690 Formattable testArgs11[] = {"Victor","other"};
691 Formattable testArgs12[] = {"Ash","male"};
692 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
693 UnicodeString exp[] = {
694 "Kirti est all\\u00E9e c'est \\u00E0 Paris." ,
695 "Victor est all\\u00E9 c'est \\u00E0 Paris.",
696 "Ash est all\\u00E9 c'est \\u00E0 Paris."};
697 //Format
698 for( int i=0; i< 3; i++){
699 internalFormat( msgFmt2 , testArgs[i], 2, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t2");
700 }
701 }
702 delete msgFmt2;
703
704 //English Pattern
705 UnicodeString t3("{0, select , male {MALE FR company} female {FEMALE FR company} other {FR otherValue}} published new books.");
706 err = U_ZERO_ERROR;
707 //Create the MessageFormat with English pattern
708 MessageFormat* msgFmt3 = internalCreate(t3, Locale("en"),err,(char*)"From TestMessageFormat::TestSelectFormat create t3");
709 if (!U_FAILURE(err)) {
710 //Arguments
711 Formattable testArgs10[] = {"female"};
712 Formattable testArgs11[] = {"other"};
713 Formattable testArgs12[] = {"male"};
714 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
715 UnicodeString exp[] = {
716 "FEMALE FR company published new books." ,
717 "FR otherValue published new books.",
718 "MALE FR company published new books."};
719 //Format
720 for( int i=0; i< 3; i++){
721 internalFormat( msgFmt3 , testArgs[i], 1, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t3");
722 }
723 }
724 delete msgFmt3;
725
726 //Nested patterns with plural, number ,choice ,select format etc.
727 //Select Format with embedded number format
728 UnicodeString t4("{0} est {1, select, female {{2,number,integer} all\\u00E9e} other {all\\u00E9}} \\u00E0 Paris.");
729 //Create the MessageFormat with Select Format with embedded number format (nested pattern)
730 MessageFormat* msgFmt4 = internalCreate(t4.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t4");
731 if (!U_FAILURE(err)) {
732 //Arguments
733 Formattable testArgs10[] = {"Kirti","female",(int32_t)6};
734 Formattable testArgs11[] = {"Kirti","female",100.100};
735 Formattable testArgs12[] = {"Kirti","other",(int32_t)6};
736 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12};
737 UnicodeString exp[] = {
738 "Kirti est 6 all\\u00E9e \\u00E0 Paris." ,
739 "Kirti est 100 all\\u00E9e \\u00E0 Paris.",
740 "Kirti est all\\u00E9 \\u00E0 Paris."};
741 //Format
742 for( int i=0; i< 3; i++){
743 internalFormat( msgFmt4 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t4");
744 }
745 }
746 delete msgFmt4;
747
748 err = U_ZERO_ERROR;
749 //Plural format with embedded select format
750 UnicodeString t5("{0} {1, plural, one {est {2, select, female {all\\u00E9e} other {all\\u00E9}}} other {sont {2, select, female {all\\u00E9es} other {all\\u00E9s}}}} \\u00E0 Paris.");
751 err = U_ZERO_ERROR;
752 //Create the MessageFormat with Plural format with embedded select format(nested pattern)
753 MessageFormat* msgFmt5 = internalCreate(t5.unescape(), Locale("fr"),err,(char*)"From TestMessageFormat::TestSelectFormat create t5");
754 if (!U_FAILURE(err)) {
755 //Arguments
756 Formattable testArgs10[] = {"Kirti",(int32_t)6,"female"};
757 Formattable testArgs11[] = {"Kirti",(int32_t)1,"female"};
758 Formattable testArgs12[] = {"Ash",(int32_t)1,"other"};
759 Formattable testArgs13[] = {"Ash",(int32_t)5,"other"};
760 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13};
761 UnicodeString exp[] = {
762 "Kirti sont all\\u00E9es \\u00E0 Paris." ,
763 "Kirti est all\\u00E9e \\u00E0 Paris.",
764 "Ash est all\\u00E9 \\u00E0 Paris.",
765 "Ash sont all\\u00E9s \\u00E0 Paris."};
766 //Format
767 for( int i=0; i< 4; i++){
768 internalFormat( msgFmt5 , testArgs[i], 3, exp[i].unescape() ,(char*)"From TestMessageFormat::testSelectFormat format t5");
769 }
770 }
771 delete msgFmt5;
772
773 err = U_ZERO_ERROR;
774 //Select, plural, and number formats heavily nested
775 UnicodeString t6("{0} und {1, select, female {{2, plural, one {{3, select, female {ihre Freundin} other {ihr Freund}} } other {ihre {2, number, integer} {3, select, female {Freundinnen} other {Freunde}} } }} other{{2, plural, one {{3, select, female {seine Freundin} other {sein Freund}}} other {seine {2, number, integer} {3, select, female {Freundinnen} other {Freunde}}}}} } gingen nach Paris.");
776 //Create the MessageFormat with Select, plural, and number formats heavily nested
777 MessageFormat* msgFmt6 = internalCreate(t6, Locale("de"),err,(char*)"From TestMessageFormat::TestSelectFormat create t6");
778 if (!U_FAILURE(err)) {
779 //Arguments
780 Formattable testArgs10[] = {"Kirti","other",(int32_t)1,"other"};
781 Formattable testArgs11[] = {"Kirti","other",(int32_t)6,"other"};
782 Formattable testArgs12[] = {"Kirti","other",(int32_t)1,"female"};
783 Formattable testArgs13[] = {"Kirti","other",(int32_t)3,"female"};
784 Formattable testArgs14[] = {"Kirti","female",(int32_t)1,"female"};
785 Formattable testArgs15[] = {"Kirti","female",(int32_t)5,"female"};
786 Formattable testArgs16[] = {"Kirti","female",(int32_t)1,"other"};
787 Formattable testArgs17[] = {"Kirti","female",(int32_t)5,"other"};
788 Formattable testArgs18[] = {"Kirti","mixed",(int32_t)1,"mixed"};
789 Formattable testArgs19[] = {"Kirti","mixed",(int32_t)1,"other"};
790 Formattable testArgs20[] = {"Kirti","female",(int32_t)1,"mixed"};
791 Formattable testArgs21[] = {"Kirti","mixed",(int32_t)5,"mixed"};
792 Formattable testArgs22[] = {"Kirti","mixed",(int32_t)5,"other"};
793 Formattable testArgs23[] = {"Kirti","female",(int32_t)5,"mixed"};
794 Formattable* testArgs[] = {testArgs10,testArgs11,testArgs12,testArgs13,
795 testArgs14,testArgs15,testArgs16,testArgs17,
796 testArgs18,testArgs19,testArgs20,testArgs21,
797 testArgs22,testArgs23 };
798 UnicodeString exp[] = {
799 "Kirti und sein Freund gingen nach Paris." ,
800 "Kirti und seine 6 Freunde gingen nach Paris." ,
801 "Kirti und seine Freundin gingen nach Paris.",
802 "Kirti und seine 3 Freundinnen gingen nach Paris.",
803 "Kirti und ihre Freundin gingen nach Paris.",
804 "Kirti und ihre 5 Freundinnen gingen nach Paris.",
805 "Kirti und ihr Freund gingen nach Paris.",
806 "Kirti und ihre 5 Freunde gingen nach Paris.",
807 "Kirti und sein Freund gingen nach Paris.",
808 "Kirti und sein Freund gingen nach Paris.",
809 "Kirti und ihr Freund gingen nach Paris.",
810 "Kirti und seine 5 Freunde gingen nach Paris." ,
811 "Kirti und seine 5 Freunde gingen nach Paris." ,
812 "Kirti und ihre 5 Freunde gingen nach Paris."
813 };
814 //Format
815 for( int i=0; i< 14; i++){
816 internalFormat( msgFmt6 , testArgs[i], 4, exp[i] ,(char*)"From TestMessageFormat::testSelectFormat format t6");
817 }
818 }
819 delete msgFmt6;
820 }
821
822 //---------------------------------
823 // API Tests
824 //---------------------------------
825
testCopyConstructor()826 void TestMessageFormat::testCopyConstructor()
827 {
828 UErrorCode success = U_ZERO_ERROR;
829 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
830 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
831 MessageFormat *y = 0;
832 y = new MessageFormat(*x);
833 if ( (*x == *y) &&
834 (*x != *z) &&
835 (*y != *z) )
836 logln("First test (operator ==): Passed!");
837 else {
838 errln("TestMessageFormat::testCopyConstructor failed #1");
839 logln("First test (operator ==): Failed!");
840 }
841 if ( ((*x == *y) && (*y == *x)) &&
842 ((*x != *z) && (*z != *x)) &&
843 ((*y != *z) && (*z != *y)) )
844 logln("Second test (equals): Passed!");
845 else {
846 errln("TestMessageFormat::testCopyConstructor failed #2");
847 logln("Second test (equals): Failed!");
848 }
849
850 delete x;
851 delete y;
852 delete z;
853 }
854
855
testAssignment()856 void TestMessageFormat::testAssignment()
857 {
858 UErrorCode success = U_ZERO_ERROR;
859 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
860 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
861 MessageFormat *y = new MessageFormat("There are {0} files on {1} created", success);
862 *y = *x;
863 if ( (*x == *y) &&
864 (*x != *z) &&
865 (*y != *z) )
866 logln("First test (operator ==): Passed!");
867 else {
868 errln( "TestMessageFormat::testAssignment failed #1");
869 logln("First test (operator ==): Failed!");
870 }
871 if ( ((*x == *y) && (*y == *x)) &&
872 ((*x != *z) && (*z != *x)) &&
873 ((*y != *z) && (*z != *y)) )
874 logln("Second test (equals): Passed!");
875 else {
876 errln("TestMessageFormat::testAssignment failed #2");
877 logln("Second test (equals): Failed!");
878 }
879
880 delete x;
881 delete y;
882 delete z;
883 }
884
testClone()885 void TestMessageFormat::testClone()
886 {
887 UErrorCode success = U_ZERO_ERROR;
888 MessageFormat *x = new MessageFormat("There are {0} files on {1}", success);
889 MessageFormat *z = new MessageFormat("There are {0} files on {1} created", success);
890 MessageFormat *y = 0;
891 y = (MessageFormat*)x->clone();
892 if ( (*x == *y) &&
893 (*x != *z) &&
894 (*y != *z) )
895 logln("First test (operator ==): Passed!");
896 else {
897 errln("TestMessageFormat::testClone failed #1");
898 logln("First test (operator ==): Failed!");
899 }
900 if ( ((*x == *y) && (*y == *x)) &&
901 ((*x != *z) && (*z != *x)) &&
902 ((*y != *z) && (*z != *y)) )
903 logln("Second test (equals): Passed!");
904 else {
905 errln("TestMessageFormat::testClone failed #2");
906 logln("Second test (equals): Failed!");
907 }
908
909 delete x;
910 delete y;
911 delete z;
912 }
913
testEquals()914 void TestMessageFormat::testEquals()
915 {
916 UErrorCode success = U_ZERO_ERROR;
917 MessageFormat x("There are {0} files on {1}", success);
918 MessageFormat y("There are {0} files on {1}", success);
919 if (!(x == y)) {
920 errln( "TestMessageFormat::testEquals failed #1");
921 logln("First test (operator ==): Failed!");
922 }
923
924 }
925
testNotEquals()926 void TestMessageFormat::testNotEquals()
927 {
928 UErrorCode success = U_ZERO_ERROR;
929 MessageFormat x("There are {0} files on {1}", success);
930 MessageFormat y(x);
931 y.setLocale(Locale("fr"));
932 if (!(x != y)) {
933 errln( "TestMessageFormat::testEquals failed #1");
934 logln("First test (operator !=): Failed!");
935 }
936 y = x;
937 y.applyPattern("There are {0} files on {1} the disk", success);
938 if (!(x != y)) {
939 errln( "TestMessageFormat::testEquals failed #1");
940 logln("Second test (operator !=): Failed!");
941 }
942 }
943
944
testSetLocale()945 void TestMessageFormat::testSetLocale()
946 {
947 UErrorCode err = U_ZERO_ERROR;
948 GregorianCalendar cal(err);
949 Formattable arguments[] = {
950 456.83,
951 Formattable(UDate(8.71068e+011), Formattable::kIsDate),
952 "deposit"
953 };
954
955 UnicodeString result;
956
957 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
958 UnicodeString formatStr = "At <time> on {1,date}, you made a {2} of {0,number,currency}.";
959 // {sfb} to get $, would need Locale::US, not Locale::ENGLISH
960 // Just use unlocalized currency symbol.
961 //UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of $456.83.";
962 UnicodeString compareStrEng = "At <time> on Aug 8, 1997, you made a deposit of ";
963 compareStrEng += (UChar) 0x00a4;
964 compareStrEng += "456.83.";
965 // {sfb} to get DM, would need Locale::GERMANY, not Locale::GERMAN
966 // Just use unlocalized currency symbol.
967 //UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of 456,83 DM.";
968 UnicodeString compareStrGer = "At <time> on 08.08.1997, you made a deposit of ";
969 compareStrGer += "456,83";
970 compareStrGer += (UChar) 0x00a0;
971 compareStrGer += (UChar) 0x00a4;
972 compareStrGer += ".";
973
974 MessageFormat msg( formatStr, err);
975 result = "";
976 FieldPosition pos(0);
977 result = msg.format(
978 arguments,
979 3,
980 result,
981 pos,
982 err);
983
984 logln(result);
985 if (result != compareStrEng) {
986 dataerrln("*** MSG format err. - %s", u_errorName(err));
987 }
988
989 msg.setLocale(Locale::getEnglish());
990 UBool getLocale_ok = TRUE;
991 if (msg.getLocale() != Locale::getEnglish()) {
992 errln("*** MSG getLocal err.");
993 getLocale_ok = FALSE;
994 }
995
996 msg.setLocale(Locale::getGerman());
997
998 if (msg.getLocale() != Locale::getGerman()) {
999 errln("*** MSG getLocal err.");
1000 getLocale_ok = FALSE;
1001 }
1002
1003 msg.applyPattern( formatStr, err);
1004
1005 pos.setField(0);
1006 result = "";
1007 result = msg.format(
1008 arguments,
1009 3,
1010 result,
1011 pos,
1012 err);
1013
1014 logln(result);
1015 if (result == compareStrGer) {
1016 logln("MSG setLocale tested.");
1017 }else{
1018 dataerrln( "*** MSG setLocale err. - %s", u_errorName(err));
1019 }
1020
1021 if (getLocale_ok) {
1022 logln("MSG getLocale tested.");
1023 }
1024 }
1025
testFormat()1026 void TestMessageFormat::testFormat()
1027 {
1028 UErrorCode err = U_ZERO_ERROR;
1029 GregorianCalendar cal(err);
1030
1031 const Formattable ftarray[] =
1032 {
1033 Formattable( UDate(8.71068e+011), Formattable::kIsDate )
1034 };
1035 const int32_t ft_cnt = sizeof(ftarray) / sizeof(Formattable);
1036 Formattable ft_arr( ftarray, ft_cnt );
1037
1038 Formattable* fmt = new Formattable(UDate(8.71068e+011), Formattable::kIsDate);
1039
1040 UnicodeString result;
1041
1042 //UnicodeString formatStr = "At {1,time} on {1,date}, you made a {2} of {0,number,currency}.";
1043 UnicodeString formatStr = "On {0,date}, it began.";
1044 UnicodeString compareStr = "On Aug 8, 1997, it began.";
1045
1046 err = U_ZERO_ERROR;
1047 MessageFormat msg( formatStr, err);
1048 FieldPosition fp(0);
1049
1050 result = "";
1051 fp = 0;
1052 result = msg.format(
1053 *fmt,
1054 result,
1055 //FieldPosition(0),
1056 fp,
1057 err);
1058
1059 if (err != U_ILLEGAL_ARGUMENT_ERROR) {
1060 dataerrln("*** MSG format without expected error code. - %s", u_errorName(err));
1061 }
1062 err = U_ZERO_ERROR;
1063
1064 result = "";
1065 fp = 0;
1066 result = msg.format(
1067 ft_arr,
1068 result,
1069 //FieldPosition(0),
1070 fp,
1071 err);
1072
1073 logln("MSG format( Formattable&, ... ) expected:" + compareStr);
1074 logln("MSG format( Formattable&, ... ) result:" + result);
1075 if (result != compareStr) {
1076 dataerrln("*** MSG format( Formattable&, .... ) err. - %s", u_errorName(err));
1077 }else{
1078 logln("MSG format( Formattable&, ... ) tested.");
1079 }
1080
1081 delete fmt;
1082
1083 }
1084
testParse()1085 void TestMessageFormat::testParse()
1086 {
1087 UErrorCode err = U_ZERO_ERROR;
1088 int32_t count;
1089 UnicodeString msgFormatString = "{0} =sep= {1}";
1090 MessageFormat msg( msgFormatString, err);
1091 UnicodeString source = "abc =sep= def";
1092 UnicodeString tmp1, tmp2;
1093
1094 Formattable* fmt_arr = msg.parse( source, count, err );
1095 if (U_FAILURE(err) || (!fmt_arr)) {
1096 errln("*** MSG parse (ustring, count, err) error.");
1097 }else{
1098 logln("MSG parse -- count: %d", count);
1099 if (count != 2) {
1100 errln("*** MSG parse (ustring, count, err) count err.");
1101 }else{
1102 if ((fmt_arr[0].getType() == Formattable::kString)
1103 && (fmt_arr[1].getType() == Formattable::kString)
1104 && (fmt_arr[0].getString(tmp1) == "abc")
1105 && (fmt_arr[1].getString(tmp2) == "def")) {
1106 logln("MSG parse (ustring, count, err) tested.");
1107 }else{
1108 errln("*** MSG parse (ustring, count, err) result err.");
1109 }
1110 }
1111 }
1112 delete[] fmt_arr;
1113
1114 ParsePosition pp(0);
1115
1116 fmt_arr = msg.parse( source, pp, count );
1117 if ((pp == 0) || (!fmt_arr)) {
1118 errln("*** MSG parse (ustring, parsepos., count) error.");
1119 }else{
1120 logln("MSG parse -- count: %d", count);
1121 if (count != 2) {
1122 errln("*** MSG parse (ustring, parsepos., count) count err.");
1123 }else{
1124 if ((fmt_arr[0].getType() == Formattable::kString)
1125 && (fmt_arr[1].getType() == Formattable::kString)
1126 && (fmt_arr[0].getString(tmp1) == "abc")
1127 && (fmt_arr[1].getString(tmp2) == "def")) {
1128 logln("MSG parse (ustring, parsepos., count) tested.");
1129 }else{
1130 errln("*** MSG parse (ustring, parsepos., count) result err.");
1131 }
1132 }
1133 }
1134 delete[] fmt_arr;
1135
1136 pp = 0;
1137 Formattable fmta;
1138
1139 msg.parseObject( source, fmta, pp );
1140 if (pp == 0) {
1141 errln("*** MSG parse (ustring, Formattable, parsepos ) error.");
1142 }else{
1143 logln("MSG parse -- count: %d", count);
1144 fmta.getArray(count);
1145 if (count != 2) {
1146 errln("*** MSG parse (ustring, Formattable, parsepos ) count err.");
1147 }else{
1148 if ((fmta[0].getType() == Formattable::kString)
1149 && (fmta[1].getType() == Formattable::kString)
1150 && (fmta[0].getString(tmp1) == "abc")
1151 && (fmta[1].getString(tmp2) == "def")) {
1152 logln("MSG parse (ustring, Formattable, parsepos ) tested.");
1153 }else{
1154 errln("*** MSG parse (ustring, Formattable, parsepos ) result err.");
1155 }
1156 }
1157 }
1158 }
1159
1160
testAdopt()1161 void TestMessageFormat::testAdopt()
1162 {
1163 UErrorCode err = U_ZERO_ERROR;
1164
1165 UnicodeString formatStr("{0,date},{1},{2,number}", "");
1166 UnicodeString formatStrChange("{0,number},{1,number},{2,date}", "");
1167 err = U_ZERO_ERROR;
1168 MessageFormat msg( formatStr, err);
1169 MessageFormat msgCmp( formatStr, err);
1170 int32_t count, countCmp;
1171 const Format** formats = msg.getFormats(count);
1172 const Format** formatsCmp = msgCmp.getFormats(countCmp);
1173 const Format** formatsChg = 0;
1174 const Format** formatsAct = 0;
1175 int32_t countAct;
1176 const Format* a;
1177 const Format* b;
1178 UnicodeString patCmp;
1179 UnicodeString patAct;
1180 Format** formatsToAdopt;
1181
1182 if (!formats || !formatsCmp || (count <= 0) || (count != countCmp)) {
1183 dataerrln("Error getting Formats");
1184 return;
1185 }
1186
1187 int32_t i;
1188
1189 for (i = 0; i < count; i++) {
1190 a = formats[i];
1191 b = formatsCmp[i];
1192 if ((a != NULL) && (b != NULL)) {
1193 if (*a != *b) {
1194 errln("a != b");
1195 return;
1196 }
1197 }else if ((a != NULL) || (b != NULL)) {
1198 errln("(a != NULL) || (b != NULL)");
1199 return;
1200 }
1201 }
1202
1203 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1204 int32_t countChg;
1205 formatsChg = msg.getFormats(countChg); // tested function
1206 if (!formatsChg || (countChg != count)) {
1207 errln("Error getting Formats");
1208 return;
1209 }
1210
1211 UBool diff;
1212 diff = TRUE;
1213 for (i = 0; i < count; i++) {
1214 a = formatsChg[i];
1215 b = formatsCmp[i];
1216 if ((a != NULL) && (b != NULL)) {
1217 if (*a == *b) {
1218 logln("formatsChg == formatsCmp at index %d", i);
1219 diff = FALSE;
1220 }
1221 }
1222 }
1223 if (!diff) {
1224 errln("*** MSG getFormats diff err.");
1225 return;
1226 }
1227
1228 logln("MSG getFormats tested.");
1229
1230 msg.setFormats( formatsCmp, countCmp ); //tested function
1231
1232 formatsAct = msg.getFormats(countAct);
1233 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1234 errln("Error getting Formats");
1235 return;
1236 }
1237
1238 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1239 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1240
1241 for (i = 0; i < countAct; i++) {
1242 a = formatsAct[i];
1243 b = formatsCmp[i];
1244 if ((a != NULL) && (b != NULL)) {
1245 if (*a != *b) {
1246 logln("formatsAct != formatsCmp at index %d", i);
1247 errln("a != b");
1248 return;
1249 }
1250 }else if ((a != NULL) || (b != NULL)) {
1251 errln("(a != NULL) || (b != NULL)");
1252 return;
1253 }
1254 }
1255 logln("MSG setFormats tested.");
1256
1257 //----
1258
1259 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1260
1261 formatsToAdopt = new Format* [countCmp];
1262 if (!formatsToAdopt) {
1263 errln("memory allocation error");
1264 return;
1265 }
1266
1267 for (i = 0; i < countCmp; i++) {
1268 if (formatsCmp[i] == NULL) {
1269 formatsToAdopt[i] = NULL;
1270 }else{
1271 formatsToAdopt[i] = formatsCmp[i]->clone();
1272 if (!formatsToAdopt[i]) {
1273 errln("Can't clone format at index %d", i);
1274 return;
1275 }
1276 }
1277 }
1278 msg.adoptFormats( formatsToAdopt, countCmp ); // function to test
1279 delete[] formatsToAdopt;
1280
1281 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1282 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1283
1284 formatsAct = msg.getFormats(countAct);
1285 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1286 errln("Error getting Formats");
1287 return;
1288 }
1289
1290 for (i = 0; i < countAct; i++) {
1291 a = formatsAct[i];
1292 b = formatsCmp[i];
1293 if ((a != NULL) && (b != NULL)) {
1294 if (*a != *b) {
1295 errln("a != b");
1296 return;
1297 }
1298 }else if ((a != NULL) || (b != NULL)) {
1299 errln("(a != NULL) || (b != NULL)");
1300 return;
1301 }
1302 }
1303 logln("MSG adoptFormats tested.");
1304
1305 //---- adoptFormat
1306
1307 msg.applyPattern( formatStrChange, err ); //set msg formats to something different
1308
1309 formatsToAdopt = new Format* [countCmp];
1310 if (!formatsToAdopt) {
1311 errln("memory allocation error");
1312 return;
1313 }
1314
1315 for (i = 0; i < countCmp; i++) {
1316 if (formatsCmp[i] == NULL) {
1317 formatsToAdopt[i] = NULL;
1318 }else{
1319 formatsToAdopt[i] = formatsCmp[i]->clone();
1320 if (!formatsToAdopt[i]) {
1321 errln("Can't clone format at index %d", i);
1322 return;
1323 }
1324 }
1325 }
1326
1327 for ( i = 0; i < countCmp; i++ ) {
1328 msg.adoptFormat( i, formatsToAdopt[i] ); // function to test
1329 }
1330 delete[] formatsToAdopt; // array itself not needed in this case;
1331
1332 assertEquals("msgCmp.toPattern()", formatStr, msgCmp.toPattern(patCmp.remove()));
1333 assertEquals("msg.toPattern()", formatStr, msg.toPattern(patAct.remove()));
1334
1335 formatsAct = msg.getFormats(countAct);
1336 if (!formatsAct || (countAct <=0) || (countAct != countCmp)) {
1337 errln("Error getting Formats");
1338 return;
1339 }
1340
1341 for (i = 0; i < countAct; i++) {
1342 a = formatsAct[i];
1343 b = formatsCmp[i];
1344 if ((a != NULL) && (b != NULL)) {
1345 if (*a != *b) {
1346 errln("a != b");
1347 return;
1348 }
1349 }else if ((a != NULL) || (b != NULL)) {
1350 errln("(a != NULL) || (b != NULL)");
1351 return;
1352 }
1353 }
1354 logln("MSG adoptFormat tested.");
1355 }
1356
1357 // This test is a regression test for a fixed bug in the copy constructor.
1358 // It is kept as a global function rather than as a method since the test depends on memory values.
1359 // (At least before the bug was fixed, whether it showed up or not depended on memory contents,
1360 // which is probably why it didn't show up in the regular test for the copy constructor.)
1361 // For this reason, the test isn't changed even though it contains function calls whose results are
1362 // not tested and had no problems. Actually, the test failed by *crashing*.
_testCopyConstructor2()1363 static void _testCopyConstructor2()
1364 {
1365 UErrorCode status = U_ZERO_ERROR;
1366 UnicodeString formatStr("Hello World on {0,date,full}", "");
1367 UnicodeString resultStr(" ", "");
1368 UnicodeString result;
1369 FieldPosition fp(0);
1370 UDate d = Calendar::getNow();
1371 const Formattable fargs( d, Formattable::kIsDate );
1372
1373 MessageFormat* fmt1 = new MessageFormat( formatStr, status );
1374 MessageFormat* fmt2 = new MessageFormat( *fmt1 );
1375 MessageFormat* fmt3;
1376 MessageFormat* fmt4;
1377
1378 if (fmt1 == NULL) it_err("testCopyConstructor2: (fmt1 != NULL)");
1379
1380 result = fmt1->format( &fargs, 1, resultStr, fp, status );
1381
1382 if (fmt2 == NULL) it_err("testCopyConstructor2: (fmt2 != NULL)");
1383
1384 fmt3 = (MessageFormat*) fmt1->clone();
1385 fmt4 = (MessageFormat*) fmt2->clone();
1386
1387 if (fmt3 == NULL) it_err("testCopyConstructor2: (fmt3 != NULL)");
1388 if (fmt4 == NULL) it_err("testCopyConstructor2: (fmt4 != NULL)");
1389
1390 result = fmt1->format( &fargs, 1, resultStr, fp, status );
1391 result = fmt2->format( &fargs, 1, resultStr, fp, status );
1392 result = fmt3->format( &fargs, 1, resultStr, fp, status );
1393 result = fmt4->format( &fargs, 1, resultStr, fp, status );
1394 delete fmt1;
1395 delete fmt2;
1396 delete fmt3;
1397 delete fmt4;
1398 }
1399
testCopyConstructor2()1400 void TestMessageFormat::testCopyConstructor2() {
1401 _testCopyConstructor2();
1402 }
1403
1404 /**
1405 * Verify that MessageFormat accomodates more than 10 arguments and
1406 * more than 10 subformats.
1407 */
TestUnlimitedArgsAndSubformats()1408 void TestMessageFormat::TestUnlimitedArgsAndSubformats() {
1409 UErrorCode ec = U_ZERO_ERROR;
1410 const UnicodeString pattern =
1411 "On {0,date} (aka {0,date,short}, aka {0,date,long}) "
1412 "at {0,time} (aka {0,time,short}, aka {0,time,long}) "
1413 "there were {1,number} werjes "
1414 "(a {3,number,percent} increase over {2,number}) "
1415 "despite the {4}''s efforts "
1416 "and to delight of {5}, {6}, {7}, {8}, {9}, and {10} {11}.";
1417 MessageFormat msg(pattern, ec);
1418 if (U_FAILURE(ec)) {
1419 dataerrln("FAIL: constructor failed - %s", u_errorName(ec));
1420 return;
1421 }
1422
1423 const Formattable ARGS[] = {
1424 Formattable(UDate(1e13), Formattable::kIsDate),
1425 Formattable((int32_t)1303),
1426 Formattable((int32_t)1202),
1427 Formattable(1303.0/1202 - 1),
1428 Formattable("Glimmung"),
1429 Formattable("the printers"),
1430 Formattable("Nick"),
1431 Formattable("his father"),
1432 Formattable("his mother"),
1433 Formattable("the spiddles"),
1434 Formattable("of course"),
1435 Formattable("Horace"),
1436 };
1437 const int32_t ARGS_LENGTH = sizeof(ARGS) / sizeof(ARGS[0]);
1438 Formattable ARGS_OBJ(ARGS, ARGS_LENGTH);
1439
1440 UnicodeString expected =
1441 "On Nov 20, 2286 (aka 11/20/86, aka November 20, 2286) "
1442 "at 9:46:40 AM (aka 9:46 AM, aka 9:46:40 AM PST) "
1443 "there were 1,303 werjes "
1444 "(a 8% increase over 1,202) "
1445 "despite the Glimmung's efforts "
1446 "and to delight of the printers, Nick, his father, "
1447 "his mother, the spiddles, and of course Horace.";
1448 UnicodeString result;
1449 msg.format(ARGS_OBJ, result, ec);
1450 if (result == expected) {
1451 logln(result);
1452 } else {
1453 errln((UnicodeString)"FAIL: Got " + result +
1454 ", expected " + expected);
1455 }
1456 }
1457
1458 // test RBNF extensions to message format
TestRBNF(void)1459 void TestMessageFormat::TestRBNF(void) {
1460 // WARNING: this depends on the RBNF formats for en_US
1461 Locale locale("en", "US", "");
1462
1463 UErrorCode ec = U_ZERO_ERROR;
1464
1465 UnicodeString values[] = {
1466 // decimal values do not format completely for ordinal or duration, and
1467 // do not always parse, so do not include them
1468 "0", "1", "12", "100", "123", "1001", "123,456", "-17",
1469 };
1470 int32_t values_count = sizeof(values)/sizeof(values[0]);
1471
1472 UnicodeString formats[] = {
1473 "There are {0,spellout} files to search.",
1474 "There are {0,spellout,%simplified} files to search.",
1475 "The bogus spellout {0,spellout,%BOGUS} files behaves like the default.",
1476 "This is the {0,ordinal} file to search.", // TODO fix bug, ordinal does not parse
1477 "Searching this file will take {0,duration} to complete.",
1478 "Searching this file will take {0,duration,%with-words} to complete.",
1479 };
1480 int32_t formats_count = sizeof(formats)/sizeof(formats[0]);
1481
1482 Formattable args[1];
1483
1484 NumberFormat* numFmt = NumberFormat::createInstance(locale, ec);
1485 if (U_FAILURE(ec)) {
1486 dataerrln("Error calling NumberFormat::createInstance()");
1487 return;
1488 }
1489
1490 for (int i = 0; i < formats_count; ++i) {
1491 MessageFormat* fmt = new MessageFormat(formats[i], locale, ec);
1492 logln((UnicodeString)"Testing format pattern: '" + formats[i] + "'");
1493
1494 for (int j = 0; j < values_count; ++j) {
1495 ec = U_ZERO_ERROR;
1496 numFmt->parse(values[j], args[0], ec);
1497 if (U_FAILURE(ec)) {
1498 errln((UnicodeString)"Failed to parse test argument " + values[j]);
1499 } else {
1500 FieldPosition fp(0);
1501 UnicodeString result;
1502 fmt->format(args, 1, result, fp, ec);
1503 logln((UnicodeString)"value: " + toString(args[0]) + " --> " + result + UnicodeString(" ec: ") + u_errorName(ec));
1504
1505 if (i != 3) { // TODO: fix this, for now skip ordinal parsing (format string at index 3)
1506 int32_t count = 0;
1507 Formattable* parseResult = fmt->parse(result, count, ec);
1508 if (count != 1) {
1509 errln((UnicodeString)"parse returned " + count + " args");
1510 } else if (parseResult[0] != args[0]) {
1511 errln((UnicodeString)"parsed argument " + toString(parseResult[0]) + " != " + toString(args[0]));
1512 }
1513 delete []parseResult;
1514 }
1515 }
1516 }
1517 delete fmt;
1518 }
1519 delete numFmt;
1520 }
1521
testAutoQuoteApostrophe(void)1522 void TestMessageFormat::testAutoQuoteApostrophe(void) {
1523 const char* patterns[] = { // pattern, expected pattern
1524 "'", "''",
1525 "''", "''",
1526 "'{", "'{'",
1527 "' {", "'' {",
1528 "'a", "''a",
1529 "'{'a", "'{'a",
1530 "'{a'", "'{a'",
1531 "'{}", "'{}'",
1532 "{'", "{'",
1533 "{'a", "{'a",
1534 "{'a{}'a}'a", "{'a{}'a}''a",
1535 "'}'", "'}'",
1536 "'} '{'}'", "'} '{'}''",
1537 "'} {{{''", "'} {{{'''",
1538 };
1539 int32_t pattern_count = sizeof(patterns)/sizeof(patterns[0]);
1540
1541 for (int i = 0; i < pattern_count; i += 2) {
1542 UErrorCode status = U_ZERO_ERROR;
1543 UnicodeString result = MessageFormat::autoQuoteApostrophe(patterns[i], status);
1544 UnicodeString target(patterns[i+1]);
1545 if (target != result) {
1546 const int BUF2_LEN = 64;
1547 char buf[256];
1548 char buf2[BUF2_LEN];
1549 int32_t len = result.extract(0, result.length(), buf2, BUF2_LEN);
1550 if (len >= BUF2_LEN) {
1551 buf2[BUF2_LEN-1] = 0;
1552 }
1553 sprintf(buf, "[%2d] test \"%s\": target (\"%s\") != result (\"%s\")\n", i/2, patterns[i], patterns[i+1], buf2);
1554 errln(buf);
1555 }
1556 }
1557 }
1558
testCoverage(void)1559 void TestMessageFormat::testCoverage(void) {
1560 UErrorCode status = U_ZERO_ERROR;
1561 UnicodeString testformat("{argument, plural, one{C''est # fichier} other {Ce sont # fichiers}} dans la liste.");
1562 MessageFormat *msgfmt = new MessageFormat(testformat, Locale("fr"), status);
1563 if (msgfmt == NULL || U_FAILURE(status)) {
1564 dataerrln("FAIL: Unable to create MessageFormat.: %s", u_errorName(status));
1565 return;
1566 }
1567 if (!msgfmt->usesNamedArguments()) {
1568 errln("FAIL: Unable to detect usage of named arguments.");
1569 }
1570 const double limit[] = {0.0, 1.0, 2.0};
1571 const UnicodeString formats[] = {"0.0<=Arg<1.0",
1572 "1.0<=Arg<2.0",
1573 "2.0<-Arg"};
1574 ChoiceFormat cf(limit, formats, 3);
1575
1576 msgfmt->setFormat("set", cf, status);
1577
1578 StringEnumeration *en = msgfmt->getFormatNames(status);
1579 if (en == NULL || U_FAILURE(status)) {
1580 errln("FAIL: Unable to get format names enumeration.");
1581 } else {
1582 int32_t count = 0;
1583 en->reset(status);
1584 count = en->count(status);
1585 if (U_FAILURE(status)) {
1586 errln("FAIL: Unable to get format name enumeration count.");
1587 } else {
1588 for (int32_t i = 0; i < count; i++) {
1589 en->snext(status);
1590 if (U_FAILURE(status)) {
1591 errln("FAIL: Error enumerating through names.");
1592 break;
1593 }
1594 }
1595 }
1596 }
1597
1598 msgfmt->adoptFormat("adopt", &cf, status);
1599
1600 delete en;
1601 delete msgfmt;
1602
1603 msgfmt = new MessageFormat("'", status);
1604 if (msgfmt == NULL || U_FAILURE(status)) {
1605 errln("FAIL: Unable to create MessageFormat.");
1606 return;
1607 }
1608 if (msgfmt->usesNamedArguments()) {
1609 errln("FAIL: Unable to detect usage of named arguments.");
1610 }
1611
1612 msgfmt->setFormat("formatName", cf, status);
1613 if (!U_FAILURE(status)) {
1614 errln("FAIL: Should fail to setFormat instead of passing.");
1615 }
1616 status = U_ZERO_ERROR;
1617 en = msgfmt->getFormatNames(status);
1618 if (!U_FAILURE(status)) {
1619 errln("FAIL: Should fail to get format names enumeration instead of passing.");
1620 }
1621
1622 delete en;
1623 delete msgfmt;
1624 }
1625
1626 #endif /* #if !UCONFIG_NO_FORMATTING */
1627