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