1/*********************************************************************** 2 * Copyright (c) 1997-2011, 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 24class MyNumberFormatTest : public NumberFormat 25{ 26public: 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 92int32_t gMyNumberFormatTestClassID; 93UClassID 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 105void 106NumberFormatRegressionTest::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 CASE(61,Test8199); 172 173 default: name = ""; break; 174 } 175} 176 177UBool 178NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const Locale& l, UBool possibleDataError) 179{ 180 if(U_FAILURE(status)) { 181 if (possibleDataError) { 182 dataerrln(UnicodeString("FAIL: ", "") + msg 183 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 184 } else { 185 errcheckln(status, UnicodeString("FAIL: ", "") + msg 186 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 187 } 188 return TRUE; 189 } 190 191 return FALSE; 192} 193 194UBool 195NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const char *l, UBool possibleDataError) 196{ 197 if(U_FAILURE(status)) { 198 if (possibleDataError) { 199 dataerrln(UnicodeString("FAIL: ", "") + msg 200 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 201 } else { 202 errcheckln(status, UnicodeString("FAIL: ", "") + msg 203 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 204 } 205 return TRUE; 206 } 207 208 return FALSE; 209} 210 211UBool 212NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, UBool possibleDataError) 213{ 214 if(U_FAILURE(status)) { 215 if (possibleDataError) { 216 dataerrln(UnicodeString("FAIL: ", "") + msg 217 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 218 } else { 219 errcheckln(status, UnicodeString("FAIL: ", "") + msg 220 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 221 } 222 return TRUE; 223 } 224 225 return FALSE; 226} 227 228/** 229 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects 230 */ 231inline UnicodeString str(const char *input) 232{ 233 return CharsToUnicodeString(input); 234} 235 236/* @bug 4075713 237 * NumberFormat.equals comparing with null should always return false. 238 */ 239// {sfb} kind of silly in C++, just checking for new success 240void NumberFormatRegressionTest::Test4075713(void) 241{ 242 //try { 243 MyNumberFormatTest *tmp = new MyNumberFormatTest(); 244 if(tmp != NULL) 245 logln("NumberFormat.equals passed"); 246 /*} catch (NullPointerException e) { 247 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); 248 }*/ 249 250 delete tmp; 251} 252 253/* @bug 4074620 254 * NumberFormat.equals comparing two obj equal even the setGroupingUsed 255 * flag is different. 256 */ 257void NumberFormatRegressionTest::Test4074620(void) 258{ 259 260 MyNumberFormatTest *nf1 = new MyNumberFormatTest(); 261 MyNumberFormatTest *nf2 = new MyNumberFormatTest(); 262 263 nf1->setGroupingUsed(FALSE); 264 nf2->setGroupingUsed(TRUE); 265 266 if(nf1 == nf2) 267 errln("Test for bug 4074620 failed"); 268 else 269 logln("Test for bug 4074620 passed."); 270 271 delete nf1; 272 delete nf2; 273} 274 275 276/* @bug 4088161 277 * DecimalFormat.format() incorrectly uses maxFractionDigits setting. 278 */ 279 280void NumberFormatRegressionTest::Test4088161 (void) 281{ 282 UErrorCode status = U_ZERO_ERROR; 283 DecimalFormat *df = new DecimalFormat(status); 284 if (!failure(status, "new DecimalFormat", "")) { 285 double d = 100; 286 df->setMinimumFractionDigits(0); 287 df->setMaximumFractionDigits(16); 288 UnicodeString sBuf1; 289 FieldPosition fp1(0); 290 logln(UnicodeString("d = ") + d); 291 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 292 293 logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'"); 294 df->setMaximumFractionDigits(17); 295 UnicodeString sBuf2; 296 FieldPosition fp2(0); 297 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 298 sBuf2 = df->format(d, sBuf2, fp2); 299 if(sBuf2 != "100") 300 errln(" format(d) = '" + sBuf2 + "'"); 301 } 302 303 delete df; 304} 305 306/* @bug 4087245 307 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. 308 * DecimalFormat(String, DecimalFormatSymbols). 309 */ 310void NumberFormatRegressionTest::Test4087245 (void) 311{ 312 UErrorCode status = U_ZERO_ERROR; 313 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(status); 314 failure(status, "new DecimalFormatSymbols", ""); 315 // {sfb} One note about this test: if you pass in a pointer 316 // to the symbols, they are adopted and this test will fail, 317 // even though that is the correct behavior. To test the cloning 318 // of the symbols, it is necessary to pass in a reference to the symbols 319 DecimalFormat *df = new DecimalFormat("#,##0.0", *symbols, status); 320 failure(status, "new DecimalFormat with symbols", ""); 321 int32_t n = 123; 322 UnicodeString buf1; 323 UnicodeString buf2; 324 FieldPosition pos(FieldPosition::DONT_CARE); 325 logln(UnicodeString("format(") + n + ") = " + 326 df->format(n, buf1, pos)); 327 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString((UChar)0x70)); // change value of field 328 logln(UnicodeString("format(") + n + ") = " + 329 df->format(n, buf2, pos)); 330 if(buf1 != buf2) 331 errln("Test for bug 4087245 failed"); 332 333 delete df; 334 delete symbols; 335} 336 337/* @bug 4087535 338 * DecimalFormat.format() incorrectly formats 0.0 339 */ 340void NumberFormatRegressionTest::Test4087535 (void) 341{ 342 UErrorCode status = U_ZERO_ERROR; 343 DecimalFormat *df = new DecimalFormat(status); 344 failure(status, "new DecimalFormat", ""); 345 df->setMinimumIntegerDigits(0); 346 347 double n = 0; 348 UnicodeString buffer; 349 FieldPosition pos(FieldPosition::DONT_CARE); 350 buffer = df->format(n, buffer, pos); 351 if (buffer.length() == 0) 352 errln(/*n + */": '" + buffer + "'"); 353 n = 0.1; 354 buffer = df->format(n, buffer, pos); 355 if (buffer.length() == 0) 356 errln(/*n + */": '" + buffer + "'"); 357 358 delete df; 359} 360 361/* @bug 4088503 362 * DecimalFormat.format fails when groupingSize is set to 0. 363 */ 364// {sfb} how do I tell if this worked? --> FieldPosition doesn't change ?? 365void NumberFormatRegressionTest::Test4088503 (void) 366{ 367 UErrorCode status = U_ZERO_ERROR; 368 DecimalFormat *df = new DecimalFormat(status); 369 failure(status, "new DecimalFormat", ""); 370 df->setGroupingSize(0); 371 UnicodeString sBuf; 372 FieldPosition fp(FieldPosition::DONT_CARE); 373 //try { 374 logln(df->format((int32_t)123, sBuf, fp)); 375 //if(fp == FieldPosition(0)) 376 // errln("Test for bug 4088503 failed."); 377 /*} catch (Exception foo) { 378 errln("Test for bug 4088503 failed."); 379 }*/ 380 delete df; 381 382} 383/* @bug 4066646 384 * NumberFormat.getCurrencyInstance is wrong. 385 */ 386void NumberFormatRegressionTest::Test4066646 (void) 387{ 388 assignFloatValue(2.04f); 389 assignFloatValue(2.03f); 390 assignFloatValue(2.02f); 391 assignFloatValue(0.0f); 392} 393 394float 395NumberFormatRegressionTest::assignFloatValue(float returnfloat) 396{ 397 logln(UnicodeString(" VALUE ") + returnfloat); 398 UErrorCode status = U_ZERO_ERROR; 399 NumberFormat *nfcommon = NumberFormat::createCurrencyInstance(Locale::getUS(), status); 400 if (failure(status, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE)){ 401 delete nfcommon; 402 return returnfloat; 403 } 404 nfcommon->setGroupingUsed(FALSE); 405 406 UnicodeString stringValue; 407 stringValue = nfcommon->format(returnfloat, stringValue); 408 logln(" DISPLAYVALUE " + stringValue); 409 Formattable result; 410 nfcommon->parse(stringValue, result, status); 411 failure(status, "nfcommon->parse", Locale::getUS()); 412 float floatResult = (float) (result.getType() == Formattable::kDouble 413 ? result.getDouble() : result.getLong()); 414 if( uprv_fabs(floatResult - returnfloat) > 0.0001) 415 //String stringValue = nfcommon.format(returnfloat).substring(1); 416 //if (Float.valueOf(stringValue).floatValue() != returnfloat) 417 errln(UnicodeString("FAIL: expected ") + returnfloat + ", got " + floatResult + " (" + stringValue+")"); 418 419 delete nfcommon; 420 return returnfloat; 421} // End Of assignFloatValue() 422 423/* @bug 4059870 424 * DecimalFormat throws exception when parsing "0" 425 */ 426void NumberFormatRegressionTest::Test4059870(void) 427{ 428 UErrorCode status = U_ZERO_ERROR; 429 DecimalFormat *format = new DecimalFormat("00", status); 430 failure(status, "new Decimalformat", Locale::getUS()); 431 //try { 432 Formattable result; 433 UnicodeString str; 434 format->parse(UnicodeString("0"), result, status); 435 failure(status, "format->parse", Locale::getUS()); 436 437 /*} 438 catch (Exception e) { 439 errln("Test for bug 4059870 failed : " + e); 440 }*/ 441 442 delete format; 443} 444/* @bug 4083018 445 * DecimalFormatSymbol.equals should always return false when 446 * comparing with null. 447 */ 448// {sfb} this is silly in C++ 449void NumberFormatRegressionTest::Test4083018 (void) 450{ 451 UErrorCode status = U_ZERO_ERROR; 452 DecimalFormatSymbols *dfs = new DecimalFormatSymbols(status); 453 failure(status, "new DecimalFormatSymbols", Locale::getUS()); 454 //try { 455 if (dfs != NULL) 456 logln("Test Passed!"); 457 else 458 errln("Test for bug 4083018 failed"); 459 /*} catch (Exception foo) { 460 errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); 461 }*/ 462 463 delete dfs; 464} 465 466/* @bug 4071492 467 * DecimalFormat does not round up correctly. 468 */ 469void NumberFormatRegressionTest::Test4071492 (void) 470{ 471 double x = 0.00159999; 472 UErrorCode status = U_ZERO_ERROR; 473 NumberFormat *nf = NumberFormat::createInstance(status); 474 if (failure(status, "NumberFormat::createInstance", Locale::getUS(), TRUE)) { 475 delete nf; 476 return; 477 } 478 nf->setMaximumFractionDigits(4); 479 UnicodeString out; 480 FieldPosition pos(FieldPosition::DONT_CARE); 481 out = nf->format(x, out, pos); 482 logln("0.00159999 formats with 4 fractional digits to " + out); 483 UnicodeString expected("0.0016"); 484 if (out != expected) 485 errln("FAIL: Expected " + expected); 486 487 delete nf; 488} 489 490/* @bug 4086575 491 * A space as a group separator for localized pattern causes 492 * wrong format. WorkAround : use non-breaking space. 493 */ 494void NumberFormatRegressionTest::Test4086575(void) 495{ 496 UErrorCode status = U_ZERO_ERROR; 497 NumberFormat *nf1 = NumberFormat::createInstance(Locale::getFrance(), status); 498 499 // TODO: There is not a good way to find out that the creation of this number format has 500 // failed. Major rewiring of format construction proposed. 501 if(U_FAILURE(status)) { 502 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status)); 503 delete nf1; 504 return; 505 } 506 failure(status, "NumberFormat::createInstance", Locale::getFrance()); 507 508 // C++ workaround to make sure cast works 509 DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nf1); 510 if(nf == NULL) { 511 errln("NumberFormat::createInstance returned incorrect type."); 512 return; 513 } 514 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() 574void 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++ 607void 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 */ 632void 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 */ 669void 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 */ 696void 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(UnicodeString(" getMaximumFractionDigits() = ") + i); 716 logln(UnicodeString(" 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 */ 727void 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 754void 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 */ 780void 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 */ 834void 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 DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf); 846 if(df == NULL) { 847 errln("expected DecimalFormat!"); 848 return; 849 } 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 */ 880void 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 */ 957void 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 */ 1029void 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 DEM"; 1036 String expectedPercent = "-578.998%"; 1037 */ 1038 UnicodeString expectedDefault("-5.789,988"); 1039 UnicodeString expectedCurrency("5.789,99\\u00A0DEM"); 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 */ 1097void 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("-ITL\\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 */ 1162void 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 1191void 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 */ 1203void 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 */ 1227void 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 dataerrln("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 */ 1272void 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 */ 1297void 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 */ 1314void 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 */ 1337void 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 */ 1375void 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 */ 1397void 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 */ 1438void 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 */ 1474void 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 */ 1508void 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 */ 1533void 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 */ 1567void 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 1607void 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 */ 1633void 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->getWithFallback("NumberElements", status); 1645 failure(status, "rb.get(NumberElements)"); 1646 numPat = numPat.getWithFallback("latn",status); 1647 failure(status, "rb.get(latn)"); 1648 numPat = numPat.getWithFallback("patterns",status); 1649 failure(status, "rb.get(patterns)"); 1650 numPat = numPat.getWithFallback("currencyFormat",status); 1651 failure(status, "rb.get(currencyFormat)"); 1652 // 1653 // Get the currency pattern for this locale. We have to fish it 1654 // out of the ResourceBundle directly, since DecimalFormat.toPattern 1655 // will return the localized symbol, not \00a4 1656 // 1657 UnicodeString pattern = numPat.getString(status); 1658 failure(status, "rb->getString()"); 1659 1660 UChar fo[] = { 0x00A4 }; 1661 UnicodeString foo(fo, 1, 1); 1662 1663 //if (pattern.indexOf("\u00A4") == -1 ) { 1664 if (pattern.indexOf(foo) == -1 ) { 1665 errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) + 1666 " does not contain generic currency symbol:" + 1667 pattern ); 1668 } 1669 1670 // Create a DecimalFormat using the pattern we got and format a number 1671 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status); 1672 failure(status, "new DecimalFormatSymbols"); 1673 DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status); 1674 failure(status, "new DecimalFormat"); 1675 1676 UnicodeString result1; 1677 FieldPosition pos(FieldPosition::DONT_CARE); 1678 result1 = fmt1->format(1.111, result1, pos); 1679 1680 // 1681 // Now substitute in the locale's currency symbol and create another 1682 // pattern. We have to skip locales where the currency symbol 1683 // contains decimal separators, because that confuses things 1684 // 1685 UChar ba[] = { 0x002E/*'.'*/ }; 1686 UnicodeString bar(ba, 1, 1); 1687 1688 if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) { 1689 // {sfb} Also, switch the decimal separator to the monetary decimal 1690 // separator to mimic the behavior of a currency format 1691 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, 1692 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol)); 1693 1694 UnicodeString buf(pattern); 1695 for (int j = 0; j < buf.length(); j++) { 1696 if (buf[j] == 0x00a4 ) { 1697 if(buf[j + 1] == 0x00a4) { 1698 // {sfb} added to support double currency marker (intl currency sign) 1699 buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1700 j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length(); 1701 } 1702 else { 1703 buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol)); 1704 j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1; 1705 } 1706 } 1707 } 1708 1709 DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status); 1710 failure(status, "new DecimalFormat"); 1711 1712 // Get the currency (if there is one) so we can set the rounding and fraction 1713 const UChar *currency = fmt1->getCurrency(); 1714 if (*currency != 0) { 1715 double rounding = ucurr_getRoundingIncrement(currency, &status); 1716 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status); 1717 if (U_SUCCESS(status)) { 1718 fmt2->setRoundingIncrement(rounding); 1719 fmt2->setMinimumFractionDigits(frac); 1720 fmt2->setMaximumFractionDigits(frac); 1721 } 1722 else { 1723 failure(status, "Fetching currency rounding/fractions"); 1724 } 1725 } 1726 1727 UnicodeString result2; 1728 fmt2->format(1.111, result2, pos); 1729 1730 if (result1 != result2) { 1731 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " + 1732 result1 + " vs " + result2); 1733 } 1734 1735 delete fmt2; 1736 } 1737 1738 delete rb; 1739 delete fmt1; 1740 delete symbols; 1741 } 1742} 1743 1744/* @bug 4125885 1745 * DecimalFormat.format() delivers wrong string. 1746 */ 1747void NumberFormatRegressionTest::Test4125885(void) 1748{ 1749 UErrorCode status = U_ZERO_ERROR; 1750 double rate = 12.34; 1751 DecimalFormat *formatDec = new DecimalFormat ("000.00", status); 1752 if(U_FAILURE(status)) { 1753 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1754 delete formatDec; 1755 return; 1756 } 1757 failure(status, "new DecimalFormat"); 1758 UnicodeString temp; 1759 logln("toPattern: " + formatDec->toPattern(temp)); 1760 UnicodeString rateString; 1761 FieldPosition pos(FieldPosition::DONT_CARE); 1762 rateString = formatDec->format(rate, rateString, pos); 1763 if (rateString != UnicodeString("012.34")) 1764 errln("result : " + rateString + " expected : 012.34"); 1765 rate = 0.1234; 1766 delete formatDec;// = null; 1767 formatDec = new DecimalFormat ("+000.00%;-000.00%", status); 1768 failure(status, "new DecimalFormat"); 1769 logln("toPattern: " + formatDec->toPattern(temp)); 1770 rateString.remove(); 1771 rateString = formatDec->format(rate, rateString, pos); 1772 if (rateString != UnicodeString("+012.34%")) 1773 errln("result : " + rateString + " expected : +012.34%"); 1774 1775 delete formatDec; 1776} 1777 1778/** 1779 * @bug 4134034 1780 * DecimalFormat produces extra zeros when formatting numbers. 1781 */ 1782void NumberFormatRegressionTest::Test4134034(void) 1783{ 1784 UErrorCode status = U_ZERO_ERROR; 1785 DecimalFormat *nf = new DecimalFormat("##,###,###.00", status); 1786 if (!failure(status, "new DecimalFormat")) { 1787 UnicodeString f; 1788 FieldPosition pos(FieldPosition::DONT_CARE); 1789 f = nf->format(9.02, f, pos); 1790 if (f == UnicodeString("9.02")) 1791 logln(f + " ok"); 1792 else 1793 errln("9.02 -> " + f + "; want 9.02"); 1794 1795 f.remove(); 1796 f = nf->format((int32_t)0, f, pos); 1797 if (f == UnicodeString(".00")) 1798 logln(f + " ok"); 1799 else 1800 errln("0 -> " + f + "; want .00"); 1801 } 1802 1803 delete nf; 1804} 1805 1806/** 1807 * @bug 4134300 1808 * CANNOT REPRODUCE - This bug could not be reproduced. It may be 1809 * a duplicate of 4134034. 1810 * 1811 * JDK 1.1.6 Bug, did NOT occur in 1.1.5 1812 * Possibly related to bug 4125885. 1813 * 1814 * This class demonstrates a regression in version 1.1.6 1815 * of DecimalFormat class. 1816 * 1817 * 1.1.6 Results 1818 * Value 1.2 Format #.00 Result '01.20' !!!wrong 1819 * Value 1.2 Format 0.00 Result '001.20' !!!wrong 1820 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong 1821 * Value 1.2 Format #0.0# Result '1.2' 1822 * Value 1.2 Format #0.00 Result '001.20' !!!wrong 1823 * 1824 * 1.1.5 Results 1825 * Value 1.2 Format #.00 Result '1.20' 1826 * Value 1.2 Format 0.00 Result '1.20' 1827 * Value 1.2 Format 00.00 Result '01.20' 1828 * Value 1.2 Format #0.0# Result '1.2' 1829 * Value 1.2 Format #0.00 Result '1.20' 1830 */ 1831void NumberFormatRegressionTest::Test4134300(void) { 1832 UnicodeString DATA [] = { 1833 // Pattern Expected string 1834 UnicodeString("#.00"), UnicodeString("1.20"), 1835 UnicodeString("0.00"), UnicodeString("1.20"), 1836 UnicodeString("00.00"), UnicodeString("01.20"), 1837 UnicodeString("#0.0#"), UnicodeString("1.2"), 1838 UnicodeString("#0.00"), UnicodeString("1.20") 1839 }; 1840 1841 for (int i=0; i< 10; i+=2) { 1842 UnicodeString result; 1843 UErrorCode status = U_ZERO_ERROR; 1844 DecimalFormat *df = new DecimalFormat(DATA[i], status); 1845 if (!failure(status, "new DecimalFormat")) { 1846 FieldPosition pos(FieldPosition::DONT_CARE); 1847 result = df->format(1.2, result, pos); 1848 if (result != DATA[i+1]) { 1849 errln("Fail: 1.2 x " + DATA[i] + " = " + result + 1850 "; want " + DATA[i+1]); 1851 } 1852 else { 1853 logln("Ok: 1.2 x " + DATA[i] + " = " + result); 1854 } 1855 } 1856 1857 delete df; 1858 } 1859} 1860 1861/** 1862 * @bug 4140009 1863 * Empty pattern produces double negative prefix. 1864 */ 1865void NumberFormatRegressionTest::Test4140009(void) 1866{ 1867 UErrorCode status = U_ZERO_ERROR; 1868 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 1869 failure(status, "new DecimalFormatSymbols"); 1870 DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status); 1871 if (!failure(status, "new DecimalFormat")) { 1872 UnicodeString s; 1873 FieldPosition pos(FieldPosition::DONT_CARE); 1874 s = f->format(123.456, s, pos); 1875 if (s != UnicodeString("123.456")) 1876 errln("Fail: Format empty pattern x 123.456 => " + s); 1877 s.remove(); 1878 s = f->format(-123.456, s, pos); 1879 if (s != UnicodeString("-123.456")) 1880 errln("Fail: Format empty pattern x -123.456 => " + s); 1881 } 1882 delete f; 1883} 1884 1885/** 1886 * @bug 4141750 1887 * BigDecimal numbers get their fractions truncated by NumberFormat. 1888 */ 1889// {sfb} not pertinent in C++ ?? 1890void NumberFormatRegressionTest::Test4141750(void) { 1891 /*try { 1892 UnicodeString str("12345.67"); 1893 BigDecimal bd = new BigDecimal(str); 1894 String sd = NumberFormat.getInstance(Locale.US).format(bd); 1895 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd); 1896 } 1897 catch (Exception e) { 1898 errln(e.toString()); 1899 e.printStackTrace(); 1900 }*/ 1901} 1902 1903/** 1904 * @bug 4145457 1905 * DecimalFormat toPattern() doesn't quote special characters or handle 1906 * single quotes. 1907 */ 1908void NumberFormatRegressionTest::Test4145457() { 1909 //try { 1910 UErrorCode status = U_ZERO_ERROR; 1911 NumberFormat *nff = NumberFormat::createInstance(status); 1912 if (failure(status, "NumberFormat::createInstance", TRUE)){ 1913 delete nff; 1914 return; 1915 }; 1916 DecimalFormat *nf = dynamic_cast<DecimalFormat *>(nff); 1917 if(nf == NULL) { 1918 errln("DecimalFormat needed to continue"); 1919 return; 1920 } 1921 1922 DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols(); 1923 sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027); 1924 nf->setDecimalFormatSymbols(*sym); 1925 double pi = 3.14159; 1926 1927 UnicodeString PATS [] = { 1928 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''") 1929 }; 1930 1931 for (int32_t i=0; i<2; ++i) { 1932 nf->applyPattern(PATS[i], status); 1933 failure(status, "nf->applyPattern"); 1934 UnicodeString out; 1935 FieldPosition pos(FieldPosition::DONT_CARE); 1936 out = nf->format(pi, out, pos); 1937 UnicodeString pat; 1938 pat = nf->toPattern(pat); 1939 Formattable num; 1940 ParsePosition pp(0); 1941 nf->parse(out, num, pp); 1942 double val = num.getDouble(); 1943 1944 nf->applyPattern(pat, status); 1945 failure(status, "nf->applyPattern"); 1946 UnicodeString out2; 1947 out2 = nf->format(pi, out2, pos); 1948 UnicodeString pat2; 1949 pat2 = nf->toPattern(pat2); 1950 pp.setIndex(0); 1951 nf->parse(out2, num, pp); 1952 double val2 = num.getDouble(); 1953 1954 if (pat != pat2) 1955 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" + 1956 pat + "\" vs. \"" + pat2 + "\""); 1957 else 1958 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"'); 1959 1960 if (val == val2 && out == out2) { 1961 logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1962 out + "\" -> " + val + " -> \"" + 1963 out2 + "\" -> " + val2); 1964 } 1965 else { 1966 errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1967 out + "\" -> " + val + " -> \"" + 1968 out2 + "\" -> " + val2); 1969 } 1970 } 1971 /*} 1972 catch (ParseException e) { 1973 errln("Fail: " + e); 1974 e.printStackTrace(); 1975 }*/ 1976 1977 delete nff; 1978} 1979 1980/** 1981 * @bug 4147295 1982 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. 1983 * CANNOT REPRODUCE 1984 * This bug is a duplicate of 4139344, which is a duplicate of 4134300 1985 */ 1986void NumberFormatRegressionTest::Test4147295(void) 1987{ 1988 UErrorCode status = U_ZERO_ERROR; 1989 DecimalFormat *sdf = new DecimalFormat(status); 1990 UnicodeString pattern("#,###"); 1991 logln("Applying pattern \"" + pattern + "\""); 1992 sdf->applyPattern(pattern, status); 1993 if (!failure(status, "sdf->applyPattern")) { 1994 int minIntDig = sdf->getMinimumIntegerDigits(); 1995 if (minIntDig != 0) { 1996 errln("Test failed"); 1997 errln(UnicodeString(" Minimum integer digits : ") + minIntDig); 1998 UnicodeString temp; 1999 errln(UnicodeString(" new pattern: ") + sdf->toPattern(temp)); 2000 } else { 2001 logln("Test passed"); 2002 logln(UnicodeString(" Minimum integer digits : ") + minIntDig); 2003 } 2004 } 2005 delete sdf; 2006} 2007 2008/** 2009 * @bug 4147706 2010 * DecimalFormat formats -0.0 as +0.0 2011 * See also older related bug 4106658, 4106667 2012 */ 2013void NumberFormatRegressionTest::Test4147706(void) 2014{ 2015 UErrorCode status = U_ZERO_ERROR; 2016 DecimalFormat *df = new DecimalFormat("#,##0.0##", status); 2017 failure(status, "new DecimalFormat"); 2018 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 2019 if (!failure(status, "new DecimalFormatSymbols")) { 2020 UnicodeString f1; 2021 UnicodeString f2, temp; 2022 FieldPosition pos(FieldPosition::DONT_CARE); 2023 volatile double d1 = 0.0; // volatile to prevent code optimization 2024 double d2 = -0.0001; 2025 2026#if defined(U_HPUX) 2027 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword 2028#else 2029 d1 *= -1.0; // Some compilers have a problem with defining -0.0 2030#endif 2031 df->adoptDecimalFormatSymbols(syms); 2032 f1 = df->format(d1, f1, pos); 2033 f2 = df->format(d2, f2, pos); 2034 if (f1 != UnicodeString("-0.0")) { 2035 errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"'); 2036 } 2037 if (f2 != UnicodeString("-0.0")) { 2038 errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"'); 2039 } 2040 } 2041 2042 delete df; 2043} 2044 2045 2046// Not applicable, since no serialization in C++ 2047/*class myformat implements Serializable 2048{ 2049DateFormat _dateFormat = DateFormat.getDateInstance(); 2050 2051public String Now() 2052{ 2053 GregorianCalendar calendar = new GregorianCalendar(); 2054 Date t = calendar.getTime(); 2055 String nowStr = _dateFormat.format(t); 2056 return nowStr; 2057} 2058}*/ 2059 2060/** 2061 * @bug 4162198 2062 * NumberFormat cannot format Double.MAX_VALUE 2063 */ 2064// TODO: make this test actually test something 2065void 2066NumberFormatRegressionTest::Test4162198(void) 2067{ 2068 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof) 2069 double dbl = INT32_MAX * 1000.0; 2070 UErrorCode status = U_ZERO_ERROR; 2071 NumberFormat *f = NumberFormat::createInstance(status); 2072 if(U_FAILURE(status)) { 2073 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2074 return; 2075 } 2076 f->setMaximumFractionDigits(INT32_MAX); 2077 f->setMaximumIntegerDigits(INT32_MAX); 2078 UnicodeString s; 2079 f->format(dbl,s); 2080 logln(UnicodeString("The number ") + dbl + " formatted to " + s); 2081 Formattable n; 2082 //try { 2083 f->parse(s, n, status); 2084 if(U_FAILURE(status)) 2085 errln("Couldn't parse!"); 2086 //} catch (java.text.ParseException e) { 2087 // errln("Caught a ParseException:"); 2088 // e.printStackTrace(); 2089 //} 2090 2091 //logln("The string " + s + " parsed as " + n); 2092 2093 // {dlf} The old code assumes n is a double, but it isn't any more... 2094 // Formattable apparently does not and never did interconvert... too bad. 2095 //if(n.getDouble() != dbl) { 2096 // errln("Round trip failure"); 2097 //} 2098 if (n.getInt64() != dbl) { 2099 errln("Round trip failure"); 2100 } 2101 2102 delete f; 2103} 2104 2105/** 2106 * @bug 4162852 2107 * NumberFormat does not parse negative zero. 2108 */ 2109void 2110NumberFormatRegressionTest::Test4162852(void) 2111{ 2112 UErrorCode status = U_ZERO_ERROR; 2113 for(int32_t i=0; i < 2; ++i) { 2114 NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status) 2115 : NumberFormat::createPercentInstance(status); 2116 if(U_FAILURE(status)) { 2117 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2118 return; 2119 } 2120 double d = 0.0; 2121 d *= -1.0; 2122 UnicodeString s; 2123 f->format(d, s); 2124 Formattable n; 2125 f->parse(s, n, status); 2126 if(U_FAILURE(status)) 2127 errln("Couldn't parse!"); 2128 double e = n.getDouble(); 2129 logln(UnicodeString("") + 2130 d + " -> " + 2131 '"' + s + '"' + " -> " + e); 2132#if (defined(OS390) && !defined(IEEE_754)) || defined(OS400) 2133 if (e != 0.0) { 2134#else 2135 if (e != 0.0 || 1.0/e > 0.0) { 2136#endif 2137 logln("Failed to parse negative zero"); 2138 } 2139 delete f; 2140 } 2141} 2142 2143static double _u_abs(double a) { return a<0?-a:a; } 2144 2145/** 2146 * May 17 1999 sync up - liu 2147 * @bug 4167494 2148 * NumberFormat truncates data 2149 */ 2150void NumberFormatRegressionTest::Test4167494(void) { 2151 UErrorCode status = U_ZERO_ERROR; 2152 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2153 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2154 delete fmt; 2155 return; 2156 }; 2157 2158 double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf 2159 UnicodeString s; 2160 fmt->format(a, s); 2161 Formattable num; 2162 fmt->parse(s, num, status); 2163 failure(status, "Parse"); 2164 if (num.getType() == Formattable::kDouble && 2165 _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1% 2166 logln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2167 toString(num) + " ok"); 2168 } else { 2169 errln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2170 toString(num) + " FAIL"); 2171 } 2172 2173 // We don't test Double.MIN_VALUE because the locale data for the US 2174 // currently doesn't specify enough digits to display Double.MIN_VALUE. 2175 // This is correct for now; however, we leave this here as a reminder 2176 // in case we want to address this later. 2177 2178 delete fmt; 2179} 2180 2181/** 2182 * May 17 1999 sync up - liu 2183 * @bug 4170798 2184 * DecimalFormat.parse() fails when ParseIntegerOnly set to true 2185 */ 2186void NumberFormatRegressionTest::Test4170798(void) { 2187 UErrorCode status = U_ZERO_ERROR; 2188 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2189 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2190 delete nf; 2191 return; 2192 }; 2193 DecimalFormat *df = dynamic_cast<DecimalFormat *>(nf); 2194 if(df == NULL) { 2195 errln("DecimalFormat needed to continue"); 2196 return; 2197 } 2198 df->setParseIntegerOnly(TRUE); 2199 Formattable n; 2200 ParsePosition pos(0); 2201 df->parse("-0.0", n, pos); 2202 if (n.getType() != Formattable::kLong 2203 || n.getLong() != 0) { 2204 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n)); 2205 } 2206 delete nf; 2207} 2208 2209/** 2210 * May 17 1999 sync up - liu 2211 * toPattern only puts the first grouping separator in. 2212 */ 2213void NumberFormatRegressionTest::Test4176114(void) { 2214 const char* DATA[] = { 2215 "00", "#00", 2216 "000", "#000", // No grouping 2217 "#000", "#000", // No grouping 2218 "#,##0", "#,##0", 2219 "#,000", "#,000", 2220 "0,000", "#0,000", 2221 "00,000", "#00,000", 2222 "000,000", "#,000,000", 2223 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported 2224 }; 2225 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2226 UErrorCode status = U_ZERO_ERROR; 2227 UnicodeString s; 2228 for (int i=0; i<DATA_length; i+=2) { 2229 DecimalFormat df(DATA[i], status); 2230 if (!failure(status, "DecimalFormat constructor")) { 2231 df.toPattern(s); 2232 UnicodeString exp(DATA[i+1]); 2233 if (s != exp) { 2234 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " + 2235 s + ", want " + exp); 2236 } 2237 } 2238 } 2239} 2240 2241/** 2242 * May 17 1999 sync up - liu 2243 * @bug 4179818 2244 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 2245 */ 2246void NumberFormatRegressionTest::Test4179818(void) { 2247 const char* DATA[] = { 2248 // Input Pattern Expected output 2249 "1.2511", "#.#", "1.3", 2250 "1.2501", "#.#", "1.3", 2251 "0.9999", "#", "1", 2252 }; 2253 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2254 double DOUBLE[] = { 2255 1.2511, 2256 1.2501, 2257 0.9999, 2258 }; 2259 UErrorCode status = U_ZERO_ERROR; 2260 DecimalFormatSymbols sym(Locale::getUS(), status); 2261 failure(status, "Construct DecimalFormatSymbols"); 2262 DecimalFormat fmt("#", sym, status); 2263 if (!failure(status, "Construct DecimalFormat")) { 2264 for (int i=0; i<DATA_length; i+=3) { 2265 double in = DOUBLE[i/3]; 2266 UnicodeString pat(DATA[i+1]); 2267 UnicodeString exp(DATA[i+2]); 2268 fmt.applyPattern(pat, status); 2269 failure(status, "applyPattern"); 2270 UnicodeString out; 2271 FieldPosition pos; 2272 fmt.format(in, out, pos); 2273 if (out == exp) { 2274 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out); 2275 } else { 2276 errln(UnicodeString("FAIL: ") + in + " x " + pat + " = " + out + 2277 ", expected " + exp); 2278 } 2279 } 2280 } 2281} 2282 2283/** 2284 * May 17 1999 sync up - liu 2285 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat. 2286 * This includes the minus sign, currency symbol, international currency 2287 * symbol, percent, and permille. This is filed as bugs 4212072 and 2288 * 4212073. 2289 */ 2290void NumberFormatRegressionTest::Test4212072(void) { 2291 UErrorCode status = U_ZERO_ERROR; 2292 DecimalFormatSymbols sym(Locale::getUS(), status); 2293 2294 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2295 DecimalFormat fmt(UnicodeString("#"), sym, status); 2296 if(failure(status, "DecimalFormat ct", Locale::getUS())) { 2297 return; 2298 } 2299 2300 UnicodeString s; 2301 FieldPosition pos; 2302 2303 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e); 2304 fmt.setDecimalFormatSymbols(sym); 2305 s.remove(); 2306 if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) { 2307 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s + 2308 ", exp ^1"); 2309 } 2310 s.remove(); 2311 if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) { 2312 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") + 2313 s + ", exp ^"); 2314 } 2315 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d); 2316 2317 fmt.applyPattern(UnicodeString("#%"), status); 2318 failure(status, "applyPattern percent"); 2319 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e); 2320 fmt.setDecimalFormatSymbols(sym); 2321 s.remove(); 2322 if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) { 2323 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s + 2324 ", exp 25^"); 2325 } 2326 s.remove(); 2327 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2328 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") + 2329 s + ", exp ^"); 2330 } 2331 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25); 2332 2333 fmt.applyPattern(str("#\\u2030"), status); 2334 failure(status, "applyPattern permill"); 2335 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e); 2336 fmt.setDecimalFormatSymbols(sym); 2337 s.remove(); 2338 if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) { 2339 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s + 2340 ", exp 250^"); 2341 } 2342 s.remove(); 2343 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2344 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") + 2345 s + ", exp ^"); 2346 } 2347 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030); 2348 2349 fmt.applyPattern(str("\\u00A4#.00"), status); 2350 failure(status, "applyPattern currency"); 2351 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd"); 2352 fmt.setDecimalFormatSymbols(sym); 2353 s.remove(); 2354 if (fmt.format(12.5, s, pos) != UnicodeString("usd12.50")) { 2355 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s + 2356 ", exp usd12.50"); 2357 } 2358 s.remove(); 2359 if (fmt.getPositivePrefix(s) != UnicodeString("usd")) { 2360 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") + 2361 s + ", exp usd"); 2362 } 2363 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$"); 2364 2365 fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status); 2366 failure(status, "applyPattern intl currency"); 2367 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL"); 2368 fmt.setDecimalFormatSymbols(sym); 2369 s.remove(); 2370 if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) { 2371 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s + 2372 ", exp DOL12.50"); 2373 } 2374 s.remove(); 2375 if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) { 2376 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") + 2377 s + ", exp DOL"); 2378 } 2379 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD"); 2380 2381 // Since the pattern logic has changed, make sure that patterns round 2382 // trip properly. Test stream in/out integrity too. 2383 int32_t n; 2384 const Locale* avail = NumberFormat::getAvailableLocales(n); 2385 static const char* type[] = { 2386 "", 2387 "$ ", 2388 "% ", 2389 }; 2390 for (int i=0; i<n; ++i) { 2391 for (int j=0; j<3; ++j) { 2392 status = U_ZERO_ERROR; 2393 NumberFormat *nf; 2394 switch (j) { 2395 case 0: 2396 nf = NumberFormat::createInstance(avail[i], status); 2397 failure(status, "createInstance", avail[i]); 2398 break; 2399 case 1: 2400 nf = NumberFormat::createCurrencyInstance(avail[i], status); 2401 failure(status, "createCurrencyInstance", avail[i]); 2402 break; 2403 default: 2404 nf = NumberFormat::createPercentInstance(avail[i], status); 2405 failure(status, "createPercentInstance", avail[i]); 2406 break; 2407 } 2408 if (U_FAILURE(status)) { 2409 continue; 2410 } 2411 DecimalFormat *df = (DecimalFormat*) nf; 2412 2413 // Test toPattern/applyPattern round trip 2414 UnicodeString pat; 2415 df->toPattern(pat); 2416 DecimalFormatSymbols symb(avail[i], status); 2417 failure(status, "Construct DecimalFormatSymbols", avail[i]); 2418 DecimalFormat f2(pat, symb, status); 2419 if (failure(status, 2420 UnicodeString("Construct DecimalFormat(") + pat + ")")) { 2421 continue; 2422 } 2423 if (*df != f2) { 2424 UnicodeString l, p; 2425 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2426 " -> \"" + pat + 2427 "\" -> \"" + f2.toPattern(p) + "\""); 2428 } else { 2429 UnicodeString l, p; 2430 logln(UnicodeString("PASS: ") + type[j] + avail[i].getDisplayName(l) + 2431 " -> \"" + pat + 2432 "\""); 2433 } 2434 2435 // Test toLocalizedPattern/applyLocalizedPattern round trip 2436 df->toLocalizedPattern(pat); 2437 f2.applyLocalizedPattern(pat, status); 2438 failure(status, 2439 UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]); 2440 if (U_FAILURE(status)) { 2441 continue; 2442 } 2443 2444 // Make sure we set the currency attributes appropriately 2445 if (j == 1) { // Currency format 2446 f2.setCurrency(f2.getCurrency(), status); 2447 } 2448 failure(status, 2449 UnicodeString("setCurrency() for (") + pat + ")", avail[i]); 2450 if (U_FAILURE(status)) { 2451 continue; 2452 } 2453 2454 if (*df != f2) { 2455 UnicodeString l, p; 2456 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2457 " -> localized \"" + pat + 2458 "\" -> \"" + f2.toPattern(p) + "\""); 2459 } 2460 2461 delete nf; 2462 2463 // Test writeObject/readObject round trip 2464 // NOT ON ICU -- Java only 2465 } 2466 } 2467} 2468 2469/** 2470 * May 17 1999 sync up - liu 2471 * DecimalFormat.parse() fails for mulipliers 2^n. 2472 */ 2473void NumberFormatRegressionTest::Test4216742(void) { 2474 UErrorCode status = U_ZERO_ERROR; 2475 DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status); 2476 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2477 delete fmt; 2478 return; 2479 }; 2480 int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 }; 2481 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2482 for (int i=0; i<DATA_length; ++i) { 2483 UnicodeString str((UnicodeString)"" + DATA[i]); 2484 for (int m = 1; m <= 100; m++) { 2485 fmt->setMultiplier(m); 2486 Formattable num; 2487 fmt->parse(str, num, status); 2488 failure(status, "parse", Locale::getUS()); 2489 if (num.getType() != Formattable::kLong && 2490 num.getType() != Formattable::kDouble) { 2491 errln(UnicodeString("FAIL: Wanted number, got ") + 2492 toString(num)); 2493 } else { 2494 double d = num.getType() == Formattable::kDouble ? 2495 num.getDouble() : (double) num.getLong(); 2496 if ((d > 0) != (DATA[i] > 0)) { 2497 errln(UnicodeString("\"") + str + "\" parse(x " + 2498 fmt->getMultiplier() + 2499 ") => " + toString(num)); 2500 } 2501 } 2502 } 2503 } 2504 delete fmt; 2505} 2506 2507/** 2508 * May 17 1999 sync up - liu 2509 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction 2510 * digits. 2511 */ 2512void NumberFormatRegressionTest::Test4217661(void) { 2513 const double D[] = { 0.001, 1.001, 0.006, 1.006 }; 2514 const char* S[] = { "0", "1", "0.01", "1.01" }; 2515 int D_length = (int)(sizeof(D) / sizeof(D[0])); 2516 UErrorCode status = U_ZERO_ERROR; 2517 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2518 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2519 delete fmt; 2520 return; 2521 }; 2522 fmt->setMaximumFractionDigits(2); 2523 for (int i=0; i<D_length; i++) { 2524 UnicodeString s; 2525 fmt->format(D[i], s); 2526 if (s != UnicodeString(S[i])) { 2527 errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]); 2528 } 2529 } 2530 delete fmt; 2531} 2532 2533/** 2534 * alphaWorks upgrade 2535 */ 2536void NumberFormatRegressionTest::Test4161100(void) { 2537 UErrorCode status = U_ZERO_ERROR; 2538 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2539 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2540 delete nf; 2541 return; 2542 }; 2543 nf->setMinimumFractionDigits(1); 2544 nf->setMaximumFractionDigits(1); 2545 double a = -0.09; 2546 UnicodeString s; 2547 nf->format(a, s); 2548 UnicodeString pat; 2549 logln(UnicodeString() + a + " x " + 2550 ((DecimalFormat*) nf)->toPattern(pat) + " = " + s); 2551 if (s != UnicodeString("-0.1")) { 2552 errln("FAIL"); 2553 } 2554 delete nf; 2555} 2556 2557/** 2558 * June 16 1999 sync up - liu 2559 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1) 2560 */ 2561void NumberFormatRegressionTest::Test4243011(void) { 2562 UErrorCode status = U_ZERO_ERROR; 2563 DecimalFormatSymbols sym(Locale::getUS(), status); 2564 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2565 DecimalFormat fmt(UnicodeString("0."), sym, status); 2566 2567 if (!failure(status, "DecimalFormat ct", Locale::getUS())) { 2568 const double NUM[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 }; 2569 const char* STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." }; 2570 int32_t N = (int32_t)(sizeof(NUM) / sizeof(NUM[0])); 2571 2572 for (int32_t i=0; i<N; ++i) { 2573 UnicodeString str; 2574 UnicodeString exp(STR[i]); 2575 FieldPosition pos; 2576 fmt.format(NUM[i], str, pos); 2577 if (str == exp) { 2578 logln(UnicodeString("Ok ") + NUM[i] + " x 0. = " + str); 2579 } else { 2580 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str + 2581 ", want " + exp); 2582 } 2583 } 2584 } 2585} 2586 2587/** 2588 * June 16 1999 sync up - liu 2589 * format(0.0) gives "0.1" if preceded by parse("99.99"). 2590 * (Regression in 1.2.2 RC1) 2591 */ 2592void NumberFormatRegressionTest::Test4243108(void) { 2593 UErrorCode status = U_ZERO_ERROR; 2594 DecimalFormatSymbols sym(Locale::getUS(), status); 2595 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2596 DecimalFormat fmt(UnicodeString("#.#"), sym, status); 2597 if (failure(status, "DecimalFormat ct", Locale::getUS())) { 2598 return; 2599 } 2600 2601 UnicodeString str; 2602 FieldPosition pos; 2603 2604 fmt.format(0.0, str, pos); 2605 UnicodeString exp("0"); 2606 if (str == exp) { 2607 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2608 } else { 2609 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2610 ", want " + exp); 2611 } 2612 2613 str = "99.99"; 2614 Formattable val; 2615 fmt.parse(str, val, status); 2616 failure(status, "DecimalFormat.parse(99.99)", Locale::getUS()); 2617 if (val.getType() == Formattable::kDouble && 2618 val.getDouble() == 99.99) { 2619 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val)); 2620 } else { 2621 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) + 2622 ", want " + 99.99); 2623 } 2624 2625 str.remove(); 2626 fmt.format(0.0, str, pos); 2627 if (str == exp) { 2628 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2629 } else { 2630 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2631 ", want " + exp); 2632 } 2633} 2634 2635 2636/** 2637 * DateFormat should call setIntegerParseOnly(TRUE) on adopted 2638 * NumberFormat objects. 2639 */ 2640void NumberFormatRegressionTest::TestJ691(void) { 2641 UErrorCode status = U_ZERO_ERROR; 2642 Locale loc("fr", "CH"); 2643 2644 // set up the input date string & expected output 2645 UnicodeString udt("11.10.2000", ""); 2646 UnicodeString exp("11.10.00", ""); 2647 2648 // create a Calendar for this locale 2649 Calendar *cal = Calendar::createInstance(loc, status); 2650 if (U_FAILURE(status)) { 2651 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status)); 2652 return; 2653 } 2654 2655 // create a NumberFormat for this locale 2656 NumberFormat *nf = NumberFormat::createInstance(loc, status); 2657 if (U_FAILURE(status)) { 2658 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2659 return; 2660 } 2661 2662 // *** Here's the key: We don't want to have to do THIS: 2663 // nf->setParseIntegerOnly(TRUE); 2664 2665 // create the DateFormat 2666 DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc); 2667 if (U_FAILURE(status)) { 2668 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2669 return; 2670 } 2671 2672 df->adoptCalendar(cal); 2673 df->adoptNumberFormat(nf); 2674 2675 // set parsing to lenient & parse 2676 df->setLenient(TRUE); 2677 UDate ulocdat = df->parse(udt, status); 2678 2679 // format back to a string 2680 UnicodeString outString; 2681 df->format(ulocdat, outString); 2682 2683 if (outString != exp) { 2684 errln("FAIL: " + udt + " => " + outString); 2685 } 2686 2687 delete df; 2688} 2689 2690//--------------------------------------------------------------------------- 2691// 2692// Error Checking / Reporting macros 2693// 2694//--------------------------------------------------------------------------- 2695#define TEST_CHECK_STATUS(status) \ 2696 if (U_FAILURE(status)) {\ 2697 errln("File %s, Line %d. status=%s\n", __FILE__, __LINE__, u_errorName(status));\ 2698 return;\ 2699 } 2700 2701#define TEST_ASSERT(expr) \ 2702 if ((expr)==FALSE) {\ 2703 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\ 2704 } 2705 2706 2707// Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18 2708 2709void NumberFormatRegressionTest::Test8199(void) { 2710 UErrorCode status = U_ZERO_ERROR; 2711 NumberFormat *nf = NumberFormat::createInstance(Locale::getEnglish(), status); 2712 if (nf == NULL) { 2713 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)"); 2714 return; 2715 } 2716 TEST_CHECK_STATUS(status); 2717 2718 // Note: Retrieving parsed values from a Formattable as a reduced-precision type 2719 // should always truncate, no other rounding scheme. 2720 2721 UnicodeString numStr = "1000000000.6"; // 9 zeroes 2722 Formattable val; 2723 nf->parse(numStr, val, status); 2724 TEST_CHECK_STATUS(status); 2725 TEST_ASSERT(Formattable::kDouble == val.getType()); 2726 TEST_ASSERT(1000000000 == val.getInt64(status)); 2727 TEST_CHECK_STATUS(status); 2728 TEST_ASSERT(1000000000.6 == val.getDouble(status)); 2729 TEST_CHECK_STATUS(status); 2730 2731 numStr = "100000000000000001.1"; // approx 1E17, parses as a double rather 2732 // than int64 because of the fraction 2733 // even though int64 is more precise. 2734 nf->parse(numStr, val, status); 2735 TEST_CHECK_STATUS(status); 2736 TEST_ASSERT(Formattable::kDouble == val.getType()); 2737 TEST_ASSERT(100000000000000001LL == val.getInt64(status)); 2738 TEST_CHECK_STATUS(status); 2739 TEST_ASSERT(100000000000000000.0 == val.getDouble(status)); 2740 TEST_CHECK_STATUS(status); 2741 2742 numStr = "1E17"; // Parses with the internal decimal number having non-zero exponent 2743 nf->parse(numStr, val, status); 2744 TEST_CHECK_STATUS(status); 2745 TEST_ASSERT(Formattable::kInt64 == val.getType()); 2746 TEST_ASSERT(100000000000000000LL == val.getInt64()); 2747 TEST_ASSERT(1.0E17 == val.getDouble(status)); 2748 TEST_CHECK_STATUS(status); 2749 2750 numStr = "9223372036854775807"; // largest int64_t 2751 nf->parse(numStr, val, status); 2752 TEST_CHECK_STATUS(status); 2753 TEST_ASSERT(Formattable::kInt64 == val.getType()); 2754 TEST_ASSERT(9223372036854775807LL == val.getInt64()); 2755 // In the following check, note that a substantial range of integers will 2756 // convert to the same double value. There are also platform variations 2757 // in the rounding at compile time of double constants. 2758 TEST_ASSERT(9223372036854775808.0 >= val.getDouble(status)); 2759 TEST_ASSERT(9223372036854774700.0 <= val.getDouble(status)); 2760 TEST_CHECK_STATUS(status); 2761 2762 numStr = "-9223372036854775808"; // smallest int64_t 2763 nf->parse(numStr, val, status); 2764 TEST_CHECK_STATUS(status); 2765 TEST_ASSERT(Formattable::kInt64 == val.getType()); 2766 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant. 2767 TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64()); 2768 TEST_ASSERT(-9223372036854775808.0 == val.getDouble(status)); 2769 TEST_CHECK_STATUS(status); 2770 2771 numStr = "9223372036854775808"; // largest int64_t + 1 2772 nf->parse(numStr, val, status); 2773 TEST_CHECK_STATUS(status); 2774 TEST_ASSERT(Formattable::kDouble == val.getType()); 2775 TEST_ASSERT(9223372036854775807LL == val.getInt64(status)); 2776 TEST_ASSERT(status == U_INVALID_FORMAT_ERROR); 2777 status = U_ZERO_ERROR; 2778 TEST_ASSERT(9223372036854775810.0 == val.getDouble(status)); 2779 TEST_CHECK_STATUS(status); 2780 2781 numStr = "-9223372036854775809"; // smallest int64_t - 1 2782 nf->parse(numStr, val, status); 2783 TEST_CHECK_STATUS(status); 2784 TEST_ASSERT(Formattable::kDouble == val.getType()); 2785 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings 2786 TEST_ASSERT((int64_t)0x8000000000000000LL == val.getInt64(status)); 2787 TEST_ASSERT(status == U_INVALID_FORMAT_ERROR); 2788 status = U_ZERO_ERROR; 2789 TEST_ASSERT(-9223372036854775810.0 == val.getDouble(status)); 2790 TEST_CHECK_STATUS(status); 2791 2792 // Test values near the limit of where doubles can represent all integers. 2793 // The implementation strategy of getInt64() changes at this boundary. 2794 // Strings to be parsed include a decimal fraction to force them to be 2795 // parsed as doubles rather than ints. The fraction is discarded 2796 // from the parsed double value because it is beyond what can be represented. 2797 2798 status = U_ZERO_ERROR; 2799 numStr = "9007199254740991.1"; // largest 53 bit int 2800 nf->parse(numStr, val, status); 2801 TEST_CHECK_STATUS(status); 2802 // printf("getInt64() returns %lld\n", val.getInt64(status)); 2803 TEST_ASSERT(Formattable::kDouble == val.getType()); 2804 TEST_ASSERT(9007199254740991LL == val.getInt64(status)); 2805 TEST_ASSERT(9007199254740991.0 == val.getDouble(status)); 2806 TEST_CHECK_STATUS(status); 2807 2808 status = U_ZERO_ERROR; 2809 numStr = "9007199254740992.1"; // 54 bits for the int part. 2810 nf->parse(numStr, val, status); 2811 TEST_CHECK_STATUS(status); 2812 TEST_ASSERT(Formattable::kDouble == val.getType()); 2813 TEST_ASSERT(9007199254740992LL == val.getInt64(status)); 2814 TEST_ASSERT(9007199254740992.0 == val.getDouble(status)); 2815 TEST_CHECK_STATUS(status); 2816 2817 status = U_ZERO_ERROR; 2818 numStr = "9007199254740993.1"; // 54 bits for the int part. Double will round 2819 nf->parse(numStr, val, status); // the ones digit, putting it up to ...994 2820 TEST_CHECK_STATUS(status); 2821 TEST_ASSERT(Formattable::kDouble == val.getType()); 2822 TEST_ASSERT(9007199254740993LL == val.getInt64(status)); 2823 TEST_ASSERT(9007199254740994.0 == val.getDouble(status)); 2824 TEST_CHECK_STATUS(status); 2825 2826 delete nf; 2827} 2828 2829 2830#endif /* #if !UCONFIG_NO_FORMATTING */ 2831