1 /********************************************************************
3 * Copyright (c) 1997-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
13 #include "unicode/currpinf.h"
14 #include "unicode/dcfmtsym.h"
15 #include "unicode/decimfmt.h"
16 #include "unicode/fmtable.h"
17 #include "unicode/localpointer.h"
18 #include "unicode/parseerr.h"
19 #include "unicode/stringpiece.h"
22 #include "plurrule_impl.h"
25 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
26 // try to test the full functionality. It just calls each function in the class and
27 // verifies that it works on a basic level.
29 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
31 if (exec
) logln((UnicodeString
)"TestSuite DecimalFormatAPI");
33 case 0: name
= "DecimalFormat API test";
35 logln((UnicodeString
)"DecimalFormat API test---"); logln((UnicodeString
)"");
36 UErrorCode status
= U_ZERO_ERROR
;
38 Locale::setDefault(Locale::getEnglish(), status
);
39 if(U_FAILURE(status
)) {
40 errln((UnicodeString
)"ERROR: Could not set default locale, test may not give correct results");
43 Locale::setDefault(saveLocale
, status
);
46 case 1: name
= "Rounding test";
48 logln((UnicodeString
)"DecimalFormat Rounding test---");
49 testRounding(/*par*/);
52 case 2: name
= "Test6354";
54 logln((UnicodeString
)"DecimalFormat Rounding Increment test---");
55 testRoundingInc(/*par*/);
58 case 3: name
= "TestCurrencyPluralInfo";
60 logln((UnicodeString
)"CurrencyPluralInfo API test---");
61 TestCurrencyPluralInfo();
64 case 4: name
= "TestScale";
66 logln((UnicodeString
)"Scale test---");
70 case 5: name
= "TestFixedDecimal";
72 logln((UnicodeString
)"TestFixedDecimal ---");
76 case 6: name
= "TestBadFastpath";
78 logln((UnicodeString
)"TestBadFastpath ---");
82 case 7: name
= "TestRequiredDecimalPoint";
84 logln((UnicodeString
)"TestRequiredDecimalPoint ---");
85 TestRequiredDecimalPoint();
88 default: name
= ""; break;
93 * This test checks various generic API methods in DecimalFormat to achieve 100%
96 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
98 UErrorCode status
= U_ZERO_ERROR
;
100 // ======= Test constructors
102 logln((UnicodeString
)"Testing DecimalFormat constructors");
104 DecimalFormat
def(status
);
105 if(U_FAILURE(status
)) {
106 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
111 status
= U_ZERO_ERROR
;
112 DecimalFormat
noGrouping("###0.##", status
);
113 if (noGrouping
.getGroupingSize() != 0) {
114 errln("Grouping size should be 0 for no grouping.");
118 status
= U_ZERO_ERROR
;
119 const UnicodeString
pattern("#,##0.# FF");
120 DecimalFormat
pat(pattern
, status
);
121 if(U_FAILURE(status
)) {
122 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern)");
126 status
= U_ZERO_ERROR
;
127 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(Locale::getFrench(), status
);
128 if(U_FAILURE(status
)) {
129 errln((UnicodeString
)"ERROR: Could not create DecimalFormatSymbols (French)");
133 status
= U_ZERO_ERROR
;
134 DecimalFormat
cust1(pattern
, symbols
, status
);
135 if(U_FAILURE(status
)) {
136 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
139 status
= U_ZERO_ERROR
;
140 DecimalFormat
cust2(pattern
, *symbols
, status
);
141 if(U_FAILURE(status
)) {
142 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols)");
145 DecimalFormat
copy(pat
);
147 // ======= Test clone(), assignment, and equality
149 logln((UnicodeString
)"Testing clone(), assignment and equality operators");
151 if( ! (copy
== pat
) || copy
!= pat
) {
152 errln((UnicodeString
)"ERROR: Copy constructor or == failed");
157 errln((UnicodeString
)"ERROR: Assignment (or !=) failed");
160 Format
*clone
= def
.clone();
161 if( ! (*clone
== def
) ) {
162 errln((UnicodeString
)"ERROR: Clone() failed");
166 // ======= Test various format() methods
168 logln((UnicodeString
)"Testing various format() methods");
170 double d
= -10456.0037;
171 int32_t l
= 100000000;
175 UnicodeString res1
, res2
, res3
, res4
;
176 FieldPosition
pos1(0), pos2(0), pos3(0), pos4(0);
178 res1
= def
.format(d
, res1
, pos1
);
179 logln( (UnicodeString
) "" + (int32_t) d
+ " formatted to " + res1
);
181 res2
= pat
.format(l
, res2
, pos2
);
182 logln((UnicodeString
) "" + (int32_t) l
+ " formatted to " + res2
);
184 status
= U_ZERO_ERROR
;
185 res3
= cust1
.format(fD
, res3
, pos3
, status
);
186 if(U_FAILURE(status
)) {
187 errln((UnicodeString
)"ERROR: format(Formattable [double]) failed");
189 logln((UnicodeString
) "" + (int32_t) fD
.getDouble() + " formatted to " + res3
);
191 status
= U_ZERO_ERROR
;
192 res4
= cust2
.format(fL
, res4
, pos4
, status
);
193 if(U_FAILURE(status
)) {
194 errln((UnicodeString
)"ERROR: format(Formattable [long]) failed");
196 logln((UnicodeString
) "" + fL
.getLong() + " formatted to " + res4
);
198 // ======= Test parse()
200 logln((UnicodeString
)"Testing parse()");
202 UnicodeString
text("-10,456.0037");
203 Formattable result1
, result2
;
204 ParsePosition
pos(0);
205 UnicodeString
patt("#,##0.#");
206 status
= U_ZERO_ERROR
;
207 pat
.applyPattern(patt
, status
);
208 if(U_FAILURE(status
)) {
209 errln((UnicodeString
)"ERROR: applyPattern() failed");
211 pat
.parse(text
, result1
, pos
);
212 if(result1
.getType() != Formattable::kDouble
&& result1
.getDouble() != d
) {
213 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
215 logln(text
+ " parsed into " + (int32_t) result1
.getDouble());
217 status
= U_ZERO_ERROR
;
218 pat
.parse(text
, result2
, status
);
219 if(U_FAILURE(status
)) {
220 errln((UnicodeString
)"ERROR: parse() failed");
222 if(result2
.getType() != Formattable::kDouble
&& result2
.getDouble() != d
) {
223 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
225 logln(text
+ " parsed into " + (int32_t) result2
.getDouble());
227 // ======= Test getters and setters
229 logln((UnicodeString
)"Testing getters and setters");
231 const DecimalFormatSymbols
*syms
= pat
.getDecimalFormatSymbols();
232 DecimalFormatSymbols
*newSyms
= new DecimalFormatSymbols(*syms
);
233 def
.setDecimalFormatSymbols(*newSyms
);
234 def
.adoptDecimalFormatSymbols(newSyms
); // don't use newSyms after this
235 if( *(pat
.getDecimalFormatSymbols()) != *(def
.getDecimalFormatSymbols())) {
236 errln((UnicodeString
)"ERROR: adopt or set DecimalFormatSymbols() failed");
239 UnicodeString posPrefix
;
240 pat
.setPositivePrefix("+");
241 posPrefix
= pat
.getPositivePrefix(posPrefix
);
242 logln((UnicodeString
)"Positive prefix (should be +): " + posPrefix
);
243 if(posPrefix
!= "+") {
244 errln((UnicodeString
)"ERROR: setPositivePrefix() failed");
247 UnicodeString negPrefix
;
248 pat
.setNegativePrefix("-");
249 negPrefix
= pat
.getNegativePrefix(negPrefix
);
250 logln((UnicodeString
)"Negative prefix (should be -): " + negPrefix
);
251 if(negPrefix
!= "-") {
252 errln((UnicodeString
)"ERROR: setNegativePrefix() failed");
255 UnicodeString posSuffix
;
256 pat
.setPositiveSuffix("_");
257 posSuffix
= pat
.getPositiveSuffix(posSuffix
);
258 logln((UnicodeString
)"Positive suffix (should be _): " + posSuffix
);
259 if(posSuffix
!= "_") {
260 errln((UnicodeString
)"ERROR: setPositiveSuffix() failed");
263 UnicodeString negSuffix
;
264 pat
.setNegativeSuffix("~");
265 negSuffix
= pat
.getNegativeSuffix(negSuffix
);
266 logln((UnicodeString
)"Negative suffix (should be ~): " + negSuffix
);
267 if(negSuffix
!= "~") {
268 errln((UnicodeString
)"ERROR: setNegativeSuffix() failed");
271 int32_t multiplier
= 0;
272 pat
.setMultiplier(8);
273 multiplier
= pat
.getMultiplier();
274 logln((UnicodeString
)"Multiplier (should be 8): " + multiplier
);
275 if(multiplier
!= 8) {
276 errln((UnicodeString
)"ERROR: setMultiplier() failed");
279 int32_t groupingSize
= 0;
280 pat
.setGroupingSize(2);
281 groupingSize
= pat
.getGroupingSize();
282 logln((UnicodeString
)"Grouping size (should be 2): " + (int32_t) groupingSize
);
283 if(groupingSize
!= 2) {
284 errln((UnicodeString
)"ERROR: setGroupingSize() failed");
287 pat
.setDecimalSeparatorAlwaysShown(TRUE
);
288 UBool tf
= pat
.isDecimalSeparatorAlwaysShown();
289 logln((UnicodeString
)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString
) (tf
? "TRUE" : "FALSE"));
291 errln((UnicodeString
)"ERROR: setDecimalSeparatorAlwaysShown() failed");
293 // Added by Ken Liu testing set/isExponentSignAlwaysShown
294 pat
.setExponentSignAlwaysShown(TRUE
);
295 UBool esas
= pat
.isExponentSignAlwaysShown();
296 logln((UnicodeString
)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString
) (esas
? "TRUE" : "FALSE"));
298 errln((UnicodeString
)"ERROR: ExponentSignAlwaysShown() failed");
301 // Added by Ken Liu testing set/isScientificNotation
302 pat
.setScientificNotation(TRUE
);
303 UBool sn
= pat
.isScientificNotation();
304 logln((UnicodeString
)"isScientificNotation (should be TRUE) is " + (UnicodeString
) (sn
? "TRUE" : "FALSE"));
306 errln((UnicodeString
)"ERROR: setScientificNotation() failed");
309 // Added by Ken Liu testing set/getMinimumExponentDigits
310 int8_t MinimumExponentDigits
= 0;
311 pat
.setMinimumExponentDigits(2);
312 MinimumExponentDigits
= pat
.getMinimumExponentDigits();
313 logln((UnicodeString
)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits
);
314 if(MinimumExponentDigits
!= 2) {
315 errln((UnicodeString
)"ERROR: setMinimumExponentDigits() failed");
318 // Added by Ken Liu testing set/getRoundingIncrement
319 double RoundingIncrement
= 0.0;
320 pat
.setRoundingIncrement(2.0);
321 RoundingIncrement
= pat
.getRoundingIncrement();
322 logln((UnicodeString
)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement
);
323 if(RoundingIncrement
!= 2.0) {
324 errln((UnicodeString
)"ERROR: setRoundingIncrement() failed");
326 //end of Ken's Adding
328 UnicodeString funkyPat
;
329 funkyPat
= pat
.toPattern(funkyPat
);
330 logln((UnicodeString
)"Pattern is " + funkyPat
);
332 UnicodeString locPat
;
333 locPat
= pat
.toLocalizedPattern(locPat
);
334 logln((UnicodeString
)"Localized pattern is " + locPat
);
336 // ======= Test applyPattern()
338 logln((UnicodeString
)"Testing applyPattern()");
340 UnicodeString
p1("#,##0.0#;(#,##0.0#)");
341 logln((UnicodeString
)"Applying pattern " + p1
);
342 status
= U_ZERO_ERROR
;
343 pat
.applyPattern(p1
, status
);
344 if(U_FAILURE(status
)) {
345 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
348 s2
= pat
.toPattern(s2
);
349 logln((UnicodeString
)"Extracted pattern is " + s2
);
351 errln((UnicodeString
)"ERROR: toPattern() result did not match pattern applied");
354 if(pat
.getSecondaryGroupingSize() != 0) {
355 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat
.getSecondaryGroupingSize());
358 if(pat
.getGroupingSize() != 3) {
359 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
362 UnicodeString
p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
363 logln((UnicodeString
)"Applying pattern " + p2
);
364 status
= U_ZERO_ERROR
;
365 pat
.applyLocalizedPattern(p2
, status
);
366 if(U_FAILURE(status
)) {
367 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
370 s3
= pat
.toLocalizedPattern(s3
);
371 logln((UnicodeString
)"Extracted pattern is " + s3
);
373 errln((UnicodeString
)"ERROR: toLocalizedPattern() result did not match pattern applied");
376 status
= U_ZERO_ERROR
;
378 pat
.applyLocalizedPattern(p2
, pe
, status
);
379 if(U_FAILURE(status
)) {
380 errln((UnicodeString
)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status
);
383 s4
= pat
.toLocalizedPattern(s3
);
384 logln((UnicodeString
)"Extracted pattern is " + s4
);
386 errln((UnicodeString
)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
389 if(pat
.getSecondaryGroupingSize() != 2) {
390 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat
.getSecondaryGroupingSize());
393 if(pat
.getGroupingSize() != 3) {
394 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
397 // ======= Test getStaticClassID()
399 logln((UnicodeString
)"Testing getStaticClassID()");
401 status
= U_ZERO_ERROR
;
402 NumberFormat
*test
= new DecimalFormat(status
);
403 if(U_FAILURE(status
)) {
404 errln((UnicodeString
)"ERROR: Couldn't create a DecimalFormat");
407 if(test
->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
408 errln((UnicodeString
)"ERROR: getDynamicClassID() didn't return the expected value");
414 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
415 UErrorCode status
= U_ZERO_ERROR
;
417 CurrencyPluralInfo
*cpi
= new CurrencyPluralInfo(status
);
418 if(U_FAILURE(status
)) {
419 errln((UnicodeString
)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
422 CurrencyPluralInfo cpi1
= *cpi
;
424 if(cpi
->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
425 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
428 cpi
->setCurrencyPluralPattern("","",status
);
429 if(U_FAILURE(status
)) {
430 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
433 cpi
->setLocale(Locale::getCanada(), status
);
434 if(U_FAILURE(status
)) {
435 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setLocale");
438 cpi
->setPluralRules("",status
);
439 if(U_FAILURE(status
)) {
440 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setPluralRules");
443 DecimalFormat
*df
= new DecimalFormat(status
);
444 if(U_FAILURE(status
)) {
445 errcheckln(status
, "ERROR: Could not create DecimalFormat - %s", u_errorName(status
));
448 df
->adoptCurrencyPluralInfo(cpi
);
450 df
->getCurrencyPluralInfo();
452 df
->setCurrencyPluralInfo(cpi1
);
457 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
459 UErrorCode status
= U_ZERO_ERROR
;
460 double Roundingnumber
= 2.55;
461 double Roundingnumber1
= -2.55;
462 //+2.55 results -2.55 results
463 double result
[]={ 3.0, -2.0, // kRoundCeiling 0,
464 2.0, -3.0, // kRoundFloor 1,
465 2.0, -2.0, // kRoundDown 2,
466 3.0, -3.0, // kRoundUp 3,
467 3.0, -3.0, // kRoundHalfEven 4,
468 3.0, -3.0, // kRoundHalfDown 5,
469 3.0, -3.0 // kRoundHalfUp 6
471 DecimalFormat
pat(status
);
472 if(U_FAILURE(status
)) {
473 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
478 UnicodeString message
;
479 UnicodeString resultStr
;
480 for(mode
=0;mode
< 7;mode
++){
481 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
482 if(pat
.getRoundingMode() != (DecimalFormat::ERoundingMode
)mode
){
483 errln((UnicodeString
)"SetRoundingMode or GetRoundingMode failed for mode=" + mode
);
487 //for +2.55 with RoundingIncrement=1.0
488 pat
.setRoundingIncrement(1.0);
489 pat
.format(Roundingnumber
, resultStr
);
490 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
491 verify(message
, resultStr
, result
[i
++]);
495 //for -2.55 with RoundingIncrement=1.0
496 pat
.format(Roundingnumber1
, resultStr
);
497 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber1
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
498 verify(message
, resultStr
, result
[i
++]);
504 void IntlTestDecimalFormatAPI::verify(const UnicodeString
& message
, const UnicodeString
& got
, double expected
){
505 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
506 UnicodeString
expectedStr("");
507 expectedStr
=expectedStr
+ expected
;
508 if(got
!= expectedStr
) {
509 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expectedStr
);
513 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString
& message
, const UnicodeString
& got
, UnicodeString
& expected
){
514 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
515 if(got
!= expected
) {
516 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expected
);
520 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
522 UErrorCode status
= U_ZERO_ERROR
;
523 DecimalFormat
pat(UnicodeString("#,##0.00"),status
);
524 if(U_FAILURE(status
)) {
525 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
529 // get default rounding increment
530 double roundingInc
= pat
.getRoundingIncrement();
531 if (roundingInc
!= 0.0) {
532 errln((UnicodeString
)"ERROR: Rounding increment not zero");
536 // With rounding now being handled by decNumber, we no longer
537 // set a rounding increment to enable non-default mode rounding,
538 // checking of which was the original point of this test.
540 // set rounding mode with zero increment. Rounding
541 // increment should not be set by this operation
542 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)0);
543 roundingInc
= pat
.getRoundingIncrement();
544 if (roundingInc
!= 0.0) {
545 errln((UnicodeString
)"ERROR: Rounding increment not zero after setRoundingMode");
550 void IntlTestDecimalFormatAPI::TestScale()
552 typedef struct TestData
{
555 const char *expectedOutput
;
558 static TestData testData
[] = {
559 { 100.0, 3, "100,000" },
560 { 10034.0, -2, "100.34" },
561 { 0.86, -3, "0.0009" },
562 { -0.000455, 1, "-0%" },
563 { -0.000555, 1, "-1%" },
564 { 0.000455, 1, "0%" },
565 { 0.000555, 1, "1%" },
568 UErrorCode status
= U_ZERO_ERROR
;
569 DecimalFormat
pat(status
);
570 if(U_FAILURE(status
)) {
571 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
575 UnicodeString message
;
576 UnicodeString resultStr
;
578 UnicodeString
percentPattern("#,##0%");
579 pat
.setMaximumFractionDigits(4);
581 for(int32_t i
=0; i
< UPRV_LENGTHOF(testData
); i
++) {
583 pat
.applyPattern(percentPattern
,status
);
585 pat
.setAttribute(UNUM_SCALE
,testData
[i
].inputScale
,status
);
586 pat
.format(testData
[i
].inputValue
, resultStr
);
587 message
= UnicodeString("Unexpected output for ") + testData
[i
].inputValue
+ UnicodeString(" and scale ") +
588 testData
[i
].inputScale
+ UnicodeString(". Got: ");
589 exp
= testData
[i
].expectedOutput
;
590 verifyString(message
, resultStr
, exp
);
598 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
599 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
601 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
602 UErrorCode status
= U_ZERO_ERROR
;
604 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
605 TEST_ASSERT_STATUS(status
);
606 FixedDecimal fd
= df
->getFixedDecimal(44, status
);
607 TEST_ASSERT_STATUS(status
);
608 ASSERT_EQUAL(44, fd
.source
);
609 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
611 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status
), status
);
612 TEST_ASSERT_STATUS(status
);
613 fd
= df
->getFixedDecimal(123.456, status
);
614 TEST_ASSERT_STATUS(status
);
615 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
);
616 ASSERT_EQUAL(456, fd
.decimalDigits
);
617 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
);
618 ASSERT_EQUAL(123, fd
.intValue
);
619 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
620 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
622 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status
), status
);
623 TEST_ASSERT_STATUS(status
);
624 fd
= df
->getFixedDecimal(123.456, status
);
625 TEST_ASSERT_STATUS(status
);
626 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
627 ASSERT_EQUAL(0, fd
.decimalDigits
);
628 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
629 ASSERT_EQUAL(123, fd
.intValue
);
630 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
631 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
633 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
634 TEST_ASSERT_STATUS(status
);
635 fd
= df
->getFixedDecimal(123.01, status
);
636 TEST_ASSERT_STATUS(status
);
637 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
638 ASSERT_EQUAL(0, fd
.decimalDigits
);
639 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
640 ASSERT_EQUAL(123, fd
.intValue
);
641 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
642 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
644 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
645 TEST_ASSERT_STATUS(status
);
646 fd
= df
->getFixedDecimal(123.06, status
);
647 TEST_ASSERT_STATUS(status
);
648 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
649 ASSERT_EQUAL(1, fd
.decimalDigits
);
650 ASSERT_EQUAL(1, fd
.decimalDigitsWithoutTrailingZeros
);
651 ASSERT_EQUAL(123, fd
.intValue
);
652 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
653 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
655 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
656 TEST_ASSERT_STATUS(status
);
657 fd
= df
->getFixedDecimal(123, status
);
658 TEST_ASSERT_STATUS(status
);
659 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
660 ASSERT_EQUAL(0, fd
.decimalDigits
);
661 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
662 ASSERT_EQUAL(123, fd
.intValue
);
663 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
664 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
666 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
667 TEST_ASSERT_STATUS(status
);
668 fd
= df
->getFixedDecimal(1.23, status
);
669 TEST_ASSERT_STATUS(status
);
670 ASSERT_EQUAL(4, fd
.visibleDecimalDigitCount
);
671 ASSERT_EQUAL(2300, fd
.decimalDigits
);
672 ASSERT_EQUAL(23, fd
.decimalDigitsWithoutTrailingZeros
);
673 ASSERT_EQUAL(1, fd
.intValue
);
674 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
675 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
677 fd
= df
->getFixedDecimal(uprv_getInfinity(), status
);
678 TEST_ASSERT_STATUS(status
);
679 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
680 fd
= df
->getFixedDecimal(0.0, status
);
681 ASSERT_EQUAL(FALSE
, fd
.isNanOrInfinity
);
682 fd
= df
->getFixedDecimal(uprv_getNaN(), status
);
683 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
684 TEST_ASSERT_STATUS(status
);
686 // Test Big Decimal input.
687 // 22 digits before and after decimal, will exceed the precision of a double
688 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
689 df
.adoptInsteadAndCheckErrorCode(
690 new DecimalFormat("#####################0.00####################", status
), status
);
691 TEST_ASSERT_STATUS(status
);
692 Formattable
fable("12.34", status
);
693 TEST_ASSERT_STATUS(status
);
694 fd
= df
->getFixedDecimal(fable
, status
);
695 TEST_ASSERT_STATUS(status
);
696 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
697 ASSERT_EQUAL(34, fd
.decimalDigits
);
698 ASSERT_EQUAL(34, fd
.decimalDigitsWithoutTrailingZeros
);
699 ASSERT_EQUAL(12, fd
.intValue
);
700 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
701 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
703 fable
.setDecimalNumber("12.345678901234567890123456789", status
);
704 TEST_ASSERT_STATUS(status
);
705 fd
= df
->getFixedDecimal(fable
, status
);
706 TEST_ASSERT_STATUS(status
);
707 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
708 ASSERT_EQUAL(345678901234567890LL, fd
.decimalDigits
);
709 ASSERT_EQUAL(34567890123456789LL, fd
.decimalDigitsWithoutTrailingZeros
);
710 ASSERT_EQUAL(12, fd
.intValue
);
711 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
712 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
714 // On field overflow, Integer part is truncated on the left, fraction part on the right.
715 fable
.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status
);
716 TEST_ASSERT_STATUS(status
);
717 fd
= df
->getFixedDecimal(fable
, status
);
718 TEST_ASSERT_STATUS(status
);
719 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
720 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigits
);
721 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigitsWithoutTrailingZeros
);
722 ASSERT_EQUAL(345678901234567890LL, fd
.intValue
);
723 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
724 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
726 // Digits way to the right of the decimal but within the format's precision aren't truncated
727 fable
.setDecimalNumber("1.0000000000000000000012", status
);
728 TEST_ASSERT_STATUS(status
);
729 fd
= df
->getFixedDecimal(fable
, status
);
730 TEST_ASSERT_STATUS(status
);
731 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
732 ASSERT_EQUAL(12, fd
.decimalDigits
);
733 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
734 ASSERT_EQUAL(1, fd
.intValue
);
735 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
736 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
738 // Digits beyond the precision of the format are rounded away
739 fable
.setDecimalNumber("1.000000000000000000000012", status
);
740 TEST_ASSERT_STATUS(status
);
741 fd
= df
->getFixedDecimal(fable
, status
);
742 TEST_ASSERT_STATUS(status
);
743 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
744 ASSERT_EQUAL(0, fd
.decimalDigits
);
745 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
746 ASSERT_EQUAL(1, fd
.intValue
);
747 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
748 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
750 // Negative numbers come through
751 fable
.setDecimalNumber("-1.0000000000000000000012", status
);
752 TEST_ASSERT_STATUS(status
);
753 fd
= df
->getFixedDecimal(fable
, status
);
754 TEST_ASSERT_STATUS(status
);
755 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
756 ASSERT_EQUAL(12, fd
.decimalDigits
);
757 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
758 ASSERT_EQUAL(1, fd
.intValue
);
759 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
760 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
762 // MinFractionDigits from format larger than from number.
763 fable
.setDecimalNumber("1000000000000000000000.3", status
);
764 TEST_ASSERT_STATUS(status
);
765 fd
= df
->getFixedDecimal(fable
, status
);
766 TEST_ASSERT_STATUS(status
);
767 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
768 ASSERT_EQUAL(30, fd
.decimalDigits
);
769 ASSERT_EQUAL(3, fd
.decimalDigitsWithoutTrailingZeros
);
770 ASSERT_EQUAL(100000000000000000LL, fd
.intValue
);
771 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
772 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
774 // Test some int64_t values that are out of the range of a double
775 fable
.setInt64(4503599627370496LL);
776 TEST_ASSERT_STATUS(status
);
777 fd
= df
->getFixedDecimal(fable
, status
);
778 TEST_ASSERT_STATUS(status
);
779 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
780 ASSERT_EQUAL(0, fd
.decimalDigits
);
781 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
782 ASSERT_EQUAL(4503599627370496LL, fd
.intValue
);
783 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
784 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
786 fable
.setInt64(4503599627370497LL);
787 TEST_ASSERT_STATUS(status
);
788 fd
= df
->getFixedDecimal(fable
, status
);
789 TEST_ASSERT_STATUS(status
);
790 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
791 ASSERT_EQUAL(0, fd
.decimalDigits
);
792 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
793 ASSERT_EQUAL(4503599627370497LL, fd
.intValue
);
794 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
795 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
797 fable
.setInt64(9223372036854775807LL);
798 TEST_ASSERT_STATUS(status
);
799 fd
= df
->getFixedDecimal(fable
, status
);
800 TEST_ASSERT_STATUS(status
);
801 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
802 ASSERT_EQUAL(0, fd
.decimalDigits
);
803 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
804 // note: going through DigitList path to FixedDecimal, which is trimming
805 // int64_t fields to 18 digits. See ticket Ticket #10374
806 // ASSERT_EQUAL(223372036854775807LL, fd.intValue);
807 if (!(fd
.intValue
== 223372036854775807LL || fd
.intValue
== 9223372036854775807LL)) {
808 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__
, __LINE__
, fd
.intValue
);
810 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
811 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
815 void IntlTestDecimalFormatAPI::TestBadFastpath() {
816 UErrorCode status
= U_ZERO_ERROR
;
818 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
819 if (U_FAILURE(status
)) {
820 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
826 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
827 df
->setGroupingUsed(FALSE
);
829 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
830 df
->setGroupingUsed(TRUE
);
832 assertEquals("Format 1234 w/ grouping", "1,234", df
->format(1234, fmt
));
835 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
836 UErrorCode status
= U_ZERO_ERROR
;
837 UnicodeString
text("99");
839 UnicodeString
pat1("##.0000");
840 UnicodeString
pat2("00.0");
842 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pat1
, status
), status
);
843 if (U_FAILURE(status
)) {
844 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
848 status
= U_ZERO_ERROR
;
849 df
->applyPattern(pat1
, status
);
850 if(U_FAILURE(status
)) {
851 errln((UnicodeString
)"ERROR: applyPattern() failed");
853 df
->parse(text
, result1
, status
);
854 if(U_FAILURE(status
)) {
855 errln((UnicodeString
)"ERROR: parse() failed");
857 df
->setDecimalPatternMatchRequired(TRUE
);
858 df
->parse(text
, result1
, status
);
859 if(U_SUCCESS(status
)) {
860 errln((UnicodeString
)"ERROR: unexpected parse()");
864 status
= U_ZERO_ERROR
;
865 df
->applyPattern(pat2
, status
);
866 df
->setDecimalPatternMatchRequired(FALSE
);
867 if(U_FAILURE(status
)) {
868 errln((UnicodeString
)"ERROR: applyPattern(2) failed");
870 df
->parse(text
, result1
, status
);
871 if(U_FAILURE(status
)) {
872 errln((UnicodeString
)"ERROR: parse(2) failed - " + u_errorName(status
));
874 df
->setDecimalPatternMatchRequired(TRUE
);
875 df
->parse(text
, result1
, status
);
876 if(U_SUCCESS(status
)) {
877 errln((UnicodeString
)"ERROR: unexpected parse(2)");
881 #endif /* #if !UCONFIG_NO_FORMATTING */