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