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