1/*********************************************************************** 2 * Copyright (c) 1997-2009, 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 172 default: name = ""; break; 173 } 174} 175 176UBool 177NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const Locale& l, UBool possibleDataError) 178{ 179 if(U_FAILURE(status)) { 180 if (possibleDataError) { 181 dataerrln(UnicodeString("FAIL: ", "") + msg 182 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 183 } else { 184 errcheckln(status, UnicodeString("FAIL: ", "") + msg 185 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l.getName(),"")); 186 } 187 return TRUE; 188 } 189 190 return FALSE; 191} 192 193UBool 194NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, const char *l, UBool possibleDataError) 195{ 196 if(U_FAILURE(status)) { 197 if (possibleDataError) { 198 dataerrln(UnicodeString("FAIL: ", "") + msg 199 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 200 } else { 201 errcheckln(status, UnicodeString("FAIL: ", "") + msg 202 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "") + UnicodeString(l, "")); 203 } 204 return TRUE; 205 } 206 207 return FALSE; 208} 209 210UBool 211NumberFormatRegressionTest::failure(UErrorCode status, const UnicodeString& msg, UBool possibleDataError) 212{ 213 if(U_FAILURE(status)) { 214 if (possibleDataError) { 215 dataerrln(UnicodeString("FAIL: ", "") + msg 216 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 217 } else { 218 errcheckln(status, UnicodeString("FAIL: ", "") + msg 219 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status), "")); 220 } 221 return TRUE; 222 } 223 224 return FALSE; 225} 226 227/** 228 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects 229 */ 230inline UnicodeString str(const char *input) 231{ 232 return CharsToUnicodeString(input); 233} 234 235/* @bug 4075713 236 * NumberFormat.equals comparing with null should always return false. 237 */ 238// {sfb} kind of silly in C++, just checking for new success 239void NumberFormatRegressionTest::Test4075713(void) 240{ 241 //try { 242 MyNumberFormatTest *tmp = new MyNumberFormatTest(); 243 if(tmp != NULL) 244 logln("NumberFormat.equals passed"); 245 /*} catch (NullPointerException e) { 246 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception"); 247 }*/ 248 249 delete tmp; 250} 251 252/* @bug 4074620 253 * NumberFormat.equals comparing two obj equal even the setGroupingUsed 254 * flag is different. 255 */ 256void NumberFormatRegressionTest::Test4074620(void) 257{ 258 259 MyNumberFormatTest *nf1 = new MyNumberFormatTest(); 260 MyNumberFormatTest *nf2 = new MyNumberFormatTest(); 261 262 nf1->setGroupingUsed(FALSE); 263 nf2->setGroupingUsed(TRUE); 264 265 if(nf1 == nf2) 266 errln("Test for bug 4074620 failed"); 267 else 268 logln("Test for bug 4074620 passed."); 269 270 delete nf1; 271 delete nf2; 272} 273 274 275/* @bug 4088161 276 * DecimalFormat.format() incorrectly uses maxFractionDigits setting. 277 */ 278 279void NumberFormatRegressionTest::Test4088161 (void) 280{ 281 UErrorCode status = U_ZERO_ERROR; 282 DecimalFormat *df = new DecimalFormat(status); 283 if (!failure(status, "new DecimalFormat", "")) { 284 double d = 100; 285 df->setMinimumFractionDigits(0); 286 df->setMaximumFractionDigits(16); 287 UnicodeString sBuf1; 288 FieldPosition fp1(0); 289 logln(UnicodeString("d = ") + d); 290 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 291 292 logln(" format(d) = '" + df->format(d, sBuf1, fp1) + "'"); 293 df->setMaximumFractionDigits(17); 294 UnicodeString sBuf2; 295 FieldPosition fp2(0); 296 logln("maxFractionDigits = " + df->getMaximumFractionDigits()); 297 sBuf2 = df->format(d, sBuf2, fp2); 298 if(sBuf2 != "100") 299 errln(" format(d) = '" + sBuf2 + "'"); 300 } 301 302 delete df; 303} 304 305/* @bug 4087245 306 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat. 307 * DecimalFormat(String, DecimalFormatSymbols). 308 */ 309void NumberFormatRegressionTest::Test4087245 (void) 310{ 311 UErrorCode status = U_ZERO_ERROR; 312 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(status); 313 failure(status, "new DecimalFormatSymbols", ""); 314 // {sfb} One note about this test: if you pass in a pointer 315 // to the symbols, they are adopted and this test will fail, 316 // even though that is the correct behavior. To test the cloning 317 // of the symbols, it is necessary to pass in a reference to the symbols 318 DecimalFormat *df = new DecimalFormat("#,##0.0", *symbols, status); 319 failure(status, "new DecimalFormat with symbols", ""); 320 int32_t n = 123; 321 UnicodeString buf1; 322 UnicodeString buf2; 323 FieldPosition pos(FieldPosition::DONT_CARE); 324 logln(UnicodeString("format(") + n + ") = " + 325 df->format(n, buf1, pos)); 326 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, UnicodeString((UChar)0x70)); // change value of field 327 logln(UnicodeString("format(") + n + ") = " + 328 df->format(n, buf2, pos)); 329 if(buf1 != buf2) 330 errln("Test for bug 4087245 failed"); 331 332 delete df; 333 delete symbols; 334} 335 336/* @bug 4087535 337 * DecimalFormat.format() incorrectly formats 0.0 338 */ 339void NumberFormatRegressionTest::Test4087535 (void) 340{ 341 UErrorCode status = U_ZERO_ERROR; 342 DecimalFormat *df = new DecimalFormat(status); 343 failure(status, "new DecimalFormat", ""); 344 df->setMinimumIntegerDigits(0); 345 346 double n = 0; 347 UnicodeString buffer; 348 FieldPosition pos(FieldPosition::DONT_CARE); 349 buffer = df->format(n, buffer, pos); 350 if (buffer.length() == 0) 351 errln(/*n + */": '" + buffer + "'"); 352 n = 0.1; 353 buffer = df->format(n, buffer, pos); 354 if (buffer.length() == 0) 355 errln(/*n + */": '" + buffer + "'"); 356 357 delete df; 358} 359 360/* @bug 4088503 361 * DecimalFormat.format fails when groupingSize is set to 0. 362 */ 363// {sfb} how do I tell if this worked? --> FieldPosition doesn't change ?? 364void NumberFormatRegressionTest::Test4088503 (void) 365{ 366 UErrorCode status = U_ZERO_ERROR; 367 DecimalFormat *df = new DecimalFormat(status); 368 failure(status, "new DecimalFormat", ""); 369 df->setGroupingSize(0); 370 UnicodeString sBuf; 371 FieldPosition fp(FieldPosition::DONT_CARE); 372 //try { 373 logln(df->format((int32_t)123, sBuf, fp)); 374 //if(fp == FieldPosition(0)) 375 // errln("Test for bug 4088503 failed."); 376 /*} catch (Exception foo) { 377 errln("Test for bug 4088503 failed."); 378 }*/ 379 delete df; 380 381} 382/* @bug 4066646 383 * NumberFormat.getCurrencyInstance is wrong. 384 */ 385void NumberFormatRegressionTest::Test4066646 (void) 386{ 387 assignFloatValue(2.04f); 388 assignFloatValue(2.03f); 389 assignFloatValue(2.02f); 390 assignFloatValue(0.0f); 391} 392 393float 394NumberFormatRegressionTest::assignFloatValue(float returnfloat) 395{ 396 logln(UnicodeString(" VALUE ") + returnfloat); 397 UErrorCode status = U_ZERO_ERROR; 398 NumberFormat *nfcommon = NumberFormat::createCurrencyInstance(Locale::getUS(), status); 399 if (failure(status, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE)){ 400 delete nfcommon; 401 return returnfloat; 402 } 403 nfcommon->setGroupingUsed(FALSE); 404 405 UnicodeString stringValue; 406 stringValue = nfcommon->format(returnfloat, stringValue); 407 logln(" DISPLAYVALUE " + stringValue); 408 Formattable result; 409 nfcommon->parse(stringValue, result, status); 410 failure(status, "nfcommon->parse", Locale::getUS()); 411 float floatResult = (float) (result.getType() == Formattable::kDouble 412 ? result.getDouble() : result.getLong()); 413 if( uprv_fabs(floatResult - returnfloat) > 0.0001) 414 //String stringValue = nfcommon.format(returnfloat).substring(1); 415 //if (Float.valueOf(stringValue).floatValue() != returnfloat) 416 errln(UnicodeString("FAIL: expected ") + returnfloat + ", got " + floatResult + " (" + stringValue+")"); 417 418 delete nfcommon; 419 return returnfloat; 420} // End Of assignFloatValue() 421 422/* @bug 4059870 423 * DecimalFormat throws exception when parsing "0" 424 */ 425void NumberFormatRegressionTest::Test4059870(void) 426{ 427 UErrorCode status = U_ZERO_ERROR; 428 DecimalFormat *format = new DecimalFormat("00", status); 429 failure(status, "new Decimalformat", Locale::getUS()); 430 //try { 431 Formattable result; 432 UnicodeString str; 433 format->parse(UnicodeString("0"), result, status); 434 failure(status, "format->parse", Locale::getUS()); 435 436 /*} 437 catch (Exception e) { 438 errln("Test for bug 4059870 failed : " + e); 439 }*/ 440 441 delete format; 442} 443/* @bug 4083018 444 * DecimalFormatSymbol.equals should always return false when 445 * comparing with null. 446 */ 447// {sfb} this is silly in C++ 448void NumberFormatRegressionTest::Test4083018 (void) 449{ 450 UErrorCode status = U_ZERO_ERROR; 451 DecimalFormatSymbols *dfs = new DecimalFormatSymbols(status); 452 failure(status, "new DecimalFormatSymbols", Locale::getUS()); 453 //try { 454 if (dfs != NULL) 455 logln("Test Passed!"); 456 else 457 errln("Test for bug 4083018 failed"); 458 /*} catch (Exception foo) { 459 errln("Test for bug 4083018 failed => Message : " + foo.getMessage()); 460 }*/ 461 462 delete dfs; 463} 464 465/* @bug 4071492 466 * DecimalFormat does not round up correctly. 467 */ 468void NumberFormatRegressionTest::Test4071492 (void) 469{ 470 double x = 0.00159999; 471 UErrorCode status = U_ZERO_ERROR; 472 NumberFormat *nf = NumberFormat::createInstance(status); 473 if (failure(status, "NumberFormat::createInstance", Locale::getUS(), TRUE)) { 474 delete nf; 475 return; 476 } 477 nf->setMaximumFractionDigits(4); 478 UnicodeString out; 479 FieldPosition pos(FieldPosition::DONT_CARE); 480 out = nf->format(x, out, pos); 481 logln("0.00159999 formats with 4 fractional digits to " + out); 482 UnicodeString expected("0.0016"); 483 if (out != expected) 484 errln("FAIL: Expected " + expected); 485 486 delete nf; 487} 488 489/* @bug 4086575 490 * A space as a group separator for localized pattern causes 491 * wrong format. WorkAround : use non-breaking space. 492 */ 493void NumberFormatRegressionTest::Test4086575(void) 494{ 495 UErrorCode status = U_ZERO_ERROR; 496 NumberFormat *nf1 = NumberFormat::createInstance(Locale::getFrance(), status); 497 498 // TODO: There is not a good way to find out that the creation of this number format has 499 // failed. Major rewiring of format construction proposed. 500 if(U_FAILURE(status)) { 501 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status)); 502 delete nf1; 503 return; 504 } 505 failure(status, "NumberFormat::createInstance", Locale::getFrance()); 506 507 // C++ workaround to make sure cast works 508 // Wouldn't dynamic_cast<DecimalFormat*> be great? 509 if(nf1->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 510 errln("NumberFormat::createInstance returned incorrect type."); 511 return; 512 } 513 514 DecimalFormat *nf = (DecimalFormat*) nf1; 515 UnicodeString temp; 516 logln("nf toPattern1: " + nf->toPattern(temp)); 517 logln("nf toLocPattern1: " + nf->toLocalizedPattern(temp)); 518 519 // No group separator 520 logln("...applyLocalizedPattern ###,00;(###,00) "); 521 nf->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status); 522 failure(status, "nf->applyLocalizedPattern", Locale::getFrance()); 523 logln("nf toPattern2: " + nf->toPattern(temp)); 524 logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp)); 525 526 FieldPosition pos(FieldPosition::DONT_CARE); 527 logln("nf: " + nf->format((int32_t)1234, temp, pos)); // 1234,00 528 logln("nf: " + nf->format((int32_t)-1234, temp, pos)); // (1234,00) 529 530 // Space as group separator 531 532 logln("...applyLocalizedPattern # ###,00;(# ###,00) "); 533 // nbsp = \u00a0 534 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)"); 535 UChar patChars[] = { 536 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b, 537 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29 538 }; 539 UnicodeString pat(patChars, 19, 19); 540 nf->applyLocalizedPattern(pat, status); 541 failure(status, "nf->applyLocalizedPattern", Locale::getFrance()); 542 logln("nf toPattern2: " + nf->toPattern(temp)); 543 logln("nf toLocPattern2: " + nf->toLocalizedPattern(temp)); 544 UnicodeString buffer; 545 buffer = nf->format((int32_t)1234, buffer, pos); 546 //if (buffer != UnicodeString("1\u00a0234,00")) 547 UChar c[] = { 548 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30 549 }; 550 UnicodeString cc(c, 8, 8); 551 if (buffer != cc) 552 errln("nf : " + buffer); // Expect 1 234,00 553 554 buffer.remove(); 555 buffer = nf->format((int32_t)-1234, buffer, pos); 556 UChar c1[] = { 557 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29 558 }; 559 UnicodeString cc1(c1, 10, 10); 560 if (buffer != cc1) 561 errln("nf : " + buffer); // Expect (1 234,00) 562 563 // Erroneously prints: 564 // 1234,00 , 565 // (1234,00 ,) 566 567 delete nf1; 568} 569/* @bug 4068693 570 * DecimalFormat.parse returns wrong value 571 */ 572// {sfb} slightly converted into a round-trip test, since in C++ 573// there is no Double.toString() 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(" getMaximumFractionDigits() = " + i); 716 logln(" formated: " + df->format(d, sb, fp)); 717 } 718 /*} catch (Exception foo) { 719 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage()); 720 }*/ 721 722 delete df; 723} 724/* @bug 4095713 725 * DecimalFormat.parse(String str, ParsePosition pp) loses precision 726 */ 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 if (nf->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 846 errln("expected DecimalFormat!"); 847 return; 848 } 849 DecimalFormat *df = (DecimalFormat*) nf; 850 const DecimalFormatSymbols *sym = df->getDecimalFormatSymbols(); 851 UnicodeString decSep = sym->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); 852 UnicodeString monSep = sym->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); 853 if (decSep == monSep) { 854 errln("ERROR in test: want decimal sep != monetary sep"); 855 return; 856 } 857 df->setMinimumIntegerDigits(1); 858 df->setMinimumFractionDigits(2); 859 UnicodeString str; 860 FieldPosition pos; 861 df->format(1.23, str, pos); 862 UnicodeString monStr("1x23"); 863 monStr.replace((int32_t)1, 1, monSep); 864 UnicodeString decStr("1x23"); 865 decStr.replace((int32_t)1, 1, decSep); 866 if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) { 867 logln(UnicodeString("OK: 1.23 -> \"") + str + "\" contains \"" + 868 monStr + "\" and not \"" + decStr + '"'); 869 } else { 870 errln(UnicodeString("FAIL: 1.23 -> \"") + str + "\", should contain \"" + 871 monStr + 872 "\" and not \"" + decStr + '"'); 873 } 874 delete de; 875 delete nf; 876} 877/* @bug 4070798 878 * Number format data rounding errors for locale FR 879 */ 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 DM"; 1036 String expectedPercent = "-578.998%"; 1037 */ 1038 UnicodeString expectedDefault("-5.789,988"); 1039 UnicodeString expectedCurrency("5.789,99\\u00A0DM"); 1040 UnicodeString expectedPercent("-578.999\\u00A0%"); 1041 1042 expectedCurrency = expectedCurrency.unescape(); 1043 expectedPercent = expectedPercent.unescape(); 1044 1045 UErrorCode status = U_ZERO_ERROR; 1046 char loc[256]={0}; 1047 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); 1048 formatter = NumberFormat::createInstance(Locale(loc), status); 1049 if (failure(status, "NumberFormat::createNumberInstance", loc, TRUE)){ 1050 delete formatter; 1051 return; 1052 } 1053 tempString.remove(); 1054 tempString = formatter->format (-5789.9876, tempString); 1055 1056 if (tempString == expectedDefault) { 1057 logln ("Bug 4071014 default test passed."); 1058 } else { 1059 errln(UnicodeString("Failed:") + 1060 " Expected " + expectedDefault + 1061 " Received " + tempString ); 1062 } 1063 delete formatter; 1064 uloc_canonicalize("de_DE_PREEURO", loc, 256, &status); 1065 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); 1066 failure(status, "NumberFormat::createCurrencyInstance", loc); 1067 tempString.remove(); 1068 tempString = formatter->format( 5789.9876, tempString ); 1069 1070 if (tempString == expectedCurrency) { 1071 logln ("Bug 4071014 currency test assed."); 1072 } else { 1073 errln(UnicodeString("Failed:") + 1074 " Expected " + expectedCurrency + 1075 " Received " + tempString ); 1076 } 1077 delete formatter; 1078 1079 formatter = NumberFormat::createPercentInstance(Locale::getGermany(), status); 1080 failure(status, "NumberFormat::createPercentInstance", Locale::getGermany()); 1081 tempString.remove(); 1082 tempString = formatter->format (-5789.9876, tempString); 1083 1084 if (tempString == expectedPercent) { 1085 logln ("Bug 4071014 percentage test passed."); 1086 } else { 1087 errln(UnicodeString("Failed:") + 1088 " Expected " + expectedPercent + 1089 " Received " + tempString ); 1090 } 1091 1092 delete formatter; 1093} 1094/* @bug 4071859 1095 * Data rounding errors for Italian locale number formats 1096 */ 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("-IT\\u20A4\\u00A05.790", -1, US_INV); 1108 UnicodeString expectedPercent("-578.999%"); 1109 expectedCurrency = expectedCurrency.unescape(); 1110 1111 UErrorCode status = U_ZERO_ERROR; 1112 char loc[256]={0}; 1113 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1114 formatter = NumberFormat::createInstance(Locale(loc), status); 1115 if (failure(status, "NumberFormat::createNumberInstance", TRUE)){ 1116 delete formatter; 1117 return; 1118 }; 1119 tempString = formatter->format (-5789.9876, tempString); 1120 1121 if (tempString == expectedDefault) { 1122 logln ("Bug 4071859 default test passed."); 1123 } else { 1124 errln(UnicodeString("Failed:") + 1125 " Expected " + expectedDefault + 1126 " Received " + tempString ); 1127 } 1128 delete formatter; 1129 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1130 formatter = NumberFormat::createCurrencyInstance(Locale(loc), status); 1131 failure(status, "NumberFormat::createCurrencyInstance"); 1132 tempString.remove(); 1133 tempString = formatter->format( -5789.9876, tempString ); 1134 1135 if (tempString == expectedCurrency) { 1136 logln ("Bug 4071859 currency test assed."); 1137 } else { 1138 errln(UnicodeString("Failed:") + 1139 " Expected " + expectedCurrency + 1140 " Received " + tempString ); 1141 } 1142 delete formatter; 1143 uloc_canonicalize("it_IT_PREEURO", loc, 256, &status); 1144 formatter = NumberFormat::createPercentInstance(Locale(loc), status); 1145 failure(status, "NumberFormat::createPercentInstance"); 1146 tempString.remove(); 1147 tempString = formatter->format (-5789.9876, tempString); 1148 1149 if (tempString == expectedPercent) { 1150 logln ("Bug 4071859 percentage test passed."); 1151 } else { 1152 errln(UnicodeString("Failed:") + 1153 " Expected " + expectedPercent + 1154 " Received " + tempString ); 1155 } 1156 1157 delete formatter; 1158} 1159/* @bug 4071859 1160 * Test rounding for nearest even. 1161 */ 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 errln("Failed! 3456.78 p'ieces expected, but got : " + tempString); 1246 /*} catch (Exception foo) { 1247 errln("An exception was thrown for any inconsistent negative pattern."); 1248 }*/ 1249 1250 delete fmt; 1251 delete newFmt; 1252} 1253/* @bug 4099404 1254 * Tests all different comments. 1255 * Response to some comments : 1256 * [1] DecimalFormat.parse API documentation is more than just one line. 1257 * This is not a reproducable doc error in 116 source code. 1258 * [2] See updated javadoc. 1259 * [3] Fixed. 1260 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails, 1261 * a null object will be returned. The unchanged parse position also 1262 * reflects an error. 1263 * NumberFormat.parse(String) : If parsing fails, an ParseException 1264 * will be thrown. 1265 * See updated javadoc for more details. 1266 * [5] See updated javadoc. 1267 * [6] See updated javadoc. 1268 * [7] This is a correct behavior if the DateFormat object is linient. 1269 * Otherwise, an IllegalArgumentException will be thrown when formatting 1270 * "January 35". See GregorianCalendar class javadoc for more details. 1271 */ 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->get("NumberPatterns", status); 1645 failure(status, "new ResourceBundle(NumberPatterns)"); 1646 // 1647 // Get the currency pattern for this locale. We have to fish it 1648 // out of the ResourceBundle directly, since DecimalFormat.toPattern 1649 // will return the localized symbol, not \00a4 1650 // 1651 UnicodeString pattern = numPat.getStringEx(1, status); 1652 failure(status, "rb->getStringArray"); 1653 1654 UChar fo[] = { 0x00A4 }; 1655 UnicodeString foo(fo, 1, 1); 1656 1657 //if (pattern.indexOf("\u00A4") == -1 ) { 1658 if (pattern.indexOf(foo) == -1 ) { 1659 errln(UnicodeString("Currency format for ") + UnicodeString(locales[i].getName()) + 1660 " does not contain generic currency symbol:" + 1661 pattern ); 1662 } 1663 1664 // Create a DecimalFormat using the pattern we got and format a number 1665 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(locales[i], status); 1666 failure(status, "new DecimalFormatSymbols"); 1667 DecimalFormat *fmt1 = new DecimalFormat(pattern, *symbols, status); 1668 failure(status, "new DecimalFormat"); 1669 1670 UnicodeString result1; 1671 FieldPosition pos(FieldPosition::DONT_CARE); 1672 result1 = fmt1->format(1.111, result1, pos); 1673 1674 // 1675 // Now substitute in the locale's currency symbol and create another 1676 // pattern. We have to skip locales where the currency symbol 1677 // contains decimal separators, because that confuses things 1678 // 1679 UChar ba[] = { 0x002E/*'.'*/ }; 1680 UnicodeString bar(ba, 1, 1); 1681 1682 if (symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).indexOf(bar) == -1) { 1683 // {sfb} Also, switch the decimal separator to the monetary decimal 1684 // separator to mimic the behavior of a currency format 1685 symbols->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, 1686 symbols->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol)); 1687 1688 UnicodeString buf(pattern); 1689 for (int j = 0; j < buf.length(); j++) { 1690 if (buf[j] == 0x00a4 ) { 1691 if(buf[j + 1] == 0x00a4) { 1692 // {sfb} added to support double currency marker (intl currency sign) 1693 buf.replace(j, /*j+*/2, symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); 1694 j += symbols->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol).length(); 1695 } 1696 else { 1697 buf.replace(j, /*j+*/1, symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol)); 1698 j += symbols->getSymbol(DecimalFormatSymbols::kCurrencySymbol).length() - 1; 1699 } 1700 } 1701 } 1702 1703 DecimalFormat *fmt2 = new DecimalFormat(buf, *symbols, status); 1704 failure(status, "new DecimalFormat"); 1705 1706 // Get the currency (if there is one) so we can set the rounding and fraction 1707 const UChar *currency = fmt1->getCurrency(); 1708 if (*currency != 0) { 1709 double rounding = ucurr_getRoundingIncrement(currency, &status); 1710 int32_t frac = ucurr_getDefaultFractionDigits(currency, &status); 1711 if (U_SUCCESS(status)) { 1712 fmt2->setRoundingIncrement(rounding); 1713 fmt2->setMinimumFractionDigits(frac); 1714 fmt2->setMaximumFractionDigits(frac); 1715 } 1716 else { 1717 failure(status, "Fetching currency rounding/fractions"); 1718 } 1719 } 1720 1721 UnicodeString result2; 1722 fmt2->format(1.111, result2, pos); 1723 1724 if (result1 != result2) { 1725 errln("Results for " + (UnicodeString)(locales[i].getName()) + " differ: " + 1726 result1 + " vs " + result2); 1727 } 1728 1729 delete fmt2; 1730 } 1731 1732 delete rb; 1733 delete fmt1; 1734 delete symbols; 1735 } 1736} 1737 1738/* @bug 4125885 1739 * DecimalFormat.format() delivers wrong string. 1740 */ 1741void NumberFormatRegressionTest::Test4125885(void) 1742{ 1743 UErrorCode status = U_ZERO_ERROR; 1744 double rate = 12.34; 1745 DecimalFormat *formatDec = new DecimalFormat ("000.00", status); 1746 if(U_FAILURE(status)) { 1747 errcheckln(status, "Error creating DecimalFormat: %s", u_errorName(status)); 1748 delete formatDec; 1749 return; 1750 } 1751 failure(status, "new DecimalFormat"); 1752 UnicodeString temp; 1753 logln("toPattern: " + formatDec->toPattern(temp)); 1754 UnicodeString rateString; 1755 FieldPosition pos(FieldPosition::DONT_CARE); 1756 rateString = formatDec->format(rate, rateString, pos); 1757 if (rateString != UnicodeString("012.34")) 1758 errln("result : " + rateString + " expected : 012.34"); 1759 rate = 0.1234; 1760 delete formatDec;// = null; 1761 formatDec = new DecimalFormat ("+000.00%;-000.00%", status); 1762 failure(status, "new DecimalFormat"); 1763 logln("toPattern: " + formatDec->toPattern(temp)); 1764 rateString.remove(); 1765 rateString = formatDec->format(rate, rateString, pos); 1766 if (rateString != UnicodeString("+012.34%")) 1767 errln("result : " + rateString + " expected : +012.34%"); 1768 1769 delete formatDec; 1770} 1771 1772/** 1773 * @bug 4134034 1774 * DecimalFormat produces extra zeros when formatting numbers. 1775 */ 1776void NumberFormatRegressionTest::Test4134034(void) 1777{ 1778 UErrorCode status = U_ZERO_ERROR; 1779 DecimalFormat *nf = new DecimalFormat("##,###,###.00", status); 1780 if (!failure(status, "new DecimalFormat")) { 1781 UnicodeString f; 1782 FieldPosition pos(FieldPosition::DONT_CARE); 1783 f = nf->format(9.02, f, pos); 1784 if (f == UnicodeString("9.02")) 1785 logln(f + " ok"); 1786 else 1787 errln("9.02 -> " + f + "; want 9.02"); 1788 1789 f.remove(); 1790 f = nf->format((int32_t)0, f, pos); 1791 if (f == UnicodeString(".00")) 1792 logln(f + " ok"); 1793 else 1794 errln("0 -> " + f + "; want .00"); 1795 } 1796 1797 delete nf; 1798} 1799 1800/** 1801 * @bug 4134300 1802 * CANNOT REPRODUCE - This bug could not be reproduced. It may be 1803 * a duplicate of 4134034. 1804 * 1805 * JDK 1.1.6 Bug, did NOT occur in 1.1.5 1806 * Possibly related to bug 4125885. 1807 * 1808 * This class demonstrates a regression in version 1.1.6 1809 * of DecimalFormat class. 1810 * 1811 * 1.1.6 Results 1812 * Value 1.2 Format #.00 Result '01.20' !!!wrong 1813 * Value 1.2 Format 0.00 Result '001.20' !!!wrong 1814 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong 1815 * Value 1.2 Format #0.0# Result '1.2' 1816 * Value 1.2 Format #0.00 Result '001.20' !!!wrong 1817 * 1818 * 1.1.5 Results 1819 * Value 1.2 Format #.00 Result '1.20' 1820 * Value 1.2 Format 0.00 Result '1.20' 1821 * Value 1.2 Format 00.00 Result '01.20' 1822 * Value 1.2 Format #0.0# Result '1.2' 1823 * Value 1.2 Format #0.00 Result '1.20' 1824 */ 1825void NumberFormatRegressionTest::Test4134300(void) { 1826 UnicodeString DATA [] = { 1827 // Pattern Expected string 1828 UnicodeString("#.00"), UnicodeString("1.20"), 1829 UnicodeString("0.00"), UnicodeString("1.20"), 1830 UnicodeString("00.00"), UnicodeString("01.20"), 1831 UnicodeString("#0.0#"), UnicodeString("1.2"), 1832 UnicodeString("#0.00"), UnicodeString("1.20") 1833 }; 1834 1835 for (int i=0; i< 10; i+=2) { 1836 UnicodeString result; 1837 UErrorCode status = U_ZERO_ERROR; 1838 DecimalFormat *df = new DecimalFormat(DATA[i], status); 1839 if (!failure(status, "new DecimalFormat")) { 1840 FieldPosition pos(FieldPosition::DONT_CARE); 1841 result = df->format(1.2, result, pos); 1842 if (result != DATA[i+1]) { 1843 errln("Fail: 1.2 x " + DATA[i] + " = " + result + 1844 "; want " + DATA[i+1]); 1845 } 1846 else { 1847 logln("Ok: 1.2 x " + DATA[i] + " = " + result); 1848 } 1849 } 1850 1851 delete df; 1852 } 1853} 1854 1855/** 1856 * @bug 4140009 1857 * Empty pattern produces double negative prefix. 1858 */ 1859void NumberFormatRegressionTest::Test4140009(void) 1860{ 1861 UErrorCode status = U_ZERO_ERROR; 1862 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 1863 failure(status, "new DecimalFormatSymbols"); 1864 DecimalFormat *f = new DecimalFormat(UnicodeString(""), syms, status); 1865 if (!failure(status, "new DecimalFormat")) { 1866 UnicodeString s; 1867 FieldPosition pos(FieldPosition::DONT_CARE); 1868 s = f->format(123.456, s, pos); 1869 if (s != UnicodeString("123.456")) 1870 errln("Fail: Format empty pattern x 123.456 => " + s); 1871 s.remove(); 1872 s = f->format(-123.456, s, pos); 1873 if (s != UnicodeString("-123.456")) 1874 errln("Fail: Format empty pattern x -123.456 => " + s); 1875 } 1876 delete f; 1877} 1878 1879/** 1880 * @bug 4141750 1881 * BigDecimal numbers get their fractions truncated by NumberFormat. 1882 */ 1883// {sfb} not pertinent in C++ ?? 1884void NumberFormatRegressionTest::Test4141750(void) { 1885 /*try { 1886 UnicodeString str("12345.67"); 1887 BigDecimal bd = new BigDecimal(str); 1888 String sd = NumberFormat.getInstance(Locale.US).format(bd); 1889 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd); 1890 } 1891 catch (Exception e) { 1892 errln(e.toString()); 1893 e.printStackTrace(); 1894 }*/ 1895} 1896 1897/** 1898 * @bug 4145457 1899 * DecimalFormat toPattern() doesn't quote special characters or handle 1900 * single quotes. 1901 */ 1902void NumberFormatRegressionTest::Test4145457() { 1903 //try { 1904 UErrorCode status = U_ZERO_ERROR; 1905 NumberFormat *nff = NumberFormat::createInstance(status); 1906 if (failure(status, "NumberFormat::createInstance", TRUE)){ 1907 delete nff; 1908 return; 1909 }; 1910 if(nff->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 1911 errln("DecimalFormat needed to continue"); 1912 return; 1913 } 1914 1915 DecimalFormat *nf = (DecimalFormat*)nff; 1916 DecimalFormatSymbols *sym = (DecimalFormatSymbols*) nf->getDecimalFormatSymbols(); 1917 sym->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, (UChar)/*'\''*/0x0027); 1918 nf->setDecimalFormatSymbols(*sym); 1919 double pi = 3.14159; 1920 1921 UnicodeString PATS [] = { 1922 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''") 1923 }; 1924 1925 for (int32_t i=0; i<2; ++i) { 1926 nf->applyPattern(PATS[i], status); 1927 failure(status, "nf->applyPattern"); 1928 UnicodeString out; 1929 FieldPosition pos(FieldPosition::DONT_CARE); 1930 out = nf->format(pi, out, pos); 1931 UnicodeString pat; 1932 pat = nf->toPattern(pat); 1933 Formattable num; 1934 ParsePosition pp(0); 1935 nf->parse(out, num, pp); 1936 double val = num.getDouble(); 1937 1938 nf->applyPattern(pat, status); 1939 failure(status, "nf->applyPattern"); 1940 UnicodeString out2; 1941 out2 = nf->format(pi, out2, pos); 1942 UnicodeString pat2; 1943 pat2 = nf->toPattern(pat2); 1944 nf->parse(out2, num, pp); 1945 double val2 = num.getDouble(); 1946 1947 if (pat != pat2) 1948 errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" + 1949 pat + "\" vs. \"" + pat2 + "\""); 1950 else 1951 logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"'); 1952 1953 if (val == val2 && out == out2) { 1954 logln(UnicodeString("Ok ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1955 out + "\" -> " + val + " -> \"" + 1956 out2 + "\" -> " + val2); 1957 } 1958 else { 1959 errln(UnicodeString("Fail ") + pi + " x \"" + PATS[i] + "\" -> \"" + 1960 out + "\" -> " + val + " -> \"" + 1961 out2 + "\" -> " + val2); 1962 } 1963 } 1964 /*} 1965 catch (ParseException e) { 1966 errln("Fail: " + e); 1967 e.printStackTrace(); 1968 }*/ 1969 1970 delete nff; 1971} 1972 1973/** 1974 * @bug 4147295 1975 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly. 1976 * CANNOT REPRODUCE 1977 * This bug is a duplicate of 4139344, which is a duplicate of 4134300 1978 */ 1979void NumberFormatRegressionTest::Test4147295(void) 1980{ 1981 UErrorCode status = U_ZERO_ERROR; 1982 DecimalFormat *sdf = new DecimalFormat(status); 1983 UnicodeString pattern("#,###"); 1984 logln("Applying pattern \"" + pattern + "\""); 1985 sdf->applyPattern(pattern, status); 1986 if (!failure(status, "sdf->applyPattern")) { 1987 int minIntDig = sdf->getMinimumIntegerDigits(); 1988 if (minIntDig != 0) { 1989 errln("Test failed"); 1990 errln(" Minimum integer digits : " + minIntDig); 1991 UnicodeString temp; 1992 errln(" new pattern: " + sdf->toPattern(temp)); 1993 } else { 1994 logln("Test passed"); 1995 logln(" Minimum integer digits : " + minIntDig); 1996 } 1997 } 1998 delete sdf; 1999} 2000 2001/** 2002 * @bug 4147706 2003 * DecimalFormat formats -0.0 as +0.0 2004 * See also older related bug 4106658, 4106667 2005 */ 2006void NumberFormatRegressionTest::Test4147706(void) 2007{ 2008 UErrorCode status = U_ZERO_ERROR; 2009 DecimalFormat *df = new DecimalFormat("#,##0.0##", status); 2010 failure(status, "new DecimalFormat"); 2011 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale::getEnglish(), status); 2012 if (!failure(status, "new DecimalFormatSymbols")) { 2013 UnicodeString f1; 2014 UnicodeString f2, temp; 2015 FieldPosition pos(FieldPosition::DONT_CARE); 2016 volatile double d1 = 0.0; // volatile to prevent code optimization 2017 double d2 = -0.0001; 2018 2019#if defined(U_HPUX) 2020 d1 = 0.0 * -1.0; // old HPUX compiler ignores volatile keyword 2021#else 2022 d1 *= -1.0; // Some compilers have a problem with defining -0.0 2023#endif 2024 df->adoptDecimalFormatSymbols(syms); 2025 f1 = df->format(d1, f1, pos); 2026 f2 = df->format(d2, f2, pos); 2027 if (f1 != UnicodeString("-0.0")) { 2028 errln(UnicodeString("") + d1 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f1 + '"'); 2029 } 2030 if (f2 != UnicodeString("-0.0")) { 2031 errln(UnicodeString("") + d2 + UnicodeString(" x \"") + df->toPattern(temp) + "\" is formatted as \"" + f2 + '"'); 2032 } 2033 } 2034 2035 delete df; 2036} 2037 2038 2039// Not applicable, since no serialization in C++ 2040/*class myformat implements Serializable 2041{ 2042DateFormat _dateFormat = DateFormat.getDateInstance(); 2043 2044public String Now() 2045{ 2046 GregorianCalendar calendar = new GregorianCalendar(); 2047 Date t = calendar.getTime(); 2048 String nowStr = _dateFormat.format(t); 2049 return nowStr; 2050} 2051}*/ 2052 2053/** 2054 * @bug 4162198 2055 * NumberFormat cannot format Double.MAX_VALUE 2056 */ 2057// TODO: make this test actually test something 2058void 2059NumberFormatRegressionTest::Test4162198(void) 2060{ 2061 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof) 2062 double dbl = INT32_MAX * 1000.0; 2063 UErrorCode status = U_ZERO_ERROR; 2064 NumberFormat *f = NumberFormat::createInstance(status); 2065 if(U_FAILURE(status)) { 2066 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2067 return; 2068 } 2069 f->setMaximumFractionDigits(INT32_MAX); 2070 f->setMaximumIntegerDigits(INT32_MAX); 2071 UnicodeString s; 2072 f->format(dbl,s); 2073 logln(UnicodeString("The number ") + dbl + " formatted to " + s); 2074 Formattable n; 2075 //try { 2076 f->parse(s, n, status); 2077 if(U_FAILURE(status)) 2078 errln("Couldn't parse!"); 2079 //} catch (java.text.ParseException e) { 2080 // errln("Caught a ParseException:"); 2081 // e.printStackTrace(); 2082 //} 2083 2084 //logln("The string " + s + " parsed as " + n); 2085 2086 // {dlf} The old code assumes n is a double, but it isn't any more... 2087 // Formattable apparently does not and never did interconvert... too bad. 2088 //if(n.getDouble() != dbl) { 2089 // errln("Round trip failure"); 2090 //} 2091 if (n.getInt64() != dbl) { 2092 errln("Round trip failure"); 2093 } 2094 2095 delete f; 2096} 2097 2098/** 2099 * @bug 4162852 2100 * NumberFormat does not parse negative zero. 2101 */ 2102void 2103NumberFormatRegressionTest::Test4162852(void) 2104{ 2105 UErrorCode status = U_ZERO_ERROR; 2106 for(int32_t i=0; i < 2; ++i) { 2107 NumberFormat *f = (i == 0) ? NumberFormat::createInstance(status) 2108 : NumberFormat::createPercentInstance(status); 2109 if(U_FAILURE(status)) { 2110 dataerrln("Couldn't create number format - %s", u_errorName(status)); 2111 return; 2112 } 2113 double d = 0.0; 2114 d *= -1.0; 2115 UnicodeString s; 2116 f->format(d, s); 2117 Formattable n; 2118 f->parse(s, n, status); 2119 if(U_FAILURE(status)) 2120 errln("Couldn't parse!"); 2121 double e = n.getDouble(); 2122 logln(UnicodeString("") + 2123 d + " -> " + 2124 '"' + s + '"' + " -> " + e); 2125#if (defined(OS390) && !defined(IEEE_754)) || defined(OS400) 2126 if (e != 0.0) { 2127#else 2128 if (e != 0.0 || 1.0/e > 0.0) { 2129#endif 2130 logln("Failed to parse negative zero"); 2131 } 2132 delete f; 2133 } 2134} 2135 2136static double _u_abs(double a) { return a<0?-a:a; } 2137 2138/** 2139 * May 17 1999 sync up - liu 2140 * @bug 4167494 2141 * NumberFormat truncates data 2142 */ 2143void NumberFormatRegressionTest::Test4167494(void) { 2144 UErrorCode status = U_ZERO_ERROR; 2145 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2146 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2147 delete fmt; 2148 return; 2149 }; 2150 2151 double a = DBL_MAX * 0.99; // DBL_MAX itself overflows to +Inf 2152 UnicodeString s; 2153 fmt->format(a, s); 2154 Formattable num; 2155 fmt->parse(s, num, status); 2156 failure(status, "Parse"); 2157 if (num.getType() == Formattable::kDouble && 2158 _u_abs(num.getDouble() - a) / a < 0.01) { // RT within 1% 2159 logln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2160 toString(num) + " ok"); 2161 } else { 2162 errln(UnicodeString("") + a + " -> \"" + s + "\" -> " + 2163 toString(num) + " FAIL"); 2164 } 2165 2166 // We don't test Double.MIN_VALUE because the locale data for the US 2167 // currently doesn't specify enough digits to display Double.MIN_VALUE. 2168 // This is correct for now; however, we leave this here as a reminder 2169 // in case we want to address this later. 2170 2171 delete fmt; 2172} 2173 2174/** 2175 * May 17 1999 sync up - liu 2176 * @bug 4170798 2177 * DecimalFormat.parse() fails when ParseIntegerOnly set to true 2178 */ 2179void NumberFormatRegressionTest::Test4170798(void) { 2180 UErrorCode status = U_ZERO_ERROR; 2181 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2182 if (failure(status, "NumberFormat::createInstance", TRUE)){ 2183 delete nf; 2184 return; 2185 }; 2186 if(nf->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 2187 errln("DecimalFormat needed to continue"); 2188 return; 2189 } 2190 DecimalFormat *df = (DecimalFormat*) nf; 2191 df->setParseIntegerOnly(TRUE); 2192 Formattable n; 2193 ParsePosition pos(0); 2194 df->parse("-0.0", n, pos); 2195 if (n.getType() != Formattable::kLong 2196 || n.getLong() != 0) { 2197 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n)); 2198 } 2199 delete nf; 2200} 2201 2202/** 2203 * May 17 1999 sync up - liu 2204 * toPattern only puts the first grouping separator in. 2205 */ 2206void NumberFormatRegressionTest::Test4176114(void) { 2207 const char* DATA[] = { 2208 "00", "#00", 2209 "000", "#000", // No grouping 2210 "#000", "#000", // No grouping 2211 "#,##0", "#,##0", 2212 "#,000", "#,000", 2213 "0,000", "#0,000", 2214 "00,000", "#00,000", 2215 "000,000", "#,000,000", 2216 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported 2217 }; 2218 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2219 UErrorCode status = U_ZERO_ERROR; 2220 UnicodeString s; 2221 for (int i=0; i<DATA_length; i+=2) { 2222 DecimalFormat df(DATA[i], status); 2223 if (!failure(status, "DecimalFormat constructor")) { 2224 df.toPattern(s); 2225 UnicodeString exp(DATA[i+1]); 2226 if (s != exp) { 2227 errln(UnicodeString("FAIL: ") + DATA[i] + " -> " + 2228 s + ", want " + exp); 2229 } 2230 } 2231 } 2232} 2233 2234/** 2235 * May 17 1999 sync up - liu 2236 * @bug 4179818 2237 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2 2238 */ 2239void NumberFormatRegressionTest::Test4179818(void) { 2240 const char* DATA[] = { 2241 // Input Pattern Expected output 2242 "1.2511", "#.#", "1.3", 2243 "1.2501", "#.#", "1.3", 2244 "0.9999", "#", "1", 2245 }; 2246 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2247 double DOUBLE[] = { 2248 1.2511, 2249 1.2501, 2250 0.9999, 2251 }; 2252 UErrorCode status = U_ZERO_ERROR; 2253 DecimalFormatSymbols sym(Locale::getUS(), status); 2254 failure(status, "Construct DecimalFormatSymbols"); 2255 DecimalFormat fmt("#", sym, status); 2256 if (!failure(status, "Construct DecimalFormat")) { 2257 for (int i=0; i<DATA_length; i+=3) { 2258 double in = DOUBLE[i/3]; 2259 UnicodeString pat(DATA[i+1]); 2260 UnicodeString exp(DATA[i+2]); 2261 fmt.applyPattern(pat, status); 2262 failure(status, "applyPattern"); 2263 UnicodeString out; 2264 FieldPosition pos; 2265 fmt.format(in, out, pos); 2266 if (out == exp) { 2267 logln(UnicodeString("Ok: ") + in + " x " + pat + " = " + out); 2268 } else { 2269 errln(UnicodeString("FAIL: ") + in + " x " + pat + " = " + out + 2270 ", expected " + exp); 2271 } 2272 } 2273 } 2274} 2275 2276/** 2277 * May 17 1999 sync up - liu 2278 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat. 2279 * This includes the minus sign, currency symbol, international currency 2280 * symbol, percent, and permille. This is filed as bugs 4212072 and 2281 * 4212073. 2282 */ 2283void NumberFormatRegressionTest::Test4212072(void) { 2284 UErrorCode status = U_ZERO_ERROR; 2285 DecimalFormatSymbols sym(Locale::getUS(), status); 2286 2287 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2288 DecimalFormat fmt(UnicodeString("#"), sym, status); 2289 if(failure(status, "DecimalFormat ct", Locale::getUS())) { 2290 return; 2291 } 2292 2293 UnicodeString s; 2294 FieldPosition pos; 2295 2296 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x5e); 2297 fmt.setDecimalFormatSymbols(sym); 2298 s.remove(); 2299 if (fmt.format((int32_t)-1, s, pos) != UNICODE_STRING("^1", 2)) { 2300 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s + 2301 ", exp ^1"); 2302 } 2303 s.remove(); 2304 if (fmt.getNegativePrefix(s) != UnicodeString((UChar)0x5e)) { 2305 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") + 2306 s + ", exp ^"); 2307 } 2308 sym.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, (UChar)0x2d); 2309 2310 fmt.applyPattern(UnicodeString("#%"), status); 2311 failure(status, "applyPattern percent"); 2312 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x5e); 2313 fmt.setDecimalFormatSymbols(sym); 2314 s.remove(); 2315 if (fmt.format(0.25, s, pos) != UNICODE_STRING("25^", 3)) { 2316 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s + 2317 ", exp 25^"); 2318 } 2319 s.remove(); 2320 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2321 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") + 2322 s + ", exp ^"); 2323 } 2324 sym.setSymbol(DecimalFormatSymbols::kPercentSymbol, (UChar)0x25); 2325 2326 fmt.applyPattern(str("#\\u2030"), status); 2327 failure(status, "applyPattern permill"); 2328 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x5e); 2329 fmt.setDecimalFormatSymbols(sym); 2330 s.remove(); 2331 if (fmt.format(0.25, s, pos) != UNICODE_STRING("250^", 4)) { 2332 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s + 2333 ", exp 250^"); 2334 } 2335 s.remove(); 2336 if (fmt.getPositiveSuffix(s) != UnicodeString((UChar)0x5e)) { 2337 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") + 2338 s + ", exp ^"); 2339 } 2340 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, (UChar)0x2030); 2341 2342 fmt.applyPattern(str("\\u00A4#.00"), status); 2343 failure(status, "applyPattern currency"); 2344 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "usd"); 2345 fmt.setDecimalFormatSymbols(sym); 2346 s.remove(); 2347 if (fmt.format(12.5, s, pos) != UnicodeString("usd12.50")) { 2348 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s + 2349 ", exp usd12.50"); 2350 } 2351 s.remove(); 2352 if (fmt.getPositivePrefix(s) != UnicodeString("usd")) { 2353 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") + 2354 s + ", exp usd"); 2355 } 2356 sym.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "$"); 2357 2358 fmt.applyPattern(str("\\u00A4\\u00A4#.00"), status); 2359 failure(status, "applyPattern intl currency"); 2360 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "DOL"); 2361 fmt.setDecimalFormatSymbols(sym); 2362 s.remove(); 2363 if (fmt.format(12.5, s, pos) != UnicodeString("DOL12.50")) { 2364 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s + 2365 ", exp DOL12.50"); 2366 } 2367 s.remove(); 2368 if (fmt.getPositivePrefix(s) != UnicodeString("DOL")) { 2369 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") + 2370 s + ", exp DOL"); 2371 } 2372 sym.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, "USD"); 2373 2374 // Since the pattern logic has changed, make sure that patterns round 2375 // trip properly. Test stream in/out integrity too. 2376 int32_t n; 2377 const Locale* avail = NumberFormat::getAvailableLocales(n); 2378 static const char* type[] = { 2379 "", 2380 "$ ", 2381 "% ", 2382 }; 2383 for (int i=0; i<n; ++i) { 2384 for (int j=0; j<3; ++j) { 2385 status = U_ZERO_ERROR; 2386 NumberFormat *nf; 2387 switch (j) { 2388 case 0: 2389 nf = NumberFormat::createInstance(avail[i], status); 2390 failure(status, "createInstance", avail[i]); 2391 break; 2392 case 1: 2393 nf = NumberFormat::createCurrencyInstance(avail[i], status); 2394 failure(status, "createCurrencyInstance", avail[i]); 2395 break; 2396 default: 2397 nf = NumberFormat::createPercentInstance(avail[i], status); 2398 failure(status, "createPercentInstance", avail[i]); 2399 break; 2400 } 2401 if (U_FAILURE(status)) { 2402 continue; 2403 } 2404 DecimalFormat *df = (DecimalFormat*) nf; 2405 2406 // Test toPattern/applyPattern round trip 2407 UnicodeString pat; 2408 df->toPattern(pat); 2409 DecimalFormatSymbols symb(avail[i], status); 2410 failure(status, "Construct DecimalFormatSymbols", avail[i]); 2411 DecimalFormat f2(pat, symb, status); 2412 if (failure(status, 2413 UnicodeString("Construct DecimalFormat(") + pat + ")")) { 2414 continue; 2415 } 2416 if (*df != f2) { 2417 UnicodeString l, p; 2418 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2419 " -> \"" + pat + 2420 "\" -> \"" + f2.toPattern(p) + "\""); 2421 } 2422 2423 // Test toLocalizedPattern/applyLocalizedPattern round trip 2424 df->toLocalizedPattern(pat); 2425 f2.applyLocalizedPattern(pat, status); 2426 failure(status, 2427 UnicodeString("applyLocalizedPattern(") + pat + ")", avail[i]); 2428 if (U_FAILURE(status)) { 2429 continue; 2430 } 2431 2432 // Make sure we set the currency attributes appropriately 2433 if (j == 1) { // Currency format 2434 f2.setCurrency(f2.getCurrency(), status); 2435 } 2436 failure(status, 2437 UnicodeString("setCurrency() for (") + pat + ")", avail[i]); 2438 if (U_FAILURE(status)) { 2439 continue; 2440 } 2441 2442 if (*df != f2) { 2443 UnicodeString l, p; 2444 errln(UnicodeString("FAIL: ") + type[j] + avail[i].getDisplayName(l) + 2445 " -> localized \"" + pat + 2446 "\" -> \"" + f2.toPattern(p) + "\""); 2447 } 2448 2449 delete nf; 2450 2451 // Test writeObject/readObject round trip 2452 // NOT ON ICU -- Java only 2453 } 2454 } 2455} 2456 2457/** 2458 * May 17 1999 sync up - liu 2459 * DecimalFormat.parse() fails for mulipliers 2^n. 2460 */ 2461void NumberFormatRegressionTest::Test4216742(void) { 2462 UErrorCode status = U_ZERO_ERROR; 2463 DecimalFormat *fmt = (DecimalFormat*) NumberFormat::createInstance(Locale::getUS(), status); 2464 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2465 delete fmt; 2466 return; 2467 }; 2468 int32_t DATA[] = { INT32_MIN, INT32_MAX, -100000000, 100000000 }; 2469 int DATA_length = (int)(sizeof(DATA) / sizeof(DATA[0])); 2470 for (int i=0; i<DATA_length; ++i) { 2471 UnicodeString str((UnicodeString)"" + DATA[i]); 2472 for (int m = 1; m <= 100; m++) { 2473 fmt->setMultiplier(m); 2474 Formattable num; 2475 fmt->parse(str, num, status); 2476 failure(status, "parse", Locale::getUS()); 2477 if (num.getType() != Formattable::kLong && 2478 num.getType() != Formattable::kDouble) { 2479 errln(UnicodeString("FAIL: Wanted number, got ") + 2480 toString(num)); 2481 } else { 2482 double d = num.getType() == Formattable::kDouble ? 2483 num.getDouble() : (double) num.getLong(); 2484 if (d > 0 != DATA[i] > 0) { 2485 errln(UnicodeString("\"") + str + "\" parse(x " + 2486 fmt->getMultiplier() + 2487 ") => " + toString(num)); 2488 } 2489 } 2490 } 2491 } 2492 delete fmt; 2493} 2494 2495/** 2496 * May 17 1999 sync up - liu 2497 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction 2498 * digits. 2499 */ 2500void NumberFormatRegressionTest::Test4217661(void) { 2501 const double D[] = { 0.001, 1.001, 0.006, 1.006 }; 2502 const char* S[] = { "0", "1", "0.01", "1.01" }; 2503 int D_length = (int)(sizeof(D) / sizeof(D[0])); 2504 UErrorCode status = U_ZERO_ERROR; 2505 NumberFormat *fmt = NumberFormat::createInstance(Locale::getUS(), status); 2506 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2507 delete fmt; 2508 return; 2509 }; 2510 fmt->setMaximumFractionDigits(2); 2511 for (int i=0; i<D_length; i++) { 2512 UnicodeString s; 2513 fmt->format(D[i], s); 2514 if (s != UnicodeString(S[i])) { 2515 errln(UnicodeString("FAIL: Got ") + s + ", exp " + S[i]); 2516 } 2517 } 2518 delete fmt; 2519} 2520 2521/** 2522 * alphaWorks upgrade 2523 */ 2524void NumberFormatRegressionTest::Test4161100(void) { 2525 UErrorCode status = U_ZERO_ERROR; 2526 NumberFormat *nf = NumberFormat::createInstance(Locale::getUS(), status); 2527 if (failure(status, "createInstance", Locale::getUS(), TRUE)){ 2528 delete nf; 2529 return; 2530 }; 2531 nf->setMinimumFractionDigits(1); 2532 nf->setMaximumFractionDigits(1); 2533 double a = -0.09; 2534 UnicodeString s; 2535 nf->format(a, s); 2536 UnicodeString pat; 2537 logln(UnicodeString() + a + " x " + 2538 ((DecimalFormat*) nf)->toPattern(pat) + " = " + s); 2539 if (s != UnicodeString("-0.1")) { 2540 errln("FAIL"); 2541 } 2542 delete nf; 2543} 2544 2545/** 2546 * June 16 1999 sync up - liu 2547 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1) 2548 */ 2549void NumberFormatRegressionTest::Test4243011(void) { 2550 UErrorCode status = U_ZERO_ERROR; 2551 DecimalFormatSymbols sym(Locale::getUS(), status); 2552 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2553 DecimalFormat fmt(UnicodeString("0."), sym, status); 2554 2555 if (!failure(status, "DecimalFormat ct", Locale::getUS())) { 2556 const double NUM[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 }; 2557 const char* STR[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." }; 2558 int32_t N = (int32_t)(sizeof(NUM) / sizeof(NUM[0])); 2559 2560 for (int32_t i=0; i<N; ++i) { 2561 UnicodeString str; 2562 UnicodeString exp(STR[i]); 2563 FieldPosition pos; 2564 fmt.format(NUM[i], str, pos); 2565 if (str == exp) { 2566 logln(UnicodeString("Ok ") + NUM[i] + " x 0. = " + str); 2567 } else { 2568 errln(UnicodeString("FAIL ") + NUM[i] + " x 0. = " + str + 2569 ", want " + exp); 2570 } 2571 } 2572 } 2573} 2574 2575/** 2576 * June 16 1999 sync up - liu 2577 * format(0.0) gives "0.1" if preceded by parse("99.99"). 2578 * (Regression in 1.2.2 RC1) 2579 */ 2580void NumberFormatRegressionTest::Test4243108(void) { 2581 UErrorCode status = U_ZERO_ERROR; 2582 DecimalFormatSymbols sym(Locale::getUS(), status); 2583 failure(status, "DecimalFormatSymbols ct", Locale::getUS()); 2584 DecimalFormat fmt(UnicodeString("#.#"), sym, status); 2585 if (failure(status, "DecimalFormat ct", Locale::getUS())) { 2586 return; 2587 } 2588 2589 UnicodeString str; 2590 FieldPosition pos; 2591 2592 fmt.format(0.0, str, pos); 2593 UnicodeString exp("0"); 2594 if (str == exp) { 2595 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2596 } else { 2597 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2598 ", want " + exp); 2599 } 2600 2601 str = "99.99"; 2602 Formattable val; 2603 fmt.parse(str, val, status); 2604 failure(status, "DecimalFormat.parse(99.99)", Locale::getUS()); 2605 if (val.getType() == Formattable::kDouble && 2606 val.getDouble() == 99.99) { 2607 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val)); 2608 } else { 2609 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val) + 2610 ", want " + 99.99); 2611 } 2612 2613 str.remove(); 2614 fmt.format(0.0, str, pos); 2615 if (str == exp) { 2616 logln(UnicodeString("Ok 0.0 x #.# = ") + str); 2617 } else { 2618 errln(UnicodeString("FAIL 0.0 x #.# = ") + str + 2619 ", want " + exp); 2620 } 2621} 2622 2623 2624/** 2625 * DateFormat should call setIntegerParseOnly(TRUE) on adopted 2626 * NumberFormat objects. 2627 */ 2628void NumberFormatRegressionTest::TestJ691(void) { 2629 UErrorCode status = U_ZERO_ERROR; 2630 Locale loc("fr", "CH"); 2631 2632 // set up the input date string & expected output 2633 UnicodeString udt("11.10.2000", ""); 2634 UnicodeString exp("11.10.00", ""); 2635 2636 // create a Calendar for this locale 2637 Calendar *cal = Calendar::createInstance(loc, status); 2638 if (U_FAILURE(status)) { 2639 errln("FAIL: Calendar::createInstance() returned " + (UnicodeString)u_errorName(status)); 2640 return; 2641 } 2642 2643 // create a NumberFormat for this locale 2644 NumberFormat *nf = NumberFormat::createInstance(loc, status); 2645 if (U_FAILURE(status)) { 2646 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2647 return; 2648 } 2649 2650 // *** Here's the key: We don't want to have to do THIS: 2651 // nf->setParseIntegerOnly(TRUE); 2652 2653 // create the DateFormat 2654 DateFormat *df = DateFormat::createDateInstance(DateFormat::kShort, loc); 2655 if (U_FAILURE(status)) { 2656 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString)u_errorName(status)); 2657 return; 2658 } 2659 2660 df->adoptCalendar(cal); 2661 df->adoptNumberFormat(nf); 2662 2663 // set parsing to lenient & parse 2664 df->setLenient(TRUE); 2665 UDate ulocdat = df->parse(udt, status); 2666 2667 // format back to a string 2668 UnicodeString outString; 2669 df->format(ulocdat, outString); 2670 2671 if (outString != exp) { 2672 errln("FAIL: " + udt + " => " + outString); 2673 } 2674 2675 delete df; 2676} 2677 2678#endif /* #if !UCONFIG_NO_FORMATTING */ 2679