1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
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"
24 #include "plurrule_impl.h"
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.
31 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
33 if (exec
) logln((UnicodeString
)"TestSuite DecimalFormatAPI");
35 case 0: name
= "DecimalFormat API test";
37 logln((UnicodeString
)"DecimalFormat API test---"); logln((UnicodeString
)"");
38 UErrorCode status
= U_ZERO_ERROR
;
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");
45 Locale::setDefault(saveLocale
, status
);
48 case 1: name
= "Rounding test";
50 logln((UnicodeString
)"DecimalFormat Rounding test---");
51 testRounding(/*par*/);
54 case 2: name
= "Test6354";
56 logln((UnicodeString
)"DecimalFormat Rounding Increment test---");
57 testRoundingInc(/*par*/);
60 case 3: name
= "TestCurrencyPluralInfo";
62 logln((UnicodeString
)"CurrencyPluralInfo API test---");
63 TestCurrencyPluralInfo();
66 case 4: name
= "TestScale";
68 logln((UnicodeString
)"Scale test---");
72 case 5: name
= "TestFixedDecimal";
74 logln((UnicodeString
)"TestFixedDecimal ---");
78 case 6: name
= "TestBadFastpath";
80 logln((UnicodeString
)"TestBadFastpath ---");
84 case 7: name
= "TestRequiredDecimalPoint";
86 logln((UnicodeString
)"TestRequiredDecimalPoint ---");
87 TestRequiredDecimalPoint();
90 default: name
= ""; break;
95 * This test checks various generic API methods in DecimalFormat to achieve 100%
98 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
100 UErrorCode status
= U_ZERO_ERROR
;
102 // ======= Test constructors
104 logln((UnicodeString
)"Testing DecimalFormat constructors");
106 DecimalFormat
def(status
);
107 if(U_FAILURE(status
)) {
108 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
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.");
118 noGrouping
.setGroupingUsed(TRUE
);
119 if (noGrouping
.getGroupingSize() != 0) {
120 errln("Grouping size should still be 0.");
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)");
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)");
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*)");
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)");
151 DecimalFormat
copy(pat
);
153 // ======= Test clone(), assignment, and equality
155 logln((UnicodeString
)"Testing clone(), assignment and equality operators");
157 if( ! (copy
== pat
) || copy
!= pat
) {
158 errln((UnicodeString
)"ERROR: Copy constructor or == failed");
163 errln((UnicodeString
)"ERROR: Assignment (or !=) failed");
166 Format
*clone
= def
.clone();
167 if( ! (*clone
== def
) ) {
168 errln((UnicodeString
)"ERROR: Clone() failed");
172 // ======= Test various format() methods
174 logln((UnicodeString
)"Testing various format() methods");
176 double d
= -10456.0037;
177 int32_t l
= 100000000;
181 UnicodeString res1
, res2
, res3
, res4
;
182 FieldPosition
pos1(FieldPosition::DONT_CARE
), pos2(FieldPosition::DONT_CARE
), pos3(FieldPosition::DONT_CARE
), pos4(FieldPosition::DONT_CARE
);
184 res1
= def
.format(d
, res1
, pos1
);
185 logln( (UnicodeString
) "" + (int32_t) d
+ " formatted to " + res1
);
187 res2
= pat
.format(l
, res2
, pos2
);
188 logln((UnicodeString
) "" + (int32_t) l
+ " formatted to " + res2
);
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");
195 logln((UnicodeString
) "" + (int32_t) fD
.getDouble() + " formatted to " + res3
);
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");
202 logln((UnicodeString
) "" + fL
.getLong() + " formatted to " + res4
);
204 // ======= Test parse()
206 logln((UnicodeString
)"Testing parse()");
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");
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
);
221 logln(text
+ " parsed into " + (int32_t) result1
.getDouble());
223 status
= U_ZERO_ERROR
;
224 pat
.parse(text
, result2
, status
);
225 if(U_FAILURE(status
)) {
226 errln((UnicodeString
)"ERROR: parse() failed");
228 if(result2
.getType() != Formattable::kDouble
&& result2
.getDouble() != d
) {
229 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
231 logln(text
+ " parsed into " + (int32_t) result2
.getDouble());
233 // ======= Test getters and setters
235 logln((UnicodeString
)"Testing getters and setters");
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");
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");
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");
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");
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");
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");
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");
293 pat
.setDecimalSeparatorAlwaysShown(TRUE
);
294 UBool tf
= pat
.isDecimalSeparatorAlwaysShown();
295 logln((UnicodeString
)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString
) (tf
? "TRUE" : "FALSE"));
297 errln((UnicodeString
)"ERROR: setDecimalSeparatorAlwaysShown() failed");
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"));
304 errln((UnicodeString
)"ERROR: ExponentSignAlwaysShown() failed");
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"));
312 errln((UnicodeString
)"ERROR: setScientificNotation() failed");
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");
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");
332 //end of Ken's Adding
334 UnicodeString funkyPat
;
335 funkyPat
= pat
.toPattern(funkyPat
);
336 logln((UnicodeString
)"Pattern is " + funkyPat
);
338 UnicodeString locPat
;
339 locPat
= pat
.toLocalizedPattern(locPat
);
340 logln((UnicodeString
)"Localized pattern is " + locPat
);
342 // ======= Test applyPattern()
344 logln((UnicodeString
)"Testing applyPattern()");
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
);
354 s2
= pat
.toPattern(s2
);
355 logln((UnicodeString
)"Extracted pattern is " + s2
);
357 errln((UnicodeString
)"ERROR: toPattern() result did not match pattern applied");
360 if(pat
.getSecondaryGroupingSize() != 0) {
361 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat
.getSecondaryGroupingSize());
364 if(pat
.getGroupingSize() != 3) {
365 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
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
);
376 s3
= pat
.toLocalizedPattern(s3
);
377 logln((UnicodeString
)"Extracted pattern is " + s3
);
379 errln((UnicodeString
)"ERROR: toLocalizedPattern() result did not match pattern applied");
382 status
= U_ZERO_ERROR
;
384 pat
.applyLocalizedPattern(p2
, pe
, status
);
385 if(U_FAILURE(status
)) {
386 errln((UnicodeString
)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status
);
389 s4
= pat
.toLocalizedPattern(s3
);
390 logln((UnicodeString
)"Extracted pattern is " + s4
);
392 errln((UnicodeString
)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
395 if(pat
.getSecondaryGroupingSize() != 2) {
396 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat
.getSecondaryGroupingSize());
399 if(pat
.getGroupingSize() != 3) {
400 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
403 // ======= Test getStaticClassID()
405 logln((UnicodeString
)"Testing getStaticClassID()");
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");
413 if(test
->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
414 errln((UnicodeString
)"ERROR: getDynamicClassID() didn't return the expected value");
420 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
421 UErrorCode status
= U_ZERO_ERROR
;
423 CurrencyPluralInfo
*cpi
= new CurrencyPluralInfo(status
);
424 if(U_FAILURE(status
)) {
425 errln((UnicodeString
)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
428 CurrencyPluralInfo cpi1
= *cpi
;
430 if(cpi
->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
431 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
434 cpi
->setCurrencyPluralPattern("","",status
);
435 if(U_FAILURE(status
)) {
436 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
439 cpi
->setLocale(Locale::getCanada(), status
);
440 if(U_FAILURE(status
)) {
441 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setLocale");
444 cpi
->setPluralRules("",status
);
445 if(U_FAILURE(status
)) {
446 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setPluralRules");
449 DecimalFormat
*df
= new DecimalFormat(status
);
450 if(U_FAILURE(status
)) {
451 errcheckln(status
, "ERROR: Could not create DecimalFormat - %s", u_errorName(status
));
455 df
->adoptCurrencyPluralInfo(cpi
);
457 df
->getCurrencyPluralInfo();
459 df
->setCurrencyPluralInfo(cpi1
);
464 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
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
478 DecimalFormat
pat(status
);
479 if(U_FAILURE(status
)) {
480 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
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
);
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
++]);
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
++]);
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
);
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
);
527 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
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
));
536 // get default rounding increment
537 double roundingInc
= pat
.getRoundingIncrement();
538 if (roundingInc
!= 0.0) {
539 errln((UnicodeString
)"ERROR: Rounding increment not zero");
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.
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");
557 void IntlTestDecimalFormatAPI::TestScale()
559 typedef struct TestData
{
562 const char *expectedOutput
;
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%" },
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
));
582 UnicodeString message
;
583 UnicodeString resultStr
;
585 UnicodeString
percentPattern("#,##0%");
586 pat
.setMaximumFractionDigits(4);
588 for(int32_t i
=0; i
< UPRV_LENGTHOF(testData
); i
++) {
590 pat
.applyPattern(percentPattern
,status
);
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
);
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__); }
608 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
609 UErrorCode status
= U_ZERO_ERROR
;
611 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
612 TEST_ASSERT_STATUS(status
);
613 if (status
== U_MISSING_RESOURCE_ERROR
) {
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
695 // test esoteric rounding
696 df
->setMaximumFractionDigits(6);
697 df
->setRoundingIncrement(7.3);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
918 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
919 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
923 void IntlTestDecimalFormatAPI::TestBadFastpath() {
924 UErrorCode status
= U_ZERO_ERROR
;
926 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
927 if (U_FAILURE(status
)) {
928 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
934 assertEquals("Format 1234", "1234", df
->format((int32_t)1234, fmt
));
935 df
->setGroupingUsed(FALSE
);
937 assertEquals("Format 1234", "1234", df
->format((int32_t)1234, fmt
));
938 df
->setGroupingUsed(TRUE
);
939 df
->setGroupingSize(3);
941 assertEquals("Format 1234 w/ grouping", "1,234", df
->format((int32_t)1234, fmt
));
944 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
945 UErrorCode status
= U_ZERO_ERROR
;
946 UnicodeString
text("99");
948 UnicodeString
pat1("##.0000");
949 UnicodeString
pat2("00.0");
951 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pat1
, status
), status
);
952 if (U_FAILURE(status
)) {
953 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
957 status
= U_ZERO_ERROR
;
958 df
->applyPattern(pat1
, status
);
959 if(U_FAILURE(status
)) {
960 errln((UnicodeString
)"ERROR: applyPattern() failed");
962 df
->parse(text
, result1
, status
);
963 if(U_FAILURE(status
)) {
964 errln((UnicodeString
)"ERROR: parse() failed");
966 df
->setDecimalPatternMatchRequired(TRUE
);
967 df
->parse(text
, result1
, status
);
968 if(U_SUCCESS(status
)) {
969 errln((UnicodeString
)"ERROR: unexpected parse()");
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");
979 df
->parse(text
, result1
, status
);
980 if(U_FAILURE(status
)) {
981 errln((UnicodeString
)"ERROR: parse(2) failed - " + u_errorName(status
));
983 df
->setDecimalPatternMatchRequired(TRUE
);
984 df
->parse(text
, result1
, status
);
985 if(U_SUCCESS(status
)) {
986 errln((UnicodeString
)"ERROR: unexpected parse(2)");
990 #endif /* #if !UCONFIG_NO_FORMATTING */