• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 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 "number_decimalquantity.h"
26 
27 #include <stdio.h>
28 
29 // This is an API test, not a unit test.  It doesn't test very many cases, and doesn't
30 // try to test the full functionality.  It just calls each function in the class and
31 // verifies that it works on a basic level.
32 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)33 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
34 {
35     if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI");
36     switch (index) {
37         case 0: name = "DecimalFormat API test";
38                 if (exec) {
39                     logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)"");
40                     UErrorCode status = U_ZERO_ERROR;
41                     Locale saveLocale;
42                     Locale::setDefault(Locale::getEnglish(), status);
43                     if(U_FAILURE(status)) {
44                         errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results");
45                     }
46                     testAPI(/*par*/);
47                     Locale::setDefault(saveLocale, status);
48                 }
49                 break;
50         case 1: name = "Rounding test";
51             if(exec) {
52                logln((UnicodeString)"DecimalFormat Rounding test---");
53                testRounding(/*par*/);
54             }
55             break;
56         case 2: name = "Test6354";
57             if(exec) {
58                logln((UnicodeString)"DecimalFormat Rounding Increment test---");
59                testRoundingInc(/*par*/);
60             }
61             break;
62         case 3: name = "TestCurrencyPluralInfo";
63             if(exec) {
64                logln((UnicodeString)"CurrencyPluralInfo API test---");
65                TestCurrencyPluralInfo();
66             }
67             break;
68         case 4: name = "TestScale";
69             if(exec) {
70                logln((UnicodeString)"Scale test---");
71                TestScale();
72             }
73             break;
74          case 5: name = "TestFixedDecimal";
75             if(exec) {
76                logln((UnicodeString)"TestFixedDecimal ---");
77                TestFixedDecimal();
78             }
79             break;
80          case 6: name = "TestBadFastpath";
81             if(exec) {
82                logln((UnicodeString)"TestBadFastpath ---");
83                TestBadFastpath();
84             }
85             break;
86          case 7: name = "TestRequiredDecimalPoint";
87             if(exec) {
88                logln((UnicodeString)"TestRequiredDecimalPoint ---");
89                TestRequiredDecimalPoint();
90             }
91             break;
92          case 8: name = "testErrorCode";
93             if(exec) {
94                logln((UnicodeString)"testErrorCode ---");
95                testErrorCode();
96             }
97             break;
98        default: name = ""; break;
99     }
100 }
101 
102 /**
103  * This test checks various generic API methods in DecimalFormat to achieve 100%
104  * API coverage.
105  */
testAPI()106 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
107 {
108     UErrorCode status = U_ZERO_ERROR;
109 
110 // ======= Test constructors
111 
112     logln((UnicodeString)"Testing DecimalFormat constructors");
113 
114     DecimalFormat def(status);
115     if(U_FAILURE(status)) {
116         errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
117         return;
118     }
119 
120     // bug 10864
121     status = U_ZERO_ERROR;
122     DecimalFormat noGrouping("###0.##", status);
123     assertEquals("Grouping size should be 0 for no grouping.", 0, noGrouping.getGroupingSize());
124     noGrouping.setGroupingUsed(TRUE);
125     assertEquals("Grouping size should still be 0.", 0, noGrouping.getGroupingSize());
126     // end bug 10864
127 
128     // bug 13442 comment 14
129     status = U_ZERO_ERROR;
130     {
131         DecimalFormat df("0", {"en", status}, status);
132         UnicodeString result;
133         assertEquals("pat 0: ", 0, df.getGroupingSize());
134         assertEquals("pat 0: ", (UBool) FALSE, (UBool) df.isGroupingUsed());
135         df.setGroupingUsed(false);
136         assertEquals("pat 0 then disabled: ", 0, df.getGroupingSize());
137         assertEquals("pat 0 then disabled: ", u"1111", df.format(1111, result.remove()));
138         df.setGroupingUsed(true);
139         assertEquals("pat 0 then enabled: ", 0, df.getGroupingSize());
140         assertEquals("pat 0 then enabled: ", u"1111", df.format(1111, result.remove()));
141     }
142     {
143         DecimalFormat df("#,##0", {"en", status}, status);
144         UnicodeString result;
145         assertEquals("pat #,##0: ", 3, df.getGroupingSize());
146         assertEquals("pat #,##0: ", (UBool) TRUE, (UBool) df.isGroupingUsed());
147         df.setGroupingUsed(false);
148         assertEquals("pat #,##0 then disabled: ", 3, df.getGroupingSize());
149         assertEquals("pat #,##0 then disabled: ", u"1111", df.format(1111, result.remove()));
150         df.setGroupingUsed(true);
151         assertEquals("pat #,##0 then enabled: ", 3, df.getGroupingSize());
152         assertEquals("pat #,##0 then enabled: ", u"1,111", df.format(1111, result.remove()));
153     }
154     // end bug 13442 comment 14
155 
156     status = U_ZERO_ERROR;
157     const UnicodeString pattern("#,##0.# FF");
158     DecimalFormat pat(pattern, status);
159     if(U_FAILURE(status)) {
160         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)");
161         return;
162     }
163 
164     status = U_ZERO_ERROR;
165     DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status);
166     if(U_FAILURE(status)) {
167         errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)");
168         return;
169     }
170 
171     status = U_ZERO_ERROR;
172     DecimalFormat cust1(pattern, symbols, status);
173     if(U_FAILURE(status)) {
174         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
175     }
176 
177     status = U_ZERO_ERROR;
178     DecimalFormat cust2(pattern, *symbols, status);
179     if(U_FAILURE(status)) {
180         errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)");
181     }
182 
183     DecimalFormat copy(pat);
184 
185 // ======= Test clone(), assignment, and equality
186 
187     logln((UnicodeString)"Testing clone(), assignment and equality operators");
188 
189     if( ! (copy == pat) || copy != pat) {
190         errln((UnicodeString)"ERROR: Copy constructor or == failed");
191     }
192 
193     copy = cust1;
194     if(copy != cust1) {
195         errln((UnicodeString)"ERROR: Assignment (or !=) failed");
196     }
197 
198     Format *clone = def.clone();
199     if( ! (*clone == def) ) {
200         errln((UnicodeString)"ERROR: Clone() failed");
201     }
202     delete clone;
203 
204 // ======= Test various format() methods
205 
206     logln((UnicodeString)"Testing various format() methods");
207 
208     double d = -10456.0037;
209     int32_t l = 100000000;
210     Formattable fD(d);
211     Formattable fL(l);
212 
213     UnicodeString res1, res2, res3, res4;
214     FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE), pos3(FieldPosition::DONT_CARE), pos4(FieldPosition::DONT_CARE);
215 
216     res1 = def.format(d, res1, pos1);
217     logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1);
218 
219     res2 = pat.format(l, res2, pos2);
220     logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2);
221 
222     status = U_ZERO_ERROR;
223     res3 = cust1.format(fD, res3, pos3, status);
224     if(U_FAILURE(status)) {
225         errln((UnicodeString)"ERROR: format(Formattable [double]) failed");
226     }
227     logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3);
228 
229     status = U_ZERO_ERROR;
230     res4 = cust2.format(fL, res4, pos4, status);
231     if(U_FAILURE(status)) {
232         errln((UnicodeString)"ERROR: format(Formattable [long]) failed");
233     }
234     logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4);
235 
236 // ======= Test parse()
237 
238     logln((UnicodeString)"Testing parse()");
239 
240     UnicodeString text("-10,456.0037");
241     Formattable result1, result2;
242     ParsePosition pos(0);
243     UnicodeString patt("#,##0.#");
244     status = U_ZERO_ERROR;
245     pat.applyPattern(patt, status);
246     if(U_FAILURE(status)) {
247         errln((UnicodeString)"ERROR: applyPattern() failed");
248     }
249     pat.parse(text, result1, pos);
250     if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) {
251         errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
252     }
253     logln(text + " parsed into " + (int32_t) result1.getDouble());
254 
255     status = U_ZERO_ERROR;
256     pat.parse(text, result2, status);
257     if(U_FAILURE(status)) {
258         errln((UnicodeString)"ERROR: parse() failed");
259     }
260     if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) {
261         errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
262     }
263     logln(text + " parsed into " + (int32_t) result2.getDouble());
264 
265 // ======= Test getters and setters
266 
267     logln((UnicodeString)"Testing getters and setters");
268 
269     const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols();
270     DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms);
271     def.setDecimalFormatSymbols(*newSyms);
272     def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this
273     if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) {
274         errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed");
275     }
276 
277     UnicodeString posPrefix;
278     pat.setPositivePrefix("+");
279     posPrefix = pat.getPositivePrefix(posPrefix);
280     logln((UnicodeString)"Positive prefix (should be +): " + posPrefix);
281     if(posPrefix != "+") {
282         errln((UnicodeString)"ERROR: setPositivePrefix() failed");
283     }
284 
285     UnicodeString negPrefix;
286     pat.setNegativePrefix("-");
287     negPrefix = pat.getNegativePrefix(negPrefix);
288     logln((UnicodeString)"Negative prefix (should be -): " + negPrefix);
289     if(negPrefix != "-") {
290         errln((UnicodeString)"ERROR: setNegativePrefix() failed");
291     }
292 
293     UnicodeString posSuffix;
294     pat.setPositiveSuffix("_");
295     posSuffix = pat.getPositiveSuffix(posSuffix);
296     logln((UnicodeString)"Positive suffix (should be _): " + posSuffix);
297     if(posSuffix != "_") {
298         errln((UnicodeString)"ERROR: setPositiveSuffix() failed");
299     }
300 
301     UnicodeString negSuffix;
302     pat.setNegativeSuffix("~");
303     negSuffix = pat.getNegativeSuffix(negSuffix);
304     logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix);
305     if(negSuffix != "~") {
306         errln((UnicodeString)"ERROR: setNegativeSuffix() failed");
307     }
308 
309     int32_t multiplier = 0;
310     pat.setMultiplier(8);
311     multiplier = pat.getMultiplier();
312     logln((UnicodeString)"Multiplier (should be 8): " + multiplier);
313     if(multiplier != 8) {
314         errln((UnicodeString)"ERROR: setMultiplier() failed");
315     }
316 
317     int32_t groupingSize = 0;
318     pat.setGroupingSize(2);
319     groupingSize = pat.getGroupingSize();
320     logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize);
321     if(groupingSize != 2) {
322         errln((UnicodeString)"ERROR: setGroupingSize() failed");
323     }
324 
325     pat.setDecimalSeparatorAlwaysShown(TRUE);
326     UBool tf = pat.isDecimalSeparatorAlwaysShown();
327     logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE"));
328     if(tf != TRUE) {
329         errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed");
330     }
331     // Added by Ken Liu testing set/isExponentSignAlwaysShown
332     pat.setExponentSignAlwaysShown(TRUE);
333     UBool esas = pat.isExponentSignAlwaysShown();
334     logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE"));
335     if(esas != TRUE) {
336         errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed");
337     }
338 
339     // Added by Ken Liu testing set/isScientificNotation
340     pat.setScientificNotation(TRUE);
341     UBool sn = pat.isScientificNotation();
342     logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE"));
343     if(sn != TRUE) {
344         errln((UnicodeString)"ERROR: setScientificNotation() failed");
345     }
346 
347     // Added by Ken Liu testing set/getMinimumExponentDigits
348     int8_t MinimumExponentDigits = 0;
349     pat.setMinimumExponentDigits(2);
350     MinimumExponentDigits = pat.getMinimumExponentDigits();
351     logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits);
352     if(MinimumExponentDigits != 2) {
353         errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed");
354     }
355 
356     // Added by Ken Liu testing set/getRoundingIncrement
357     double RoundingIncrement = 0.0;
358     pat.setRoundingIncrement(2.0);
359     RoundingIncrement = pat.getRoundingIncrement();
360     logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement);
361     if(RoundingIncrement != 2.0) {
362         errln((UnicodeString)"ERROR: setRoundingIncrement() failed");
363     }
364     //end of Ken's Adding
365 
366     UnicodeString funkyPat;
367     funkyPat = pat.toPattern(funkyPat);
368     logln((UnicodeString)"Pattern is " + funkyPat);
369 
370     UnicodeString locPat;
371     locPat = pat.toLocalizedPattern(locPat);
372     logln((UnicodeString)"Localized pattern is " + locPat);
373 
374 // ======= Test applyPattern()
375 
376     logln((UnicodeString)"Testing applyPattern()");
377     pat = DecimalFormat(status); // reset
378 
379     UnicodeString p1("#,##0.0#;(#,##0.0#)");
380     logln((UnicodeString)"Applying pattern " + p1);
381     status = U_ZERO_ERROR;
382     pat.applyPattern(p1, status);
383     if(U_FAILURE(status)) {
384         errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
385     }
386     UnicodeString s2;
387     s2 = pat.toPattern(s2);
388     logln((UnicodeString)"Extracted pattern is " + s2);
389     assertEquals("toPattern() result did not match pattern applied", p1, s2);
390 
391     if(pat.getSecondaryGroupingSize() != 0) {
392         errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize());
393     }
394 
395     if(pat.getGroupingSize() != 3) {
396         errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
397     }
398 
399     UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
400     logln((UnicodeString)"Applying pattern " + p2);
401     status = U_ZERO_ERROR;
402     pat.applyLocalizedPattern(p2, status);
403     if(U_FAILURE(status)) {
404         errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
405     }
406     UnicodeString s3;
407     s3 = pat.toLocalizedPattern(s3);
408     logln((UnicodeString)"Extracted pattern is " + s3);
409     assertEquals("toLocalizedPattern() result did not match pattern applied", p2, s3);
410 
411     status = U_ZERO_ERROR;
412     UParseError pe;
413     pat.applyLocalizedPattern(p2, pe, status);
414     if(U_FAILURE(status)) {
415         errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status);
416     }
417     UnicodeString s4;
418     s4 = pat.toLocalizedPattern(s3);
419     logln((UnicodeString)"Extracted pattern is " + s4);
420     assertEquals("toLocalizedPattern(with ParseErr) result did not match pattern applied", p2, s4);
421 
422     if(pat.getSecondaryGroupingSize() != 2) {
423         errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize());
424     }
425 
426     if(pat.getGroupingSize() != 3) {
427         errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
428     }
429 
430 // ======= Test getStaticClassID()
431 
432     logln((UnicodeString)"Testing getStaticClassID()");
433 
434     status = U_ZERO_ERROR;
435     NumberFormat *test = new DecimalFormat(status);
436     if(U_FAILURE(status)) {
437         errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat");
438     }
439 
440     if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
441         errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value");
442     }
443 
444     delete test;
445 }
446 
TestCurrencyPluralInfo()447 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
448     UErrorCode status = U_ZERO_ERROR;
449 
450     CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status);
451     if(U_FAILURE(status)) {
452         errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
453     }
454 
455     CurrencyPluralInfo cpi1 = *cpi;
456 
457     if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
458         errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
459     }
460 
461     cpi->setCurrencyPluralPattern("","",status);
462     if(U_FAILURE(status)) {
463         errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
464     }
465 
466     cpi->setLocale(Locale::getCanada(), status);
467     if(U_FAILURE(status)) {
468         errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale");
469     }
470 
471     cpi->setPluralRules("",status);
472     if(U_FAILURE(status)) {
473         errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules");
474     }
475 
476     DecimalFormat *df = new DecimalFormat(status);
477     if(U_FAILURE(status)) {
478         errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status));
479         return;
480     }
481 
482     df->adoptCurrencyPluralInfo(cpi);
483 
484     df->getCurrencyPluralInfo();
485 
486     df->setCurrencyPluralInfo(cpi1);
487 
488     delete df;
489 }
490 
testRounding()491 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
492 {
493     UErrorCode status = U_ZERO_ERROR;
494     double Roundingnumber = 2.55;
495     double Roundingnumber1 = -2.55;
496                       //+2.55 results   -2.55 results
497     double result[]={   3.0,            -2.0,    //  kRoundCeiling  0,
498                         2.0,            -3.0,    //  kRoundFloor    1,
499                         2.0,            -2.0,    //  kRoundDown     2,
500                         3.0,            -3.0,    //  kRoundUp       3,
501                         3.0,            -3.0,    //  kRoundHalfEven 4,
502                         3.0,            -3.0,    //  kRoundHalfDown 5,
503                         3.0,            -3.0     //  kRoundHalfUp   6
504     };
505     DecimalFormat pat(status);
506     if(U_FAILURE(status)) {
507       errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
508       return;
509     }
510     uint16_t mode;
511     uint16_t i=0;
512     UnicodeString message;
513     UnicodeString resultStr;
514     for(mode=0;mode < 7;mode++){
515         pat.setRoundingMode((DecimalFormat::ERoundingMode)mode);
516         if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){
517             errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode);
518         }
519 
520 
521         //for +2.55 with RoundingIncrement=1.0
522         pat.setRoundingIncrement(1.0);
523         pat.format(Roundingnumber, resultStr);
524         message= (UnicodeString)"round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
525         verify(message, resultStr, result[i++]);
526         message.remove();
527         resultStr.remove();
528 
529         //for -2.55 with RoundingIncrement=1.0
530         pat.format(Roundingnumber1, resultStr);
531         message= (UnicodeString)"round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
532         verify(message, resultStr, result[i++]);
533         message.remove();
534         resultStr.remove();
535     }
536 
537 }
verify(const UnicodeString & message,const UnicodeString & got,double expected)538 void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){
539     logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
540     UnicodeString expectedStr("");
541     expectedStr=expectedStr + expected;
542     if(got != expectedStr ) {
543             errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)"  Expected : " + expectedStr);
544         }
545 }
546 
verifyString(const UnicodeString & message,const UnicodeString & got,UnicodeString & expected)547 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){
548     logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
549     if(got != expected ) {
550             errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)"  Expected : " + expected);
551         }
552 }
553 
testRoundingInc()554 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
555 {
556     UErrorCode status = U_ZERO_ERROR;
557     DecimalFormat pat(UnicodeString("#,##0.00"),status);
558     if(U_FAILURE(status)) {
559       errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
560       return;
561     }
562 
563     // get default rounding increment
564     double roundingInc = pat.getRoundingIncrement();
565     if (roundingInc != 0.0) {
566       errln((UnicodeString)"ERROR: Rounding increment not zero");
567       return;
568     }
569 
570     // With rounding now being handled by decNumber, we no longer
571     // set a rounding increment to enable non-default mode rounding,
572     // checking of which was the original point of this test.
573 
574     // set rounding mode with zero increment.  Rounding
575     // increment should not be set by this operation
576     pat.setRoundingMode((DecimalFormat::ERoundingMode)0);
577     roundingInc = pat.getRoundingIncrement();
578     if (roundingInc != 0.0) {
579       errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode");
580       return;
581     }
582 }
583 
TestScale()584 void IntlTestDecimalFormatAPI::TestScale()
585 {
586     typedef struct TestData {
587         double inputValue;
588         int inputScale;
589         const char *expectedOutput;
590     } TestData;
591 
592     static TestData testData[] = {
593         { 100.0, 3,  "100,000" },
594         { 10034.0, -2, "100.34" },
595         { 0.86, -3, "0.0009" },
596         { -0.000455, 1, "-0%" },
597         { -0.000555, 1, "-1%" },
598         { 0.000455, 1, "0%" },
599         { 0.000555, 1, "1%" },
600     };
601 
602     UErrorCode status = U_ZERO_ERROR;
603     DecimalFormat pat(status);
604     if(U_FAILURE(status)) {
605       errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
606       return;
607     }
608 
609     UnicodeString message;
610     UnicodeString resultStr;
611     UnicodeString exp;
612     UnicodeString percentPattern("#,##0%");
613     pat.setMaximumFractionDigits(4);
614 
615     for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) {
616         if ( i > 2 ) {
617             pat.applyPattern(percentPattern,status);
618         }
619         // Test both the attribute and the setter
620         if (i % 2 == 0) {
621             pat.setAttribute(UNUM_SCALE, testData[i].inputScale,status);
622             assertEquals("", testData[i].inputScale, pat.getMultiplierScale());
623         } else {
624             pat.setMultiplierScale(testData[i].inputScale);
625             assertEquals("", testData[i].inputScale, pat.getAttribute(UNUM_SCALE, status));
626         }
627         pat.format(testData[i].inputValue, resultStr);
628         message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") +
629                   testData[i].inputScale + UnicodeString(". Got: ");
630         exp = testData[i].expectedOutput;
631         verifyString(message, resultStr, exp);
632         message.remove();
633         resultStr.remove();
634         exp.remove();
635     }
636 }
637 
638 
639 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
640     assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
641 
TestFixedDecimal()642 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
643     UErrorCode status = U_ZERO_ERROR;
644 
645     LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
646     TEST_ASSERT_STATUS(status);
647     if (status == U_MISSING_RESOURCE_ERROR) {
648         return;
649     }
650     number::impl::DecimalQuantity fd;
651     df->formatToDecimalQuantity(44, fd, status);
652     TEST_ASSERT_STATUS(status);
653     ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N));
654     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
655     ASSERT_EQUAL(FALSE, fd.isNegative());
656 
657     df->formatToDecimalQuantity(-44, fd, status);
658     TEST_ASSERT_STATUS(status);
659     ASSERT_EQUAL(44, fd.getPluralOperand(PLURAL_OPERAND_N));
660     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
661     ASSERT_EQUAL(TRUE, fd.isNegative());
662 
663     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status);
664     TEST_ASSERT_STATUS(status);
665     df->formatToDecimalQuantity(123.456, fd, status);
666     TEST_ASSERT_STATUS(status);
667     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
668     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
669     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
670     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
671     ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
672     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
673     ASSERT_EQUAL(FALSE, fd.isNegative());
674 
675     df->formatToDecimalQuantity(-123.456, fd, status);
676     TEST_ASSERT_STATUS(status);
677     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
678     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
679     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
680     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
681     ASSERT_EQUAL(123.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
682     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
683     ASSERT_EQUAL(TRUE, fd.isNegative());
684 
685     // test max int digits
686     df->setMaximumIntegerDigits(2);
687     df->formatToDecimalQuantity(123.456, fd, status);
688     TEST_ASSERT_STATUS(status);
689     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
690     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
691     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
692     ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
693     ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
694     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
695     ASSERT_EQUAL(FALSE, fd.isNegative());
696 
697     df->formatToDecimalQuantity(-123.456, fd, status);
698     TEST_ASSERT_STATUS(status);
699     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
700     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
701     ASSERT_EQUAL(456, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
702     ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
703     ASSERT_EQUAL(23.456, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
704     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
705     ASSERT_EQUAL(TRUE, fd.isNegative());
706 
707     // test max fraction digits
708     df->setMaximumIntegerDigits(2000000000);
709     df->setMaximumFractionDigits(2);
710     df->formatToDecimalQuantity(123.456, fd, status);
711     TEST_ASSERT_STATUS(status);
712     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
713     ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
714     ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
715     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
716     ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
717     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
718     ASSERT_EQUAL(FALSE, fd.isNegative());
719 
720     df->formatToDecimalQuantity(-123.456, fd, status);
721     TEST_ASSERT_STATUS(status);
722     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
723     ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
724     ASSERT_EQUAL(46, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
725     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
726     ASSERT_EQUAL(123.46, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
727     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
728     ASSERT_EQUAL(TRUE, fd.isNegative());
729 
730     // test esoteric rounding
731     df->setMaximumFractionDigits(6);
732     df->setRoundingIncrement(7.3);
733 
734     df->formatToDecimalQuantity(30.0, fd, status);
735     TEST_ASSERT_STATUS(status);
736     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
737     ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
738     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
739     ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
740     ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
741     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
742     ASSERT_EQUAL(FALSE, fd.isNegative());
743 
744     df->formatToDecimalQuantity(-30.0, fd, status);
745     TEST_ASSERT_STATUS(status);
746     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V)); // v
747     ASSERT_EQUAL(20, fd.getPluralOperand(PLURAL_OPERAND_F)); // f
748     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_T)); // t
749     ASSERT_EQUAL(29, fd.getPluralOperand(PLURAL_OPERAND_I)); // i
750     ASSERT_EQUAL(29.2, fd.getPluralOperand(PLURAL_OPERAND_N)); // n
751     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
752     ASSERT_EQUAL(TRUE, fd.isNegative());
753 
754     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status);
755     TEST_ASSERT_STATUS(status);
756     df->formatToDecimalQuantity(123.456, fd, status);
757     TEST_ASSERT_STATUS(status);
758     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_V));
759     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
760     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
761     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
762     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
763     ASSERT_EQUAL(FALSE, fd.isNegative());
764 
765     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
766     TEST_ASSERT_STATUS(status);
767     df->formatToDecimalQuantity(123.01, fd, status);
768     TEST_ASSERT_STATUS(status);
769     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V));
770     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
771     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
772     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
773     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
774     ASSERT_EQUAL(FALSE, fd.isNegative());
775 
776     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
777     TEST_ASSERT_STATUS(status);
778     df->formatToDecimalQuantity(123.06, fd, status);
779     TEST_ASSERT_STATUS(status);
780     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_V));
781     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_F));
782     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_T));
783     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
784     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
785     ASSERT_EQUAL(FALSE, fd.isNegative());
786 
787     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status);  // Significant Digits
788     TEST_ASSERT_STATUS(status);
789     df->formatToDecimalQuantity(123, fd, status);
790     TEST_ASSERT_STATUS(status);
791     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
792     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
793     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
794     ASSERT_EQUAL(123, fd.getPluralOperand(PLURAL_OPERAND_I));
795     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
796     ASSERT_EQUAL(FALSE, fd.isNegative());
797 
798     df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status);  // Significant Digits
799     TEST_ASSERT_STATUS(status);
800     df->formatToDecimalQuantity(1.23, fd, status);
801     TEST_ASSERT_STATUS(status);
802     ASSERT_EQUAL(4, fd.getPluralOperand(PLURAL_OPERAND_V));
803     ASSERT_EQUAL(2300, fd.getPluralOperand(PLURAL_OPERAND_F));
804     ASSERT_EQUAL(23, fd.getPluralOperand(PLURAL_OPERAND_T));
805     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
806     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
807     ASSERT_EQUAL(FALSE, fd.isNegative());
808 
809     df->formatToDecimalQuantity(uprv_getInfinity(), fd, status);
810     TEST_ASSERT_STATUS(status);
811     ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite());
812     df->formatToDecimalQuantity(0.0, fd, status);
813     ASSERT_EQUAL(FALSE, fd.isNaN() || fd.isInfinite());
814     df->formatToDecimalQuantity(uprv_getNaN(), fd, status);
815     ASSERT_EQUAL(TRUE, fd.isNaN() || fd.isInfinite());
816     TEST_ASSERT_STATUS(status);
817 
818     // Test Big Decimal input.
819     // 22 digits before and after decimal, will exceed the precision of a double
820     //    and force DecimalFormat::getFixedDecimal() to work with a digit list.
821     df.adoptInsteadAndCheckErrorCode(
822         new DecimalFormat("#####################0.00####################", status), status);
823     TEST_ASSERT_STATUS(status);
824     Formattable fable("12.34", status);
825     TEST_ASSERT_STATUS(status);
826     df->formatToDecimalQuantity(fable, fd, status);
827     TEST_ASSERT_STATUS(status);
828     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
829     ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_F));
830     ASSERT_EQUAL(34, fd.getPluralOperand(PLURAL_OPERAND_T));
831     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I));
832     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
833     ASSERT_EQUAL(FALSE, fd.isNegative());
834 
835     fable.setDecimalNumber("12.3456789012345678900123456789", status);
836     TEST_ASSERT_STATUS(status);
837     df->formatToDecimalQuantity(fable, fd, status);
838     TEST_ASSERT_STATUS(status);
839     ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
840     ASSERT_EQUAL(3456789012345678900LL, fd.getPluralOperand(PLURAL_OPERAND_F));
841     ASSERT_EQUAL(34567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_T));
842     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_I));
843     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
844     ASSERT_EQUAL(FALSE, fd.isNegative());
845 
846     // On field overflow, Integer part is truncated on the left, fraction part on the right.
847     fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status);
848     TEST_ASSERT_STATUS(status);
849     df->formatToDecimalQuantity(fable, fd, status);
850     TEST_ASSERT_STATUS(status);
851     ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
852     ASSERT_EQUAL(1234567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_F));
853     ASSERT_EQUAL(1234567890123456789LL, fd.getPluralOperand(PLURAL_OPERAND_T));
854     ASSERT_EQUAL(345678901234567890LL, fd.getPluralOperand(PLURAL_OPERAND_I));
855     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
856     ASSERT_EQUAL(FALSE, fd.isNegative());
857 
858     // Digits way to the right of the decimal but within the format's precision aren't truncated
859     fable.setDecimalNumber("1.0000000000000000000012", status);
860     TEST_ASSERT_STATUS(status);
861     df->formatToDecimalQuantity(fable, fd, status);
862     TEST_ASSERT_STATUS(status);
863     ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
864     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F));
865     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T));
866     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
867     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
868     ASSERT_EQUAL(FALSE, fd.isNegative());
869 
870     // Digits beyond the precision of the format are rounded away
871     fable.setDecimalNumber("1.000000000000000000000012", status);
872     TEST_ASSERT_STATUS(status);
873     df->formatToDecimalQuantity(fable, fd, status);
874     TEST_ASSERT_STATUS(status);
875     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
876     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
877     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
878     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
879     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
880     ASSERT_EQUAL(FALSE, fd.isNegative());
881 
882     // Negative numbers come through
883     fable.setDecimalNumber("-1.0000000000000000000012", status);
884     TEST_ASSERT_STATUS(status);
885     df->formatToDecimalQuantity(fable, fd, status);
886     TEST_ASSERT_STATUS(status);
887     ASSERT_EQUAL(22, fd.getPluralOperand(PLURAL_OPERAND_V));
888     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_F));
889     ASSERT_EQUAL(12, fd.getPluralOperand(PLURAL_OPERAND_T));
890     ASSERT_EQUAL(1, fd.getPluralOperand(PLURAL_OPERAND_I));
891     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
892     ASSERT_EQUAL(TRUE, fd.isNegative());
893 
894     // MinFractionDigits from format larger than from number.
895     fable.setDecimalNumber("1000000000000000000000.3", status);
896     TEST_ASSERT_STATUS(status);
897     df->formatToDecimalQuantity(fable, fd, status);
898     TEST_ASSERT_STATUS(status);
899     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
900     ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F));
901     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T));
902     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_I));
903     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
904     ASSERT_EQUAL(FALSE, fd.isNegative());
905 
906     fable.setDecimalNumber("1000000000000000050000.3", status);
907     TEST_ASSERT_STATUS(status);
908     df->formatToDecimalQuantity(fable, fd, status);
909     TEST_ASSERT_STATUS(status);
910     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
911     ASSERT_EQUAL(30, fd.getPluralOperand(PLURAL_OPERAND_F));
912     ASSERT_EQUAL(3, fd.getPluralOperand(PLURAL_OPERAND_T));
913     ASSERT_EQUAL(50000LL, fd.getPluralOperand(PLURAL_OPERAND_I));
914     ASSERT_EQUAL(FALSE, fd.hasIntegerValue());
915     ASSERT_EQUAL(FALSE, fd.isNegative());
916 
917     // Test some int64_t values that are out of the range of a double
918     fable.setInt64(4503599627370496LL);
919     TEST_ASSERT_STATUS(status);
920     df->formatToDecimalQuantity(fable, fd, status);
921     TEST_ASSERT_STATUS(status);
922     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
923     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
924     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
925     ASSERT_EQUAL(4503599627370496LL, fd.getPluralOperand(PLURAL_OPERAND_I));
926     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
927     ASSERT_EQUAL(FALSE, fd.isNegative());
928 
929     fable.setInt64(4503599627370497LL);
930     TEST_ASSERT_STATUS(status);
931     df->formatToDecimalQuantity(fable, fd, status);
932     TEST_ASSERT_STATUS(status);
933     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
934     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
935     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
936     ASSERT_EQUAL(4503599627370497LL, fd.getPluralOperand(PLURAL_OPERAND_I));
937     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
938     ASSERT_EQUAL(FALSE, fd.isNegative());
939 
940     fable.setInt64(9223372036854775807LL);
941     TEST_ASSERT_STATUS(status);
942     df->formatToDecimalQuantity(fable, fd, status);
943     TEST_ASSERT_STATUS(status);
944     ASSERT_EQUAL(2, fd.getPluralOperand(PLURAL_OPERAND_V));
945     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_F));
946     ASSERT_EQUAL(0, fd.getPluralOperand(PLURAL_OPERAND_T));
947     // note: going through DigitList path to FixedDecimal, which is trimming
948     //       int64_t fields to 18 digits. See ticket Ticket #10374
949     // ASSERT_EQUAL(223372036854775807LL, fd.getPluralOperand(PLURAL_OPERAND_I);
950     if (!(
951             fd.getPluralOperand(PLURAL_OPERAND_I) == 223372036854775807LL ||
952             fd.getPluralOperand(PLURAL_OPERAND_I) == 9223372036854775807LL)) {
953         dataerrln(
954                 "File %s, Line %d, fd.getPluralOperand(PLURAL_OPERAND_I = %lld",
955                 __FILE__,
956                 __LINE__,
957                 fd.getPluralOperand(PLURAL_OPERAND_I));
958     }
959     ASSERT_EQUAL(TRUE, fd.hasIntegerValue());
960     ASSERT_EQUAL(FALSE, fd.isNegative());
961 
962 }
963 
TestBadFastpath()964 void IntlTestDecimalFormatAPI::TestBadFastpath() {
965     UErrorCode status = U_ZERO_ERROR;
966 
967     LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
968     if (U_FAILURE(status)) {
969         dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
970         return;
971     }
972 
973     UnicodeString fmt;
974     fmt.remove();
975     assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
976     df->setGroupingUsed(FALSE);
977     fmt.remove();
978     assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
979     df->setGroupingUsed(TRUE);
980     df->setGroupingSize(3);
981     fmt.remove();
982     assertEquals("Format 1234 w/ grouping", "1,234", df->format((int32_t)1234, fmt));
983 }
984 
TestRequiredDecimalPoint()985 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
986     UErrorCode status = U_ZERO_ERROR;
987     UnicodeString text("99");
988     Formattable result1;
989     UnicodeString pat1("##.0000");
990     UnicodeString pat2("00.0");
991 
992     LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status);
993     if (U_FAILURE(status)) {
994         dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
995         return;
996     }
997 
998     status = U_ZERO_ERROR;
999     df->applyPattern(pat1, status);
1000     if(U_FAILURE(status)) {
1001         errln((UnicodeString)"ERROR: applyPattern() failed");
1002     }
1003     df->parse(text, result1, status);
1004     if(U_FAILURE(status)) {
1005         errln((UnicodeString)"ERROR: parse() failed");
1006     }
1007     df->setDecimalPatternMatchRequired(TRUE);
1008     df->parse(text, result1, status);
1009     if(U_SUCCESS(status)) {
1010         errln((UnicodeString)"ERROR: unexpected parse()");
1011     }
1012 
1013 
1014     status = U_ZERO_ERROR;
1015     df->applyPattern(pat2, status);
1016     df->setDecimalPatternMatchRequired(FALSE);
1017     if(U_FAILURE(status)) {
1018         errln((UnicodeString)"ERROR: applyPattern(2) failed");
1019     }
1020     df->parse(text, result1, status);
1021     if(U_FAILURE(status)) {
1022         errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status));
1023     }
1024     df->setDecimalPatternMatchRequired(TRUE);
1025     df->parse(text, result1, status);
1026     if(U_SUCCESS(status)) {
1027         errln((UnicodeString)"ERROR: unexpected parse(2)");
1028     }
1029 }
1030 
1031 // WHERE Macro yields a literal string of the form "source_file_name:line number "
1032 #define WHERE __FILE__ ":" XLINE(__LINE__) " "
1033 #define XLINE(s) LINE(s)
1034 #define LINE(s) #s
1035 
testErrorCode()1036 void IntlTestDecimalFormatAPI::testErrorCode() {
1037     // Try each DecimalFormat constructor with an errorCode set on input,
1038     // Verify no crashes or leaks, and that the errorCode is not altered.
1039 
1040     UErrorCode status = U_ZERO_ERROR;
1041     const UnicodeString pattern(u"0.###E0");
1042     UParseError pe;
1043     DecimalFormatSymbols symbols(Locale::getUS(), status);
1044     assertSuccess(WHERE, status);
1045 
1046     {
1047         status = U_INTERNAL_PROGRAM_ERROR;
1048         DecimalFormat df(status);
1049         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1050     }
1051     {
1052         status = U_INTERNAL_PROGRAM_ERROR;
1053         DecimalFormat df(pattern, status);
1054         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1055     }
1056     {
1057         status = U_INTERNAL_PROGRAM_ERROR;
1058         DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), status);
1059         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1060     }
1061     {
1062         status = U_INTERNAL_PROGRAM_ERROR;
1063         DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), UNUM_DECIMAL_COMPACT_LONG, status);
1064         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1065     }
1066     {
1067         status = U_INTERNAL_PROGRAM_ERROR;
1068         DecimalFormat df(pattern, new DecimalFormatSymbols(symbols), pe, status);
1069         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1070     }
1071     {
1072         status = U_INTERNAL_PROGRAM_ERROR;
1073         DecimalFormat df(pattern, symbols ,status);
1074         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1075     }
1076 
1077     // Try each DecimalFormat method with an error code parameter, verifying that
1078     //  an input error is not altered.
1079 
1080     status = U_INTERNAL_PROGRAM_ERROR;
1081     DecimalFormat dfBogus(status);
1082     assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1083 
1084     status = U_ZERO_ERROR;
1085     DecimalFormat dfGood(pattern, new DecimalFormatSymbols(symbols), status);
1086     assertSuccess(WHERE, status);
1087 
1088     for (DecimalFormat *df: {&dfBogus, &dfGood}) {
1089         status = U_INTERNAL_PROGRAM_ERROR;
1090         df->setAttribute(UNUM_PARSE_INT_ONLY, 0, status);
1091         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1092 
1093         status = U_INTERNAL_PROGRAM_ERROR;
1094         df->getAttribute(UNUM_MAX_FRACTION_DIGITS, status);
1095         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1096 
1097         status = U_INTERNAL_PROGRAM_ERROR;
1098         UnicodeString dest;
1099         FieldPosition fp;
1100         df->format(1.2, dest, fp, status);
1101         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1102 
1103         status = U_INTERNAL_PROGRAM_ERROR;
1104         df->format(1.2, dest, nullptr, status);
1105         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1106 
1107         status = U_INTERNAL_PROGRAM_ERROR;
1108         df->format((int32_t)666, dest, nullptr, status);
1109         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1110 
1111         status = U_INTERNAL_PROGRAM_ERROR;
1112         df->format((int64_t)666, dest, nullptr, status);
1113         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1114 
1115         status = U_INTERNAL_PROGRAM_ERROR;
1116         df->format(StringPiece("3.1415926535897932384626"), dest, nullptr, status);
1117         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1118 
1119         status = U_INTERNAL_PROGRAM_ERROR;
1120         df->applyPattern(pattern, status);
1121         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1122 
1123         status = U_INTERNAL_PROGRAM_ERROR;
1124         df->applyLocalizedPattern(pattern, pe, status);
1125         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1126 
1127         status = U_INTERNAL_PROGRAM_ERROR;
1128         df->applyLocalizedPattern(pattern, status);
1129         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1130 
1131         status = U_INTERNAL_PROGRAM_ERROR;
1132         df->setCurrency(u"USD", status);
1133         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1134 
1135         status = U_INTERNAL_PROGRAM_ERROR;
1136         df->setCurrencyUsage(UCURR_USAGE_CASH, &status);
1137         assertEquals(WHERE, U_INTERNAL_PROGRAM_ERROR, status);
1138     }
1139 }
1140 
1141 #endif /* #if !UCONFIG_NO_FORMATTING */
1142