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