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 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 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 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 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 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 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 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. */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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*. 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 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 */ 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 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 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 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