| /******************************************************************** |
| * COPYRIGHT: |
| * Copyright (c) 1997-2015, International Business Machines Corporation and |
| * others. All Rights Reserved. |
| ********************************************************************/ |
| |
| #include "unicode/utypes.h" |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| #include "dcfmapts.h" |
| |
| #include "unicode/currpinf.h" |
| #include "unicode/dcfmtsym.h" |
| #include "unicode/decimfmt.h" |
| #include "unicode/fmtable.h" |
| #include "unicode/localpointer.h" |
| #include "unicode/parseerr.h" |
| #include "unicode/stringpiece.h" |
| |
| #include "putilimp.h" |
| #include "plurrule_impl.h" |
| #include <stdio.h> |
| |
| // This is an API test, not a unit test. It doesn't test very many cases, and doesn't |
| // try to test the full functionality. It just calls each function in the class and |
| // verifies that it works on a basic level. |
| |
| void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) |
| { |
| if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI"); |
| switch (index) { |
| case 0: name = "DecimalFormat API test"; |
| if (exec) { |
| logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)""); |
| UErrorCode status = U_ZERO_ERROR; |
| Locale saveLocale; |
| Locale::setDefault(Locale::getEnglish(), status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results"); |
| } |
| testAPI(/*par*/); |
| Locale::setDefault(saveLocale, status); |
| } |
| break; |
| case 1: name = "Rounding test"; |
| if(exec) { |
| logln((UnicodeString)"DecimalFormat Rounding test---"); |
| testRounding(/*par*/); |
| } |
| break; |
| case 2: name = "Test6354"; |
| if(exec) { |
| logln((UnicodeString)"DecimalFormat Rounding Increment test---"); |
| testRoundingInc(/*par*/); |
| } |
| break; |
| case 3: name = "TestCurrencyPluralInfo"; |
| if(exec) { |
| logln((UnicodeString)"CurrencyPluralInfo API test---"); |
| TestCurrencyPluralInfo(); |
| } |
| break; |
| case 4: name = "TestScale"; |
| if(exec) { |
| logln((UnicodeString)"Scale test---"); |
| TestScale(); |
| } |
| break; |
| case 5: name = "TestFixedDecimal"; |
| if(exec) { |
| logln((UnicodeString)"TestFixedDecimal ---"); |
| TestFixedDecimal(); |
| } |
| break; |
| case 6: name = "TestBadFastpath"; |
| if(exec) { |
| logln((UnicodeString)"TestBadFastpath ---"); |
| TestBadFastpath(); |
| } |
| break; |
| case 7: name = "TestRequiredDecimalPoint"; |
| if(exec) { |
| logln((UnicodeString)"TestRequiredDecimalPoint ---"); |
| TestRequiredDecimalPoint(); |
| } |
| break; |
| default: name = ""; break; |
| } |
| } |
| |
| /** |
| * This test checks various generic API methods in DecimalFormat to achieve 100% |
| * API coverage. |
| */ |
| void IntlTestDecimalFormatAPI::testAPI(/*char *par*/) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| |
| // ======= Test constructors |
| |
| logln((UnicodeString)"Testing DecimalFormat constructors"); |
| |
| DecimalFormat def(status); |
| if(U_FAILURE(status)) { |
| errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
| return; |
| } |
| |
| // bug 10864 |
| status = U_ZERO_ERROR; |
| DecimalFormat noGrouping("###0.##", status); |
| if (noGrouping.getGroupingSize() != 0) { |
| errln("Grouping size should be 0 for no grouping."); |
| } |
| noGrouping.setGroupingUsed(TRUE); |
| if (noGrouping.getGroupingSize() != 0) { |
| errln("Grouping size should still be 0."); |
| } |
| // end bug 10864 |
| |
| status = U_ZERO_ERROR; |
| const UnicodeString pattern("#,##0.# FF"); |
| DecimalFormat pat(pattern, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)"); |
| return; |
| } |
| |
| status = U_ZERO_ERROR; |
| DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)"); |
| return; |
| } |
| |
| status = U_ZERO_ERROR; |
| DecimalFormat cust1(pattern, symbols, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)"); |
| } |
| |
| status = U_ZERO_ERROR; |
| DecimalFormat cust2(pattern, *symbols, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)"); |
| } |
| |
| DecimalFormat copy(pat); |
| |
| // ======= Test clone(), assignment, and equality |
| |
| logln((UnicodeString)"Testing clone(), assignment and equality operators"); |
| |
| if( ! (copy == pat) || copy != pat) { |
| errln((UnicodeString)"ERROR: Copy constructor or == failed"); |
| } |
| |
| copy = cust1; |
| if(copy != cust1) { |
| errln((UnicodeString)"ERROR: Assignment (or !=) failed"); |
| } |
| |
| Format *clone = def.clone(); |
| if( ! (*clone == def) ) { |
| errln((UnicodeString)"ERROR: Clone() failed"); |
| } |
| delete clone; |
| |
| // ======= Test various format() methods |
| |
| logln((UnicodeString)"Testing various format() methods"); |
| |
| double d = -10456.0037; |
| int32_t l = 100000000; |
| Formattable fD(d); |
| Formattable fL(l); |
| |
| UnicodeString res1, res2, res3, res4; |
| FieldPosition pos1(0), pos2(0), pos3(0), pos4(0); |
| |
| res1 = def.format(d, res1, pos1); |
| logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); |
| |
| res2 = pat.format(l, res2, pos2); |
| logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); |
| |
| status = U_ZERO_ERROR; |
| res3 = cust1.format(fD, res3, pos3, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: format(Formattable [double]) failed"); |
| } |
| logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3); |
| |
| status = U_ZERO_ERROR; |
| res4 = cust2.format(fL, res4, pos4, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: format(Formattable [long]) failed"); |
| } |
| logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4); |
| |
| // ======= Test parse() |
| |
| logln((UnicodeString)"Testing parse()"); |
| |
| UnicodeString text("-10,456.0037"); |
| Formattable result1, result2; |
| ParsePosition pos(0); |
| UnicodeString patt("#,##0.#"); |
| status = U_ZERO_ERROR; |
| pat.applyPattern(patt, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern() failed"); |
| } |
| pat.parse(text, result1, pos); |
| if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { |
| errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); |
| } |
| logln(text + " parsed into " + (int32_t) result1.getDouble()); |
| |
| status = U_ZERO_ERROR; |
| pat.parse(text, result2, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: parse() failed"); |
| } |
| if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { |
| errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text); |
| } |
| logln(text + " parsed into " + (int32_t) result2.getDouble()); |
| |
| // ======= Test getters and setters |
| |
| logln((UnicodeString)"Testing getters and setters"); |
| |
| const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols(); |
| DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms); |
| def.setDecimalFormatSymbols(*newSyms); |
| def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this |
| if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) { |
| errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed"); |
| } |
| |
| UnicodeString posPrefix; |
| pat.setPositivePrefix("+"); |
| posPrefix = pat.getPositivePrefix(posPrefix); |
| logln((UnicodeString)"Positive prefix (should be +): " + posPrefix); |
| if(posPrefix != "+") { |
| errln((UnicodeString)"ERROR: setPositivePrefix() failed"); |
| } |
| |
| UnicodeString negPrefix; |
| pat.setNegativePrefix("-"); |
| negPrefix = pat.getNegativePrefix(negPrefix); |
| logln((UnicodeString)"Negative prefix (should be -): " + negPrefix); |
| if(negPrefix != "-") { |
| errln((UnicodeString)"ERROR: setNegativePrefix() failed"); |
| } |
| |
| UnicodeString posSuffix; |
| pat.setPositiveSuffix("_"); |
| posSuffix = pat.getPositiveSuffix(posSuffix); |
| logln((UnicodeString)"Positive suffix (should be _): " + posSuffix); |
| if(posSuffix != "_") { |
| errln((UnicodeString)"ERROR: setPositiveSuffix() failed"); |
| } |
| |
| UnicodeString negSuffix; |
| pat.setNegativeSuffix("~"); |
| negSuffix = pat.getNegativeSuffix(negSuffix); |
| logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix); |
| if(negSuffix != "~") { |
| errln((UnicodeString)"ERROR: setNegativeSuffix() failed"); |
| } |
| |
| int32_t multiplier = 0; |
| pat.setMultiplier(8); |
| multiplier = pat.getMultiplier(); |
| logln((UnicodeString)"Multiplier (should be 8): " + multiplier); |
| if(multiplier != 8) { |
| errln((UnicodeString)"ERROR: setMultiplier() failed"); |
| } |
| |
| int32_t groupingSize = 0; |
| pat.setGroupingSize(2); |
| groupingSize = pat.getGroupingSize(); |
| logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize); |
| if(groupingSize != 2) { |
| errln((UnicodeString)"ERROR: setGroupingSize() failed"); |
| } |
| |
| pat.setDecimalSeparatorAlwaysShown(TRUE); |
| UBool tf = pat.isDecimalSeparatorAlwaysShown(); |
| logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE")); |
| if(tf != TRUE) { |
| errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed"); |
| } |
| // Added by Ken Liu testing set/isExponentSignAlwaysShown |
| pat.setExponentSignAlwaysShown(TRUE); |
| UBool esas = pat.isExponentSignAlwaysShown(); |
| logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE")); |
| if(esas != TRUE) { |
| errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed"); |
| } |
| |
| // Added by Ken Liu testing set/isScientificNotation |
| pat.setScientificNotation(TRUE); |
| UBool sn = pat.isScientificNotation(); |
| logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE")); |
| if(sn != TRUE) { |
| errln((UnicodeString)"ERROR: setScientificNotation() failed"); |
| } |
| |
| // Added by Ken Liu testing set/getMinimumExponentDigits |
| int8_t MinimumExponentDigits = 0; |
| pat.setMinimumExponentDigits(2); |
| MinimumExponentDigits = pat.getMinimumExponentDigits(); |
| logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits); |
| if(MinimumExponentDigits != 2) { |
| errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed"); |
| } |
| |
| // Added by Ken Liu testing set/getRoundingIncrement |
| double RoundingIncrement = 0.0; |
| pat.setRoundingIncrement(2.0); |
| RoundingIncrement = pat.getRoundingIncrement(); |
| logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement); |
| if(RoundingIncrement != 2.0) { |
| errln((UnicodeString)"ERROR: setRoundingIncrement() failed"); |
| } |
| //end of Ken's Adding |
| |
| UnicodeString funkyPat; |
| funkyPat = pat.toPattern(funkyPat); |
| logln((UnicodeString)"Pattern is " + funkyPat); |
| |
| UnicodeString locPat; |
| locPat = pat.toLocalizedPattern(locPat); |
| logln((UnicodeString)"Localized pattern is " + locPat); |
| |
| // ======= Test applyPattern() |
| |
| logln((UnicodeString)"Testing applyPattern()"); |
| |
| UnicodeString p1("#,##0.0#;(#,##0.0#)"); |
| logln((UnicodeString)"Applying pattern " + p1); |
| status = U_ZERO_ERROR; |
| pat.applyPattern(p1, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); |
| } |
| UnicodeString s2; |
| s2 = pat.toPattern(s2); |
| logln((UnicodeString)"Extracted pattern is " + s2); |
| if(s2 != p1) { |
| errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied"); |
| } |
| |
| if(pat.getSecondaryGroupingSize() != 0) { |
| errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize()); |
| } |
| |
| if(pat.getGroupingSize() != 3) { |
| errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); |
| } |
| |
| UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)"); |
| logln((UnicodeString)"Applying pattern " + p2); |
| status = U_ZERO_ERROR; |
| pat.applyLocalizedPattern(p2, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status); |
| } |
| UnicodeString s3; |
| s3 = pat.toLocalizedPattern(s3); |
| logln((UnicodeString)"Extracted pattern is " + s3); |
| if(s3 != p2) { |
| errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied"); |
| } |
| |
| status = U_ZERO_ERROR; |
| UParseError pe; |
| pat.applyLocalizedPattern(p2, pe, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status); |
| } |
| UnicodeString s4; |
| s4 = pat.toLocalizedPattern(s3); |
| logln((UnicodeString)"Extracted pattern is " + s4); |
| if(s4 != p2) { |
| errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied"); |
| } |
| |
| if(pat.getSecondaryGroupingSize() != 2) { |
| errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize()); |
| } |
| |
| if(pat.getGroupingSize() != 3) { |
| errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize()); |
| } |
| |
| // ======= Test getStaticClassID() |
| |
| logln((UnicodeString)"Testing getStaticClassID()"); |
| |
| status = U_ZERO_ERROR; |
| NumberFormat *test = new DecimalFormat(status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat"); |
| } |
| |
| if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { |
| errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value"); |
| } |
| |
| delete test; |
| } |
| |
| void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){ |
| UErrorCode status = U_ZERO_ERROR; |
| |
| CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created"); |
| } |
| |
| CurrencyPluralInfo cpi1 = *cpi; |
| |
| if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){ |
| errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value"); |
| } |
| |
| cpi->setCurrencyPluralPattern("","",status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern"); |
| } |
| |
| cpi->setLocale(Locale::getCanada(), status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale"); |
| } |
| |
| cpi->setPluralRules("",status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules"); |
| } |
| |
| DecimalFormat *df = new DecimalFormat(status); |
| if(U_FAILURE(status)) { |
| errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status)); |
| return; |
| } |
| |
| df->adoptCurrencyPluralInfo(cpi); |
| |
| df->getCurrencyPluralInfo(); |
| |
| df->setCurrencyPluralInfo(cpi1); |
| |
| delete df; |
| } |
| |
| void IntlTestDecimalFormatAPI::testRounding(/*char *par*/) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| double Roundingnumber = 2.55; |
| double Roundingnumber1 = -2.55; |
| //+2.55 results -2.55 results |
| double result[]={ 3.0, -2.0, // kRoundCeiling 0, |
| 2.0, -3.0, // kRoundFloor 1, |
| 2.0, -2.0, // kRoundDown 2, |
| 3.0, -3.0, // kRoundUp 3, |
| 3.0, -3.0, // kRoundHalfEven 4, |
| 3.0, -3.0, // kRoundHalfDown 5, |
| 3.0, -3.0 // kRoundHalfUp 6 |
| }; |
| DecimalFormat pat(status); |
| if(U_FAILURE(status)) { |
| errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
| return; |
| } |
| uint16_t mode; |
| uint16_t i=0; |
| UnicodeString message; |
| UnicodeString resultStr; |
| for(mode=0;mode < 7;mode++){ |
| pat.setRoundingMode((DecimalFormat::ERoundingMode)mode); |
| if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){ |
| errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode); |
| } |
| |
| |
| //for +2.55 with RoundingIncrement=1.0 |
| pat.setRoundingIncrement(1.0); |
| pat.format(Roundingnumber, resultStr); |
| message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); |
| verify(message, resultStr, result[i++]); |
| message.remove(); |
| resultStr.remove(); |
| |
| //for -2.55 with RoundingIncrement=1.0 |
| pat.format(Roundingnumber1, resultStr); |
| message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>"); |
| verify(message, resultStr, result[i++]); |
| message.remove(); |
| resultStr.remove(); |
| } |
| |
| } |
| void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){ |
| logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); |
| UnicodeString expectedStr(""); |
| expectedStr=expectedStr + expected; |
| if(got != expectedStr ) { |
| errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr); |
| } |
| } |
| |
| void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){ |
| logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected); |
| if(got != expected ) { |
| errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected); |
| } |
| } |
| |
| void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/) |
| { |
| UErrorCode status = U_ZERO_ERROR; |
| DecimalFormat pat(UnicodeString("#,##0.00"),status); |
| if(U_FAILURE(status)) { |
| errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
| return; |
| } |
| |
| // get default rounding increment |
| double roundingInc = pat.getRoundingIncrement(); |
| if (roundingInc != 0.0) { |
| errln((UnicodeString)"ERROR: Rounding increment not zero"); |
| return; |
| } |
| |
| // With rounding now being handled by decNumber, we no longer |
| // set a rounding increment to enable non-default mode rounding, |
| // checking of which was the original point of this test. |
| |
| // set rounding mode with zero increment. Rounding |
| // increment should not be set by this operation |
| pat.setRoundingMode((DecimalFormat::ERoundingMode)0); |
| roundingInc = pat.getRoundingIncrement(); |
| if (roundingInc != 0.0) { |
| errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode"); |
| return; |
| } |
| } |
| |
| void IntlTestDecimalFormatAPI::TestScale() |
| { |
| typedef struct TestData { |
| double inputValue; |
| int inputScale; |
| const char *expectedOutput; |
| } TestData; |
| |
| static TestData testData[] = { |
| { 100.0, 3, "100,000" }, |
| { 10034.0, -2, "100.34" }, |
| { 0.86, -3, "0.0009" }, |
| { -0.000455, 1, "-0%" }, |
| { -0.000555, 1, "-1%" }, |
| { 0.000455, 1, "0%" }, |
| { 0.000555, 1, "1%" }, |
| }; |
| |
| UErrorCode status = U_ZERO_ERROR; |
| DecimalFormat pat(status); |
| if(U_FAILURE(status)) { |
| errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status)); |
| return; |
| } |
| |
| UnicodeString message; |
| UnicodeString resultStr; |
| UnicodeString exp; |
| UnicodeString percentPattern("#,##0%"); |
| pat.setMaximumFractionDigits(4); |
| |
| for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) { |
| if ( i > 2 ) { |
| pat.applyPattern(percentPattern,status); |
| } |
| pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status); |
| pat.format(testData[i].inputValue, resultStr); |
| message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") + |
| testData[i].inputScale + UnicodeString(". Got: "); |
| exp = testData[i].expectedOutput; |
| verifyString(message, resultStr, exp); |
| message.remove(); |
| resultStr.remove(); |
| exp.remove(); |
| } |
| } |
| |
| |
| #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \ |
| assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); } |
| |
| void IntlTestDecimalFormatAPI::TestFixedDecimal() { |
| UErrorCode status = U_ZERO_ERROR; |
| |
| LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); |
| TEST_ASSERT_STATUS(status); |
| if (status == U_MISSING_RESOURCE_ERROR) { |
| return; |
| } |
| FixedDecimal fd = df->getFixedDecimal(44, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(44, fd.source); |
| ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(-44, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(44, fd.source); |
| ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(456, fd.decimalDigits); // f |
| ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(123, fd.intValue); // i |
| ASSERT_EQUAL(123.456, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(-123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(456, fd.decimalDigits); // f |
| ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(123, fd.intValue); // i |
| ASSERT_EQUAL(123.456, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| // test max int digits |
| df->setMaximumIntegerDigits(2); |
| fd = df->getFixedDecimal(123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(456, fd.decimalDigits); // f |
| ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(23, fd.intValue); // i |
| ASSERT_EQUAL(23.456, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(-123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(456, fd.decimalDigits); // f |
| ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(23, fd.intValue); // i |
| ASSERT_EQUAL(23.456, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| // test max fraction digits |
| df->setMaximumIntegerDigits(2000000000); |
| df->setMaximumFractionDigits(2); |
| fd = df->getFixedDecimal(123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(46, fd.decimalDigits); // f |
| ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(123, fd.intValue); // i |
| ASSERT_EQUAL(123.46, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(-123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(46, fd.decimalDigits); // f |
| ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(123, fd.intValue); // i |
| ASSERT_EQUAL(123.46, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| // test esoteric rounding |
| df->setMaximumFractionDigits(6); |
| df->setRoundingIncrement(7.3); |
| |
| fd = df->getFixedDecimal(30.0, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(20, fd.decimalDigits); // f |
| ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(29, fd.intValue); // i |
| ASSERT_EQUAL(29.2, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(-30.0, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v |
| ASSERT_EQUAL(20, fd.decimalDigits); // f |
| ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t |
| ASSERT_EQUAL(29, fd.intValue); // i |
| ASSERT_EQUAL(29.2, fd.source); // n |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(123.456, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(0, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(123, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(123.01, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(123, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(123.06, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(1, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(1, fd.decimalDigits); |
| ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(123, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(123, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(123, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(1.23, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(4, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(2300, fd.decimalDigits); |
| ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(1, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fd = df->getFixedDecimal(uprv_getInfinity(), status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); |
| fd = df->getFixedDecimal(0.0, status); |
| ASSERT_EQUAL(FALSE, fd.isNanOrInfinity); |
| fd = df->getFixedDecimal(uprv_getNaN(), status); |
| ASSERT_EQUAL(TRUE, fd.isNanOrInfinity); |
| TEST_ASSERT_STATUS(status); |
| |
| // Test Big Decimal input. |
| // 22 digits before and after decimal, will exceed the precision of a double |
| // and force DecimalFormat::getFixedDecimal() to work with a digit list. |
| df.adoptInsteadAndCheckErrorCode( |
| new DecimalFormat("#####################0.00####################", status), status); |
| TEST_ASSERT_STATUS(status); |
| Formattable fable("12.34", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(34, fd.decimalDigits); |
| ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(12, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fable.setDecimalNumber("12.345678901234567890123456789", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits); |
| ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(12, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| // On field overflow, Integer part is truncated on the left, fraction part on the right. |
| fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits); |
| ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(345678901234567890LL, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| // Digits way to the right of the decimal but within the format's precision aren't truncated |
| fable.setDecimalNumber("1.0000000000000000000012", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(12, fd.decimalDigits); |
| ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(1, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| // Digits beyond the precision of the format are rounded away |
| fable.setDecimalNumber("1.000000000000000000000012", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(1, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| // Negative numbers come through |
| fable.setDecimalNumber("-1.0000000000000000000012", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(22, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(12, fd.decimalDigits); |
| ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(1, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(TRUE, fd.isNegative); |
| |
| // MinFractionDigits from format larger than from number. |
| fable.setDecimalNumber("1000000000000000000000.3", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(30, fd.decimalDigits); |
| ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(100000000000000000LL, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fable.setDecimalNumber("1000000000000000050000.3", status); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(30, fd.decimalDigits); |
| ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(50000LL, fd.intValue); |
| ASSERT_EQUAL(FALSE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| // Test some int64_t values that are out of the range of a double |
| fable.setInt64(4503599627370496LL); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(4503599627370496LL, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fable.setInt64(4503599627370497LL); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| ASSERT_EQUAL(4503599627370497LL, fd.intValue); |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| fable.setInt64(9223372036854775807LL); |
| TEST_ASSERT_STATUS(status); |
| fd = df->getFixedDecimal(fable, status); |
| TEST_ASSERT_STATUS(status); |
| ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); |
| ASSERT_EQUAL(0, fd.decimalDigits); |
| ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros); |
| // note: going through DigitList path to FixedDecimal, which is trimming |
| // int64_t fields to 18 digits. See ticket Ticket #10374 |
| // ASSERT_EQUAL(223372036854775807LL, fd.intValue); |
| if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) { |
| dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue); |
| } |
| ASSERT_EQUAL(TRUE, fd.hasIntegerValue); |
| ASSERT_EQUAL(FALSE, fd.isNegative); |
| |
| } |
| |
| void IntlTestDecimalFormatAPI::TestBadFastpath() { |
| UErrorCode status = U_ZERO_ERROR; |
| |
| LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status); |
| if (U_FAILURE(status)) { |
| dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); |
| return; |
| } |
| |
| UnicodeString fmt; |
| fmt.remove(); |
| assertEquals("Format 1234", "1234", df->format(1234, fmt)); |
| df->setGroupingUsed(FALSE); |
| fmt.remove(); |
| assertEquals("Format 1234", "1234", df->format(1234, fmt)); |
| df->setGroupingUsed(TRUE); |
| df->setGroupingSize(3); |
| fmt.remove(); |
| assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt)); |
| } |
| |
| void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() { |
| UErrorCode status = U_ZERO_ERROR; |
| UnicodeString text("99"); |
| Formattable result1; |
| UnicodeString pat1("##.0000"); |
| UnicodeString pat2("00.0"); |
| |
| LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status); |
| if (U_FAILURE(status)) { |
| dataerrln("Error creating new DecimalFormat - %s", u_errorName(status)); |
| return; |
| } |
| |
| status = U_ZERO_ERROR; |
| df->applyPattern(pat1, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern() failed"); |
| } |
| df->parse(text, result1, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: parse() failed"); |
| } |
| df->setDecimalPatternMatchRequired(TRUE); |
| df->parse(text, result1, status); |
| if(U_SUCCESS(status)) { |
| errln((UnicodeString)"ERROR: unexpected parse()"); |
| } |
| |
| |
| status = U_ZERO_ERROR; |
| df->applyPattern(pat2, status); |
| df->setDecimalPatternMatchRequired(FALSE); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: applyPattern(2) failed"); |
| } |
| df->parse(text, result1, status); |
| if(U_FAILURE(status)) { |
| errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status)); |
| } |
| df->setDecimalPatternMatchRequired(TRUE); |
| df->parse(text, result1, status); |
| if(U_SUCCESS(status)) { |
| errln((UnicodeString)"ERROR: unexpected parse(2)"); |
| } |
| } |
| |
| #endif /* #if !UCONFIG_NO_FORMATTING */ |