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