1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 #include "unicode/utypes.h" 8 9 #if !UCONFIG_NO_FORMATTING 10 11 #include "dcfmapts.h" 12 13 #include "unicode/currpinf.h" 14 #include "unicode/dcfmtsym.h" 15 #include "unicode/decimfmt.h" 16 #include "unicode/fmtable.h" 17 #include "unicode/localpointer.h" 18 #include "unicode/parseerr.h" 19 #include "unicode/stringpiece.h" 20 21 #include "putilimp.h" 22 #include "plurrule_impl.h" 23 #include <stdio.h> 24 25 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't 26 // try to test the full functionality. It just calls each function in the class and 27 // verifies that it works on a basic level. 28 29 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 30 { 31 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); 32 switch (index) { 33 case 0: name = "DecimalFormat API test"; 34 if (exec) { 35 logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)""); 36 UErrorCode status = U_ZERO_ERROR; 37 Locale saveLocale; 38 Locale::setDefault(Locale::getEnglish(), status); 39 if(U_FAILURE(status)) { 40 errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results"); 41 } 42 testAPI(/*par*/); 43 Locale::setDefault(saveLocale, status); 44 } 45 break; 46 case 1: name = "Rounding test"; 47 if(exec) { 48 logln((UnicodeString)"DecimalFormat Rounding test---"); 49 testRounding(/*par*/); 50 } 51 break; 52 case 2: name = "Test6354"; 53 if(exec) { 54 logln((UnicodeString)"DecimalFormat Rounding Increment test---"); 55 testRoundingInc(/*par*/); 56 } 57 break; 58 case 3: name = "TestCurrencyPluralInfo"; 59 if(exec) { 60 logln((UnicodeString)"CurrencyPluralInfo API test---"); 61 TestCurrencyPluralInfo(); 62 } 63 break; 64 case 4: name = "TestScale"; 65 if(exec) { 66 logln((UnicodeString)"Scale test---"); 67 TestScale(); 68 } 69 break; 70 case 5: name = "TestFixedDecimal"; 71 if(exec) { 72 logln((UnicodeString)"TestFixedDecimal ---"); 73 TestFixedDecimal(); 74 } 75 break; 76 case 6: name = "TestBadFastpath"; 77 if(exec) { 78 logln((UnicodeString)"TestBadFastpath ---"); 79 TestBadFastpath(); 80 } 81 break; 82 case 7: name = "TestRequiredDecimalPoint"; 83 if(exec) { 84 logln((UnicodeString)"TestRequiredDecimalPoint ---"); 85 TestRequiredDecimalPoint(); 86 } 87 break; 88 default: name = ""; break; 89 } 90 } 91 92 /** 93 * This test checks various generic API methods in DecimalFormat to achieve 100% 94 * API coverage. 95 */ 96 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) 97 { 98 UErrorCode status = U_ZERO_ERROR; 99 100 // ======= Test constructors 101 102 logln((UnicodeString)"Testing DecimalFormat constructors"); 103 104 DecimalFormat def(status); 105 if(U_FAILURE(status)) { 106 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 107 return; 108 } 109 110 // bug 10864 111 status = U_ZERO_ERROR; 112 DecimalFormat noGrouping("###0.##", status); 113 if (noGrouping.getGroupingSize() != 0) { 114 errln("Grouping size should be 0 for no grouping."); 115 } 116 noGrouping.setGroupingUsed(TRUE); 117 if (noGrouping.getGroupingSize() != 0) { 118 errln("Grouping size should still be 0."); 119 } 120 // end bug 10864 121 122 status = U_ZERO_ERROR; 123 const UnicodeString pattern("#,##0.# FF"); 124 DecimalFormat pat(pattern, status); 125 if(U_FAILURE(status)) { 126 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); 127 return; 128 } 129 130 status = U_ZERO_ERROR; 131 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status); 132 if(U_FAILURE(status)) { 133 errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)"); 134 return; 135 } 136 137 status = U_ZERO_ERROR; 138 DecimalFormat cust1(pattern, symbols, status); 139 if(U_FAILURE(status)) { 140 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); 141 } 142 143 status = U_ZERO_ERROR; 144 DecimalFormat cust2(pattern, *symbols, status); 145 if(U_FAILURE(status)) { 146 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)"); 147 } 148 149 DecimalFormat copy(pat); 150 151 // ======= Test clone(), assignment, and equality 152 153 logln((UnicodeString)"Testing clone(), assignment and equality operators"); 154 155 if( ! (copy == pat) || copy != pat) { 156 errln((UnicodeString)"ERROR: Copy constructor or == failed"); 157 } 158 159 copy = cust1; 160 if(copy != cust1) { 161 errln((UnicodeString)"ERROR: Assignment (or !=) failed"); 162 } 163 164 Format *clone = def.clone(); 165 if( ! (*clone == def) ) { 166 errln((UnicodeString)"ERROR: Clone() failed"); 167 } 168 delete clone; 169 170 // ======= Test various format() methods 171 172 logln((UnicodeString)"Testing various format() methods"); 173 174 double d = -10456.0037; 175 int32_t l = 100000000; 176 Formattable fD(d); 177 Formattable fL(l); 178 179 UnicodeString res1, res2, res3, res4; 180 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); 181 182 res1 = def.format(d, res1, pos1); 183 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); 184 185 res2 = pat.format(l, res2, pos2); 186 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); 187 188 status = U_ZERO_ERROR; 189 res3 = cust1.format(fD, res3, pos3, status); 190 if(U_FAILURE(status)) { 191 errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); 192 } 193 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3); 194 195 status = U_ZERO_ERROR; 196 res4 = cust2.format(fL, res4, pos4, status); 197 if(U_FAILURE(status)) { 198 errln((UnicodeString)"ERROR: format(Formattable [long]) failed"); 199 } 200 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4); 201 202 // ======= Test parse() 203 204 logln((UnicodeString)"Testing parse()"); 205 206 UnicodeString text("-10,456.0037"); 207 Formattable result1, result2; 208 ParsePosition pos(0); 209 UnicodeString patt("#,##0.#"); 210 status = U_ZERO_ERROR; 211 pat.applyPattern(patt, status); 212 if(U_FAILURE(status)) { 213 errln((UnicodeString)"ERROR: applyPattern() failed"); 214 } 215 pat.parse(text, result1, pos); 216 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { 217 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 218 } 219 logln(text + " parsed into " + (int32_t) result1.getDouble()); 220 221 status = U_ZERO_ERROR; 222 pat.parse(text, result2, status); 223 if(U_FAILURE(status)) { 224 errln((UnicodeString)"ERROR: parse() failed"); 225 } 226 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { 227 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 228 } 229 logln(text + " parsed into " + (int32_t) result2.getDouble()); 230 231 // ======= Test getters and setters 232 233 logln((UnicodeString)"Testing getters and setters"); 234 235 const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols(); 236 DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms); 237 def.setDecimalFormatSymbols(*newSyms); 238 def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this 239 if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) { 240 errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed"); 241 } 242 243 UnicodeString posPrefix; 244 pat.setPositivePrefix("+"); 245 posPrefix = pat.getPositivePrefix(posPrefix); 246 logln((UnicodeString)"Positive prefix (should be +): " + posPrefix); 247 if(posPrefix != "+") { 248 errln((UnicodeString)"ERROR: setPositivePrefix() failed"); 249 } 250 251 UnicodeString negPrefix; 252 pat.setNegativePrefix("-"); 253 negPrefix = pat.getNegativePrefix(negPrefix); 254 logln((UnicodeString)"Negative prefix (should be -): " + negPrefix); 255 if(negPrefix != "-") { 256 errln((UnicodeString)"ERROR: setNegativePrefix() failed"); 257 } 258 259 UnicodeString posSuffix; 260 pat.setPositiveSuffix("_"); 261 posSuffix = pat.getPositiveSuffix(posSuffix); 262 logln((UnicodeString)"Positive suffix (should be _): " + posSuffix); 263 if(posSuffix != "_") { 264 errln((UnicodeString)"ERROR: setPositiveSuffix() failed"); 265 } 266 267 UnicodeString negSuffix; 268 pat.setNegativeSuffix("~"); 269 negSuffix = pat.getNegativeSuffix(negSuffix); 270 logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix); 271 if(negSuffix != "~") { 272 errln((UnicodeString)"ERROR: setNegativeSuffix() failed"); 273 } 274 275 int32_t multiplier = 0; 276 pat.setMultiplier(8); 277 multiplier = pat.getMultiplier(); 278 logln((UnicodeString)"Multiplier (should be 8): " + multiplier); 279 if(multiplier != 8) { 280 errln((UnicodeString)"ERROR: setMultiplier() failed"); 281 } 282 283 int32_t groupingSize = 0; 284 pat.setGroupingSize(2); 285 groupingSize = pat.getGroupingSize(); 286 logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize); 287 if(groupingSize != 2) { 288 errln((UnicodeString)"ERROR: setGroupingSize() failed"); 289 } 290 291 pat.setDecimalSeparatorAlwaysShown(TRUE); 292 UBool tf = pat.isDecimalSeparatorAlwaysShown(); 293 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE")); 294 if(tf != TRUE) { 295 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed"); 296 } 297 // Added by Ken Liu testing set/isExponentSignAlwaysShown 298 pat.setExponentSignAlwaysShown(TRUE); 299 UBool esas = pat.isExponentSignAlwaysShown(); 300 logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE")); 301 if(esas != TRUE) { 302 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); 303 } 304 305 // Added by Ken Liu testing set/isScientificNotation 306 pat.setScientificNotation(TRUE); 307 UBool sn = pat.isScientificNotation(); 308 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE")); 309 if(sn != TRUE) { 310 errln((UnicodeString)"ERROR: setScientificNotation() failed"); 311 } 312 313 // Added by Ken Liu testing set/getMinimumExponentDigits 314 int8_t MinimumExponentDigits = 0; 315 pat.setMinimumExponentDigits(2); 316 MinimumExponentDigits = pat.getMinimumExponentDigits(); 317 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits); 318 if(MinimumExponentDigits != 2) { 319 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); 320 } 321 322 // Added by Ken Liu testing set/getRoundingIncrement 323 double RoundingIncrement = 0.0; 324 pat.setRoundingIncrement(2.0); 325 RoundingIncrement = pat.getRoundingIncrement(); 326 logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement); 327 if(RoundingIncrement != 2.0) { 328 errln((UnicodeString)"ERROR: setRoundingIncrement() failed"); 329 } 330 //end of Ken's Adding 331 332 UnicodeString funkyPat; 333 funkyPat = pat.toPattern(funkyPat); 334 logln((UnicodeString)"Pattern is " + funkyPat); 335 336 UnicodeString locPat; 337 locPat = pat.toLocalizedPattern(locPat); 338 logln((UnicodeString)"Localized pattern is " + locPat); 339 340 // ======= Test applyPattern() 341 342 logln((UnicodeString)"Testing applyPattern()"); 343 344 UnicodeString p1("#,##0.0#;(#,##0.0#)"); 345 logln((UnicodeString)"Applying pattern " + p1); 346 status = U_ZERO_ERROR; 347 pat.applyPattern(p1, status); 348 if(U_FAILURE(status)) { 349 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 350 } 351 UnicodeString s2; 352 s2 = pat.toPattern(s2); 353 logln((UnicodeString)"Extracted pattern is " + s2); 354 if(s2 != p1) { 355 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied"); 356 } 357 358 if(pat.getSecondaryGroupingSize() != 0) { 359 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize()); 360 } 361 362 if(pat.getGroupingSize() != 3) { 363 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 364 } 365 366 UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)"); 367 logln((UnicodeString)"Applying pattern " + p2); 368 status = U_ZERO_ERROR; 369 pat.applyLocalizedPattern(p2, status); 370 if(U_FAILURE(status)) { 371 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 372 } 373 UnicodeString s3; 374 s3 = pat.toLocalizedPattern(s3); 375 logln((UnicodeString)"Extracted pattern is " + s3); 376 if(s3 != p2) { 377 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied"); 378 } 379 380 status = U_ZERO_ERROR; 381 UParseError pe; 382 pat.applyLocalizedPattern(p2, pe, status); 383 if(U_FAILURE(status)) { 384 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status); 385 } 386 UnicodeString s4; 387 s4 = pat.toLocalizedPattern(s3); 388 logln((UnicodeString)"Extracted pattern is " + s4); 389 if(s4 != p2) { 390 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied"); 391 } 392 393 if(pat.getSecondaryGroupingSize() != 2) { 394 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize()); 395 } 396 397 if(pat.getGroupingSize() != 3) { 398 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 399 } 400 401 // ======= Test getStaticClassID() 402 403 logln((UnicodeString)"Testing getStaticClassID()"); 404 405 status = U_ZERO_ERROR; 406 NumberFormat *test = new DecimalFormat(status); 407 if(U_FAILURE(status)) { 408 errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat"); 409 } 410 411 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 412 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value"); 413 } 414 415 delete test; 416 } 417 418 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ 419 UErrorCode status = U_ZERO_ERROR; 420 421 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); 422 if(U_FAILURE(status)) { 423 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); 424 } 425 426 CurrencyPluralInfo cpi1 = *cpi; 427 428 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){ 429 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value"); 430 } 431 432 cpi->setCurrencyPluralPattern("","",status); 433 if(U_FAILURE(status)) { 434 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern"); 435 } 436 437 cpi->setLocale(Locale::getCanada(), status); 438 if(U_FAILURE(status)) { 439 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); 440 } 441 442 cpi->setPluralRules("",status); 443 if(U_FAILURE(status)) { 444 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); 445 } 446 447 DecimalFormat *df = new DecimalFormat(status); 448 if(U_FAILURE(status)) { 449 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); 450 return; 451 } 452 453 df->adoptCurrencyPluralInfo(cpi); 454 455 df->getCurrencyPluralInfo(); 456 457 df->setCurrencyPluralInfo(cpi1); 458 459 delete df; 460 } 461 462 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) 463 { 464 UErrorCode status = U_ZERO_ERROR; 465 double Roundingnumber = 2.55; 466 double Roundingnumber1 = -2.55; 467 //+2.55 results -2.55 results 468 double result[]={ 3.0, -2.0, // kRoundCeiling 0, 469 2.0, -3.0, // kRoundFloor 1, 470 2.0, -2.0, // kRoundDown 2, 471 3.0, -3.0, // kRoundUp 3, 472 3.0, -3.0, // kRoundHalfEven 4, 473 3.0, -3.0, // kRoundHalfDown 5, 474 3.0, -3.0 // kRoundHalfUp 6 475 }; 476 DecimalFormat pat(status); 477 if(U_FAILURE(status)) { 478 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 479 return; 480 } 481 uint16_t mode; 482 uint16_t i=0; 483 UnicodeString message; 484 UnicodeString resultStr; 485 for(mode=0;mode < 7;mode++){ 486 pat.setRoundingMode((DecimalFormat::ERoundingMode)mode); 487 if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){ 488 errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode); 489 } 490 491 492 //for +2.55 with RoundingIncrement=1.0 493 pat.setRoundingIncrement(1.0); 494 pat.format(Roundingnumber, resultStr); 495 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 496 verify(message, resultStr, result[i++]); 497 message.remove(); 498 resultStr.remove(); 499 500 //for -2.55 with RoundingIncrement=1.0 501 pat.format(Roundingnumber1, resultStr); 502 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 503 verify(message, resultStr, result[i++]); 504 message.remove(); 505 resultStr.remove(); 506 } 507 508 } 509 void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){ 510 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 511 UnicodeString expectedStr(""); 512 expectedStr=expectedStr + expected; 513 if(got != expectedStr ) { 514 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr); 515 } 516 } 517 518 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){ 519 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 520 if(got != expected ) { 521 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected); 522 } 523 } 524 525 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/) 526 { 527 UErrorCode status = U_ZERO_ERROR; 528 DecimalFormat pat(UnicodeString("#,##0.00"),status); 529 if(U_FAILURE(status)) { 530 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 531 return; 532 } 533 534 // get default rounding increment 535 double roundingInc = pat.getRoundingIncrement(); 536 if (roundingInc != 0.0) { 537 errln((UnicodeString)"ERROR: Rounding increment not zero"); 538 return; 539 } 540 541 // With rounding now being handled by decNumber, we no longer 542 // set a rounding increment to enable non-default mode rounding, 543 // checking of which was the original point of this test. 544 545 // set rounding mode with zero increment. Rounding 546 // increment should not be set by this operation 547 pat.setRoundingMode((DecimalFormat::ERoundingMode)0); 548 roundingInc = pat.getRoundingIncrement(); 549 if (roundingInc != 0.0) { 550 errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode"); 551 return; 552 } 553 } 554 555 void IntlTestDecimalFormatAPI::TestScale() 556 { 557 typedef struct TestData { 558 double inputValue; 559 int inputScale; 560 const char *expectedOutput; 561 } TestData; 562 563 static TestData testData[] = { 564 { 100.0, 3, "100,000" }, 565 { 10034.0, -2, "100.34" }, 566 { 0.86, -3, "0.0009" }, 567 { -0.000455, 1, "-0%" }, 568 { -0.000555, 1, "-1%" }, 569 { 0.000455, 1, "0%" }, 570 { 0.000555, 1, "1%" }, 571 }; 572 573 UErrorCode status = U_ZERO_ERROR; 574 DecimalFormat pat(status); 575 if(U_FAILURE(status)) { 576 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 577 return; 578 } 579 580 UnicodeString message; 581 UnicodeString resultStr; 582 UnicodeString exp; 583 UnicodeString percentPattern("#,##0%"); 584 pat.setMaximumFractionDigits(4); 585 586 for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) { 587 if ( i > 2 ) { 588 pat.applyPattern(percentPattern,status); 589 } 590 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); 591 pat.format(testData[i].inputValue, resultStr); 592 message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + 593 testData[i].inputScale + UnicodeString(". Got: "); 594 exp = testData[i].expectedOutput; 595 verifyString(message, resultStr, exp); 596 message.remove(); 597 resultStr.remove(); 598 exp.remove(); 599 } 600 } 601 602 603 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \ 604 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); } 605 606 void IntlTestDecimalFormatAPI::TestFixedDecimal() { 607 UErrorCode status = U_ZERO_ERROR; 608 609 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); 610 TEST_ASSERT_STATUS(status); 611 if (status == U_MISSING_RESOURCE_ERROR) { 612 return; 613 } 614 FixedDecimal fd = df->getFixedDecimal(44, status); 615 TEST_ASSERT_STATUS(status); 616 ASSERT_EQUAL(44, fd.source); 617 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); 618 ASSERT_EQUAL(FALSE, fd.isNegative); 619 620 fd = df->getFixedDecimal(-44, status); 621 TEST_ASSERT_STATUS(status); 622 ASSERT_EQUAL(44, fd.source); 623 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); 624 ASSERT_EQUAL(TRUE, fd.isNegative); 625 626 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status); 627 TEST_ASSERT_STATUS(status); 628 fd = df->getFixedDecimal(123.456, status); 629 TEST_ASSERT_STATUS(status); 630 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v 631 ASSERT_EQUAL(456, fd.decimalDigits); // f 632 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t 633 ASSERT_EQUAL(123, fd.intValue); // i 634 ASSERT_EQUAL(123.456, fd.source); // n 635 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 636 ASSERT_EQUAL(FALSE, fd.isNegative); 637 638 fd = df->getFixedDecimal(-123.456, status); 639 TEST_ASSERT_STATUS(status); 640 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v 641 ASSERT_EQUAL(456, fd.decimalDigits); // f 642 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t 643 ASSERT_EQUAL(123, fd.intValue); // i 644 ASSERT_EQUAL(123.456, fd.source); // n 645 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 646 ASSERT_EQUAL(TRUE, fd.isNegative); 647 648 // test max int digits 649 df->setMaximumIntegerDigits(2); 650 fd = df->getFixedDecimal(123.456, status); 651 TEST_ASSERT_STATUS(status); 652 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v 653 ASSERT_EQUAL(456, fd.decimalDigits); // f 654 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t 655 ASSERT_EQUAL(23, fd.intValue); // i 656 ASSERT_EQUAL(23.456, fd.source); // n 657 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 658 ASSERT_EQUAL(FALSE, fd.isNegative); 659 660 fd = df->getFixedDecimal(-123.456, status); 661 TEST_ASSERT_STATUS(status); 662 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v 663 ASSERT_EQUAL(456, fd.decimalDigits); // f 664 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t 665 ASSERT_EQUAL(23, fd.intValue); // i 666 ASSERT_EQUAL(23.456, fd.source); // n 667 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 668 ASSERT_EQUAL(TRUE, fd.isNegative); 669 670 // test max fraction digits 671 df->setMaximumIntegerDigits(2000000000); 672 df->setMaximumFractionDigits(2); 673 fd = df->getFixedDecimal(123.456, status); 674 TEST_ASSERT_STATUS(status); 675 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v 676 ASSERT_EQUAL(46, fd.decimalDigits); // f 677 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t 678 ASSERT_EQUAL(123, fd.intValue); // i 679 ASSERT_EQUAL(123.46, fd.source); // n 680 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 681 ASSERT_EQUAL(FALSE, fd.isNegative); 682 683 fd = df->getFixedDecimal(-123.456, status); 684 TEST_ASSERT_STATUS(status); 685 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v 686 ASSERT_EQUAL(46, fd.decimalDigits); // f 687 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t 688 ASSERT_EQUAL(123, fd.intValue); // i 689 ASSERT_EQUAL(123.46, fd.source); // n 690 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 691 ASSERT_EQUAL(TRUE, fd.isNegative); 692 693 // test esoteric rounding 694 df->setMaximumFractionDigits(6); 695 df->setRoundingIncrement(7.3); 696 697 fd = df->getFixedDecimal(30.0, status); 698 TEST_ASSERT_STATUS(status); 699 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v 700 ASSERT_EQUAL(20, fd.decimalDigits); // f 701 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t 702 ASSERT_EQUAL(29, fd.intValue); // i 703 ASSERT_EQUAL(29.2, fd.source); // n 704 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 705 ASSERT_EQUAL(FALSE, fd.isNegative); 706 707 fd = df->getFixedDecimal(-30.0, status); 708 TEST_ASSERT_STATUS(status); 709 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v 710 ASSERT_EQUAL(20, fd.decimalDigits); // f 711 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t 712 ASSERT_EQUAL(29, fd.intValue); // i 713 ASSERT_EQUAL(29.2, fd.source); // n 714 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 715 ASSERT_EQUAL(TRUE, fd.isNegative); 716 717 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status); 718 TEST_ASSERT_STATUS(status); 719 fd = df->getFixedDecimal(123.456, status); 720 TEST_ASSERT_STATUS(status); 721 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); 722 ASSERT_EQUAL(0, fd.decimalDigits); 723 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 724 ASSERT_EQUAL(123, fd.intValue); 725 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 726 ASSERT_EQUAL(FALSE, fd.isNegative); 727 728 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); 729 TEST_ASSERT_STATUS(status); 730 fd = df->getFixedDecimal(123.01, status); 731 TEST_ASSERT_STATUS(status); 732 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); 733 ASSERT_EQUAL(0, fd.decimalDigits); 734 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 735 ASSERT_EQUAL(123, fd.intValue); 736 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 737 ASSERT_EQUAL(FALSE, fd.isNegative); 738 739 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); 740 TEST_ASSERT_STATUS(status); 741 fd = df->getFixedDecimal(123.06, status); 742 TEST_ASSERT_STATUS(status); 743 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); 744 ASSERT_EQUAL(1, fd.decimalDigits); 745 ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros); 746 ASSERT_EQUAL(123, fd.intValue); 747 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 748 ASSERT_EQUAL(FALSE, fd.isNegative); 749 750 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits 751 TEST_ASSERT_STATUS(status); 752 fd = df->getFixedDecimal(123, status); 753 TEST_ASSERT_STATUS(status); 754 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 755 ASSERT_EQUAL(0, fd.decimalDigits); 756 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 757 ASSERT_EQUAL(123, fd.intValue); 758 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 759 ASSERT_EQUAL(FALSE, fd.isNegative); 760 761 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits 762 TEST_ASSERT_STATUS(status); 763 fd = df->getFixedDecimal(1.23, status); 764 TEST_ASSERT_STATUS(status); 765 ASSERT_EQUAL(4, fd.visibleDecimalDigitCount); 766 ASSERT_EQUAL(2300, fd.decimalDigits); 767 ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros); 768 ASSERT_EQUAL(1, fd.intValue); 769 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 770 ASSERT_EQUAL(FALSE, fd.isNegative); 771 772 fd = df->getFixedDecimal(uprv_getInfinity(), status); 773 TEST_ASSERT_STATUS(status); 774 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); 775 fd = df->getFixedDecimal(0.0, status); 776 ASSERT_EQUAL(FALSE, fd.isNanOrInfinity); 777 fd = df->getFixedDecimal(uprv_getNaN(), status); 778 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); 779 TEST_ASSERT_STATUS(status); 780 781 // Test Big Decimal input. 782 // 22 digits before and after decimal, will exceed the precision of a double 783 // and force DecimalFormat::getFixedDecimal() to work with a digit list. 784 df.adoptInsteadAndCheckErrorCode( 785 new DecimalFormat("#####################0.00####################", status), status); 786 TEST_ASSERT_STATUS(status); 787 Formattable fable("12.34", status); 788 TEST_ASSERT_STATUS(status); 789 fd = df->getFixedDecimal(fable, status); 790 TEST_ASSERT_STATUS(status); 791 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 792 ASSERT_EQUAL(34, fd.decimalDigits); 793 ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros); 794 ASSERT_EQUAL(12, fd.intValue); 795 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 796 ASSERT_EQUAL(FALSE, fd.isNegative); 797 798 fable.setDecimalNumber("12.345678901234567890123456789", status); 799 TEST_ASSERT_STATUS(status); 800 fd = df->getFixedDecimal(fable, status); 801 TEST_ASSERT_STATUS(status); 802 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 803 ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits); 804 ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros); 805 ASSERT_EQUAL(12, fd.intValue); 806 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 807 ASSERT_EQUAL(FALSE, fd.isNegative); 808 809 // On field overflow, Integer part is truncated on the left, fraction part on the right. 810 fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status); 811 TEST_ASSERT_STATUS(status); 812 fd = df->getFixedDecimal(fable, status); 813 TEST_ASSERT_STATUS(status); 814 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 815 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits); 816 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros); 817 ASSERT_EQUAL(345678901234567890LL, fd.intValue); 818 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 819 ASSERT_EQUAL(FALSE, fd.isNegative); 820 821 // Digits way to the right of the decimal but within the format's precision aren't truncated 822 fable.setDecimalNumber("1.0000000000000000000012", status); 823 TEST_ASSERT_STATUS(status); 824 fd = df->getFixedDecimal(fable, status); 825 TEST_ASSERT_STATUS(status); 826 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 827 ASSERT_EQUAL(12, fd.decimalDigits); 828 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); 829 ASSERT_EQUAL(1, fd.intValue); 830 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 831 ASSERT_EQUAL(FALSE, fd.isNegative); 832 833 // Digits beyond the precision of the format are rounded away 834 fable.setDecimalNumber("1.000000000000000000000012", status); 835 TEST_ASSERT_STATUS(status); 836 fd = df->getFixedDecimal(fable, status); 837 TEST_ASSERT_STATUS(status); 838 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 839 ASSERT_EQUAL(0, fd.decimalDigits); 840 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 841 ASSERT_EQUAL(1, fd.intValue); 842 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 843 ASSERT_EQUAL(FALSE, fd.isNegative); 844 845 // Negative numbers come through 846 fable.setDecimalNumber("-1.0000000000000000000012", status); 847 TEST_ASSERT_STATUS(status); 848 fd = df->getFixedDecimal(fable, status); 849 TEST_ASSERT_STATUS(status); 850 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 851 ASSERT_EQUAL(12, fd.decimalDigits); 852 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); 853 ASSERT_EQUAL(1, fd.intValue); 854 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 855 ASSERT_EQUAL(TRUE, fd.isNegative); 856 857 // MinFractionDigits from format larger than from number. 858 fable.setDecimalNumber("1000000000000000000000.3", status); 859 TEST_ASSERT_STATUS(status); 860 fd = df->getFixedDecimal(fable, status); 861 TEST_ASSERT_STATUS(status); 862 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 863 ASSERT_EQUAL(30, fd.decimalDigits); 864 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros); 865 ASSERT_EQUAL(100000000000000000LL, fd.intValue); 866 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 867 ASSERT_EQUAL(FALSE, fd.isNegative); 868 869 fable.setDecimalNumber("1000000000000000050000.3", status); 870 TEST_ASSERT_STATUS(status); 871 fd = df->getFixedDecimal(fable, status); 872 TEST_ASSERT_STATUS(status); 873 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 874 ASSERT_EQUAL(30, fd.decimalDigits); 875 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros); 876 ASSERT_EQUAL(50000LL, fd.intValue); 877 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 878 ASSERT_EQUAL(FALSE, fd.isNegative); 879 880 // Test some int64_t values that are out of the range of a double 881 fable.setInt64(4503599627370496LL); 882 TEST_ASSERT_STATUS(status); 883 fd = df->getFixedDecimal(fable, status); 884 TEST_ASSERT_STATUS(status); 885 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 886 ASSERT_EQUAL(0, fd.decimalDigits); 887 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 888 ASSERT_EQUAL(4503599627370496LL, fd.intValue); 889 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 890 ASSERT_EQUAL(FALSE, fd.isNegative); 891 892 fable.setInt64(4503599627370497LL); 893 TEST_ASSERT_STATUS(status); 894 fd = df->getFixedDecimal(fable, status); 895 TEST_ASSERT_STATUS(status); 896 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 897 ASSERT_EQUAL(0, fd.decimalDigits); 898 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 899 ASSERT_EQUAL(4503599627370497LL, fd.intValue); 900 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 901 ASSERT_EQUAL(FALSE, fd.isNegative); 902 903 fable.setInt64(9223372036854775807LL); 904 TEST_ASSERT_STATUS(status); 905 fd = df->getFixedDecimal(fable, status); 906 TEST_ASSERT_STATUS(status); 907 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 908 ASSERT_EQUAL(0, fd.decimalDigits); 909 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 910 // note: going through DigitList path to FixedDecimal, which is trimming 911 // int64_t fields to 18 digits. See ticket Ticket #10374 912 // ASSERT_EQUAL(223372036854775807LL, fd.intValue); 913 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) { 914 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue); 915 } 916 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 917 ASSERT_EQUAL(FALSE, fd.isNegative); 918 919 } 920 921 void IntlTestDecimalFormatAPI::TestBadFastpath() { 922 UErrorCode status = U_ZERO_ERROR; 923 924 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); 925 if (U_FAILURE(status)) { 926 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); 927 return; 928 } 929 930 UnicodeString fmt; 931 fmt.remove(); 932 assertEquals("Format 1234", "1234", df->format(1234, fmt)); 933 df->setGroupingUsed(FALSE); 934 fmt.remove(); 935 assertEquals("Format 1234", "1234", df->format(1234, fmt)); 936 df->setGroupingUsed(TRUE); 937 df->setGroupingSize(3); 938 fmt.remove(); 939 assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt)); 940 } 941 942 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() { 943 UErrorCode status = U_ZERO_ERROR; 944 UnicodeString text("99"); 945 Formattable result1; 946 UnicodeString pat1("##.0000"); 947 UnicodeString pat2("00.0"); 948 949 LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status); 950 if (U_FAILURE(status)) { 951 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); 952 return; 953 } 954 955 status = U_ZERO_ERROR; 956 df->applyPattern(pat1, status); 957 if(U_FAILURE(status)) { 958 errln((UnicodeString)"ERROR: applyPattern() failed"); 959 } 960 df->parse(text, result1, status); 961 if(U_FAILURE(status)) { 962 errln((UnicodeString)"ERROR: parse() failed"); 963 } 964 df->setDecimalPatternMatchRequired(TRUE); 965 df->parse(text, result1, status); 966 if(U_SUCCESS(status)) { 967 errln((UnicodeString)"ERROR: unexpected parse()"); 968 } 969 970 971 status = U_ZERO_ERROR; 972 df->applyPattern(pat2, status); 973 df->setDecimalPatternMatchRequired(FALSE); 974 if(U_FAILURE(status)) { 975 errln((UnicodeString)"ERROR: applyPattern(2) failed"); 976 } 977 df->parse(text, result1, status); 978 if(U_FAILURE(status)) { 979 errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status)); 980 } 981 df->setDecimalPatternMatchRequired(TRUE); 982 df->parse(text, result1, status); 983 if(U_SUCCESS(status)) { 984 errln((UnicodeString)"ERROR: unexpected parse(2)"); 985 } 986 } 987 988 #endif /* #if !UCONFIG_NO_FORMATTING */ 989