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