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