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 #define LENGTHOF(array) ((int32_t)(sizeof(array)/sizeof((array)[0])))
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 default: name
= ""; break;
89 * This test checks various generic API methods in DecimalFormat to achieve 100%
92 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
94 UErrorCode status
= U_ZERO_ERROR
;
96 // ======= Test constructors
98 logln((UnicodeString
)"Testing DecimalFormat constructors");
100 DecimalFormat
def(status
);
101 if(U_FAILURE(status
)) {
102 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
106 status
= U_ZERO_ERROR
;
107 const UnicodeString
pattern("#,##0.# FF");
108 DecimalFormat
pat(pattern
, status
);
109 if(U_FAILURE(status
)) {
110 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern)");
114 status
= U_ZERO_ERROR
;
115 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(Locale::getFrench(), status
);
116 if(U_FAILURE(status
)) {
117 errln((UnicodeString
)"ERROR: Could not create DecimalFormatSymbols (French)");
121 status
= U_ZERO_ERROR
;
122 DecimalFormat
cust1(pattern
, symbols
, status
);
123 if(U_FAILURE(status
)) {
124 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
127 status
= U_ZERO_ERROR
;
128 DecimalFormat
cust2(pattern
, *symbols
, status
);
129 if(U_FAILURE(status
)) {
130 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols)");
133 DecimalFormat
copy(pat
);
135 // ======= Test clone(), assignment, and equality
137 logln((UnicodeString
)"Testing clone(), assignment and equality operators");
139 if( ! (copy
== pat
) || copy
!= pat
) {
140 errln((UnicodeString
)"ERROR: Copy constructor or == failed");
145 errln((UnicodeString
)"ERROR: Assignment (or !=) failed");
148 Format
*clone
= def
.clone();
149 if( ! (*clone
== def
) ) {
150 errln((UnicodeString
)"ERROR: Clone() failed");
154 // ======= Test various format() methods
156 logln((UnicodeString
)"Testing various format() methods");
158 double d
= -10456.0037;
159 int32_t l
= 100000000;
163 UnicodeString res1
, res2
, res3
, res4
;
164 FieldPosition
pos1(0), pos2(0), pos3(0), pos4(0);
166 res1
= def
.format(d
, res1
, pos1
);
167 logln( (UnicodeString
) "" + (int32_t) d
+ " formatted to " + res1
);
169 res2
= pat
.format(l
, res2
, pos2
);
170 logln((UnicodeString
) "" + (int32_t) l
+ " formatted to " + res2
);
172 status
= U_ZERO_ERROR
;
173 res3
= cust1
.format(fD
, res3
, pos3
, status
);
174 if(U_FAILURE(status
)) {
175 errln((UnicodeString
)"ERROR: format(Formattable [double]) failed");
177 logln((UnicodeString
) "" + (int32_t) fD
.getDouble() + " formatted to " + res3
);
179 status
= U_ZERO_ERROR
;
180 res4
= cust2
.format(fL
, res4
, pos4
, status
);
181 if(U_FAILURE(status
)) {
182 errln((UnicodeString
)"ERROR: format(Formattable [long]) failed");
184 logln((UnicodeString
) "" + fL
.getLong() + " formatted to " + res4
);
186 // ======= Test parse()
188 logln((UnicodeString
)"Testing parse()");
190 UnicodeString
text("-10,456.0037");
191 Formattable result1
, result2
;
192 ParsePosition
pos(0);
193 UnicodeString
patt("#,##0.#");
194 status
= U_ZERO_ERROR
;
195 pat
.applyPattern(patt
, status
);
196 if(U_FAILURE(status
)) {
197 errln((UnicodeString
)"ERROR: applyPattern() failed");
199 pat
.parse(text
, result1
, pos
);
200 if(result1
.getType() != Formattable::kDouble
&& result1
.getDouble() != d
) {
201 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
203 logln(text
+ " parsed into " + (int32_t) result1
.getDouble());
205 status
= U_ZERO_ERROR
;
206 pat
.parse(text
, result2
, status
);
207 if(U_FAILURE(status
)) {
208 errln((UnicodeString
)"ERROR: parse() failed");
210 if(result2
.getType() != Formattable::kDouble
&& result2
.getDouble() != d
) {
211 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
213 logln(text
+ " parsed into " + (int32_t) result2
.getDouble());
215 // ======= Test getters and setters
217 logln((UnicodeString
)"Testing getters and setters");
219 const DecimalFormatSymbols
*syms
= pat
.getDecimalFormatSymbols();
220 DecimalFormatSymbols
*newSyms
= new DecimalFormatSymbols(*syms
);
221 def
.setDecimalFormatSymbols(*newSyms
);
222 def
.adoptDecimalFormatSymbols(newSyms
); // don't use newSyms after this
223 if( *(pat
.getDecimalFormatSymbols()) != *(def
.getDecimalFormatSymbols())) {
224 errln((UnicodeString
)"ERROR: adopt or set DecimalFormatSymbols() failed");
227 UnicodeString posPrefix
;
228 pat
.setPositivePrefix("+");
229 posPrefix
= pat
.getPositivePrefix(posPrefix
);
230 logln((UnicodeString
)"Positive prefix (should be +): " + posPrefix
);
231 if(posPrefix
!= "+") {
232 errln((UnicodeString
)"ERROR: setPositivePrefix() failed");
235 UnicodeString negPrefix
;
236 pat
.setNegativePrefix("-");
237 negPrefix
= pat
.getNegativePrefix(negPrefix
);
238 logln((UnicodeString
)"Negative prefix (should be -): " + negPrefix
);
239 if(negPrefix
!= "-") {
240 errln((UnicodeString
)"ERROR: setNegativePrefix() failed");
243 UnicodeString posSuffix
;
244 pat
.setPositiveSuffix("_");
245 posSuffix
= pat
.getPositiveSuffix(posSuffix
);
246 logln((UnicodeString
)"Positive suffix (should be _): " + posSuffix
);
247 if(posSuffix
!= "_") {
248 errln((UnicodeString
)"ERROR: setPositiveSuffix() failed");
251 UnicodeString negSuffix
;
252 pat
.setNegativeSuffix("~");
253 negSuffix
= pat
.getNegativeSuffix(negSuffix
);
254 logln((UnicodeString
)"Negative suffix (should be ~): " + negSuffix
);
255 if(negSuffix
!= "~") {
256 errln((UnicodeString
)"ERROR: setNegativeSuffix() failed");
259 int32_t multiplier
= 0;
260 pat
.setMultiplier(8);
261 multiplier
= pat
.getMultiplier();
262 logln((UnicodeString
)"Multiplier (should be 8): " + multiplier
);
263 if(multiplier
!= 8) {
264 errln((UnicodeString
)"ERROR: setMultiplier() failed");
267 int32_t groupingSize
= 0;
268 pat
.setGroupingSize(2);
269 groupingSize
= pat
.getGroupingSize();
270 logln((UnicodeString
)"Grouping size (should be 2): " + (int32_t) groupingSize
);
271 if(groupingSize
!= 2) {
272 errln((UnicodeString
)"ERROR: setGroupingSize() failed");
275 pat
.setDecimalSeparatorAlwaysShown(TRUE
);
276 UBool tf
= pat
.isDecimalSeparatorAlwaysShown();
277 logln((UnicodeString
)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString
) (tf
? "TRUE" : "FALSE"));
279 errln((UnicodeString
)"ERROR: setDecimalSeparatorAlwaysShown() failed");
281 // Added by Ken Liu testing set/isExponentSignAlwaysShown
282 pat
.setExponentSignAlwaysShown(TRUE
);
283 UBool esas
= pat
.isExponentSignAlwaysShown();
284 logln((UnicodeString
)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString
) (esas
? "TRUE" : "FALSE"));
286 errln((UnicodeString
)"ERROR: ExponentSignAlwaysShown() failed");
289 // Added by Ken Liu testing set/isScientificNotation
290 pat
.setScientificNotation(TRUE
);
291 UBool sn
= pat
.isScientificNotation();
292 logln((UnicodeString
)"isScientificNotation (should be TRUE) is " + (UnicodeString
) (sn
? "TRUE" : "FALSE"));
294 errln((UnicodeString
)"ERROR: setScientificNotation() failed");
297 // Added by Ken Liu testing set/getMinimumExponentDigits
298 int8_t MinimumExponentDigits
= 0;
299 pat
.setMinimumExponentDigits(2);
300 MinimumExponentDigits
= pat
.getMinimumExponentDigits();
301 logln((UnicodeString
)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits
);
302 if(MinimumExponentDigits
!= 2) {
303 errln((UnicodeString
)"ERROR: setMinimumExponentDigits() failed");
306 // Added by Ken Liu testing set/getRoundingIncrement
307 double RoundingIncrement
= 0.0;
308 pat
.setRoundingIncrement(2.0);
309 RoundingIncrement
= pat
.getRoundingIncrement();
310 logln((UnicodeString
)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement
);
311 if(RoundingIncrement
!= 2.0) {
312 errln((UnicodeString
)"ERROR: setRoundingIncrement() failed");
314 //end of Ken's Adding
316 UnicodeString funkyPat
;
317 funkyPat
= pat
.toPattern(funkyPat
);
318 logln((UnicodeString
)"Pattern is " + funkyPat
);
320 UnicodeString locPat
;
321 locPat
= pat
.toLocalizedPattern(locPat
);
322 logln((UnicodeString
)"Localized pattern is " + locPat
);
324 // ======= Test applyPattern()
326 logln((UnicodeString
)"Testing applyPattern()");
328 UnicodeString
p1("#,##0.0#;(#,##0.0#)");
329 logln((UnicodeString
)"Applying pattern " + p1
);
330 status
= U_ZERO_ERROR
;
331 pat
.applyPattern(p1
, status
);
332 if(U_FAILURE(status
)) {
333 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
336 s2
= pat
.toPattern(s2
);
337 logln((UnicodeString
)"Extracted pattern is " + s2
);
339 errln((UnicodeString
)"ERROR: toPattern() result did not match pattern applied");
342 if(pat
.getSecondaryGroupingSize() != 0) {
343 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat
.getSecondaryGroupingSize());
346 if(pat
.getGroupingSize() != 3) {
347 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
350 UnicodeString
p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
351 logln((UnicodeString
)"Applying pattern " + p2
);
352 status
= U_ZERO_ERROR
;
353 pat
.applyLocalizedPattern(p2
, status
);
354 if(U_FAILURE(status
)) {
355 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
358 s3
= pat
.toLocalizedPattern(s3
);
359 logln((UnicodeString
)"Extracted pattern is " + s3
);
361 errln((UnicodeString
)"ERROR: toLocalizedPattern() result did not match pattern applied");
364 status
= U_ZERO_ERROR
;
366 pat
.applyLocalizedPattern(p2
, pe
, status
);
367 if(U_FAILURE(status
)) {
368 errln((UnicodeString
)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status
);
371 s4
= pat
.toLocalizedPattern(s3
);
372 logln((UnicodeString
)"Extracted pattern is " + s4
);
374 errln((UnicodeString
)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
377 if(pat
.getSecondaryGroupingSize() != 2) {
378 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat
.getSecondaryGroupingSize());
381 if(pat
.getGroupingSize() != 3) {
382 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
385 // ======= Test getStaticClassID()
387 logln((UnicodeString
)"Testing getStaticClassID()");
389 status
= U_ZERO_ERROR
;
390 NumberFormat
*test
= new DecimalFormat(status
);
391 if(U_FAILURE(status
)) {
392 errln((UnicodeString
)"ERROR: Couldn't create a DecimalFormat");
395 if(test
->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
396 errln((UnicodeString
)"ERROR: getDynamicClassID() didn't return the expected value");
402 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
403 UErrorCode status
= U_ZERO_ERROR
;
405 CurrencyPluralInfo
*cpi
= new CurrencyPluralInfo(status
);
406 if(U_FAILURE(status
)) {
407 errln((UnicodeString
)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
410 CurrencyPluralInfo cpi1
= *cpi
;
412 if(cpi
->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
413 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
416 cpi
->setCurrencyPluralPattern("","",status
);
417 if(U_FAILURE(status
)) {
418 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
421 cpi
->setLocale(Locale::getCanada(), status
);
422 if(U_FAILURE(status
)) {
423 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setLocale");
426 cpi
->setPluralRules("",status
);
427 if(U_FAILURE(status
)) {
428 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setPluralRules");
431 DecimalFormat
*df
= new DecimalFormat(status
);
432 if(U_FAILURE(status
)) {
433 errcheckln(status
, "ERROR: Could not create DecimalFormat - %s", u_errorName(status
));
436 df
->adoptCurrencyPluralInfo(cpi
);
438 df
->getCurrencyPluralInfo();
440 df
->setCurrencyPluralInfo(cpi1
);
445 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
447 UErrorCode status
= U_ZERO_ERROR
;
448 double Roundingnumber
= 2.55;
449 double Roundingnumber1
= -2.55;
450 //+2.55 results -2.55 results
451 double result
[]={ 3.0, -2.0, // kRoundCeiling 0,
452 2.0, -3.0, // kRoundFloor 1,
453 2.0, -2.0, // kRoundDown 2,
454 3.0, -3.0, // kRoundUp 3,
455 3.0, -3.0, // kRoundHalfEven 4,
456 3.0, -3.0, // kRoundHalfDown 5,
457 3.0, -3.0 // kRoundHalfUp 6
459 DecimalFormat
pat(status
);
460 if(U_FAILURE(status
)) {
461 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
466 UnicodeString message
;
467 UnicodeString resultStr
;
468 for(mode
=0;mode
< 7;mode
++){
469 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
470 if(pat
.getRoundingMode() != (DecimalFormat::ERoundingMode
)mode
){
471 errln((UnicodeString
)"SetRoundingMode or GetRoundingMode failed for mode=" + mode
);
475 //for +2.55 with RoundingIncrement=1.0
476 pat
.setRoundingIncrement(1.0);
477 pat
.format(Roundingnumber
, resultStr
);
478 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
479 verify(message
, resultStr
, result
[i
++]);
483 //for -2.55 with RoundingIncrement=1.0
484 pat
.format(Roundingnumber1
, resultStr
);
485 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber1
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
486 verify(message
, resultStr
, result
[i
++]);
492 void IntlTestDecimalFormatAPI::verify(const UnicodeString
& message
, const UnicodeString
& got
, double expected
){
493 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
494 UnicodeString
expectedStr("");
495 expectedStr
=expectedStr
+ expected
;
496 if(got
!= expectedStr
) {
497 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expectedStr
);
501 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString
& message
, const UnicodeString
& got
, UnicodeString
& expected
){
502 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
503 if(got
!= expected
) {
504 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expected
);
508 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
510 UErrorCode status
= U_ZERO_ERROR
;
511 DecimalFormat
pat(UnicodeString("#,##0.00"),status
);
512 if(U_FAILURE(status
)) {
513 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
517 // get default rounding increment
518 double roundingInc
= pat
.getRoundingIncrement();
519 if (roundingInc
!= 0.0) {
520 errln((UnicodeString
)"ERROR: Rounding increment not zero");
524 // With rounding now being handled by decNumber, we no longer
525 // set a rounding increment to enable non-default mode rounding,
526 // checking of which was the original point of this test.
528 // set rounding mode with zero increment. Rounding
529 // increment should not be set by this operation
530 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)0);
531 roundingInc
= pat
.getRoundingIncrement();
532 if (roundingInc
!= 0.0) {
533 errln((UnicodeString
)"ERROR: Rounding increment not zero after setRoundingMode");
538 void IntlTestDecimalFormatAPI::TestScale()
540 typedef struct TestData
{
543 const char *expectedOutput
;
546 static TestData testData
[] = {
547 { 100.0, 3, "100,000" },
548 { 10034.0, -2, "100.34" },
549 { 0.86, -3, "0.0009" },
550 { -0.000455, 1, "-0%" },
551 { -0.000555, 1, "-1%" },
552 { 0.000455, 1, "0%" },
553 { 0.000555, 1, "1%" },
556 UErrorCode status
= U_ZERO_ERROR
;
557 DecimalFormat
pat(status
);
558 if(U_FAILURE(status
)) {
559 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
563 UnicodeString message
;
564 UnicodeString resultStr
;
566 UnicodeString
percentPattern("#,##0%");
567 pat
.setMaximumFractionDigits(4);
569 for(int32_t i
=0; i
< LENGTHOF(testData
); i
++) {
571 pat
.applyPattern(percentPattern
,status
);
573 pat
.setAttribute(UNUM_SCALE
,testData
[i
].inputScale
,status
);
574 pat
.format(testData
[i
].inputValue
, resultStr
);
575 message
= UnicodeString("Unexpected output for ") + testData
[i
].inputValue
+ UnicodeString(" and scale ") +
576 testData
[i
].inputScale
+ UnicodeString(". Got: ");
577 exp
= testData
[i
].expectedOutput
;
578 verifyString(message
, resultStr
, exp
);
586 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
587 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
589 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
590 UErrorCode status
= U_ZERO_ERROR
;
592 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
));
593 TEST_ASSERT_STATUS(status
);
594 FixedDecimal fd
= df
->getFixedDecimal(44, status
);
595 TEST_ASSERT_STATUS(status
);
596 ASSERT_EQUAL(44, fd
.source
);
597 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
599 df
.adoptInstead(new DecimalFormat("###.00##", status
));
600 TEST_ASSERT_STATUS(status
);
601 fd
= df
->getFixedDecimal(123.456, status
);
602 TEST_ASSERT_STATUS(status
);
603 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
);
604 ASSERT_EQUAL(456, fd
.decimalDigits
);
605 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
);
606 ASSERT_EQUAL(123, fd
.intValue
);
607 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
608 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
610 df
.adoptInstead(new DecimalFormat("###", status
));
611 TEST_ASSERT_STATUS(status
);
612 fd
= df
->getFixedDecimal(123.456, status
);
613 TEST_ASSERT_STATUS(status
);
614 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
615 ASSERT_EQUAL(0, fd
.decimalDigits
);
616 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
617 ASSERT_EQUAL(123, fd
.intValue
);
618 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
619 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
621 df
.adoptInstead(new DecimalFormat("###.0", status
));
622 TEST_ASSERT_STATUS(status
);
623 fd
= df
->getFixedDecimal(123.01, status
);
624 TEST_ASSERT_STATUS(status
);
625 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
626 ASSERT_EQUAL(0, fd
.decimalDigits
);
627 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
628 ASSERT_EQUAL(123, fd
.intValue
);
629 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
630 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
632 df
.adoptInstead(new DecimalFormat("###.0", status
));
633 TEST_ASSERT_STATUS(status
);
634 fd
= df
->getFixedDecimal(123.06, status
);
635 TEST_ASSERT_STATUS(status
);
636 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
637 ASSERT_EQUAL(1, fd
.decimalDigits
);
638 ASSERT_EQUAL(1, fd
.decimalDigitsWithoutTrailingZeros
);
639 ASSERT_EQUAL(123, fd
.intValue
);
640 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
641 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
643 df
.adoptInstead(new DecimalFormat("@@@@@", status
)); // Significant Digits
644 TEST_ASSERT_STATUS(status
);
645 fd
= df
->getFixedDecimal(123, status
);
646 TEST_ASSERT_STATUS(status
);
647 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
648 ASSERT_EQUAL(0, fd
.decimalDigits
);
649 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
650 ASSERT_EQUAL(123, fd
.intValue
);
651 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
652 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
654 df
.adoptInstead(new DecimalFormat("@@@@@", status
)); // Significant Digits
655 TEST_ASSERT_STATUS(status
);
656 fd
= df
->getFixedDecimal(1.23, status
);
657 TEST_ASSERT_STATUS(status
);
658 ASSERT_EQUAL(4, fd
.visibleDecimalDigitCount
);
659 ASSERT_EQUAL(2300, fd
.decimalDigits
);
660 ASSERT_EQUAL(23, fd
.decimalDigitsWithoutTrailingZeros
);
661 ASSERT_EQUAL(1, fd
.intValue
);
662 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
663 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
665 fd
= df
->getFixedDecimal(uprv_getInfinity(), status
);
666 TEST_ASSERT_STATUS(status
);
667 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
668 fd
= df
->getFixedDecimal(0.0, status
);
669 ASSERT_EQUAL(FALSE
, fd
.isNanOrInfinity
);
670 fd
= df
->getFixedDecimal(uprv_getNaN(), status
);
671 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
672 TEST_ASSERT_STATUS(status
);
674 // Test Big Decimal input.
675 // 22 digits before and after decimal, will exceed the precision of a double
676 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
677 df
.adoptInstead(new DecimalFormat("#####################0.00####################", status
));
678 TEST_ASSERT_STATUS(status
);
679 Formattable
fable("12.34", status
);
680 TEST_ASSERT_STATUS(status
);
681 fd
= df
->getFixedDecimal(fable
, status
);
682 TEST_ASSERT_STATUS(status
);
683 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
684 ASSERT_EQUAL(34, fd
.decimalDigits
);
685 ASSERT_EQUAL(34, fd
.decimalDigitsWithoutTrailingZeros
);
686 ASSERT_EQUAL(12, fd
.intValue
);
687 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
688 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
690 fable
.setDecimalNumber("12.345678901234567890123456789", status
);
691 TEST_ASSERT_STATUS(status
);
692 fd
= df
->getFixedDecimal(fable
, status
);
693 TEST_ASSERT_STATUS(status
);
694 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
695 ASSERT_EQUAL(345678901234567890LL, fd
.decimalDigits
);
696 ASSERT_EQUAL(34567890123456789LL, fd
.decimalDigitsWithoutTrailingZeros
);
697 ASSERT_EQUAL(12, fd
.intValue
);
698 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
699 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
701 // On field overflow, Integer part is truncated on the left, fraction part on the right.
702 fable
.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status
);
703 TEST_ASSERT_STATUS(status
);
704 fd
= df
->getFixedDecimal(fable
, status
);
705 TEST_ASSERT_STATUS(status
);
706 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
707 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigits
);
708 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigitsWithoutTrailingZeros
);
709 ASSERT_EQUAL(345678901234567890LL, fd
.intValue
);
710 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
711 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
713 // Digits way to the right of the decimal but within the format's precision aren't truncated
714 fable
.setDecimalNumber("1.0000000000000000000012", status
);
715 TEST_ASSERT_STATUS(status
);
716 fd
= df
->getFixedDecimal(fable
, status
);
717 TEST_ASSERT_STATUS(status
);
718 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
719 ASSERT_EQUAL(12, fd
.decimalDigits
);
720 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
721 ASSERT_EQUAL(1, fd
.intValue
);
722 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
723 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
725 // Digits beyond the precision of the format are rounded away
726 fable
.setDecimalNumber("1.000000000000000000000012", status
);
727 TEST_ASSERT_STATUS(status
);
728 fd
= df
->getFixedDecimal(fable
, status
);
729 TEST_ASSERT_STATUS(status
);
730 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
731 ASSERT_EQUAL(0, fd
.decimalDigits
);
732 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
733 ASSERT_EQUAL(1, fd
.intValue
);
734 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
735 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
737 // Negative numbers come through
738 fable
.setDecimalNumber("-1.0000000000000000000012", status
);
739 TEST_ASSERT_STATUS(status
);
740 fd
= df
->getFixedDecimal(fable
, status
);
741 TEST_ASSERT_STATUS(status
);
742 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
743 ASSERT_EQUAL(12, fd
.decimalDigits
);
744 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
745 ASSERT_EQUAL(1, fd
.intValue
);
746 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
747 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
749 // MinFractionDigits from format larger than from number.
750 fable
.setDecimalNumber("1000000000000000000000.3", status
);
751 TEST_ASSERT_STATUS(status
);
752 fd
= df
->getFixedDecimal(fable
, status
);
753 TEST_ASSERT_STATUS(status
);
754 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
755 ASSERT_EQUAL(30, fd
.decimalDigits
);
756 ASSERT_EQUAL(3, fd
.decimalDigitsWithoutTrailingZeros
);
757 ASSERT_EQUAL(100000000000000000LL, fd
.intValue
);
758 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
759 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
761 // Test some int64_t values that are out of the range of a double
762 fable
.setInt64(4503599627370496LL);
763 TEST_ASSERT_STATUS(status
);
764 fd
= df
->getFixedDecimal(fable
, status
);
765 TEST_ASSERT_STATUS(status
);
766 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
767 ASSERT_EQUAL(0, fd
.decimalDigits
);
768 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
769 ASSERT_EQUAL(4503599627370496LL, fd
.intValue
);
770 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
771 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
773 fable
.setInt64(4503599627370497LL);
774 TEST_ASSERT_STATUS(status
);
775 fd
= df
->getFixedDecimal(fable
, status
);
776 TEST_ASSERT_STATUS(status
);
777 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
778 ASSERT_EQUAL(0, fd
.decimalDigits
);
779 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
780 ASSERT_EQUAL(4503599627370497LL, fd
.intValue
);
781 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
782 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
784 fable
.setInt64(9223372036854775807LL);
785 TEST_ASSERT_STATUS(status
);
786 fd
= df
->getFixedDecimal(fable
, status
);
787 TEST_ASSERT_STATUS(status
);
788 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
789 ASSERT_EQUAL(0, fd
.decimalDigits
);
790 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
791 // note: going through DigitList path to FixedDecimal, which is trimming
792 // int64_t fields to 18 digits. See ticket Ticket #10374
793 // ASSERT_EQUAL(223372036854775807LL, fd.intValue);
794 if (!(fd
.intValue
== 223372036854775807LL || fd
.intValue
== 9223372036854775807LL)) {
795 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__
, __LINE__
, fd
.intValue
);
797 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
798 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
802 void IntlTestDecimalFormatAPI::TestBadFastpath() {
803 UErrorCode status
= U_ZERO_ERROR
;
805 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
));
806 if (U_FAILURE(status
)) {
807 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
813 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
814 df
->setGroupingUsed(FALSE
);
816 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
817 df
->setGroupingUsed(TRUE
);
819 assertEquals("Format 1234 w/ grouping", "1,234", df
->format(1234, fmt
));
822 #endif /* #if !UCONFIG_NO_FORMATTING */