1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2013, 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/decimfmt.h" 14#include "unicode/dcfmtsym.h" 15#include "unicode/parseerr.h" 16#include "unicode/currpinf.h" 17 18// This is an API test, not a unit test. It doesn't test very many cases, and doesn't 19// try to test the full functionality. It just calls each function in the class and 20// verifies that it works on a basic level. 21 22void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 23{ 24 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); 25 switch (index) { 26 case 0: name = "DecimalFormat API test"; 27 if (exec) { 28 logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)""); 29 UErrorCode status = U_ZERO_ERROR; 30 Locale saveLocale; 31 Locale::setDefault(Locale::getEnglish(), status); 32 if(U_FAILURE(status)) { 33 errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results"); 34 } 35 testAPI(/*par*/); 36 Locale::setDefault(saveLocale, status); 37 } 38 break; 39 case 1: name = "Rounding test"; 40 if(exec) { 41 logln((UnicodeString)"DecimalFormat Rounding test---"); 42 testRounding(/*par*/); 43 } 44 break; 45 case 2: name = "Test6354"; 46 if(exec) { 47 logln((UnicodeString)"DecimalFormat Rounding Increment test---"); 48 testRoundingInc(/*par*/); 49 } 50 break; 51 case 3: name = "TestCurrencyPluralInfo"; 52 if(exec) { 53 logln((UnicodeString)"CurrencyPluralInfo API test---"); 54 TestCurrencyPluralInfo(); 55 } 56 break; 57 case 4: name = "TestScale"; 58 if(exec) { 59 logln((UnicodeString)"Scale test---"); 60 TestScale(); 61 } 62 break; 63 default: name = ""; break; 64 } 65} 66 67/** 68 * This test checks various generic API methods in DecimalFormat to achieve 100% 69 * API coverage. 70 */ 71void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) 72{ 73 UErrorCode status = U_ZERO_ERROR; 74 75// ======= Test constructors 76 77 logln((UnicodeString)"Testing DecimalFormat constructors"); 78 79 DecimalFormat def(status); 80 if(U_FAILURE(status)) { 81 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 82 return; 83 } 84 85 status = U_ZERO_ERROR; 86 const UnicodeString pattern("#,##0.# FF"); 87 DecimalFormat pat(pattern, status); 88 if(U_FAILURE(status)) { 89 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); 90 return; 91 } 92 93 status = U_ZERO_ERROR; 94 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status); 95 if(U_FAILURE(status)) { 96 errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)"); 97 return; 98 } 99 100 status = U_ZERO_ERROR; 101 DecimalFormat cust1(pattern, symbols, status); 102 if(U_FAILURE(status)) { 103 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); 104 } 105 106 status = U_ZERO_ERROR; 107 DecimalFormat cust2(pattern, *symbols, status); 108 if(U_FAILURE(status)) { 109 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)"); 110 } 111 112 DecimalFormat copy(pat); 113 114// ======= Test clone(), assignment, and equality 115 116 logln((UnicodeString)"Testing clone(), assignment and equality operators"); 117 118 if( ! (copy == pat) || copy != pat) { 119 errln((UnicodeString)"ERROR: Copy constructor or == failed"); 120 } 121 122 copy = cust1; 123 if(copy != cust1) { 124 errln((UnicodeString)"ERROR: Assignment (or !=) failed"); 125 } 126 127 Format *clone = def.clone(); 128 if( ! (*clone == def) ) { 129 errln((UnicodeString)"ERROR: Clone() failed"); 130 } 131 delete clone; 132 133// ======= Test various format() methods 134 135 logln((UnicodeString)"Testing various format() methods"); 136 137 double d = -10456.0037; 138 int32_t l = 100000000; 139 Formattable fD(d); 140 Formattable fL(l); 141 142 UnicodeString res1, res2, res3, res4; 143 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); 144 145 res1 = def.format(d, res1, pos1); 146 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); 147 148 res2 = pat.format(l, res2, pos2); 149 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); 150 151 status = U_ZERO_ERROR; 152 res3 = cust1.format(fD, res3, pos3, status); 153 if(U_FAILURE(status)) { 154 errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); 155 } 156 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3); 157 158 status = U_ZERO_ERROR; 159 res4 = cust2.format(fL, res4, pos4, status); 160 if(U_FAILURE(status)) { 161 errln((UnicodeString)"ERROR: format(Formattable [long]) failed"); 162 } 163 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4); 164 165// ======= Test parse() 166 167 logln((UnicodeString)"Testing parse()"); 168 169 UnicodeString text("-10,456.0037"); 170 Formattable result1, result2; 171 ParsePosition pos(0); 172 UnicodeString patt("#,##0.#"); 173 status = U_ZERO_ERROR; 174 pat.applyPattern(patt, status); 175 if(U_FAILURE(status)) { 176 errln((UnicodeString)"ERROR: applyPattern() failed"); 177 } 178 pat.parse(text, result1, pos); 179 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { 180 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 181 } 182 logln(text + " parsed into " + (int32_t) result1.getDouble()); 183 184 status = U_ZERO_ERROR; 185 pat.parse(text, result2, status); 186 if(U_FAILURE(status)) { 187 errln((UnicodeString)"ERROR: parse() failed"); 188 } 189 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { 190 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); 191 } 192 logln(text + " parsed into " + (int32_t) result2.getDouble()); 193 194// ======= Test getters and setters 195 196 logln((UnicodeString)"Testing getters and setters"); 197 198 const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols(); 199 DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms); 200 def.setDecimalFormatSymbols(*newSyms); 201 def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this 202 if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) { 203 errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed"); 204 } 205 206 UnicodeString posPrefix; 207 pat.setPositivePrefix("+"); 208 posPrefix = pat.getPositivePrefix(posPrefix); 209 logln((UnicodeString)"Positive prefix (should be +): " + posPrefix); 210 if(posPrefix != "+") { 211 errln((UnicodeString)"ERROR: setPositivePrefix() failed"); 212 } 213 214 UnicodeString negPrefix; 215 pat.setNegativePrefix("-"); 216 negPrefix = pat.getNegativePrefix(negPrefix); 217 logln((UnicodeString)"Negative prefix (should be -): " + negPrefix); 218 if(negPrefix != "-") { 219 errln((UnicodeString)"ERROR: setNegativePrefix() failed"); 220 } 221 222 UnicodeString posSuffix; 223 pat.setPositiveSuffix("_"); 224 posSuffix = pat.getPositiveSuffix(posSuffix); 225 logln((UnicodeString)"Positive suffix (should be _): " + posSuffix); 226 if(posSuffix != "_") { 227 errln((UnicodeString)"ERROR: setPositiveSuffix() failed"); 228 } 229 230 UnicodeString negSuffix; 231 pat.setNegativeSuffix("~"); 232 negSuffix = pat.getNegativeSuffix(negSuffix); 233 logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix); 234 if(negSuffix != "~") { 235 errln((UnicodeString)"ERROR: setNegativeSuffix() failed"); 236 } 237 238 int32_t multiplier = 0; 239 pat.setMultiplier(8); 240 multiplier = pat.getMultiplier(); 241 logln((UnicodeString)"Multiplier (should be 8): " + multiplier); 242 if(multiplier != 8) { 243 errln((UnicodeString)"ERROR: setMultiplier() failed"); 244 } 245 246 int32_t groupingSize = 0; 247 pat.setGroupingSize(2); 248 groupingSize = pat.getGroupingSize(); 249 logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize); 250 if(groupingSize != 2) { 251 errln((UnicodeString)"ERROR: setGroupingSize() failed"); 252 } 253 254 pat.setDecimalSeparatorAlwaysShown(TRUE); 255 UBool tf = pat.isDecimalSeparatorAlwaysShown(); 256 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE")); 257 if(tf != TRUE) { 258 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed"); 259 } 260 // Added by Ken Liu testing set/isExponentSignAlwaysShown 261 pat.setExponentSignAlwaysShown(TRUE); 262 UBool esas = pat.isExponentSignAlwaysShown(); 263 logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE")); 264 if(esas != TRUE) { 265 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); 266 } 267 268 // Added by Ken Liu testing set/isScientificNotation 269 pat.setScientificNotation(TRUE); 270 UBool sn = pat.isScientificNotation(); 271 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE")); 272 if(sn != TRUE) { 273 errln((UnicodeString)"ERROR: setScientificNotation() failed"); 274 } 275 276 // Added by Ken Liu testing set/getMinimumExponentDigits 277 int8_t MinimumExponentDigits = 0; 278 pat.setMinimumExponentDigits(2); 279 MinimumExponentDigits = pat.getMinimumExponentDigits(); 280 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits); 281 if(MinimumExponentDigits != 2) { 282 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); 283 } 284 285 // Added by Ken Liu testing set/getRoundingIncrement 286 double RoundingIncrement = 0.0; 287 pat.setRoundingIncrement(2.0); 288 RoundingIncrement = pat.getRoundingIncrement(); 289 logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement); 290 if(RoundingIncrement != 2.0) { 291 errln((UnicodeString)"ERROR: setRoundingIncrement() failed"); 292 } 293 //end of Ken's Adding 294 295 UnicodeString funkyPat; 296 funkyPat = pat.toPattern(funkyPat); 297 logln((UnicodeString)"Pattern is " + funkyPat); 298 299 UnicodeString locPat; 300 locPat = pat.toLocalizedPattern(locPat); 301 logln((UnicodeString)"Localized pattern is " + locPat); 302 303// ======= Test applyPattern() 304 305 logln((UnicodeString)"Testing applyPattern()"); 306 307 UnicodeString p1("#,##0.0#;(#,##0.0#)"); 308 logln((UnicodeString)"Applying pattern " + p1); 309 status = U_ZERO_ERROR; 310 pat.applyPattern(p1, status); 311 if(U_FAILURE(status)) { 312 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 313 } 314 UnicodeString s2; 315 s2 = pat.toPattern(s2); 316 logln((UnicodeString)"Extracted pattern is " + s2); 317 if(s2 != p1) { 318 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied"); 319 } 320 321 if(pat.getSecondaryGroupingSize() != 0) { 322 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize()); 323 } 324 325 if(pat.getGroupingSize() != 3) { 326 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 327 } 328 329 UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)"); 330 logln((UnicodeString)"Applying pattern " + p2); 331 status = U_ZERO_ERROR; 332 pat.applyLocalizedPattern(p2, status); 333 if(U_FAILURE(status)) { 334 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); 335 } 336 UnicodeString s3; 337 s3 = pat.toLocalizedPattern(s3); 338 logln((UnicodeString)"Extracted pattern is " + s3); 339 if(s3 != p2) { 340 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied"); 341 } 342 343 status = U_ZERO_ERROR; 344 UParseError pe; 345 pat.applyLocalizedPattern(p2, pe, status); 346 if(U_FAILURE(status)) { 347 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status); 348 } 349 UnicodeString s4; 350 s4 = pat.toLocalizedPattern(s3); 351 logln((UnicodeString)"Extracted pattern is " + s4); 352 if(s4 != p2) { 353 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied"); 354 } 355 356 if(pat.getSecondaryGroupingSize() != 2) { 357 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize()); 358 } 359 360 if(pat.getGroupingSize() != 3) { 361 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); 362 } 363 364// ======= Test getStaticClassID() 365 366 logln((UnicodeString)"Testing getStaticClassID()"); 367 368 status = U_ZERO_ERROR; 369 NumberFormat *test = new DecimalFormat(status); 370 if(U_FAILURE(status)) { 371 errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat"); 372 } 373 374 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { 375 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value"); 376 } 377 378 delete test; 379} 380 381void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ 382 UErrorCode status = U_ZERO_ERROR; 383 384 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); 385 if(U_FAILURE(status)) { 386 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); 387 } 388 389 CurrencyPluralInfo cpi1 = *cpi; 390 391 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){ 392 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value"); 393 } 394 395 cpi->setCurrencyPluralPattern("","",status); 396 if(U_FAILURE(status)) { 397 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern"); 398 } 399 400 cpi->setLocale(Locale::getCanada(), status); 401 if(U_FAILURE(status)) { 402 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); 403 } 404 405 cpi->setPluralRules("",status); 406 if(U_FAILURE(status)) { 407 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); 408 } 409 410 DecimalFormat *df = new DecimalFormat(status); 411 if(U_FAILURE(status)) { 412 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); 413 } 414 415 df->adoptCurrencyPluralInfo(cpi); 416 417 df->getCurrencyPluralInfo(); 418 419 df->setCurrencyPluralInfo(cpi1); 420 421 delete df; 422} 423 424void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) 425{ 426 UErrorCode status = U_ZERO_ERROR; 427 double Roundingnumber = 2.55; 428 double Roundingnumber1 = -2.55; 429 //+2.55 results -2.55 results 430 double result[]={ 3.0, -2.0, // kRoundCeiling 0, 431 2.0, -3.0, // kRoundFloor 1, 432 2.0, -2.0, // kRoundDown 2, 433 3.0, -3.0, // kRoundUp 3, 434 3.0, -3.0, // kRoundHalfEven 4, 435 3.0, -3.0, // kRoundHalfDown 5, 436 3.0, -3.0 // kRoundHalfUp 6 437 }; 438 DecimalFormat pat(status); 439 if(U_FAILURE(status)) { 440 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 441 return; 442 } 443 uint16_t mode; 444 uint16_t i=0; 445 UnicodeString message; 446 UnicodeString resultStr; 447 for(mode=0;mode < 7;mode++){ 448 pat.setRoundingMode((DecimalFormat::ERoundingMode)mode); 449 if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){ 450 errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode); 451 } 452 453 454 //for +2.55 with RoundingIncrement=1.0 455 pat.setRoundingIncrement(1.0); 456 pat.format(Roundingnumber, resultStr); 457 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 458 verify(message, resultStr, result[i++]); 459 message.remove(); 460 resultStr.remove(); 461 462 //for -2.55 with RoundingIncrement=1.0 463 pat.format(Roundingnumber1, resultStr); 464 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); 465 verify(message, resultStr, result[i++]); 466 message.remove(); 467 resultStr.remove(); 468 } 469 470} 471void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){ 472 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 473 UnicodeString expectedStr(""); 474 expectedStr=expectedStr + expected; 475 if(got != expectedStr ) { 476 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr); 477 } 478} 479 480void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){ 481 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); 482 if(got != expected ) { 483 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected); 484 } 485} 486 487void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/) 488{ 489 UErrorCode status = U_ZERO_ERROR; 490 DecimalFormat pat(UnicodeString("#,##0.00"),status); 491 if(U_FAILURE(status)) { 492 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 493 return; 494 } 495 496 // get default rounding increment 497 double roundingInc = pat.getRoundingIncrement(); 498 if (roundingInc != 0.0) { 499 errln((UnicodeString)"ERROR: Rounding increment not zero"); 500 return; 501 } 502 503 // With rounding now being handled by decNumber, we no longer 504 // set a rounding increment to enable non-default mode rounding, 505 // checking of which was the original point of this test. 506 507 // set rounding mode with zero increment. Rounding 508 // increment should not be set by this operation 509 pat.setRoundingMode((DecimalFormat::ERoundingMode)0); 510 roundingInc = pat.getRoundingIncrement(); 511 if (roundingInc != 0.0) { 512 errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode"); 513 return; 514 } 515} 516 517void IntlTestDecimalFormatAPI::TestScale() 518{ 519 typedef struct TestData { 520 double inputValue; 521 int inputScale; 522 char *expectedOutput; 523 } TestData; 524 525 static TestData testData[] = { 526 { 100.0, 3, "100,000" }, 527 { 10034.0, -2, "100.34" }, 528 { 0.86, -3, "0.0009" }, 529 { -0.000455, 1, "-0%" }, 530 { -0.000555, 1, "-1%" }, 531 { 0.000455, 1, "0%" }, 532 { 0.000555, 1, "1%" }, 533 }; 534 535 UErrorCode status = U_ZERO_ERROR; 536 DecimalFormat pat(status); 537 if(U_FAILURE(status)) { 538 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); 539 return; 540 } 541 542 UnicodeString message; 543 UnicodeString resultStr; 544 UnicodeString exp; 545 UnicodeString percentPattern("#,##0%"); 546 pat.setMaximumFractionDigits(4); 547 548 for(int32_t i=0;i < sizeof(testData)/sizeof(testData[0]);i++) { 549 if ( i > 2 ) { 550 pat.applyPattern(percentPattern,status); 551 } 552 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); 553 pat.format(testData[i].inputValue, resultStr); 554 message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + testData[i].inputScale + UnicodeString(". Got: "); 555 exp = testData[i].expectedOutput; 556 verifyString(message, resultStr, exp); 557 message.remove(); 558 resultStr.remove(); 559 exp.remove(); 560 } 561} 562#endif /* #if !UCONFIG_NO_FORMATTING */ 563