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