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