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