1 /*********************************************************************** 2 * Copyright (c) 1997-2010, International Business Machines Corporation 3 * and others. All Rights Reserved. 4 ***********************************************************************/ 5 6 #include "unicode/utypes.h" 7 8 #if !UCONFIG_NO_FORMATTING 9 10 #include "numrgts.h" 11 12 #include <float.h> // DBL_MIN, DBL_MAX 13 #include <stdio.h> 14 15 #include "unicode/dcfmtsym.h" 16 #include "unicode/decimfmt.h" 17 #include "unicode/locid.h" 18 #include "unicode/resbund.h" 19 #include "unicode/calendar.h" 20 #include "unicode/datefmt.h" 21 #include "unicode/ucurr.h" 22 #include "putilimp.h" 23 24 class MyNumberFormatTest : public NumberFormat 25 { 26 public: 27 28 virtual UClassID getDynamicClassID(void) const; 29 30 virtual UnicodeString& format( double number, 31 UnicodeString& toAppendTo, 32 FieldPosition& pos, 33 UErrorCode& status) const 34 { 35 return NumberFormat::format(number, toAppendTo, pos, status); 36 } 37 38 /* Just keep this here to make some of the compilers happy */ 39 virtual UnicodeString& format(const Formattable& obj, 40 UnicodeString& toAppendTo, 41 FieldPosition& pos, 42 UErrorCode& status) const 43 { 44 return NumberFormat::format(obj, toAppendTo, pos, status); 45 } 46 47 /* Just use one of the format functions */ 48 virtual UnicodeString& format( double /* number */, 49 UnicodeString& toAppendTo, 50 FieldPosition& /* pos */) const 51 { 52 toAppendTo = ""; 53 return toAppendTo; 54 } 55 56 /* 57 public Number parse(String text, ParsePosition parsePosition) 58 { return new Integer(0); } 59 */ 60 61 /* Just use one of the parse functions */ 62 virtual void parse( const UnicodeString& /* text */, 63 Formattable& result, 64 ParsePosition& /* parsePosition */) const 65 { 66 result.setLong((int32_t)0); 67 } 68 69 virtual void parse( const UnicodeString& text, 70 Formattable& result, 71 UErrorCode& status) const 72 { 73 NumberFormat::parse(text, result, status); 74 } 75 virtual Format* clone() const 76 { return NULL; } 77 78 virtual UnicodeString& format(int32_t, 79 UnicodeString& foo, 80 FieldPosition&) const 81 { return foo.remove(); } 82 83 virtual UnicodeString& format(int64_t, 84 UnicodeString& foo, 85 FieldPosition&) const 86 { return foo.remove(); } 87 88 virtual void applyPattern(const UnicodeString&, UParseError&, UErrorCode&){ 89 } 90 }; 91 92 int32_t gMyNumberFormatTestClassID; 93 UClassID MyNumberFormatTest::getDynamicClassID() const 94 { 95 return (UClassID)&gMyNumberFormatTestClassID; 96 } 97 98 99 // ***************************************************************************** 100 // class NumberFormatRegressionTest 101 // ***************************************************************************** 102 103 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break 104 105 void 106 NumberFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 107 { 108 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest"); 109 switch (index) { 110 CASE(0,Test4075713); 111 CASE(1,Test4074620); 112 CASE(2,Test4088161); 113 CASE(3,Test4087245); 114 CASE(4,Test4087535); 115 CASE(5,Test4088503); 116 CASE(6,Test4066646); 117 CASE(7,Test4059870); 118 CASE(8,Test4083018); 119 CASE(9,Test4071492); 120 CASE(10,Test4086575); 121 CASE(11,Test4068693); 122 CASE(12,Test4069754); 123 CASE(13,Test4087251); 124 CASE(14,Test4090489); 125 CASE(15,Test4090504); 126 CASE(16,Test4095713); 127 CASE(17,Test4092561); 128 CASE(18,Test4092480); 129 CASE(19,Test4087244); 130 CASE(20,Test4070798); 131 CASE(21,Test4071005); 132 CASE(22,Test4071014); 133 CASE(23,Test4071859); 134 CASE(24,Test4093610); 135 CASE(25,Test4098741); 136 CASE(26,Test4074454); 137 CASE(27,Test4099404); 138 CASE(28,Test4101481); 139 CASE(29,Test4052223); 140 CASE(30,Test4061302); 141 CASE(31,Test4062486); 142 CASE(32,Test4108738); 143 CASE(33,Test4106658); 144 CASE(34,Test4106662); 145 CASE(35,Test4114639); 146 CASE(36,Test4106664); 147 CASE(37,Test4106667); 148 CASE(38,Test4110936); 149 CASE(39,Test4122840); 150 CASE(40,Test4125885); 151 CASE(41,Test4134034); 152 CASE(42,Test4134300); 153 CASE(43,Test4140009); 154 CASE(44,Test4141750); 155 CASE(45,Test4145457); 156 CASE(46,Test4147295); 157 CASE(47,Test4147706); 158 CASE(48,Test4162198); 159 CASE(49,Test4162852); 160 CASE(50,Test4167494); 161 CASE(51,Test4170798); 162 CASE(52,Test4176114); 163 CASE(53,Test4179818); 164 CASE(54,Test4212072); 165 CASE(55,Test4216742); 166 CASE(56,Test4217661); 167 CASE(57,Test4161100); 168 CASE(58,Test4243011); 169 CASE(59,Test4243108); 170 CASE(60,TestJ691); 171 172 default: name = ""; break; 173 } 174 } 175 176 UBool 177 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const Locale& l, UBool possibleDataError) 178 { 179 if(U_FAILURE(status)) { 180 if (possibleDataError) { 181 dataerrln(UnicodeString("FAIL: ", "") + msg 182 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 183 } else { 184 errcheckln(status, UnicodeString("FAIL: ", "") + msg 185 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 186 } 187 return TRUE; 188 } 189 190 return FALSE; 191 } 192 193 UBool 194 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const char *l, UBool possibleDataError) 195 { 196 if(U_FAILURE(status)) { 197 if (possibleDataError) { 198 dataerrln(UnicodeString("FAIL: ", "") + msg 199 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 200 } else { 201 errcheckln(status, UnicodeString("FAIL: ", "") + msg 202 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 203 } 204 return TRUE; 205 } 206 207 return FALSE; 208 } 209 210 UBool 211 NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, UBool possibleDataError) 212 { 213 if(U_FAILURE(status)) { 214 if (possibleDataError) { 215 dataerrln(UnicodeString("FAIL: ", "") + msg 216 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 217 } else { 218 errcheckln(status, UnicodeString("FAIL: ", "") + msg 219 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 220 } 221 return TRUE; 222 } 223 224 return FALSE; 225 } 226 227 /** 228 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects 229 */ 230 inline UnicodeString str(const char *input) 231 { 232 return CharsToUnicodeString(input); 233 } 234 235 /* @bug 4075713 236 * NumberFormat.equals comparing with null should always return false. 237 */ 238 // {sfb} kind of silly in C++, just checking for new success 239 void NumberFormatRegressionTest::Test4075713(void) 240 { 241 //try { 242 MyNumberFormatTest *tmp = new MyNumberFormatTest(); 243 if(tmp != NULL) 244 logln("NumberFormat.equals passed"); 245 /*} catch (NullPointerException e) { 246 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); 247 }*/ 248 249 delete tmp; 250 } 251 252 /* @bug 4074620 253 * NumberFormat.equals comparing two obj equal even the setGroupingUsed 254 * flag is different. 255 */ 256 void NumberFormatRegressionTest::Test4074620(void) 257 { 258 259 MyNumberFormatTest *nf1 = new MyNumberFormatTest(); 260 MyNumberFormatTest *nf2 = new MyNumberFormatTest(); 261 262 nf1->setGroupingUsed(FALSE); 263 nf2->setGroupingUsed(TRUE); 264 265 if(nf1 == nf2) 266 errln("Test for bug 4074620 failed"); 267 else 268 logln("Test for bug 4074620 passed."); 269 270 delete nf1; 271 delete nf2; 272 } 273 274 275 /* @bug 4088161 276 * DecimalFormat.format() incorrectly uses maxFractionDigits setting. 277 */ 278 279 void NumberFormatRegressionTest::Test4088161 (void) 280 { 281 UErrorCode status = U_ZERO_ERROR; 282 DecimalFormat *df = new DecimalFormat(status); 283 if (!failure(status, "new DecimalFormat", "")) { 284 double d = 100; 285 df->setMinimumFractionDigits(0); 286 df->setMaximumFractionDigits(16); 287 UnicodeString sBuf1; 288 FieldPosition fp1(0); 289 logln(UnicodeString("d = ") + d); 290 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 291 292 logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'"); 293 df->setMaximumFractionDigits(17); 294 UnicodeString sBuf2; 295 FieldPosition fp2(0); 296 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 297 sBuf2 = df->format(d, sBuf2, fp2); 298 if(sBuf2 != "100") 299 errln(" format(d) = '" + sBuf2 + "'"); 300 } 301 302 delete df; 303 } 304 305 /* @bug 4087245 306 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. 307 * DecimalFormat(String, DecimalFormatSymbols). 308 */ 309 void NumberFormatRegressionTest::Test4087245 (void) 310 { 311 UErrorCode status = U_ZERO_ERROR; 312 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(status); 313 failure(status, "new DecimalFormatSymbols", ""); 314 // {sfb} One note about this test: if you pass in a pointer 315 // to the symbols, they are adopted and this test will fail, 316 // even though that is the correct behavior. To test the cloning 317 // of the symbols, it is necessary to pass in a reference to the symbols 318 DecimalFormat *df = new DecimalFormat("#,##0.0", *symbols, status); 319 failure(status, "new DecimalFormat with symbols", ""); 320 int32_t n = 123; 321 UnicodeString buf1; 322 UnicodeString buf2; 323 FieldPosition pos(FieldPosition::DONT_CARE); 324 logln(UnicodeString("format(") + n + ") = " + 325 df->format(n, buf1, pos)); 326 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString((UChar)0x70)); // change value of field 327 logln(UnicodeString("format(") + n + ") = " + 328 df->format(n, buf2, pos)); 329 if(buf1 != buf2) 330 errln("Test for bug 4087245 failed"); 331 332 delete df; 333 delete symbols; 334 } 335 336 /* @bug 4087535 337 * DecimalFormat.format() incorrectly formats 0.0 338 */ 339 void NumberFormatRegressionTest::Test4087535 (void) 340 { 341 UErrorCode status = U_ZERO_ERROR; 342 DecimalFormat *df = new DecimalFormat(status); 343 failure(status, "new DecimalFormat", ""); 344 df->setMinimumIntegerDigits(0); 345 346 double n = 0; 347 UnicodeString buffer; 348 FieldPosition pos(FieldPosition::DONT_CARE); 349 buffer = df->format(n, buffer, pos); 350 if (buffer.length() == 0) 351 errln(/*n + */": '" + buffer + "'"); 352 n = 0.1; 353 buffer = df->format(n, buffer, pos); 354 if (buffer.length() == 0) 355 errln(/*n + */": '" + buffer + "'"); 356 357 delete df; 358 } 359 360 /* @bug 4088503 361 * DecimalFormat.format fails when groupingSize is set to 0. 362 */ 363 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ?? 364 void NumberFormatRegressionTest::Test4088503 (void) 365 { 366 UErrorCode status = U_ZERO_ERROR; 367 DecimalFormat *df = new DecimalFormat(status); 368 failure(status, "new DecimalFormat", ""); 369 df->setGroupingSize(0); 370 UnicodeString sBuf; 371 FieldPosition fp(FieldPosition::DONT_CARE); 372 //try { 373 logln(df->format((int32_t)123, sBuf, fp)); 374 //if(fp == FieldPosition(0)) 375 // errln("Test for bug 4088503 failed."); 376 /*} catch (Exception foo) { 377 errln("Test for bug 4088503 failed."); 378 }*/ 379 delete df; 380 381 } 382 /* @bug 4066646 383 * NumberFormat.getCurrencyInstance is wrong. 384 */ 385 void NumberFormatRegressionTest::Test4066646 (void) 386 { 387 assignFloatValue(2.04f); 388 assignFloatValue(2.03f); 389 assignFloatValue(2.02f); 390 assignFloatValue(0.0f); 391 } 392 393 float 394 NumberFormatRegressionTest::assignFloatValue(float returnfloat) 395 { 396 logln(UnicodeString(" VALUE ") + returnfloat); 397 UErrorCode status = U_ZERO_ERROR; 398 NumberFormat *nfcommon = NumberFormat::createCurrencyInstance(Locale::getUS(), status); 399 if (failure(status, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE)){ 400 delete nfcommon; 401 return returnfloat; 402 } 403 nfcommon->setGroupingUsed(FALSE); 404 405 UnicodeString stringValue; 406 stringValue = nfcommon->format(returnfloat, stringValue); 407 logln(" DISPLAYVALUE " + stringValue); 408 Formattable result; 409 nfcommon->parse(stringValue, result, status); 410 failure(status, "nfcommon->parse", Locale::getUS()); 411 float floatResult = (float) (result.getType() == Formattable::kDouble 412 ? result.getDouble() : result.getLong()); 413 if( uprv_fabs(floatResult - returnfloat) > 0.0001) 414 //String stringValue = nfcommon.format(returnfloat).substring(1); 415 //if (Float.valueOf(stringValue).floatValue() != returnfloat) 416 errln(UnicodeString("FAIL: expected ") + returnfloat + ", got " + floatResult + " (" + stringValue+")"); 417 418 delete nfcommon; 419 return returnfloat; 420 } // End Of assignFloatValue() 421 422 /* @bug 4059870 423 * DecimalFormat throws exception when parsing "0" 424 */ 425 void NumberFormatRegressionTest::Test4059870(void) 426 { 427 UErrorCode status = U_ZERO_ERROR; 428 DecimalFormat *format = new DecimalFormat("00", status); 429 failure(status, "new Decimalformat", Locale::getUS()); 430 //try { 431 Formattable result; 432 UnicodeString str; 433 format->parse(UnicodeString("0"), result, status); 434 failure(status, "format->parse", Locale::getUS()); 435 436 /*} 437 catch (Exception e) { 438 errln("Test for bug 4059870 failed : " + e); 439 }*/ 440 441 delete format; 442 } 443 /* @bug 4083018 444 * DecimalFormatSymbol.equals should always return false when 445 * comparing with null. 446 */ 447 // {sfb} this is silly in C++ 448 void NumberFormatRegressionTest::Test4083018 (void) 449 { 450 UErrorCode status = U_ZERO_ERROR; 451 DecimalFormatSymbols *dfs = new DecimalFormatSymbols(status); 452 failure(status, "new DecimalFormatSymbols", Locale::getUS()); 453 //try { 454 if (dfs != NULL) 455 logln("Test Passed!"); 456 else 457 errln("Test for bug 4083018 failed"); 458 /*} catch (Exception foo) { 459 errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); 460 }*/ 461 462 delete dfs; 463 } 464 465 /* @bug 4071492 466 * DecimalFormat does not round up correctly. 467 */ 468 void NumberFormatRegressionTest::Test4071492 (void) 469 { 470 double x = 0.00159999; 471 UErrorCode status = U_ZERO_ERROR; 472 NumberFormat *nf = NumberFormat::createInstance(status); 473 if (failure(status, "NumberFormat::createInstance", Locale::getUS(), TRUE)) { 474 delete nf; 475 return; 476 } 477 nf->setMaximumFractionDigits(4); 478 UnicodeString out; 479 FieldPosition pos(FieldPosition::DONT_CARE); 480 out = nf->format(x, out, pos); 481 logln("0.00159999 formats with 4 fractional digits to " + out); 482 UnicodeString expected("0.0016"); 483 if (out != expected) 484 errln("FAIL: Expected " + expected); 485 486 delete nf; 487 } 488 489 /* @bug 4086575 490 * A space as a group separator for localized pattern causes 491 * wrong format. WorkAround : use non-breaking space. 492 */ 493 void NumberFormatRegressionTest::Test4086575(void) 494 { 495 UErrorCode status = U_ZERO_ERROR; 496 NumberFormat *nf1 = NumberFormat::createInstance(Locale::getFrance(), status); 497 498 // TODO: There is not a good way to find out that the creation of this number format has 499 // failed. Major rewiring of format construction proposed. 500 if(U_FAILURE(status)) { 501 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status)); 502 delete nf1; 503 return; 504 } 505 failure(status, "NumberFormat::createInstance", Locale::getFrance()); 506 507 // C++ workaround to make sure cast works 508 // Wouldn't dynamic_cast<DecimalFormat*> be great? 509 if(nf1->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 510 errln("NumberFormat::createInstance returned incorrect type."); 511 return; 512 } 513 514 DecimalFormat *nf = (DecimalFormat*) nf1; 515 UnicodeString temp; 516 logln("nf toPattern1: " + nf->toPattern(temp)); 517 logln("nf toLocPattern1: " + nf->toLocalizedPattern(temp)); 518 519 // No group separator 520 logln("...applyLocalizedPattern ###,00;(###,00) "); 521 nf->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status); 522 failure(status, "nf->applyLocalizedPattern", Locale::getFrance()); 523 logln("nf toPattern2: " + nf->toPattern(temp)); 524 logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp)); 525 526 FieldPosition pos(FieldPosition::DONT_CARE); 527 logln("nf: " + nf->format((int32_t)1234, temp, pos)); // 1234,00 528 logln("nf: " + nf->format((int32_t)-1234, temp, pos)); // (1234,00) 529 530 // Space as group separator 531 532 logln("...applyLocalizedPattern # ###,00;(# ###,00) "); 533 // nbsp = \u00a0 534 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); 535 UChar patChars[] = { 536 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b, 537 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29 538 }; 539 UnicodeString pat(patChars, 19, 19); 540 nf->applyLocalizedPattern(pat, status); 541 failure(status, "nf->applyLocalizedPattern", Locale::getFrance()); 542 logln("nf toPattern2: " + nf->toPattern(temp)); 543 logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp)); 544 UnicodeString buffer; 545 buffer = nf->format((int32_t)1234, buffer, pos); 546 //if (buffer != UnicodeString("1\u00a0234,00")) 547 UChar c[] = { 548 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30 549 }; 550 UnicodeString cc(c, 8, 8); 551 if (buffer != cc) 552 errln("nf : " + buffer); // Expect 1 234,00 553 554 buffer.remove(); 555 buffer = nf->format((int32_t)-1234, buffer, pos); 556 UChar c1[] = { 557 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29 558 }; 559 UnicodeString cc1(c1, 10, 10); 560 if (buffer != cc1) 561 errln("nf : " + buffer); // Expect (1 234,00) 562 563 // Erroneously prints: 564 // 1234,00 , 565 // (1234,00 ,) 566 567 delete nf1; 568 } 569 /* @bug 4068693 570 * DecimalFormat.parse returns wrong value 571 */ 572 // {sfb} slightly converted into a round-trip test, since in C++ 573 // there is no Double.toString() 574 void NumberFormatRegressionTest::Test4068693(void) 575 { 576 logln("----- Test Application -----"); 577 ParsePosition pos(0); 578 UErrorCode status = U_ZERO_ERROR; 579 DecimalFormat *df = new DecimalFormat(status); 580 if(U_FAILURE(status)) { 581 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 582 delete df; 583 return; 584 } 585 failure(status, "new DecimalFormat"); 586 Formattable d; 587 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0)); 588 df->parse(UnicodeString("123.55456"), d, pos); 589 //if (!d.toString().equals("123.55456")) { 590 UnicodeString dstr; 591 df->setMaximumFractionDigits(999); 592 df->setMaximumIntegerDigits(999); 593 FieldPosition fp(FieldPosition::DONT_CARE); 594 dstr = df->format(d.getDouble(), dstr, fp); 595 if (dstr != UnicodeString("123.55456")) { 596 errln(UnicodeString("Result -> ") + d.getDouble()); 597 } 598 599 delete df; 600 } 601 602 /* @bug 4069754, 4067878 603 * null pointer thrown when accessing a deserialized DecimalFormat 604 * object. 605 */ 606 // {sfb} doesn't apply in C++ 607 void NumberFormatRegressionTest::Test4069754(void) 608 { 609 /* try { 610 myformat it = new myformat(); 611 logln(it.Now()); 612 FileOutputStream ostream = new FileOutputStream("t.tmp"); 613 ObjectOutputStream p = new ObjectOutputStream(ostream); 614 p.writeObject(it); 615 ostream.close(); 616 logln("Saved ok."); 617 618 FileInputStream istream = new FileInputStream("t.tmp"); 619 ObjectInputStream p2 = new ObjectInputStream(istream); 620 myformat it2 = (myformat)p2.readObject(); 621 logln(it2.Now()); 622 istream.close(); 623 logln("Loaded ok."); 624 } catch (Exception foo) { 625 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage()); 626 } 627 */} 628 629 /* @bug 4087251 630 * DecimalFormat.applyPattern(String) allows illegal patterns 631 */ 632 void NumberFormatRegressionTest::Test4087251 (void) 633 { 634 UErrorCode status = U_ZERO_ERROR; 635 DecimalFormat *df = new DecimalFormat(status); 636 if(U_FAILURE(status)) { 637 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 638 delete df; 639 return; 640 } 641 failure(status, "new DecimalFormat"); 642 //try { 643 df->applyPattern(UnicodeString("#.#.#"), status); 644 if( ! U_FAILURE(status)) 645 errln("df->applyPattern with illegal pattern didn't fail"); 646 UnicodeString temp; 647 logln("toPattern() returns \"" + df->toPattern(temp) + "\""); 648 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException"); 649 /*} catch (IllegalArgumentException e) { 650 logln("Caught Illegal Argument Error !"); 651 }*/ 652 // Second test; added 5/11/98 when reported to fail on 1.2b3 653 //try { 654 df->applyPattern("#0.0#0#0", status); 655 if( ! U_FAILURE(status)) 656 errln("df->applyPattern with illegal pattern didn't fail"); 657 logln("toPattern() returns \"" + df->toPattern(temp) + "\""); 658 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException"); 659 /*} catch (IllegalArgumentException e) { 660 logln("Ok - IllegalArgumentException for #0.0#0#0"); 661 }*/ 662 663 delete df; 664 } 665 666 /* @bug 4090489 667 * DecimalFormat.format() loses precision 668 */ 669 void NumberFormatRegressionTest::Test4090489 (void) 670 { 671 // {sfb} sprintf doesn't correctly handle the double, so there is nothing 672 // that NumberFormat can do. For some reason, it does not format the last 1. 673 674 /* UErrorCode status = U_ZERO_ERROR; 675 DecimalFormat *df = new DecimalFormat(status); 676 failure(status, "new DecimalFormat"); 677 df->setMinimumFractionDigits(10); 678 df->setMaximumFractionDigits(999); 679 df->setGroupingUsed(FALSE); 680 double d = 1.000000000000001E7; 681 //BigDecimal bd = new BigDecimal(d); 682 UnicodeString sb; 683 FieldPosition fp(0); 684 logln(UnicodeString("d = ") + d); 685 //logln("BigDecimal.toString(): " + bd.toString()); 686 df->format(d, sb, fp); 687 if (sb != "10000000.0000000100") { 688 errln("DecimalFormat.format(): " + sb); 689 } 690 */ 691 } 692 693 /* @bug 4090504 694 * DecimalFormat.format() loses precision 695 */ 696 void NumberFormatRegressionTest::Test4090504 (void) 697 { 698 double d = 1; 699 logln(UnicodeString("d = ") + d); 700 UErrorCode status = U_ZERO_ERROR; 701 DecimalFormat *df = new DecimalFormat(status); 702 if(U_FAILURE(status)) { 703 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 704 delete df; 705 return; 706 } 707 failure(status, "new DecimalFormat"); 708 UnicodeString sb; 709 FieldPosition fp(FieldPosition::DONT_CARE); 710 //try { 711 for (int i = 17; i <= 20; i++) { 712 df->setMaximumFractionDigits(i); 713 //sb = new StringBuffer(""); 714 fp.setField(0); 715 logln(" getMaximumFractionDigits() = " + i); 716 logln(" formated: " + df->format(d, sb, fp)); 717 } 718 /*} catch (Exception foo) { 719 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); 720 }*/ 721 722 delete df; 723 } 724 /* @bug 4095713 725 * DecimalFormat.parse(String str, ParsePosition pp) loses precision 726 */ 727 void NumberFormatRegressionTest::Test4095713 (void) 728 { 729 UErrorCode status = U_ZERO_ERROR; 730 DecimalFormat *df = new DecimalFormat(status); 731 if(U_FAILURE(status)) { 732 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 733 delete df; 734 return; 735 } 736 failure(status, "new DecimalFormat"); 737 UnicodeString str("0.1234"); 738 double d1 = 0.1234; 739 //Double d1 = new Double(str); 740 //Double d2 = (Double) df.parse(str, new ParsePosition(0)); 741 Formattable d2; 742 ParsePosition pp(0); 743 df->parse(str, d2, pp); 744 logln(UnicodeString("") + d1); 745 if (d2.getDouble() != d1) 746 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2.getDouble()); 747 delete df; 748 } 749 750 /* @bug 4092561 751 * DecimalFormat.parse() fails when multiplier is not set to 1 752 */ 753 // {sfb} not sure what to do with this one 754 void NumberFormatRegressionTest::Test4092561 (void) 755 { 756 UErrorCode status = U_ZERO_ERROR; 757 DecimalFormat *df = new DecimalFormat(status); 758 if(U_FAILURE(status)) { 759 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 760 delete df; 761 return; 762 } 763 failure(status, "new DecimalFormat"); 764 765 // {sfb} going to cheat here and use sprintf ?? 766 767 /*UnicodeString str = Long.toString(Long.MIN_VALUE); 768 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString()); 769 df.setMultiplier(100); 770 Number num = df.parse(str, new ParsePosition(0)); 771 if (num.doubleValue() != -9.223372036854776E16) 772 errln("Bug 4092561 test failed when multiplier is set to not 1."); 773 */ 774 delete df; 775 } 776 777 /* @bug 4092480 778 * DecimalFormat: Negative format ignored. 779 */ 780 void NumberFormatRegressionTest::Test4092480 (void) 781 { 782 UErrorCode status = U_ZERO_ERROR; 783 DecimalFormat *dfFoo = new DecimalFormat(UnicodeString("000"), status); 784 if(U_FAILURE(status)) { 785 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 786 delete dfFoo; 787 return; 788 } 789 failure(status, "new DecimalFormat"); 790 791 //try { 792 dfFoo->applyPattern("0000;-000", status); 793 failure(status, "dfFoo->applyPattern"); 794 UnicodeString temp; 795 if (dfFoo->toPattern(temp) != UnicodeString("#0000")) 796 errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); 797 FieldPosition pos(FieldPosition::DONT_CARE); 798 logln(dfFoo->format((int32_t)42, temp, pos)); 799 logln(dfFoo->format((int32_t)-42, temp, pos)); 800 dfFoo->applyPattern("000;-000", status); 801 failure(status, "dfFoo->applyPattern"); 802 if (dfFoo->toPattern(temp) != UnicodeString("#000")) 803 errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); 804 logln(dfFoo->format((int32_t)42,temp, pos)); 805 logln(dfFoo->format((int32_t)-42, temp, pos)); 806 807 dfFoo->applyPattern("000;-0000", status); 808 failure(status, "dfFoo->applyPattern"); 809 if (dfFoo->toPattern(temp) != UnicodeString("#000")) 810 errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); 811 logln(dfFoo->format((int32_t)42, temp, pos)); 812 logln(dfFoo->format((int32_t)-42, temp, pos)); 813 814 dfFoo->applyPattern("0000;-000", status); 815 failure(status, "dfFoo->applyPattern"); 816 if (dfFoo->toPattern(temp) != UnicodeString("#0000")) 817 errln("dfFoo.toPattern : " + dfFoo->toPattern(temp)); 818 logln(dfFoo->format((int32_t)42, temp, pos)); 819 logln(dfFoo->format((int32_t)-42, temp, pos)); 820 /*} catch (Exception foo) { 821 errln("Message " + foo.getMessage()); 822 }*/ 823 824 delete dfFoo; 825 } 826 /* @bug 4087244 827 * NumberFormat.getCurrencyInstance() produces format that uses 828 * decimal separator instead of monetary decimal separator. 829 * 830 * Rewrote this test not to depend on the actual pattern. Pattern should 831 * never contain the monetary separator! Decimal separator in pattern is 832 * interpreted as monetary separator if currency symbol is seen! 833 */ 834 void NumberFormatRegressionTest::Test4087244 (void) { 835 UErrorCode status = U_ZERO_ERROR; 836 char loc[256] = {0}; 837 uloc_canonicalize("pt_PT_PREEURO", loc, 256, &status); 838 Locale *de = new Locale(loc); 839 NumberFormat *nf = NumberFormat::createCurrencyInstance(*de, status); 840 if(U_FAILURE(status)) { 841 dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); 842 delete nf; 843 return; 844 } 845 if (nf->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 846 errln("expected DecimalFormat!"); 847 return; 848 } 849 DecimalFormat *df = (DecimalFormat*) nf; 850 const DecimalFormatSymbols *sym = df->getDecimalFormatSymbols(); 851 UnicodeString decSep = sym->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 852 UnicodeString monSep = sym->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 853 if (decSep == monSep) { 854 errln("ERROR in test: want decimal sep != monetary sep"); 855 return; 856 } 857 df->setMinimumIntegerDigits(1); 858 df->setMinimumFractionDigits(2); 859 UnicodeString str; 860 FieldPosition pos; 861 df->format(1.23, str, pos); 862 UnicodeString monStr("1x23"); 863 monStr.replace((int32_t)1, 1, monSep); 864 UnicodeString decStr("1x23"); 865 decStr.replace((int32_t)1, 1, decSep); 866 if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { 867 logln(UnicodeString("OK: 1.23 -> \"") + str + "\" contains \"" + 868 monStr + "\" and not \"" + decStr + '"'); 869 } else { 870 errln(UnicodeString("FAIL: 1.23 -> \"") + str + "\", should contain \"" + 871 monStr + 872 "\" and not \"" + decStr + '"'); 873 } 874 delete de; 875 delete nf; 876 } 877 /* @bug 4070798 878 * Number format data rounding errors for locale FR 879 */ 880 void NumberFormatRegressionTest::Test4070798 (void) 881 { 882 NumberFormat *formatter; 883 UnicodeString tempString; 884 885 /* User error : 886 String expectedDefault = "-5\u00a0789,987"; 887 String expectedCurrency = "5\u00a0789,98\u00a0F"; 888 String expectedPercent = "-578\u00a0998%"; 889 */ 890 UChar chars1 [] = { 891 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38 892 }; 893 UChar chars2 [] = { 894 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46 895 }; 896 UChar chars3 [] = { 897 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25 898 }; 899 UnicodeString expectedDefault(chars1, 10, 10); 900 UnicodeString expectedCurrency(chars2, 10, 10); 901 UnicodeString expectedPercent(chars3, 10, 10); 902 903 UErrorCode status = U_ZERO_ERROR; 904 char loc[256]={0}; 905 int len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); 906 formatter = NumberFormat::createInstance(Locale(loc), status); 907 if(U_FAILURE(status)) { 908 dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); 909 delete formatter; 910 return; 911 } 912 failure(status, "NumberFormat::createNumberInstance", loc); 913 tempString = formatter->format (-5789.9876, tempString); 914 915 if (tempString == expectedDefault) { 916 logln ("Bug 4070798 default test passed."); 917 } else { 918 errln(UnicodeString("Failed:") + 919 " Expected " + expectedDefault + 920 " Received " + tempString ); 921 } 922 delete formatter; 923 len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); 924 formatter = NumberFormat::createCurrencyInstance(loc, status); 925 failure(status, "NumberFormat::createCurrencyInstance", loc); 926 tempString.remove(); 927 tempString = formatter->format( 5789.9876, tempString ); 928 929 if (tempString == expectedCurrency) { 930 logln ("Bug 4070798 currency test passed."); 931 } else { 932 errln(UnicodeString("Failed:") + 933 " Expected " + expectedCurrency + 934 " Received " + tempString ); 935 } 936 delete formatter; 937 938 uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status); 939 formatter = NumberFormat::createPercentInstance(Locale(loc), status); 940 failure(status, "NumberFormat::createPercentInstance", loc); 941 tempString.remove(); 942 tempString = formatter->format (-5789.9876, tempString); 943 944 if (tempString == expectedPercent) { 945 logln ("Bug 4070798 percentage test passed."); 946 } else { 947 errln(UnicodeString("Failed:") + 948 " Expected " + expectedPercent + 949 " Received " + tempString ); 950 } 951 952 delete formatter; 953 } 954 /* @bug 4071005 955 * Data rounding errors for French (Canada) locale 956 */ 957 void NumberFormatRegressionTest::Test4071005 (void) 958 { 959 NumberFormat *formatter; 960 UnicodeString tempString; 961 /* User error : 962 String expectedDefault = "-5\u00a0789,987"; 963 String expectedCurrency = "5\u00a0789,98\u00a0$"; 964 String expectedPercent = "-578\u00a0998%"; 965 */ 966 UChar chars1 [] = { 967 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38 968 }; 969 UChar chars2 [] = { 970 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24 971 }; 972 UChar chars3 [] = { 973 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25 974 }; 975 UnicodeString expectedDefault(chars1, 10, 10); 976 UnicodeString expectedCurrency(chars2, 10, 10); 977 UnicodeString expectedPercent(chars3, 10, 10); 978 979 UErrorCode status = U_ZERO_ERROR; 980 formatter = NumberFormat::createInstance(Locale::getCanadaFrench(), status); 981 if (failure(status, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE)){ 982 delete formatter; 983 return; 984 }; 985 tempString = formatter->format (-5789.9876, tempString); 986 987 if (tempString == expectedDefault) { 988 logln ("Bug 4071005 default test passed."); 989 } else { 990 errln(UnicodeString("Failed:") + 991 " Expected " + expectedDefault + 992 " Received " + tempString ); 993 } 994 delete formatter; 995 996 formatter = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status); 997 failure(status, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench()); 998 tempString.remove(); 999 tempString = formatter->format( 5789.9876, tempString ); 1000 1001 if (tempString == expectedCurrency) { 1002 logln ("Bug 4071005 currency test assed."); 1003 } else { 1004 errln(UnicodeString("Failed:") + 1005 " Expected " + expectedCurrency + 1006 " Received " + tempString ); 1007 } 1008 delete formatter; 1009 1010 formatter = NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status); 1011 failure(status, "NumberFormat::createPercentInstance", Locale::getCanadaFrench()); 1012 tempString.remove(); 1013 tempString = formatter->format (-5789.9876, tempString); 1014 1015 if (tempString == expectedPercent) { 1016 logln ("Bug 4071005 percentage test passed."); 1017 } else { 1018 errln(UnicodeString("Failed:") + 1019 " Expected " + expectedPercent + 1020 " Received " + tempString ); 1021 } 1022 1023 delete formatter; 1024 } 1025 1026 /* @bug 4071014 1027 * Data rounding errors for German (Germany) locale 1028 */ 1029 void NumberFormatRegressionTest::Test4071014 (void) 1030 { 1031 NumberFormat *formatter; 1032 UnicodeString tempString; 1033 /* user error : 1034 String expectedDefault = "-5.789,987"; 1035 String expectedCurrency = "5.789,98 DM"; 1036 String expectedPercent = "-578.998%"; 1037 */ 1038 UnicodeString expectedDefault("-5.789,988"); 1039 UnicodeString expectedCurrency("5.789,99\\u00A0DM"); 1040 UnicodeString expectedPercent("-578.999\\u00A0%"); 1041 1042 expectedCurrency = expectedCurrency.unescape(); 1043 expectedPercent = expectedPercent.unescape(); 1044 1045 UErrorCode status = U_ZERO_ERROR; 1046 char loc[256]={0}; 1047 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); 1048 formatter = NumberFormat::createInstance(Locale(loc), status); 1049 if (failure(status, "NumberFormat::createNumberInstance", loc, TRUE)){ 1050 delete formatter; 1051 return; 1052 } 1053 tempString.remove(); 1054 tempString = formatter->format (-5789.9876, tempString); 1055 1056 if (tempString == expectedDefault) { 1057 logln ("Bug 4071014 default test passed."); 1058 } else { 1059 errln(UnicodeString("Failed:") + 1060 " Expected " + expectedDefault + 1061 " Received " + tempString ); 1062 } 1063 delete formatter; 1064 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); 1065 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); 1066 failure(status, "NumberFormat::createCurrencyInstance", loc); 1067 tempString.remove(); 1068 tempString = formatter->format( 5789.9876, tempString ); 1069 1070 if (tempString == expectedCurrency) { 1071 logln ("Bug 4071014 currency test assed."); 1072 } else { 1073 errln(UnicodeString("Failed:") + 1074 " Expected " + expectedCurrency + 1075 " Received " + tempString ); 1076 } 1077 delete formatter; 1078 1079 formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status); 1080 failure(status, "NumberFormat::createPercentInstance", Locale::getGermany()); 1081 tempString.remove(); 1082 tempString = formatter->format (-5789.9876, tempString); 1083 1084 if (tempString == expectedPercent) { 1085 logln ("Bug 4071014 percentage test passed."); 1086 } else { 1087 errln(UnicodeString("Failed:") + 1088 " Expected " + expectedPercent + 1089 " Received " + tempString ); 1090 } 1091 1092 delete formatter; 1093 } 1094 /* @bug 4071859 1095 * Data rounding errors for Italian locale number formats 1096 */ 1097 void NumberFormatRegressionTest::Test4071859 (void) 1098 { 1099 NumberFormat *formatter; 1100 UnicodeString tempString; 1101 /* user error : 1102 String expectedDefault = "-5.789,987"; 1103 String expectedCurrency = "-L.\\u00A05.789,98"; 1104 String expectedPercent = "-578.998%"; 1105 */ 1106 UnicodeString expectedDefault("-5.789,988"); 1107 UnicodeString expectedCurrency("-IT\\u20A4\\u00A05.790", -1, US_INV); 1108 UnicodeString expectedPercent("-578.999%"); 1109 expectedCurrency = expectedCurrency.unescape(); 1110 1111 UErrorCode status = U_ZERO_ERROR; 1112 char loc[256]={0}; 1113 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1114 formatter = NumberFormat::createInstance(Locale(loc), status); 1115 if (failure(status, "NumberFormat::createNumberInstance", TRUE)){ 1116 delete formatter; 1117 return; 1118 }; 1119 tempString = formatter->format (-5789.9876, tempString); 1120 1121 if (tempString == expectedDefault) { 1122 logln ("Bug 4071859 default test passed."); 1123 } else { 1124 errln(UnicodeString("Failed:") + 1125 " Expected " + expectedDefault + 1126 " Received " + tempString ); 1127 } 1128 delete formatter; 1129 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1130 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); 1131 failure(status, "NumberFormat::createCurrencyInstance"); 1132 tempString.remove(); 1133 tempString = formatter->format( -5789.9876, tempString ); 1134 1135 if (tempString == expectedCurrency) { 1136 logln ("Bug 4071859 currency test assed."); 1137 } else { 1138 errln(UnicodeString("Failed:") + 1139 " Expected " + expectedCurrency + 1140 " Received " + tempString ); 1141 } 1142 delete formatter; 1143 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1144 formatter = NumberFormat::createPercentInstance(Locale(loc), status); 1145 failure(status, "NumberFormat::createPercentInstance"); 1146 tempString.remove(); 1147 tempString = formatter->format (-5789.9876, tempString); 1148 1149 if (tempString == expectedPercent) { 1150 logln ("Bug 4071859 percentage test passed."); 1151 } else { 1152 errln(UnicodeString("Failed:") + 1153 " Expected " + expectedPercent + 1154 " Received " + tempString ); 1155 } 1156 1157 delete formatter; 1158 } 1159 /* @bug 4071859 1160 * Test rounding for nearest even. 1161 */ 1162 void NumberFormatRegressionTest::Test4093610(void) 1163 { 1164 UErrorCode status = U_ZERO_ERROR; 1165 DecimalFormat *df = new DecimalFormat("#0.#", status); 1166 if (!failure(status, "new DecimalFormat")) { 1167 UnicodeString s("12.4"); 1168 roundingTest(df, 12.35, s); 1169 roundingTest(df, 12.45, s); 1170 s = "12.5"; 1171 roundingTest(df, 12.452,s); 1172 s = "12.6"; 1173 roundingTest(df, 12.55, s); 1174 roundingTest(df, 12.65, s); 1175 s = "12.7"; 1176 roundingTest(df, 12.652,s); 1177 s = "12.8"; 1178 roundingTest(df, 12.75, s); 1179 roundingTest(df, 12.752,s); 1180 roundingTest(df, 12.85, s); 1181 s = "12.9"; 1182 roundingTest(df, 12.852,s); 1183 s = "13"; 1184 roundingTest(df, 12.95, s); 1185 roundingTest(df, 12.952,s); 1186 } 1187 1188 delete df; 1189 } 1190 1191 void NumberFormatRegressionTest::roundingTest(DecimalFormat *df, double x, UnicodeString& expected) 1192 { 1193 UnicodeString out; 1194 FieldPosition pos(FieldPosition::DONT_CARE); 1195 out = df->format(x, out, pos); 1196 logln(UnicodeString("") + x + " formats with 1 fractional digits to " + out); 1197 if (out != expected) 1198 errln("FAIL: Expected " + expected); 1199 } 1200 /* @bug 4098741 1201 * Tests the setMaximumFractionDigits limit. 1202 */ 1203 void NumberFormatRegressionTest::Test4098741(void) 1204 { 1205 //try { 1206 UErrorCode status = U_ZERO_ERROR; 1207 NumberFormat *fmt = NumberFormat::createPercentInstance(status); 1208 if (U_FAILURE(status)) { 1209 dataerrln("Error calling NumberFormat::createPercentInstance"); 1210 delete fmt; 1211 return; 1212 } 1213 1214 fmt->setMaximumFractionDigits(20); 1215 UnicodeString temp; 1216 logln(fmt->format(.001, temp)); 1217 /*} catch (Exception foo) { 1218 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage()); 1219 }*/ 1220 delete fmt; 1221 } 1222 /* @bug 4074454 1223 * Tests illegal pattern exception. 1224 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated. 1225 * Part2 has been fixed. 1226 */ 1227 void NumberFormatRegressionTest::Test4074454(void) 1228 { 1229 //try { 1230 UErrorCode status = U_ZERO_ERROR; 1231 DecimalFormat *fmt = new DecimalFormat("#,#00.00;-#.#", status); 1232 if(U_FAILURE(status)) { 1233 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1234 delete fmt; 1235 return; 1236 } 1237 failure(status, "new DecimalFormat"); 1238 logln("Inconsistent negative pattern is fine."); 1239 DecimalFormat *newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status); 1240 failure(status, "new DecimalFormat"); 1241 UnicodeString tempString; 1242 FieldPosition pos(FieldPosition::DONT_CARE); 1243 tempString = newFmt->format(3456.78, tempString, pos); 1244 if (tempString != UnicodeString("3,456.78 p'ieces")) 1245 errln("Failed! 3456.78 p'ieces expected, but got : " + tempString); 1246 /*} catch (Exception foo) { 1247 errln("An exception was thrown for any inconsistent negative pattern."); 1248 }*/ 1249 1250 delete fmt; 1251 delete newFmt; 1252 } 1253 /* @bug 4099404 1254 * Tests all different comments. 1255 * Response to some comments : 1256 * [1] DecimalFormat.parse API documentation is more than just one line. 1257 * This is not a reproducable doc error in 116 source code. 1258 * [2] See updated javadoc. 1259 * [3] Fixed. 1260 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, 1261 * a null object will be returned. The unchanged parse position also 1262 * reflects an error. 1263 * NumberFormat.parse(String) : If parsing fails, an ParseException 1264 * will be thrown. 1265 * See updated javadoc for more details. 1266 * [5] See updated javadoc. 1267 * [6] See updated javadoc. 1268 * [7] This is a correct behavior if the DateFormat object is linient. 1269 * Otherwise, an IllegalArgumentException will be thrown when formatting 1270 * "January 35". See GregorianCalendar class javadoc for more details. 1271 */ 1272 void NumberFormatRegressionTest::Test4099404(void) 1273 { 1274 //try { 1275 UErrorCode status = U_ZERO_ERROR; 1276 DecimalFormat *fmt = new DecimalFormat(UnicodeString("000.0#0"), status); 1277 if(! U_FAILURE(status)) 1278 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\"")); 1279 /*} catch (Exception foo) { 1280 logln("Bug 4099404 pattern \"000.0#0\" passed"); 1281 }*/ 1282 delete fmt; 1283 fmt = 0; 1284 //try { 1285 fmt = new DecimalFormat(UnicodeString("0#0.000"), status); 1286 if( !U_FAILURE(status)) 1287 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\""); 1288 /*} catch (Exception foo) { 1289 logln("Bug 4099404 pattern \"0#0.000\" passed"); 1290 }*/ 1291 1292 delete fmt; 1293 } 1294 /* @bug 4101481 1295 * DecimalFormat.applyPattern doesn't set minimum integer digits 1296 */ 1297 void NumberFormatRegressionTest::Test4101481(void) 1298 { 1299 UErrorCode status = U_ZERO_ERROR; 1300 DecimalFormat *sdf = new DecimalFormat(UnicodeString("#,##0"), status); 1301 if(U_FAILURE(status)) { 1302 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1303 delete sdf; 1304 return; 1305 } 1306 failure(status, "new DecimalFormat"); 1307 if (sdf->getMinimumIntegerDigits() != 1) 1308 errln("Minimum integer digits : " + sdf->getMinimumIntegerDigits()); 1309 delete sdf; 1310 } 1311 /* @bug 4052223 (API addition request A27) 1312 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition(). 1313 */ 1314 void NumberFormatRegressionTest::Test4052223(void) 1315 { 1316 //try { 1317 UErrorCode status = U_ZERO_ERROR; 1318 DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,#00.00"), status); 1319 if(U_FAILURE(status)) { 1320 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1321 delete fmt; 1322 return; 1323 } 1324 failure(status, "new DecimalFormat"); 1325 Formattable num; 1326 fmt->parse(UnicodeString("abc3"), num, status); 1327 if(! U_FAILURE(status)) 1328 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/); 1329 /*} catch (ParseException foo) { 1330 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset()); 1331 }*/ 1332 delete fmt; 1333 } 1334 /* @bug 4061302 1335 * API tests for API addition request A9. 1336 */ 1337 void NumberFormatRegressionTest::Test4061302(void) 1338 { 1339 UErrorCode status = U_ZERO_ERROR; 1340 DecimalFormatSymbols *fmt = new DecimalFormatSymbols(status); 1341 failure(status, "new DecimalFormatSymbols"); 1342 UnicodeString currency(fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol)); 1343 UnicodeString intlCurrency(fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1344 UnicodeString monDecSeparator(fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol)); 1345 if (currency == UnicodeString("") || 1346 intlCurrency == UnicodeString("") || 1347 monDecSeparator == UnicodeString("")) 1348 { 1349 errln("getCurrencySymbols failed, got empty string."); 1350 } 1351 UnicodeString monDecSeparatorStr; 1352 monDecSeparatorStr.append(monDecSeparator); 1353 logln((UnicodeString)"Before set ==> Currency : " + currency +(UnicodeString)" Intl Currency : " + intlCurrency + (UnicodeString)" Monetary Decimal Separator : " + monDecSeparatorStr); 1354 fmt->setSymbol(DecimalFormatSymbols::kCurrencySymbol, UnicodeString("XYZ")); 1355 fmt->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, UnicodeString("ABC")); 1356 fmt->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, UnicodeString((UChar)0x002A/*'*'*/)); 1357 currency = fmt->getSymbol(DecimalFormatSymbols::kCurrencySymbol); 1358 intlCurrency = fmt->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); 1359 monDecSeparator = fmt->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 1360 if (currency != UnicodeString("XYZ") || 1361 intlCurrency != UnicodeString("ABC") || 1362 monDecSeparator != UnicodeString((UChar)0x002A/*'*'*/)) { 1363 errln("setCurrencySymbols failed."); 1364 } 1365 monDecSeparatorStr.remove(); 1366 monDecSeparatorStr.append(monDecSeparator); 1367 logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparatorStr); 1368 1369 delete fmt; 1370 } 1371 /* @bug 4062486 1372 * API tests for API addition request A23. FieldPosition.getBeginIndex and 1373 * FieldPosition.getEndIndex. 1374 */ 1375 void NumberFormatRegressionTest::Test4062486(void) 1376 { 1377 UErrorCode status = U_ZERO_ERROR; 1378 DecimalFormat *fmt = new DecimalFormat(UnicodeString("#,##0.00"), status); 1379 failure(status, "new DecimalFormat"); 1380 UnicodeString formatted; 1381 FieldPosition field(0); 1382 double num = 1234.5; 1383 fmt->format(num, formatted, field); 1384 if (field.getBeginIndex() != 0 && field.getEndIndex() != 5) 1385 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/); 1386 field.setBeginIndex(7); 1387 field.setEndIndex(4); 1388 if (field.getBeginIndex() != 7 && field.getEndIndex() != 4) 1389 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/); 1390 1391 delete fmt; 1392 } 1393 1394 /* @bug 4108738 1395 * DecimalFormat.parse incorrectly works with a group separator. 1396 */ 1397 void NumberFormatRegressionTest::Test4108738(void) 1398 { 1399 UErrorCode status = U_ZERO_ERROR; 1400 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getUS(), status); 1401 failure(status, "new DecimalFormatSymbols"); 1402 DecimalFormat *df = new DecimalFormat("#,##0.###", syms, status); 1403 if(U_FAILURE(status)) { 1404 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1405 delete df; 1406 return; 1407 } 1408 failure(status, "new DecimalFormat"); 1409 UnicodeString text("1.222,111"); 1410 Formattable num; 1411 ParsePosition pp(0); 1412 df->parse(text, num, pp); 1413 1414 // {sfb} how to do this (again) ? 1415 // shouldn't just be another round-trip test, should it? 1416 UnicodeString temp; 1417 FieldPosition pos(FieldPosition::DONT_CARE); 1418 temp = df->format(num.getDouble(), temp, pos); 1419 //if (!num.toString().equals("1.222")) 1420 if (temp != UnicodeString("1.222")) 1421 //errln("\"" + text + "\" is parsed as " + num); 1422 errln("\"" + text + "\" is parsed as " + temp); 1423 text = UnicodeString("1.222x111"); 1424 pp = ParsePosition(0); 1425 df->parse(text, num, pp); 1426 temp.remove(); 1427 temp = df->format(num.getDouble(), temp, pos); 1428 //if (!num.toString().equals("1.222")) 1429 if (temp != UnicodeString("1.222")) 1430 errln("\"" + text + "\" is parsed as " + temp); 1431 1432 delete df; 1433 } 1434 1435 /* @bug 4106658 1436 * DecimalFormat.format() incorrectly formats negative doubles. 1437 */ 1438 void NumberFormatRegressionTest::Test4106658(void) 1439 { 1440 UErrorCode status = U_ZERO_ERROR; 1441 DecimalFormat *df = new DecimalFormat(status); // Corrected; see 4147706 1442 if(U_FAILURE(status)) { 1443 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1444 delete df; 1445 return; 1446 } 1447 failure(status, "new DecimalFormat"); 1448 volatile double d1 = 0.0; // volatile to prevent code optimization 1449 double d2 = -0.0001; 1450 UnicodeString buffer; 1451 UnicodeString temp; 1452 FieldPosition pos(FieldPosition::DONT_CARE); 1453 1454 #if defined(U_HPUX) 1455 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword 1456 #else 1457 d1 *= -1.0; // Some compilers have a problem with defining -0.0 1458 #endif 1459 logln("pattern: \"" + df->toPattern(temp) + "\""); 1460 df->format(d1, buffer, pos); 1461 if (buffer != UnicodeString("-0")) // Corrected; see 4147706 1462 errln(UnicodeString("") + d1 + " is formatted as " + buffer); 1463 buffer.remove(); 1464 df->format(d2, buffer, pos); 1465 if (buffer != UnicodeString("-0")) // Corrected; see 4147706 1466 errln(UnicodeString("") + d2 + " is formatted as " + buffer); 1467 1468 delete df; 1469 } 1470 1471 /* @bug 4106662 1472 * DecimalFormat.parse returns 0 if string parameter is incorrect. 1473 */ 1474 void NumberFormatRegressionTest::Test4106662(void) 1475 { 1476 UErrorCode status = U_ZERO_ERROR; 1477 DecimalFormat *df = new DecimalFormat(status); 1478 if(U_FAILURE(status)) { 1479 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1480 delete df; 1481 return; 1482 } 1483 failure(status, "new DecimalFormat"); 1484 UnicodeString text("x"); 1485 ParsePosition pos1(0), pos2(0); 1486 1487 UnicodeString temp; 1488 logln("pattern: \"" + df->toPattern(temp) + "\""); 1489 Formattable num; 1490 df->parse(text, num, pos1); 1491 if (pos1 == ParsePosition(0)/*num != null*/) { 1492 errln(UnicodeString("Test Failed: \"") + text + "\" is parsed as " /*+ num*/); 1493 } 1494 delete df; 1495 df = new DecimalFormat(UnicodeString("$###.00"), status); 1496 failure(status, "new DecimalFormat"); 1497 df->parse(UnicodeString("$"), num, pos2); 1498 if (pos2 == ParsePosition(0) /*num != null*/){ 1499 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/); 1500 } 1501 1502 delete df; 1503 } 1504 1505 /* @bug 4114639 (duplicate of 4106662) 1506 * NumberFormat.parse doesn't return null 1507 */ 1508 void NumberFormatRegressionTest::Test4114639(void) 1509 { 1510 UErrorCode status = U_ZERO_ERROR; 1511 NumberFormat *format = NumberFormat::createInstance(status); 1512 if(U_FAILURE(status)) { 1513 dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); 1514 delete format; 1515 return; 1516 } 1517 failure(status, "NumberFormat::createInstance"); 1518 UnicodeString text("time 10:x"); 1519 ParsePosition pos(8); 1520 Formattable result; 1521 format->parse(text, result, pos); 1522 if (/*result != null*/pos.getErrorIndex() != 8) 1523 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't 1524 1525 delete format; 1526 } 1527 1528 /* @bug 4106664 1529 * TODO: this test does not work because we need to use a 64 bit number and a 1530 * a double only MAY only have 52 bits of precision. 1531 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG. 1532 */ 1533 void NumberFormatRegressionTest::Test4106664(void) 1534 { 1535 UErrorCode status = U_ZERO_ERROR; 1536 DecimalFormat *df = new DecimalFormat(status); 1537 if(U_FAILURE(status)) { 1538 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1539 delete df; 1540 return; 1541 } 1542 failure(status, "new DecimalFormat"); 1543 // {sfb} long in java is 64 bits 1544 /*long*/double n = 1234567890123456.0; 1545 /*int*/int32_t m = 12345678; 1546 // {sfb} will this work? 1547 //BigInteger bigN = BigInteger.valueOf(n); 1548 //bigN = bigN.multiply(BigInteger.valueOf(m)); 1549 double bigN = n * m; 1550 df->setMultiplier(m); 1551 df->setGroupingUsed(FALSE); 1552 UnicodeString temp; 1553 FieldPosition pos(FieldPosition::DONT_CARE); 1554 logln("formated: " + 1555 df->format(n, temp, pos)); 1556 1557 char buf [128]; 1558 sprintf(buf, "%g", bigN); 1559 //logln("expected: " + bigN.toString()); 1560 logln(UnicodeString("expected: ") + buf); 1561 1562 delete df; 1563 } 1564 /* @bug 4106667 (duplicate of 4106658) 1565 * DecimalFormat.format incorrectly formats -0.0. 1566 */ 1567 void NumberFormatRegressionTest::Test4106667(void) 1568 { 1569 UErrorCode status = U_ZERO_ERROR; 1570 DecimalFormat *df = new DecimalFormat(status); 1571 if(U_FAILURE(status)) { 1572 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1573 delete df; 1574 return; 1575 } 1576 failure(status, "new DecimalFormat"); 1577 UChar foo [] = { 0x002B }; 1578 UnicodeString bar(foo, 1, 1); 1579 volatile double d = 0.0; // volatile to prevent code optimization 1580 UnicodeString temp; 1581 UnicodeString buffer; 1582 FieldPosition pos(FieldPosition::DONT_CARE); 1583 1584 logln("pattern: \"" + df->toPattern(temp) + "\""); 1585 #if defined(U_HPUX) 1586 d = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword 1587 #else 1588 d *= -1.0; // Some compilers have a problem with defining -0.0 1589 #endif 1590 df->setPositivePrefix(/*"+"*/bar); 1591 df->format(d, buffer, pos); 1592 if (buffer != UnicodeString("-0")) // Corrected; see 4147706 1593 errln(/*d + */UnicodeString(" is formatted as ") + buffer); 1594 1595 delete df; 1596 } 1597 1598 /* @bug 4110936 1599 * DecimalFormat.setMaximumIntegerDigits() works incorrectly. 1600 */ 1601 #ifdef OS390 1602 # define MAX_INT_DIGITS 70 1603 #else 1604 # define MAX_INT_DIGITS 128 1605 #endif 1606 1607 void NumberFormatRegressionTest::Test4110936(void) 1608 { 1609 UErrorCode status = U_ZERO_ERROR; 1610 NumberFormat *nf = NumberFormat::createInstance(status); 1611 if(U_FAILURE(status)) { 1612 dataerrln("Error creating DecimalFormat: %s", u_errorName(status)); 1613 delete nf; 1614 return; 1615 } 1616 failure(status, "NumberFormat::createInstance"); 1617 nf->setMaximumIntegerDigits(MAX_INT_DIGITS); 1618 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)"); 1619 if (nf->getMaximumIntegerDigits() != MAX_INT_DIGITS) 1620 errln("getMaximumIntegerDigits() returns " + 1621 nf->getMaximumIntegerDigits()); 1622 1623 delete nf; 1624 } 1625 1626 /* @bug 4122840 1627 * Locale data should use generic currency symbol 1628 * 1629 * 1) Make sure that all currency formats use the generic currency symbol. 1630 * 2) Make sure we get the same results using the generic symbol or a 1631 * hard-coded one. 1632 */ 1633 void NumberFormatRegressionTest::Test4122840(void) 1634 { 1635 int32_t count = 0; 1636 const Locale *locales = Locale::getAvailableLocales(count); 1637 1638 for (int i = 0; i < count; i++) { 1639 UErrorCode status = U_ZERO_ERROR; 1640 ResourceBundle *rb = new ResourceBundle( 1641 NULL/*"java.text.resources.LocaleElements"*/, 1642 locales[i], status); 1643 failure(status, "new ResourceBundle"); 1644 ResourceBundle numPat = rb->get("NumberPatterns", status); 1645 failure(status, "new ResourceBundle(NumberPatterns)"); 1646 // 1647 // Get the currency pattern for this locale. We have to fish it 1648 // out of the ResourceBundle directly, since DecimalFormat.toPattern 1649 // will return the localized symbol, not \00a4 1650 // 1651 UnicodeString pattern = numPat.getStringEx(1, status); 1652 failure(status, "rb->getStringArray"); 1653 1654 UChar fo[] = { 0x00A4 }; 1655 UnicodeString foo(fo, 1, 1); 1656 1657 //if (pattern.indexOf("\u00A4") == -1 ) { 1658 if (pattern.indexOf(foo) == -1 ) { 1659 errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) + 1660 " does not contain generic currency symbol:" + 1661 pattern ); 1662 } 1663 1664 // Create a DecimalFormat using the pattern we got and format a number 1665 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status); 1666 failure(status, "new DecimalFormatSymbols"); 1667 DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status); 1668 failure(status, "new DecimalFormat"); 1669 1670 UnicodeString result1; 1671 FieldPosition pos(FieldPosition::DONT_CARE); 1672 result1 = fmt1->format(1.111, result1, pos); 1673 1674 // 1675 // Now substitute in the locale's currency symbol and create another 1676 // pattern. We have to skip locales where the currency symbol 1677 // contains decimal separators, because that confuses things 1678 // 1679 UChar ba[] = { 0x002E/*'.'*/ }; 1680 UnicodeString bar(ba, 1, 1); 1681 1682 if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) { 1683 // {sfb} Also, switch the decimal separator to the monetary decimal 1684 // separator to mimic the behavior of a currency format 1685 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, 1686 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol)); 1687 1688 UnicodeString buf(pattern); 1689 for (int j = 0; j < buf.length(); j++) { 1690 if (buf[j] == 0x00a4 ) { 1691 if(buf[j + 1] == 0x00a4) { 1692 // {sfb} added to support double currency marker (intl currency sign) 1693 buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1694 j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length(); 1695 } 1696 else { 1697 buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol)); 1698 j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1; 1699 } 1700 } 1701 } 1702 1703 DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status); 1704 failure(status, "new DecimalFormat"); 1705 1706 // Get the currency (if there is one) so we can set the rounding and fraction 1707 const UChar *currency = fmt1->getCurrency(); 1708 if (*currency != 0) { 1709 double rounding = ucurr_getRoundingIncrement(currency, &status); 1710 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status); 1711 if (U_SUCCESS(status)) { 1712 fmt2->setRoundingIncrement(rounding); 1713 fmt2->setMinimumFractionDigits(frac); 1714 fmt2->setMaximumFractionDigits(frac); 1715 } 1716 else { 1717 failure(status, "Fetching currency rounding/fractions"); 1718 } 1719 } 1720 1721 UnicodeString result2; 1722 fmt2->format(1.111, result2, pos); 1723 1724 if (result1 != result2) { 1725 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " + 1726 result1 + " vs " + result2); 1727 } 1728 1729 delete fmt2; 1730 } 1731 1732 delete rb; 1733 delete fmt1; 1734 delete symbols; 1735 } 1736 } 1737 1738 /* @bug 4125885 1739 * DecimalFormat.format() delivers wrong string. 1740 */ 1741 void NumberFormatRegressionTest::Test4125885(void) 1742 { 1743 UErrorCode status = U_ZERO_ERROR; 1744 double rate = 12.34; 1745 DecimalFormat *formatDec = new DecimalFormat ("000.00", status); 1746 if(U_FAILURE(status)) { 1747 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1748 delete formatDec; 1749 return; 1750 } 1751 failure(status, "new DecimalFormat"); 1752 UnicodeString temp; 1753 logln("toPattern: " + formatDec->toPattern(temp)); 1754 UnicodeString rateString; 1755 FieldPosition pos(FieldPosition::DONT_CARE); 1756 rateString = formatDec->format(rate, rateString, pos); 1757 if (rateString != UnicodeString("012.34")) 1758 errln("result : " + rateString + " expected : 012.34"); 1759 rate = 0.1234; 1760 delete formatDec;// = null; 1761 formatDec = new DecimalFormat ("+000.00%;-000.00%", status); 1762 failure(status, "new DecimalFormat"); 1763 logln("toPattern: " + formatDec->toPattern(temp)); 1764 rateString.remove(); 1765 rateString = formatDec->format(rate, rateString, pos); 1766 if (rateString != UnicodeString("+012.34%")) 1767 errln("result : " + rateString + " expected : +012.34%"); 1768 1769 delete formatDec; 1770 } 1771 1772 /** 1773 * @bug 4134034 1774 * DecimalFormat produces extra zeros when formatting numbers. 1775 */ 1776 void NumberFormatRegressionTest::Test4134034(void) 1777 { 1778 UErrorCode status = U_ZERO_ERROR; 1779 DecimalFormat *nf = new DecimalFormat("##,###,###.00", status); 1780 if (!failure(status, "new DecimalFormat")) { 1781 UnicodeString f; 1782 FieldPosition pos(FieldPosition::DONT_CARE); 1783 f = nf->format(9.02, f, pos); 1784 if (f == UnicodeString("9.02")) 1785 logln(f + " ok"); 1786 else 1787 errln("9.02 -> " + f + "; want 9.02"); 1788 1789 f.remove(); 1790 f = nf->format((int32_t)0, f, pos); 1791 if (f == UnicodeString(".00")) 1792 logln(f + " ok"); 1793 else 1794 errln("0 -> " + f + "; want .00"); 1795 } 1796 1797 delete nf; 1798 } 1799 1800 /** 1801 * @bug 4134300 1802 * CANNOT REPRODUCE - This bug could not be reproduced. It may be 1803 * a duplicate of 4134034. 1804 * 1805 * JDK 1.1.6 Bug, did NOT occur in 1.1.5 1806 * Possibly related to bug 4125885. 1807 * 1808 * This class demonstrates a regression in version 1.1.6 1809 * of DecimalFormat class. 1810 * 1811 * 1.1.6 Results 1812 * Value 1.2 Format #.00 Result '01.20' !!!wrong 1813 * Value 1.2 Format 0.00 Result '001.20' !!!wrong 1814 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong 1815 * Value 1.2 Format #0.0# Result '1.2' 1816 * Value 1.2 Format #0.00 Result '001.20' !!!wrong 1817 * 1818 * 1.1.5 Results 1819 * Value 1.2 Format #.00 Result '1.20' 1820 * Value 1.2 Format 0.00 Result '1.20' 1821 * Value 1.2 Format 00.00 Result '01.20' 1822 * Value 1.2 Format #0.0# Result '1.2' 1823 * Value 1.2 Format #0.00 Result '1.20' 1824 */ 1825 void NumberFormatRegressionTest::Test4134300(void) { 1826 UnicodeString DATA [] = { 1827 // Pattern Expected string 1828 UnicodeString("#.00"), UnicodeString("1.20"), 1829 UnicodeString("0.00"), UnicodeString("1.20"), 1830 UnicodeString("00.00"), UnicodeString("01.20"), 1831 UnicodeString("#0.0#"), UnicodeString("1.2"), 1832 UnicodeString("#0.00"), UnicodeString("1.20") 1833 }; 1834 1835 for (int i=0; i< 10; i+=2) { 1836 UnicodeString result; 1837 UErrorCode status = U_ZERO_ERROR; 1838 DecimalFormat *df = new DecimalFormat(DATA[i], status); 1839 if (!failure(status, "new DecimalFormat")) { 1840 FieldPosition pos(FieldPosition::DONT_CARE); 1841 result = df->format(1.2, result, pos); 1842 if (result != DATA[i+1]) { 1843 errln("Fail: 1.2 x " + DATA[i] + " = " + result + 1844 "; want " + DATA[i+1]); 1845 } 1846 else { 1847 logln("Ok: 1.2 x " + DATA[i] + " = " + result); 1848 } 1849 } 1850 1851 delete df; 1852 } 1853 } 1854 1855 /** 1856 * @bug 4140009 1857 * Empty pattern produces double negative prefix. 1858 */ 1859 void NumberFormatRegressionTest::Test4140009(void) 1860 { 1861 UErrorCode status = U_ZERO_ERROR; 1862 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 1863 failure(status, "new DecimalFormatSymbols"); 1864 DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status); 1865 if (!failure(status, "new DecimalFormat")) { 1866 UnicodeString s; 1867 FieldPosition pos(FieldPosition::DONT_CARE); 1868 s = f->format(123.456, s, pos); 1869 if (s != UnicodeString("123.456")) 1870 errln("Fail: Format empty pattern x 123.456 => " + s); 1871 s.remove(); 1872 s = f->format(-123.456, s, pos); 1873 if (s != UnicodeString("-123.456")) 1874 errln("Fail: Format empty pattern x -123.456 => " + s); 1875 } 1876 delete f; 1877 } 1878 1879 /** 1880 * @bug 4141750 1881 * BigDecimal numbers get their fractions truncated by NumberFormat. 1882 */ 1883 // {sfb} not pertinent in C++ ?? 1884 void NumberFormatRegressionTest::Test4141750(void) { 1885 /*try { 1886 UnicodeString str("12345.67"); 1887 BigDecimal bd = new BigDecimal(str); 1888 String sd = NumberFormat.getInstance(Locale.US).format(bd); 1889 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd); 1890 } 1891 catch (Exception e) { 1892 errln(e.toString()); 1893 e.printStackTrace(); 1894 }*/ 1895 } 1896 1897 /** 1898 * @bug 4145457 1899 * DecimalFormat toPattern() doesn't quote special characters or handle 1900 * single quotes. 1901 */ 1902 void NumberFormatRegressionTest::Test4145457() { 1903 //try { 1904 UErrorCode status = U_ZERO_ERROR; 1905 NumberFormat *nff = NumberFormat::createInstance(status); 1906 if (failure(status, "NumberFormat::createInstance", TRUE)){ 1907 delete nff; 1908 return; 1909 }; 1910 if(nff->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 1911 errln("DecimalFormat needed to continue"); 1912 return; 1913 } 1914 1915 DecimalFormat *nf = (DecimalFormat*)nff; 1916 DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols(); 1917 sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027); 1918 nf->setDecimalFormatSymbols(*sym); 1919 double pi = 3.14159; 1920 1921 UnicodeString PATS [] = { 1922 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''") 1923 }; 1924 1925 for (int32_t i=0; i<2; ++i) { 1926 nf->applyPattern(PATS[i], status); 1927 failure(status, "nf->applyPattern"); 1928 UnicodeString out; 1929 FieldPosition pos(FieldPosition::DONT_CARE); 1930 out = nf->format(pi, out, pos); 1931 UnicodeString pat; 1932 pat = nf->toPattern(pat); 1933 Formattable num; 1934 ParsePosition pp(0); 1935 nf->parse(out, num, pp); 1936 double val = num.getDouble(); 1937 1938 nf->applyPattern(pat, status); 1939 failure(status, "nf->applyPattern"); 1940 UnicodeString out2; 1941 out2 = nf->format(pi, out2, pos); 1942 UnicodeString pat2; 1943 pat2 = nf->toPattern(pat2); 1944 pp.setIndex(0); 1945 nf->parse(out2, num, pp); 1946 double val2 = num.getDouble(); 1947 1948 if (pat != pat2) 1949 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" + 1950 pat + "\" vs. \"" + pat2 + "\""); 1951 else 1952 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"'); 1953 1954 if (val == val2 && out == out2) { 1955 logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1956 out + "\" -> " + val + " -> \"" + 1957 out2 + "\" -> " + val2); 1958 } 1959 else { 1960 errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1961 out + "\" -> " + val + " -> \"" + 1962 out2 + "\" -> " + val2); 1963 } 1964 } 1965 /*} 1966 catch (ParseException e) { 1967 errln("Fail: " + e); 1968 e.printStackTrace(); 1969 }*/ 1970 1971 delete nff; 1972 } 1973 1974 /** 1975 * @bug 4147295 1976 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. 1977 * CANNOT REPRODUCE 1978 * This bug is a duplicate of 4139344, which is a duplicate of 4134300 1979 */ 1980 void NumberFormatRegressionTest::Test4147295(void) 1981 { 1982 UErrorCode status = U_ZERO_ERROR; 1983 DecimalFormat *sdf = new DecimalFormat(status); 1984 UnicodeString pattern("#,###"); 1985 logln("Applying pattern \"" + pattern + "\""); 1986 sdf->applyPattern(pattern, status); 1987 if (!failure(status, "sdf->applyPattern")) { 1988 int minIntDig = sdf->getMinimumIntegerDigits(); 1989 if (minIntDig != 0) { 1990 errln("Test failed"); 1991 errln(" Minimum integer digits : " + minIntDig); 1992 UnicodeString temp; 1993 errln(" new pattern: " + sdf->toPattern(temp)); 1994 } else { 1995 logln("Test passed"); 1996 logln(" Minimum integer digits : " + minIntDig); 1997 } 1998 } 1999 delete sdf; 2000 } 2001 2002 /** 2003 * @bug 4147706 2004 * DecimalFormat formats -0.0 as +0.0 2005 * See also older related bug 4106658, 4106667 2006 */ 2007 void NumberFormatRegressionTest::Test4147706(void) 2008 { 2009 UErrorCode status = U_ZERO_ERROR; 2010 DecimalFormat *df = new DecimalFormat("#,##0.0##", status); 2011 failure(status, "new DecimalFormat"); 2012 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 2013 if (!failure(status, "new DecimalFormatSymbols")) { 2014 UnicodeString f1; 2015 UnicodeString f2, temp; 2016 FieldPosition pos(FieldPosition::DONT_CARE); 2017 volatile double d1 = 0.0; // volatile to prevent code optimization 2018 double d2 = -0.0001; 2019 2020 #if defined(U_HPUX) 2021 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword 2022 #else 2023 d1 *= -1.0; // Some compilers have a problem with defining -0.0 2024 #endif 2025 df->adoptDecimalFormatSymbols(syms); 2026 f1 = df->format(d1, f1, pos); 2027 f2 = df->format(d2, f2, pos); 2028 if (f1 != UnicodeString("-0.0")) { 2029 errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"'); 2030 } 2031 if (f2 != UnicodeString("-0.0")) { 2032 errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"'); 2033 } 2034 } 2035 2036 delete df; 2037 } 2038 2039 2040 // Not applicable, since no serialization in C++ 2041 /*class myformat implements Serializable 2042 { 2043 DateFormat _dateFormat = DateFormat.getDateInstance(); 2044 2045 public String Now() 2046 { 2047 GregorianCalendar calendar = new GregorianCalendar(); 2048 Date t = calendar.getTime(); 2049 String nowStr = _dateFormat.format(t); 2050 return nowStr; 2051 } 2052 }*/ 2053 2054 /** 2055 * @bug 4162198 2056 * NumberFormat cannot format Double.MAX_VALUE 2057 */ 2058 // TODO: make this test actually test something 2059 void 2060 NumberFormatRegressionTest::Test4162198(void) 2061 { 2062 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof) 2063 double dbl = INT32_MAX * 1000.0; 2064 UErrorCode status = U_ZERO_ERROR; 2065 NumberFormat *f = NumberFormat::createInstance(status); 2066 if(U_FAILURE(status)) { 2067 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2068 return; 2069 } 2070 f->setMaximumFractionDigits(INT32_MAX); 2071 f->setMaximumIntegerDigits(INT32_MAX); 2072 UnicodeString s; 2073 f->format(dbl,s); 2074 logln(UnicodeString("The number ") + dbl + " formatted to " + s); 2075 Formattable n; 2076 //try { 2077 f->parse(s, n, status); 2078 if(U_FAILURE(status)) 2079 errln("Couldn't parse!"); 2080 //} catch (java.text.ParseException e) { 2081 // errln("Caught a ParseException:"); 2082 // e.printStackTrace(); 2083 //} 2084 2085 //logln("The string " + s + " parsed as " + n); 2086 2087 // {dlf} The old code assumes n is a double, but it isn't any more... 2088 // Formattable apparently does not and never did interconvert... too bad. 2089 //if(n.getDouble() != dbl) { 2090 // errln("Round trip failure"); 2091 //} 2092 if (n.getInt64() != dbl) { 2093 errln("Round trip failure"); 2094 } 2095 2096 delete f; 2097 } 2098 2099 /** 2100 * @bug 4162852 2101 * NumberFormat does not parse negative zero. 2102 */ 2103 void 2104 NumberFormatRegressionTest::Test4162852(void) 2105 { 2106 UErrorCode status = U_ZERO_ERROR; 2107 for(int32_t i=0; i < 2; ++i) { 2108 NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status) 2109 : NumberFormat::createPercentInstance(status); 2110 if(U_FAILURE(status)) { 2111 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2112 return; 2113 } 2114 double d = 0.0; 2115 d *= -1.0; 2116 UnicodeString s; 2117 f->format(d, s); 2118 Formattable n; 2119 f->parse(s, n, status); 2120 if(U_FAILURE(status)) 2121 errln("Couldn't parse!"); 2122 double e = n.getDouble(); 2123 logln(UnicodeString("") + 2124 d + " -> " + 2125 '"' + s + '"' + " -> " + e); 2126 #if (defined(OS390) && !defined(IEEE_754)) || defined(OS400) 2127 if (e != 0.0) { 2128 #else 2129 if (e != 0.0 || 1.0/e > 0.0) { 2130 #endif 2131 logln("Failed to parse negative zero"); 2132 } 2133 delete f; 2134 } 2135 } 2136 2137 static double _u_abs(double a) { return a<0?-a:a; } 2138 2139 /** 2140 * May 17 1999 sync up - liu 2141 * @bug 4167494 2142 * NumberFormat truncates data 2143 */ 2144 void NumberFormatRegressionTest::Test4167494(void) { 2145 UErrorCode status = U_ZERO_ERROR; 2146 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2147 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2148 delete fmt; 2149 return; 2150 }; 2151 2152 double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf 2153 UnicodeString s; 2154 fmt->format(a, s); 2155 Formattable num; 2156 fmt->parse(s, num, status); 2157 failure(status, "Parse"); 2158 if (num.getType() == Formattable::kDouble && 2159 _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1% 2160 logln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2161 toString(num) + " ok"); 2162 } else { 2163 errln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2164 toString(num) + " FAIL"); 2165 } 2166 2167 // We don't test Double.MIN_VALUE because the locale data for the US 2168 // currently doesn't specify enough digits to display Double.MIN_VALUE. 2169 // This is correct for now; however, we leave this here as a reminder 2170 // in case we want to address this later. 2171 2172 delete fmt; 2173 } 2174 2175 /** 2176 * May 17 1999 sync up - liu 2177 * @bug 4170798 2178 * DecimalFormat.parse() fails when ParseIntegerOnly set to true 2179 */ 2180 void NumberFormatRegressionTest::Test4170798(void) { 2181 UErrorCode status = U_ZERO_ERROR; 2182 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2183 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2184 delete nf; 2185 return; 2186 }; 2187 if(nf->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 2188 errln("DecimalFormat needed to continue"); 2189 return; 2190 } 2191 DecimalFormat *df = (DecimalFormat*) nf; 2192 df->setParseIntegerOnly(TRUE); 2193 Formattable n; 2194 ParsePosition pos(0); 2195 df->parse("-0.0", n, pos); 2196 if (n.getType() != Formattable::kLong 2197 || n.getLong() != 0) { 2198 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n)); 2199 } 2200 delete nf; 2201 } 2202 2203 /** 2204 * May 17 1999 sync up - liu 2205 * toPattern only puts the first grouping separator in. 2206 */ 2207 void NumberFormatRegressionTest::Test4176114(void) { 2208 const char* DATA[] = { 2209 "00", "#00", 2210 "000", "#000", // No grouping 2211 "#000", "#000", // No grouping 2212 "#,##0", "#,##0", 2213 "#,000", "#,000", 2214 "0,000", "#0,000", 2215 "00,000", "#00,000", 2216 "000,000", "#,000,000", 2217 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported 2218 }; 2219 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2220 UErrorCode status = U_ZERO_ERROR; 2221 UnicodeString s; 2222 for (int i=0; i<DATA_length; i+=2) { 2223 DecimalFormat df(DATA[i], status); 2224 if (!failure(status, "DecimalFormat constructor")) { 2225 df.toPattern(s); 2226 UnicodeString exp(DATA[i+1]); 2227 if (s != exp) { 2228 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " + 2229 s + ", want " + exp); 2230 } 2231 } 2232 } 2233 } 2234 2235 /** 2236 * May 17 1999 sync up - liu 2237 * @bug 4179818 2238 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 2239 */ 2240 void NumberFormatRegressionTest::Test4179818(void) { 2241 const char* DATA[] = { 2242 // Input Pattern Expected output 2243 "1.2511", "#.#", "1.3", 2244 "1.2501", "#.#", "1.3", 2245 "0.9999", "#", "1", 2246 }; 2247 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2248 double DOUBLE[] = { 2249 1.2511, 2250 1.2501, 2251 0.9999, 2252 }; 2253 UErrorCode status = U_ZERO_ERROR; 2254 DecimalFormatSymbols sym(Locale::getUS(), status); 2255 failure(status, "Construct DecimalFormatSymbols"); 2256 DecimalFormat fmt("#", sym, status); 2257 if (!failure(status, "Construct DecimalFormat")) { 2258 for (int i=0; i<DATA_length; i+=3) { 2259 double in = DOUBLE[i/3]; 2260 UnicodeString pat(DATA[i+1]); 2261 UnicodeString exp(DATA[i+2]); 2262 fmt.applyPattern(pat, status); 2263 failure(status, "applyPattern"); 2264 UnicodeString out; 2265 FieldPosition pos; 2266 fmt.format(in, out, pos); 2267 if (out == exp) { 2268 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out); 2269 } else { 2270 errln(UnicodeString("FAIL: ") + in + " x " + pat + " = " + out + 2271 ", expected " + exp); 2272 } 2273 } 2274 } 2275 } 2276 2277 /** 2278 * May 17 1999 sync up - liu 2279 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat. 2280 * This includes the minus sign, currency symbol, international currency 2281 * symbol, percent, and permille. This is filed as bugs 4212072 and 2282 * 4212073. 2283 */ 2284 void NumberFormatRegressionTest::Test4212072(void) { 2285 UErrorCode status = U_ZERO_ERROR; 2286 DecimalFormatSymbols sym(Locale::getUS(), status); 2287 2288 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2289 DecimalFormat fmt(UnicodeString("#"), sym, status); 2290 if(failure(status, "DecimalFormat ct", Locale::getUS())) { 2291 return; 2292 } 2293 2294 UnicodeString s; 2295 FieldPosition pos; 2296 2297 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e); 2298 fmt.setDecimalFormatSymbols(sym); 2299 s.remove(); 2300 if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) { 2301 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s + 2302 ", exp ^1"); 2303 } 2304 s.remove(); 2305 if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) { 2306 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") + 2307 s + ", exp ^"); 2308 } 2309 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d); 2310 2311 fmt.applyPattern(UnicodeString("#%"), status); 2312 failure(status, "applyPattern percent"); 2313 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e); 2314 fmt.setDecimalFormatSymbols(sym); 2315 s.remove(); 2316 if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) { 2317 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s + 2318 ", exp 25^"); 2319 } 2320 s.remove(); 2321 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2322 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") + 2323 s + ", exp ^"); 2324 } 2325 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25); 2326 2327 fmt.applyPattern(str("#\\u2030"), status); 2328 failure(status, "applyPattern permill"); 2329 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e); 2330 fmt.setDecimalFormatSymbols(sym); 2331 s.remove(); 2332 if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) { 2333 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s + 2334 ", exp 250^"); 2335 } 2336 s.remove(); 2337 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2338 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") + 2339 s + ", exp ^"); 2340 } 2341 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030); 2342 2343 fmt.applyPattern(str("\\u00A4#.00"), status); 2344 failure(status, "applyPattern currency"); 2345 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd"); 2346 fmt.setDecimalFormatSymbols(sym); 2347 s.remove(); 2348 if (fmt.format(12.5, s, pos) != UnicodeString("usd12.50")) { 2349 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s + 2350 ", exp usd12.50"); 2351 } 2352 s.remove(); 2353 if (fmt.getPositivePrefix(s) != UnicodeString("usd")) { 2354 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") + 2355 s + ", exp usd"); 2356 } 2357 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$"); 2358 2359 fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status); 2360 failure(status, "applyPattern intl currency"); 2361 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL"); 2362 fmt.setDecimalFormatSymbols(sym); 2363 s.remove(); 2364 if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) { 2365 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s + 2366 ", exp DOL12.50"); 2367 } 2368 s.remove(); 2369 if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) { 2370 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") + 2371 s + ", exp DOL"); 2372 } 2373 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD"); 2374 2375 // Since the pattern logic has changed, make sure that patterns round 2376 // trip properly. Test stream in/out integrity too. 2377 int32_t n; 2378 const Locale* avail = NumberFormat::getAvailableLocales(n); 2379 static const char* type[] = { 2380 "", 2381 "$ ", 2382 "% ", 2383 }; 2384 for (int i=0; i<n; ++i) { 2385 for (int j=0; j<3; ++j) { 2386 status = U_ZERO_ERROR; 2387 NumberFormat *nf; 2388 switch (j) { 2389 case 0: 2390 nf = NumberFormat::createInstance(avail[i], status); 2391 failure(status, "createInstance", avail[i]); 2392 break; 2393 case 1: 2394 nf = NumberFormat::createCurrencyInstance(avail[i], status); 2395 failure(status, "createCurrencyInstance", avail[i]); 2396 break; 2397 default: 2398 nf = NumberFormat::createPercentInstance(avail[i], status); 2399 failure(status, "createPercentInstance", avail[i]); 2400 break; 2401 } 2402 if (U_FAILURE(status)) { 2403 continue; 2404 } 2405 DecimalFormat *df = (DecimalFormat*) nf; 2406 2407 // Test toPattern/applyPattern round trip 2408 UnicodeString pat; 2409 df->toPattern(pat); 2410 DecimalFormatSymbols symb(avail[i], status); 2411 failure(status, "Construct DecimalFormatSymbols", avail[i]); 2412 DecimalFormat f2(pat, symb, status); 2413 if (failure(status, 2414 UnicodeString("Construct DecimalFormat(") + pat + ")")) { 2415 continue; 2416 } 2417 if (*df != f2) { 2418 UnicodeString l, p; 2419 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2420 " -> \"" + pat + 2421 "\" -> \"" + f2.toPattern(p) + "\""); 2422 } 2423 2424 // Test toLocalizedPattern/applyLocalizedPattern round trip 2425 df->toLocalizedPattern(pat); 2426 f2.applyLocalizedPattern(pat, status); 2427 failure(status, 2428 UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]); 2429 if (U_FAILURE(status)) { 2430 continue; 2431 } 2432 2433 // Make sure we set the currency attributes appropriately 2434 if (j == 1) { // Currency format 2435 f2.setCurrency(f2.getCurrency(), status); 2436 } 2437 failure(status, 2438 UnicodeString("setCurrency() for (") + pat + ")", avail[i]); 2439 if (U_FAILURE(status)) { 2440 continue; 2441 } 2442 2443 if (*df != f2) { 2444 UnicodeString l, p; 2445 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2446 " -> localized \"" + pat + 2447 "\" -> \"" + f2.toPattern(p) + "\""); 2448 } 2449 2450 delete nf; 2451 2452 // Test writeObject/readObject round trip 2453 // NOT ON ICU -- Java only 2454 } 2455 } 2456 } 2457 2458 /** 2459 * May 17 1999 sync up - liu 2460 * DecimalFormat.parse() fails for mulipliers 2^n. 2461 */ 2462 void NumberFormatRegressionTest::Test4216742(void) { 2463 UErrorCode status = U_ZERO_ERROR; 2464 DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status); 2465 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2466 delete fmt; 2467 return; 2468 }; 2469 int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 }; 2470 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2471 for (int i=0; i<DATA_length; ++i) { 2472 UnicodeString str((UnicodeString)"" + DATA[i]); 2473 for (int m = 1; m <= 100; m++) { 2474 fmt->setMultiplier(m); 2475 Formattable num; 2476 fmt->parse(str, num, status); 2477 failure(status, "parse", Locale::getUS()); 2478 if (num.getType() != Formattable::kLong && 2479 num.getType() != Formattable::kDouble) { 2480 errln(UnicodeString("FAIL: Wanted number, got ") + 2481 toString(num)); 2482 } else { 2483 double d = num.getType() == Formattable::kDouble ? 2484 num.getDouble() : (double) num.getLong(); 2485 if (d > 0 != DATA[i] > 0) { 2486 errln(UnicodeString("\"") + str + "\" parse(x " + 2487 fmt->getMultiplier() + 2488 ") => " + toString(num)); 2489 } 2490 } 2491 } 2492 } 2493 delete fmt; 2494 } 2495 2496 /** 2497 * May 17 1999 sync up - liu 2498 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction 2499 * digits. 2500 */ 2501 void NumberFormatRegressionTest::Test4217661(void) { 2502 const double D[] = { 0.001, 1.001, 0.006, 1.006 }; 2503 const char* S[] = { "0", "1", "0.01", "1.01" }; 2504 int D_length = (int)(sizeof(D) / sizeof(D[0])); 2505 UErrorCode status = U_ZERO_ERROR; 2506 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2507 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2508 delete fmt; 2509 return; 2510 }; 2511 fmt->setMaximumFractionDigits(2); 2512 for (int i=0; i<D_length; i++) { 2513 UnicodeString s; 2514 fmt->format(D[i], s); 2515 if (s != UnicodeString(S[i])) { 2516 errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]); 2517 } 2518 } 2519 delete fmt; 2520 } 2521 2522 /** 2523 * alphaWorks upgrade 2524 */ 2525 void NumberFormatRegressionTest::Test4161100(void) { 2526 UErrorCode status = U_ZERO_ERROR; 2527 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2528 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2529 delete nf; 2530 return; 2531 }; 2532 nf->setMinimumFractionDigits(1); 2533 nf->setMaximumFractionDigits(1); 2534 double a = -0.09; 2535 UnicodeString s; 2536 nf->format(a, s); 2537 UnicodeString pat; 2538 logln(UnicodeString() + a + " x " + 2539 ((DecimalFormat*) nf)->toPattern(pat) + " = " + s); 2540 if (s != UnicodeString("-0.1")) { 2541 errln("FAIL"); 2542 } 2543 delete nf; 2544 } 2545 2546 /** 2547 * June 16 1999 sync up - liu 2548 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1) 2549 */ 2550 void NumberFormatRegressionTest::Test4243011(void) { 2551 UErrorCode status = U_ZERO_ERROR; 2552 DecimalFormatSymbols sym(Locale::getUS(), status); 2553 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2554 DecimalFormat fmt(UnicodeString("0."), sym, status); 2555 2556 if (!failure(status, "DecimalFormat ct", Locale::getUS())) { 2557 const double NUM[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 }; 2558 const char* STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." }; 2559 int32_t N = (int32_t)(sizeof(NUM) / sizeof(NUM[0])); 2560 2561 for (int32_t i=0; i<N; ++i) { 2562 UnicodeString str; 2563 UnicodeString exp(STR[i]); 2564 FieldPosition pos; 2565 fmt.format(NUM[i], str, pos); 2566 if (str == exp) { 2567 logln(UnicodeString("Ok ") + NUM[i] + " x 0. = " + str); 2568 } else { 2569 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str + 2570 ", want " + exp); 2571 } 2572 } 2573 } 2574 } 2575 2576 /** 2577 * June 16 1999 sync up - liu 2578 * format(0.0) gives "0.1" if preceded by parse("99.99"). 2579 * (Regression in 1.2.2 RC1) 2580 */ 2581 void NumberFormatRegressionTest::Test4243108(void) { 2582 UErrorCode status = U_ZERO_ERROR; 2583 DecimalFormatSymbols sym(Locale::getUS(), status); 2584 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2585 DecimalFormat fmt(UnicodeString("#.#"), sym, status); 2586 if (failure(status, "DecimalFormat ct", Locale::getUS())) { 2587 return; 2588 } 2589 2590 UnicodeString str; 2591 FieldPosition pos; 2592 2593 fmt.format(0.0, str, pos); 2594 UnicodeString exp("0"); 2595 if (str == exp) { 2596 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2597 } else { 2598 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2599 ", want " + exp); 2600 } 2601 2602 str = "99.99"; 2603 Formattable val; 2604 fmt.parse(str, val, status); 2605 failure(status, "DecimalFormat.parse(99.99)", Locale::getUS()); 2606 if (val.getType() == Formattable::kDouble && 2607 val.getDouble() == 99.99) { 2608 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val)); 2609 } else { 2610 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) + 2611 ", want " + 99.99); 2612 } 2613 2614 str.remove(); 2615 fmt.format(0.0, str, pos); 2616 if (str == exp) { 2617 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2618 } else { 2619 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2620 ", want " + exp); 2621 } 2622 } 2623 2624 2625 /** 2626 * DateFormat should call setIntegerParseOnly(TRUE) on adopted 2627 * NumberFormat objects. 2628 */ 2629 void NumberFormatRegressionTest::TestJ691(void) { 2630 UErrorCode status = U_ZERO_ERROR; 2631 Locale loc("fr", "CH"); 2632 2633 // set up the input date string & expected output 2634 UnicodeString udt("11.10.2000", ""); 2635 UnicodeString exp("11.10.00", ""); 2636 2637 // create a Calendar for this locale 2638 Calendar *cal = Calendar::createInstance(loc, status); 2639 if (U_FAILURE(status)) { 2640 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status)); 2641 return; 2642 } 2643 2644 // create a NumberFormat for this locale 2645 NumberFormat *nf = NumberFormat::createInstance(loc, status); 2646 if (U_FAILURE(status)) { 2647 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2648 return; 2649 } 2650 2651 // *** Here's the key: We don't want to have to do THIS: 2652 // nf->setParseIntegerOnly(TRUE); 2653 2654 // create the DateFormat 2655 DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc); 2656 if (U_FAILURE(status)) { 2657 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2658 return; 2659 } 2660 2661 df->adoptCalendar(cal); 2662 df->adoptNumberFormat(nf); 2663 2664 // set parsing to lenient & parse 2665 df->setLenient(TRUE); 2666 UDate ulocdat = df->parse(udt, status); 2667 2668 // format back to a string 2669 UnicodeString outString; 2670 df->format(ulocdat, outString); 2671 2672 if (outString != exp) { 2673 errln("FAIL: " + udt + " => " + outString); 2674 } 2675 2676 delete df; 2677 } 2678 2679 #endif /* #if !UCONFIG_NO_FORMATTING */ 2680