1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2014, 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#define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0]))) 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 31void 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 default: name = ""; break; 85 } 86} 87 88/** 89 * This test checks various generic API methods in DecimalFormat to achieve 100% 90 * API coverage. 91 */ 92void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) 93{ 94 UErrorCode status = U_ZERO_ERROR; 95 96// ======= Test constructors 97 98 logln((UnicodeString)"Testing DecimalFormat constructors"); 99 100 DecimalFormat def(status); 101 if(U_FAILURE(status)) { 102 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 103 return; 104 } 105 106 status = U_ZERO_ERROR; 107 const UnicodeString pattern("#,##0.# FF"); 108 DecimalFormat pat(pattern, status); 109 if(U_FAILURE(status)) { 110 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); 111 return; 112 } 113 114 status = U_ZERO_ERROR; 115 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status); 116 if(U_FAILURE(status)) { 117 errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)"); 118 return; 119 } 120 121 status = U_ZERO_ERROR; 122 DecimalFormat cust1(pattern, symbols, status); 123 if(U_FAILURE(status)) { 124 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); 125 } 126 127 status = U_ZERO_ERROR; 128 DecimalFormat cust2(pattern, *symbols, status); 129 if(U_FAILURE(status)) { 130 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)"); 131 } 132 133 DecimalFormat copy(pat); 134 135// ======= Test clone(), assignment, and equality 136 137 logln((UnicodeString)"Testing clone(), assignment and equality operators"); 138 139 if( ! (copy == pat) || copy != pat) { 140 errln((UnicodeString)"ERROR: Copy constructor or == failed"); 141 } 142 143 copy = cust1; 144 if(copy != cust1) { 145 errln((UnicodeString)"ERROR: Assignment (or !=) failed"); 146 } 147 148 Format *clone = def.clone(); 149 if( ! (*clone == def) ) { 150 errln((UnicodeString)"ERROR: Clone() failed"); 151 } 152 delete clone; 153 154// ======= Test various format() methods 155 156 logln((UnicodeString)"Testing various format() methods"); 157 158 double d = -10456.0037; 159 int32_t l = 100000000; 160 Formattable fD(d); 161 Formattable fL(l); 162 163 UnicodeString res1, res2, res3, res4; 164 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); 165 166 res1 = def.format(d, res1, pos1); 167 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); 168 169 res2 = pat.format(l, res2, pos2); 170 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); 171 172 status = U_ZERO_ERROR; 173 res3 = cust1.format(fD, res3, pos3, status); 174 if(U_FAILURE(status)) { 175 errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); 176 } 177 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3); 178 179 status = U_ZERO_ERROR; 180 res4 = cust2.format(fL, res4, pos4, status); 181 if(U_FAILURE(status)) { 182 errln((UnicodeString)"ERROR: format(Formattable [long]) failed"); 183 } 184 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4); 185 186// ======= Test parse() 187 188 logln((UnicodeString)"Testing parse()"); 189 190 UnicodeString text("-10,456.0037"); 191 Formattable result1, result2; 192 ParsePosition pos(0); 193 UnicodeString patt("#,##0.#"); 194 status = U_ZERO_ERROR; 195 pat.applyPattern(patt, status); 196 if(U_FAILURE(status)) { 197 errln((UnicodeString)"ERROR: applyPattern() failed"); 198 } 199 pat.parse(text, result1, pos); 200 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { 201 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 202 } 203 logln(text + " parsed into " + (int32_t) result1.getDouble()); 204 205 status = U_ZERO_ERROR; 206 pat.parse(text, result2, status); 207 if(U_FAILURE(status)) { 208 errln((UnicodeString)"ERROR: parse() failed"); 209 } 210 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { 211 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 212 } 213 logln(text + " parsed into " + (int32_t) result2.getDouble()); 214 215// ======= Test getters and setters 216 217 logln((UnicodeString)"Testing getters and setters"); 218 219 const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols(); 220 DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms); 221 def.setDecimalFormatSymbols(*newSyms); 222 def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this 223 if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) { 224 errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed"); 225 } 226 227 UnicodeString posPrefix; 228 pat.setPositivePrefix("+"); 229 posPrefix = pat.getPositivePrefix(posPrefix); 230 logln((UnicodeString)"Positive prefix (should be +): " + posPrefix); 231 if(posPrefix != "+") { 232 errln((UnicodeString)"ERROR: setPositivePrefix() failed"); 233 } 234 235 UnicodeString negPrefix; 236 pat.setNegativePrefix("-"); 237 negPrefix = pat.getNegativePrefix(negPrefix); 238 logln((UnicodeString)"Negative prefix (should be -): " + negPrefix); 239 if(negPrefix != "-") { 240 errln((UnicodeString)"ERROR: setNegativePrefix() failed"); 241 } 242 243 UnicodeString posSuffix; 244 pat.setPositiveSuffix("_"); 245 posSuffix = pat.getPositiveSuffix(posSuffix); 246 logln((UnicodeString)"Positive suffix (should be _): " + posSuffix); 247 if(posSuffix != "_") { 248 errln((UnicodeString)"ERROR: setPositiveSuffix() failed"); 249 } 250 251 UnicodeString negSuffix; 252 pat.setNegativeSuffix("~"); 253 negSuffix = pat.getNegativeSuffix(negSuffix); 254 logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix); 255 if(negSuffix != "~") { 256 errln((UnicodeString)"ERROR: setNegativeSuffix() failed"); 257 } 258 259 int32_t multiplier = 0; 260 pat.setMultiplier(8); 261 multiplier = pat.getMultiplier(); 262 logln((UnicodeString)"Multiplier (should be 8): " + multiplier); 263 if(multiplier != 8) { 264 errln((UnicodeString)"ERROR: setMultiplier() failed"); 265 } 266 267 int32_t groupingSize = 0; 268 pat.setGroupingSize(2); 269 groupingSize = pat.getGroupingSize(); 270 logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize); 271 if(groupingSize != 2) { 272 errln((UnicodeString)"ERROR: setGroupingSize() failed"); 273 } 274 275 pat.setDecimalSeparatorAlwaysShown(TRUE); 276 UBool tf = pat.isDecimalSeparatorAlwaysShown(); 277 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE")); 278 if(tf != TRUE) { 279 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed"); 280 } 281 // Added by Ken Liu testing set/isExponentSignAlwaysShown 282 pat.setExponentSignAlwaysShown(TRUE); 283 UBool esas = pat.isExponentSignAlwaysShown(); 284 logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE")); 285 if(esas != TRUE) { 286 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); 287 } 288 289 // Added by Ken Liu testing set/isScientificNotation 290 pat.setScientificNotation(TRUE); 291 UBool sn = pat.isScientificNotation(); 292 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE")); 293 if(sn != TRUE) { 294 errln((UnicodeString)"ERROR: setScientificNotation() failed"); 295 } 296 297 // Added by Ken Liu testing set/getMinimumExponentDigits 298 int8_t MinimumExponentDigits = 0; 299 pat.setMinimumExponentDigits(2); 300 MinimumExponentDigits = pat.getMinimumExponentDigits(); 301 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits); 302 if(MinimumExponentDigits != 2) { 303 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); 304 } 305 306 // Added by Ken Liu testing set/getRoundingIncrement 307 double RoundingIncrement = 0.0; 308 pat.setRoundingIncrement(2.0); 309 RoundingIncrement = pat.getRoundingIncrement(); 310 logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement); 311 if(RoundingIncrement != 2.0) { 312 errln((UnicodeString)"ERROR: setRoundingIncrement() failed"); 313 } 314 //end of Ken's Adding 315 316 UnicodeString funkyPat; 317 funkyPat = pat.toPattern(funkyPat); 318 logln((UnicodeString)"Pattern is " + funkyPat); 319 320 UnicodeString locPat; 321 locPat = pat.toLocalizedPattern(locPat); 322 logln((UnicodeString)"Localized pattern is " + locPat); 323 324// ======= Test applyPattern() 325 326 logln((UnicodeString)"Testing applyPattern()"); 327 328 UnicodeString p1("#,##0.0#;(#,##0.0#)"); 329 logln((UnicodeString)"Applying pattern " + p1); 330 status = U_ZERO_ERROR; 331 pat.applyPattern(p1, status); 332 if(U_FAILURE(status)) { 333 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 334 } 335 UnicodeString s2; 336 s2 = pat.toPattern(s2); 337 logln((UnicodeString)"Extracted pattern is " + s2); 338 if(s2 != p1) { 339 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied"); 340 } 341 342 if(pat.getSecondaryGroupingSize() != 0) { 343 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize()); 344 } 345 346 if(pat.getGroupingSize() != 3) { 347 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 348 } 349 350 UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)"); 351 logln((UnicodeString)"Applying pattern " + p2); 352 status = U_ZERO_ERROR; 353 pat.applyLocalizedPattern(p2, status); 354 if(U_FAILURE(status)) { 355 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 356 } 357 UnicodeString s3; 358 s3 = pat.toLocalizedPattern(s3); 359 logln((UnicodeString)"Extracted pattern is " + s3); 360 if(s3 != p2) { 361 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied"); 362 } 363 364 status = U_ZERO_ERROR; 365 UParseError pe; 366 pat.applyLocalizedPattern(p2, pe, status); 367 if(U_FAILURE(status)) { 368 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status); 369 } 370 UnicodeString s4; 371 s4 = pat.toLocalizedPattern(s3); 372 logln((UnicodeString)"Extracted pattern is " + s4); 373 if(s4 != p2) { 374 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied"); 375 } 376 377 if(pat.getSecondaryGroupingSize() != 2) { 378 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize()); 379 } 380 381 if(pat.getGroupingSize() != 3) { 382 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 383 } 384 385// ======= Test getStaticClassID() 386 387 logln((UnicodeString)"Testing getStaticClassID()"); 388 389 status = U_ZERO_ERROR; 390 NumberFormat *test = new DecimalFormat(status); 391 if(U_FAILURE(status)) { 392 errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat"); 393 } 394 395 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 396 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value"); 397 } 398 399 delete test; 400} 401 402void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ 403 UErrorCode status = U_ZERO_ERROR; 404 405 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); 406 if(U_FAILURE(status)) { 407 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); 408 } 409 410 CurrencyPluralInfo cpi1 = *cpi; 411 412 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){ 413 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value"); 414 } 415 416 cpi->setCurrencyPluralPattern("","",status); 417 if(U_FAILURE(status)) { 418 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern"); 419 } 420 421 cpi->setLocale(Locale::getCanada(), status); 422 if(U_FAILURE(status)) { 423 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); 424 } 425 426 cpi->setPluralRules("",status); 427 if(U_FAILURE(status)) { 428 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); 429 } 430 431 DecimalFormat *df = new DecimalFormat(status); 432 if(U_FAILURE(status)) { 433 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); 434 } 435 436 df->adoptCurrencyPluralInfo(cpi); 437 438 df->getCurrencyPluralInfo(); 439 440 df->setCurrencyPluralInfo(cpi1); 441 442 delete df; 443} 444 445void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) 446{ 447 UErrorCode status = U_ZERO_ERROR; 448 double Roundingnumber = 2.55; 449 double Roundingnumber1 = -2.55; 450 //+2.55 results -2.55 results 451 double result[]={ 3.0, -2.0, // kRoundCeiling 0, 452 2.0, -3.0, // kRoundFloor 1, 453 2.0, -2.0, // kRoundDown 2, 454 3.0, -3.0, // kRoundUp 3, 455 3.0, -3.0, // kRoundHalfEven 4, 456 3.0, -3.0, // kRoundHalfDown 5, 457 3.0, -3.0 // kRoundHalfUp 6 458 }; 459 DecimalFormat pat(status); 460 if(U_FAILURE(status)) { 461 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 462 return; 463 } 464 uint16_t mode; 465 uint16_t i=0; 466 UnicodeString message; 467 UnicodeString resultStr; 468 for(mode=0;mode < 7;mode++){ 469 pat.setRoundingMode((DecimalFormat::ERoundingMode)mode); 470 if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){ 471 errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode); 472 } 473 474 475 //for +2.55 with RoundingIncrement=1.0 476 pat.setRoundingIncrement(1.0); 477 pat.format(Roundingnumber, resultStr); 478 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 479 verify(message, resultStr, result[i++]); 480 message.remove(); 481 resultStr.remove(); 482 483 //for -2.55 with RoundingIncrement=1.0 484 pat.format(Roundingnumber1, resultStr); 485 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 486 verify(message, resultStr, result[i++]); 487 message.remove(); 488 resultStr.remove(); 489 } 490 491} 492void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){ 493 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 494 UnicodeString expectedStr(""); 495 expectedStr=expectedStr + expected; 496 if(got != expectedStr ) { 497 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr); 498 } 499} 500 501void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){ 502 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 503 if(got != expected ) { 504 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected); 505 } 506} 507 508void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/) 509{ 510 UErrorCode status = U_ZERO_ERROR; 511 DecimalFormat pat(UnicodeString("#,##0.00"),status); 512 if(U_FAILURE(status)) { 513 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 514 return; 515 } 516 517 // get default rounding increment 518 double roundingInc = pat.getRoundingIncrement(); 519 if (roundingInc != 0.0) { 520 errln((UnicodeString)"ERROR: Rounding increment not zero"); 521 return; 522 } 523 524 // With rounding now being handled by decNumber, we no longer 525 // set a rounding increment to enable non-default mode rounding, 526 // checking of which was the original point of this test. 527 528 // set rounding mode with zero increment. Rounding 529 // increment should not be set by this operation 530 pat.setRoundingMode((DecimalFormat::ERoundingMode)0); 531 roundingInc = pat.getRoundingIncrement(); 532 if (roundingInc != 0.0) { 533 errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode"); 534 return; 535 } 536} 537 538void IntlTestDecimalFormatAPI::TestScale() 539{ 540 typedef struct TestData { 541 double inputValue; 542 int inputScale; 543 const char *expectedOutput; 544 } TestData; 545 546 static TestData testData[] = { 547 { 100.0, 3, "100,000" }, 548 { 10034.0, -2, "100.34" }, 549 { 0.86, -3, "0.0009" }, 550 { -0.000455, 1, "-0%" }, 551 { -0.000555, 1, "-1%" }, 552 { 0.000455, 1, "0%" }, 553 { 0.000555, 1, "1%" }, 554 }; 555 556 UErrorCode status = U_ZERO_ERROR; 557 DecimalFormat pat(status); 558 if(U_FAILURE(status)) { 559 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 560 return; 561 } 562 563 UnicodeString message; 564 UnicodeString resultStr; 565 UnicodeString exp; 566 UnicodeString percentPattern("#,##0%"); 567 pat.setMaximumFractionDigits(4); 568 569 for(int32_t i=0; i < LENGTHOF(testData); i++) { 570 if ( i > 2 ) { 571 pat.applyPattern(percentPattern,status); 572 } 573 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); 574 pat.format(testData[i].inputValue, resultStr); 575 message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + 576 testData[i].inputScale + UnicodeString(". Got: "); 577 exp = testData[i].expectedOutput; 578 verifyString(message, resultStr, exp); 579 message.remove(); 580 resultStr.remove(); 581 exp.remove(); 582 } 583} 584 585 586#define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \ 587 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); } 588 589void IntlTestDecimalFormatAPI::TestFixedDecimal() { 590 UErrorCode status = U_ZERO_ERROR; 591 592 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status)); 593 TEST_ASSERT_STATUS(status); 594 FixedDecimal fd = df->getFixedDecimal(44, status); 595 TEST_ASSERT_STATUS(status); 596 ASSERT_EQUAL(44, fd.source); 597 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); 598 599 df.adoptInstead(new DecimalFormat("###.00##", status)); 600 TEST_ASSERT_STATUS(status); 601 fd = df->getFixedDecimal(123.456, status); 602 TEST_ASSERT_STATUS(status); 603 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); 604 ASSERT_EQUAL(456, fd.decimalDigits); 605 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); 606 ASSERT_EQUAL(123, fd.intValue); 607 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 608 ASSERT_EQUAL(FALSE, fd.isNegative); 609 610 df.adoptInstead(new DecimalFormat("###", status)); 611 TEST_ASSERT_STATUS(status); 612 fd = df->getFixedDecimal(123.456, status); 613 TEST_ASSERT_STATUS(status); 614 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); 615 ASSERT_EQUAL(0, fd.decimalDigits); 616 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 617 ASSERT_EQUAL(123, fd.intValue); 618 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 619 ASSERT_EQUAL(FALSE, fd.isNegative); 620 621 df.adoptInstead(new DecimalFormat("###.0", status)); 622 TEST_ASSERT_STATUS(status); 623 fd = df->getFixedDecimal(123.01, status); 624 TEST_ASSERT_STATUS(status); 625 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); 626 ASSERT_EQUAL(0, fd.decimalDigits); 627 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 628 ASSERT_EQUAL(123, fd.intValue); 629 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 630 ASSERT_EQUAL(FALSE, fd.isNegative); 631 632 df.adoptInstead(new DecimalFormat("###.0", status)); 633 TEST_ASSERT_STATUS(status); 634 fd = df->getFixedDecimal(123.06, status); 635 TEST_ASSERT_STATUS(status); 636 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); 637 ASSERT_EQUAL(1, fd.decimalDigits); 638 ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros); 639 ASSERT_EQUAL(123, fd.intValue); 640 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 641 ASSERT_EQUAL(FALSE, fd.isNegative); 642 643 df.adoptInstead(new DecimalFormat("@@@@@", status)); // Significant Digits 644 TEST_ASSERT_STATUS(status); 645 fd = df->getFixedDecimal(123, status); 646 TEST_ASSERT_STATUS(status); 647 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 648 ASSERT_EQUAL(0, fd.decimalDigits); 649 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 650 ASSERT_EQUAL(123, fd.intValue); 651 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 652 ASSERT_EQUAL(FALSE, fd.isNegative); 653 654 df.adoptInstead(new DecimalFormat("@@@@@", status)); // Significant Digits 655 TEST_ASSERT_STATUS(status); 656 fd = df->getFixedDecimal(1.23, status); 657 TEST_ASSERT_STATUS(status); 658 ASSERT_EQUAL(4, fd.visibleDecimalDigitCount); 659 ASSERT_EQUAL(2300, fd.decimalDigits); 660 ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros); 661 ASSERT_EQUAL(1, fd.intValue); 662 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 663 ASSERT_EQUAL(FALSE, fd.isNegative); 664 665 fd = df->getFixedDecimal(uprv_getInfinity(), status); 666 TEST_ASSERT_STATUS(status); 667 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); 668 fd = df->getFixedDecimal(0.0, status); 669 ASSERT_EQUAL(FALSE, fd.isNanOrInfinity); 670 fd = df->getFixedDecimal(uprv_getNaN(), status); 671 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); 672 TEST_ASSERT_STATUS(status); 673 674 // Test Big Decimal input. 675 // 22 digits before and after decimal, will exceed the precision of a double 676 // and force DecimalFormat::getFixedDecimal() to work with a digit list. 677 df.adoptInstead(new DecimalFormat("#####################0.00####################", status)); 678 TEST_ASSERT_STATUS(status); 679 Formattable fable("12.34", status); 680 TEST_ASSERT_STATUS(status); 681 fd = df->getFixedDecimal(fable, status); 682 TEST_ASSERT_STATUS(status); 683 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 684 ASSERT_EQUAL(34, fd.decimalDigits); 685 ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros); 686 ASSERT_EQUAL(12, fd.intValue); 687 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 688 ASSERT_EQUAL(FALSE, fd.isNegative); 689 690 fable.setDecimalNumber("12.345678901234567890123456789", status); 691 TEST_ASSERT_STATUS(status); 692 fd = df->getFixedDecimal(fable, status); 693 TEST_ASSERT_STATUS(status); 694 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 695 ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits); 696 ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros); 697 ASSERT_EQUAL(12, fd.intValue); 698 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 699 ASSERT_EQUAL(FALSE, fd.isNegative); 700 701 // On field overflow, Integer part is truncated on the left, fraction part on the right. 702 fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status); 703 TEST_ASSERT_STATUS(status); 704 fd = df->getFixedDecimal(fable, status); 705 TEST_ASSERT_STATUS(status); 706 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 707 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits); 708 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros); 709 ASSERT_EQUAL(345678901234567890LL, fd.intValue); 710 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 711 ASSERT_EQUAL(FALSE, fd.isNegative); 712 713 // Digits way to the right of the decimal but within the format's precision aren't truncated 714 fable.setDecimalNumber("1.0000000000000000000012", status); 715 TEST_ASSERT_STATUS(status); 716 fd = df->getFixedDecimal(fable, status); 717 TEST_ASSERT_STATUS(status); 718 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 719 ASSERT_EQUAL(12, fd.decimalDigits); 720 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); 721 ASSERT_EQUAL(1, fd.intValue); 722 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 723 ASSERT_EQUAL(FALSE, fd.isNegative); 724 725 // Digits beyond the precision of the format are rounded away 726 fable.setDecimalNumber("1.000000000000000000000012", status); 727 TEST_ASSERT_STATUS(status); 728 fd = df->getFixedDecimal(fable, status); 729 TEST_ASSERT_STATUS(status); 730 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 731 ASSERT_EQUAL(0, fd.decimalDigits); 732 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 733 ASSERT_EQUAL(1, fd.intValue); 734 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 735 ASSERT_EQUAL(FALSE, fd.isNegative); 736 737 // Negative numbers come through 738 fable.setDecimalNumber("-1.0000000000000000000012", status); 739 TEST_ASSERT_STATUS(status); 740 fd = df->getFixedDecimal(fable, status); 741 TEST_ASSERT_STATUS(status); 742 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); 743 ASSERT_EQUAL(12, fd.decimalDigits); 744 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); 745 ASSERT_EQUAL(1, fd.intValue); 746 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 747 ASSERT_EQUAL(TRUE, fd.isNegative); 748 749 // MinFractionDigits from format larger than from number. 750 fable.setDecimalNumber("1000000000000000000000.3", status); 751 TEST_ASSERT_STATUS(status); 752 fd = df->getFixedDecimal(fable, status); 753 TEST_ASSERT_STATUS(status); 754 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 755 ASSERT_EQUAL(30, fd.decimalDigits); 756 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros); 757 ASSERT_EQUAL(100000000000000000LL, fd.intValue); 758 ASSERT_EQUAL(FALSE, fd.hasIntegerValue); 759 ASSERT_EQUAL(FALSE, fd.isNegative); 760 761 // Test some int64_t values that are out of the range of a double 762 fable.setInt64(4503599627370496LL); 763 TEST_ASSERT_STATUS(status); 764 fd = df->getFixedDecimal(fable, status); 765 TEST_ASSERT_STATUS(status); 766 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 767 ASSERT_EQUAL(0, fd.decimalDigits); 768 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 769 ASSERT_EQUAL(4503599627370496LL, fd.intValue); 770 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 771 ASSERT_EQUAL(FALSE, fd.isNegative); 772 773 fable.setInt64(4503599627370497LL); 774 TEST_ASSERT_STATUS(status); 775 fd = df->getFixedDecimal(fable, status); 776 TEST_ASSERT_STATUS(status); 777 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 778 ASSERT_EQUAL(0, fd.decimalDigits); 779 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 780 ASSERT_EQUAL(4503599627370497LL, fd.intValue); 781 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 782 ASSERT_EQUAL(FALSE, fd.isNegative); 783 784 fable.setInt64(9223372036854775807LL); 785 TEST_ASSERT_STATUS(status); 786 fd = df->getFixedDecimal(fable, status); 787 TEST_ASSERT_STATUS(status); 788 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); 789 ASSERT_EQUAL(0, fd.decimalDigits); 790 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); 791 // note: going through DigitList path to FixedDecimal, which is trimming 792 // int64_t fields to 18 digits. See ticket Ticket #10374 793 // ASSERT_EQUAL(223372036854775807LL, fd.intValue); 794 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) { 795 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue); 796 } 797 ASSERT_EQUAL(TRUE, fd.hasIntegerValue); 798 ASSERT_EQUAL(FALSE, fd.isNegative); 799 800} 801 802void IntlTestDecimalFormatAPI::TestBadFastpath() { 803 UErrorCode status = U_ZERO_ERROR; 804 805 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status)); 806 if (U_FAILURE(status)) { 807 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); 808 return; 809 } 810 811 UnicodeString fmt; 812 fmt.remove(); 813 assertEquals("Format 1234", "1234", df->format(1234, fmt)); 814 df->setGroupingUsed(FALSE); 815 fmt.remove(); 816 assertEquals("Format 1234", "1234", df->format(1234, fmt)); 817 df->setGroupingUsed(TRUE); 818 fmt.remove(); 819 assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt)); 820} 821 822#endif /* #if !UCONFIG_NO_FORMATTING */ 823