1 /********************************************************************
3 * Copyright (c) 1997-2015, 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.");
116 noGrouping
.setGroupingUsed(TRUE
);
117 if (noGrouping
.getGroupingSize() != 0) {
118 errln("Grouping size should still be 0.");
122 status
= U_ZERO_ERROR
;
123 const UnicodeString
pattern("#,##0.# FF");
124 DecimalFormat
pat(pattern
, status
);
125 if(U_FAILURE(status
)) {
126 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern)");
130 status
= U_ZERO_ERROR
;
131 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(Locale::getFrench(), status
);
132 if(U_FAILURE(status
)) {
133 errln((UnicodeString
)"ERROR: Could not create DecimalFormatSymbols (French)");
137 status
= U_ZERO_ERROR
;
138 DecimalFormat
cust1(pattern
, symbols
, status
);
139 if(U_FAILURE(status
)) {
140 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
143 status
= U_ZERO_ERROR
;
144 DecimalFormat
cust2(pattern
, *symbols
, status
);
145 if(U_FAILURE(status
)) {
146 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols)");
149 DecimalFormat
copy(pat
);
151 // ======= Test clone(), assignment, and equality
153 logln((UnicodeString
)"Testing clone(), assignment and equality operators");
155 if( ! (copy
== pat
) || copy
!= pat
) {
156 errln((UnicodeString
)"ERROR: Copy constructor or == failed");
161 errln((UnicodeString
)"ERROR: Assignment (or !=) failed");
164 Format
*clone
= def
.clone();
165 if( ! (*clone
== def
) ) {
166 errln((UnicodeString
)"ERROR: Clone() failed");
170 // ======= Test various format() methods
172 logln((UnicodeString
)"Testing various format() methods");
174 double d
= -10456.0037;
175 int32_t l
= 100000000;
179 UnicodeString res1
, res2
, res3
, res4
;
180 FieldPosition
pos1(0), pos2(0), pos3(0), pos4(0);
182 res1
= def
.format(d
, res1
, pos1
);
183 logln( (UnicodeString
) "" + (int32_t) d
+ " formatted to " + res1
);
185 res2
= pat
.format(l
, res2
, pos2
);
186 logln((UnicodeString
) "" + (int32_t) l
+ " formatted to " + res2
);
188 status
= U_ZERO_ERROR
;
189 res3
= cust1
.format(fD
, res3
, pos3
, status
);
190 if(U_FAILURE(status
)) {
191 errln((UnicodeString
)"ERROR: format(Formattable [double]) failed");
193 logln((UnicodeString
) "" + (int32_t) fD
.getDouble() + " formatted to " + res3
);
195 status
= U_ZERO_ERROR
;
196 res4
= cust2
.format(fL
, res4
, pos4
, status
);
197 if(U_FAILURE(status
)) {
198 errln((UnicodeString
)"ERROR: format(Formattable [long]) failed");
200 logln((UnicodeString
) "" + fL
.getLong() + " formatted to " + res4
);
202 // ======= Test parse()
204 logln((UnicodeString
)"Testing parse()");
206 UnicodeString
text("-10,456.0037");
207 Formattable result1
, result2
;
208 ParsePosition
pos(0);
209 UnicodeString
patt("#,##0.#");
210 status
= U_ZERO_ERROR
;
211 pat
.applyPattern(patt
, status
);
212 if(U_FAILURE(status
)) {
213 errln((UnicodeString
)"ERROR: applyPattern() failed");
215 pat
.parse(text
, result1
, pos
);
216 if(result1
.getType() != Formattable::kDouble
&& result1
.getDouble() != d
) {
217 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
219 logln(text
+ " parsed into " + (int32_t) result1
.getDouble());
221 status
= U_ZERO_ERROR
;
222 pat
.parse(text
, result2
, status
);
223 if(U_FAILURE(status
)) {
224 errln((UnicodeString
)"ERROR: parse() failed");
226 if(result2
.getType() != Formattable::kDouble
&& result2
.getDouble() != d
) {
227 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
229 logln(text
+ " parsed into " + (int32_t) result2
.getDouble());
231 // ======= Test getters and setters
233 logln((UnicodeString
)"Testing getters and setters");
235 const DecimalFormatSymbols
*syms
= pat
.getDecimalFormatSymbols();
236 DecimalFormatSymbols
*newSyms
= new DecimalFormatSymbols(*syms
);
237 def
.setDecimalFormatSymbols(*newSyms
);
238 def
.adoptDecimalFormatSymbols(newSyms
); // don't use newSyms after this
239 if( *(pat
.getDecimalFormatSymbols()) != *(def
.getDecimalFormatSymbols())) {
240 errln((UnicodeString
)"ERROR: adopt or set DecimalFormatSymbols() failed");
243 UnicodeString posPrefix
;
244 pat
.setPositivePrefix("+");
245 posPrefix
= pat
.getPositivePrefix(posPrefix
);
246 logln((UnicodeString
)"Positive prefix (should be +): " + posPrefix
);
247 if(posPrefix
!= "+") {
248 errln((UnicodeString
)"ERROR: setPositivePrefix() failed");
251 UnicodeString negPrefix
;
252 pat
.setNegativePrefix("-");
253 negPrefix
= pat
.getNegativePrefix(negPrefix
);
254 logln((UnicodeString
)"Negative prefix (should be -): " + negPrefix
);
255 if(negPrefix
!= "-") {
256 errln((UnicodeString
)"ERROR: setNegativePrefix() failed");
259 UnicodeString posSuffix
;
260 pat
.setPositiveSuffix("_");
261 posSuffix
= pat
.getPositiveSuffix(posSuffix
);
262 logln((UnicodeString
)"Positive suffix (should be _): " + posSuffix
);
263 if(posSuffix
!= "_") {
264 errln((UnicodeString
)"ERROR: setPositiveSuffix() failed");
267 UnicodeString negSuffix
;
268 pat
.setNegativeSuffix("~");
269 negSuffix
= pat
.getNegativeSuffix(negSuffix
);
270 logln((UnicodeString
)"Negative suffix (should be ~): " + negSuffix
);
271 if(negSuffix
!= "~") {
272 errln((UnicodeString
)"ERROR: setNegativeSuffix() failed");
275 int32_t multiplier
= 0;
276 pat
.setMultiplier(8);
277 multiplier
= pat
.getMultiplier();
278 logln((UnicodeString
)"Multiplier (should be 8): " + multiplier
);
279 if(multiplier
!= 8) {
280 errln((UnicodeString
)"ERROR: setMultiplier() failed");
283 int32_t groupingSize
= 0;
284 pat
.setGroupingSize(2);
285 groupingSize
= pat
.getGroupingSize();
286 logln((UnicodeString
)"Grouping size (should be 2): " + (int32_t) groupingSize
);
287 if(groupingSize
!= 2) {
288 errln((UnicodeString
)"ERROR: setGroupingSize() failed");
291 pat
.setDecimalSeparatorAlwaysShown(TRUE
);
292 UBool tf
= pat
.isDecimalSeparatorAlwaysShown();
293 logln((UnicodeString
)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString
) (tf
? "TRUE" : "FALSE"));
295 errln((UnicodeString
)"ERROR: setDecimalSeparatorAlwaysShown() failed");
297 // Added by Ken Liu testing set/isExponentSignAlwaysShown
298 pat
.setExponentSignAlwaysShown(TRUE
);
299 UBool esas
= pat
.isExponentSignAlwaysShown();
300 logln((UnicodeString
)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString
) (esas
? "TRUE" : "FALSE"));
302 errln((UnicodeString
)"ERROR: ExponentSignAlwaysShown() failed");
305 // Added by Ken Liu testing set/isScientificNotation
306 pat
.setScientificNotation(TRUE
);
307 UBool sn
= pat
.isScientificNotation();
308 logln((UnicodeString
)"isScientificNotation (should be TRUE) is " + (UnicodeString
) (sn
? "TRUE" : "FALSE"));
310 errln((UnicodeString
)"ERROR: setScientificNotation() failed");
313 // Added by Ken Liu testing set/getMinimumExponentDigits
314 int8_t MinimumExponentDigits
= 0;
315 pat
.setMinimumExponentDigits(2);
316 MinimumExponentDigits
= pat
.getMinimumExponentDigits();
317 logln((UnicodeString
)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits
);
318 if(MinimumExponentDigits
!= 2) {
319 errln((UnicodeString
)"ERROR: setMinimumExponentDigits() failed");
322 // Added by Ken Liu testing set/getRoundingIncrement
323 double RoundingIncrement
= 0.0;
324 pat
.setRoundingIncrement(2.0);
325 RoundingIncrement
= pat
.getRoundingIncrement();
326 logln((UnicodeString
)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement
);
327 if(RoundingIncrement
!= 2.0) {
328 errln((UnicodeString
)"ERROR: setRoundingIncrement() failed");
330 //end of Ken's Adding
332 UnicodeString funkyPat
;
333 funkyPat
= pat
.toPattern(funkyPat
);
334 logln((UnicodeString
)"Pattern is " + funkyPat
);
336 UnicodeString locPat
;
337 locPat
= pat
.toLocalizedPattern(locPat
);
338 logln((UnicodeString
)"Localized pattern is " + locPat
);
340 // ======= Test applyPattern()
342 logln((UnicodeString
)"Testing applyPattern()");
344 UnicodeString
p1("#,##0.0#;(#,##0.0#)");
345 logln((UnicodeString
)"Applying pattern " + p1
);
346 status
= U_ZERO_ERROR
;
347 pat
.applyPattern(p1
, status
);
348 if(U_FAILURE(status
)) {
349 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
352 s2
= pat
.toPattern(s2
);
353 logln((UnicodeString
)"Extracted pattern is " + s2
);
355 errln((UnicodeString
)"ERROR: toPattern() result did not match pattern applied");
358 if(pat
.getSecondaryGroupingSize() != 0) {
359 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat
.getSecondaryGroupingSize());
362 if(pat
.getGroupingSize() != 3) {
363 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
366 UnicodeString
p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
367 logln((UnicodeString
)"Applying pattern " + p2
);
368 status
= U_ZERO_ERROR
;
369 pat
.applyLocalizedPattern(p2
, status
);
370 if(U_FAILURE(status
)) {
371 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
374 s3
= pat
.toLocalizedPattern(s3
);
375 logln((UnicodeString
)"Extracted pattern is " + s3
);
377 errln((UnicodeString
)"ERROR: toLocalizedPattern() result did not match pattern applied");
380 status
= U_ZERO_ERROR
;
382 pat
.applyLocalizedPattern(p2
, pe
, status
);
383 if(U_FAILURE(status
)) {
384 errln((UnicodeString
)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status
);
387 s4
= pat
.toLocalizedPattern(s3
);
388 logln((UnicodeString
)"Extracted pattern is " + s4
);
390 errln((UnicodeString
)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
393 if(pat
.getSecondaryGroupingSize() != 2) {
394 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat
.getSecondaryGroupingSize());
397 if(pat
.getGroupingSize() != 3) {
398 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
401 // ======= Test getStaticClassID()
403 logln((UnicodeString
)"Testing getStaticClassID()");
405 status
= U_ZERO_ERROR
;
406 NumberFormat
*test
= new DecimalFormat(status
);
407 if(U_FAILURE(status
)) {
408 errln((UnicodeString
)"ERROR: Couldn't create a DecimalFormat");
411 if(test
->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
412 errln((UnicodeString
)"ERROR: getDynamicClassID() didn't return the expected value");
418 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
419 UErrorCode status
= U_ZERO_ERROR
;
421 CurrencyPluralInfo
*cpi
= new CurrencyPluralInfo(status
);
422 if(U_FAILURE(status
)) {
423 errln((UnicodeString
)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
426 CurrencyPluralInfo cpi1
= *cpi
;
428 if(cpi
->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
429 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
432 cpi
->setCurrencyPluralPattern("","",status
);
433 if(U_FAILURE(status
)) {
434 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
437 cpi
->setLocale(Locale::getCanada(), status
);
438 if(U_FAILURE(status
)) {
439 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setLocale");
442 cpi
->setPluralRules("",status
);
443 if(U_FAILURE(status
)) {
444 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setPluralRules");
447 DecimalFormat
*df
= new DecimalFormat(status
);
448 if(U_FAILURE(status
)) {
449 errcheckln(status
, "ERROR: Could not create DecimalFormat - %s", u_errorName(status
));
453 df
->adoptCurrencyPluralInfo(cpi
);
455 df
->getCurrencyPluralInfo();
457 df
->setCurrencyPluralInfo(cpi1
);
462 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
464 UErrorCode status
= U_ZERO_ERROR
;
465 double Roundingnumber
= 2.55;
466 double Roundingnumber1
= -2.55;
467 //+2.55 results -2.55 results
468 double result
[]={ 3.0, -2.0, // kRoundCeiling 0,
469 2.0, -3.0, // kRoundFloor 1,
470 2.0, -2.0, // kRoundDown 2,
471 3.0, -3.0, // kRoundUp 3,
472 3.0, -3.0, // kRoundHalfEven 4,
473 3.0, -3.0, // kRoundHalfDown 5,
474 3.0, -3.0 // kRoundHalfUp 6
476 DecimalFormat
pat(status
);
477 if(U_FAILURE(status
)) {
478 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
483 UnicodeString message
;
484 UnicodeString resultStr
;
485 for(mode
=0;mode
< 7;mode
++){
486 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
487 if(pat
.getRoundingMode() != (DecimalFormat::ERoundingMode
)mode
){
488 errln((UnicodeString
)"SetRoundingMode or GetRoundingMode failed for mode=" + mode
);
492 //for +2.55 with RoundingIncrement=1.0
493 pat
.setRoundingIncrement(1.0);
494 pat
.format(Roundingnumber
, resultStr
);
495 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
496 verify(message
, resultStr
, result
[i
++]);
500 //for -2.55 with RoundingIncrement=1.0
501 pat
.format(Roundingnumber1
, resultStr
);
502 message
= (UnicodeString
)"Round() failed: round(" + (double)Roundingnumber1
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
503 verify(message
, resultStr
, result
[i
++]);
509 void IntlTestDecimalFormatAPI::verify(const UnicodeString
& message
, const UnicodeString
& got
, double expected
){
510 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
511 UnicodeString
expectedStr("");
512 expectedStr
=expectedStr
+ expected
;
513 if(got
!= expectedStr
) {
514 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expectedStr
);
518 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString
& message
, const UnicodeString
& got
, UnicodeString
& expected
){
519 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
520 if(got
!= expected
) {
521 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expected
);
525 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
527 UErrorCode status
= U_ZERO_ERROR
;
528 DecimalFormat
pat(UnicodeString("#,##0.00"),status
);
529 if(U_FAILURE(status
)) {
530 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
534 // get default rounding increment
535 double roundingInc
= pat
.getRoundingIncrement();
536 if (roundingInc
!= 0.0) {
537 errln((UnicodeString
)"ERROR: Rounding increment not zero");
541 // With rounding now being handled by decNumber, we no longer
542 // set a rounding increment to enable non-default mode rounding,
543 // checking of which was the original point of this test.
545 // set rounding mode with zero increment. Rounding
546 // increment should not be set by this operation
547 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)0);
548 roundingInc
= pat
.getRoundingIncrement();
549 if (roundingInc
!= 0.0) {
550 errln((UnicodeString
)"ERROR: Rounding increment not zero after setRoundingMode");
555 void IntlTestDecimalFormatAPI::TestScale()
557 typedef struct TestData
{
560 const char *expectedOutput
;
563 static TestData testData
[] = {
564 { 100.0, 3, "100,000" },
565 { 10034.0, -2, "100.34" },
566 { 0.86, -3, "0.0009" },
567 { -0.000455, 1, "-0%" },
568 { -0.000555, 1, "-1%" },
569 { 0.000455, 1, "0%" },
570 { 0.000555, 1, "1%" },
573 UErrorCode status
= U_ZERO_ERROR
;
574 DecimalFormat
pat(status
);
575 if(U_FAILURE(status
)) {
576 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
580 UnicodeString message
;
581 UnicodeString resultStr
;
583 UnicodeString
percentPattern("#,##0%");
584 pat
.setMaximumFractionDigits(4);
586 for(int32_t i
=0; i
< UPRV_LENGTHOF(testData
); i
++) {
588 pat
.applyPattern(percentPattern
,status
);
590 pat
.setAttribute(UNUM_SCALE
,testData
[i
].inputScale
,status
);
591 pat
.format(testData
[i
].inputValue
, resultStr
);
592 message
= UnicodeString("Unexpected output for ") + testData
[i
].inputValue
+ UnicodeString(" and scale ") +
593 testData
[i
].inputScale
+ UnicodeString(". Got: ");
594 exp
= testData
[i
].expectedOutput
;
595 verifyString(message
, resultStr
, exp
);
603 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
604 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
606 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
607 UErrorCode status
= U_ZERO_ERROR
;
609 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
610 TEST_ASSERT_STATUS(status
);
611 if (status
== U_MISSING_RESOURCE_ERROR
) {
614 FixedDecimal fd
= df
->getFixedDecimal(44, status
);
615 TEST_ASSERT_STATUS(status
);
616 ASSERT_EQUAL(44, fd
.source
);
617 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
618 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
620 fd
= df
->getFixedDecimal(-44, status
);
621 TEST_ASSERT_STATUS(status
);
622 ASSERT_EQUAL(44, fd
.source
);
623 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
624 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
626 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status
), status
);
627 TEST_ASSERT_STATUS(status
);
628 fd
= df
->getFixedDecimal(123.456, status
);
629 TEST_ASSERT_STATUS(status
);
630 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
); // v
631 ASSERT_EQUAL(456, fd
.decimalDigits
); // f
632 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
); // t
633 ASSERT_EQUAL(123, fd
.intValue
); // i
634 ASSERT_EQUAL(123.456, fd
.source
); // n
635 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
636 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
638 fd
= df
->getFixedDecimal(-123.456, status
);
639 TEST_ASSERT_STATUS(status
);
640 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
); // v
641 ASSERT_EQUAL(456, fd
.decimalDigits
); // f
642 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
); // t
643 ASSERT_EQUAL(123, fd
.intValue
); // i
644 ASSERT_EQUAL(123.456, fd
.source
); // n
645 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
646 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
648 // test max int digits
649 df
->setMaximumIntegerDigits(2);
650 fd
= df
->getFixedDecimal(123.456, status
);
651 TEST_ASSERT_STATUS(status
);
652 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
); // v
653 ASSERT_EQUAL(456, fd
.decimalDigits
); // f
654 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
); // t
655 ASSERT_EQUAL(23, fd
.intValue
); // i
656 ASSERT_EQUAL(23.456, fd
.source
); // n
657 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
658 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
660 fd
= df
->getFixedDecimal(-123.456, status
);
661 TEST_ASSERT_STATUS(status
);
662 ASSERT_EQUAL(3, fd
.visibleDecimalDigitCount
); // v
663 ASSERT_EQUAL(456, fd
.decimalDigits
); // f
664 ASSERT_EQUAL(456, fd
.decimalDigitsWithoutTrailingZeros
); // t
665 ASSERT_EQUAL(23, fd
.intValue
); // i
666 ASSERT_EQUAL(23.456, fd
.source
); // n
667 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
668 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
670 // test max fraction digits
671 df
->setMaximumIntegerDigits(2000000000);
672 df
->setMaximumFractionDigits(2);
673 fd
= df
->getFixedDecimal(123.456, status
);
674 TEST_ASSERT_STATUS(status
);
675 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
); // v
676 ASSERT_EQUAL(46, fd
.decimalDigits
); // f
677 ASSERT_EQUAL(46, fd
.decimalDigitsWithoutTrailingZeros
); // t
678 ASSERT_EQUAL(123, fd
.intValue
); // i
679 ASSERT_EQUAL(123.46, fd
.source
); // n
680 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
681 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
683 fd
= df
->getFixedDecimal(-123.456, status
);
684 TEST_ASSERT_STATUS(status
);
685 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
); // v
686 ASSERT_EQUAL(46, fd
.decimalDigits
); // f
687 ASSERT_EQUAL(46, fd
.decimalDigitsWithoutTrailingZeros
); // t
688 ASSERT_EQUAL(123, fd
.intValue
); // i
689 ASSERT_EQUAL(123.46, fd
.source
); // n
690 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
691 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
693 // test esoteric rounding
694 df
->setMaximumFractionDigits(6);
695 df
->setRoundingIncrement(7.3);
697 fd
= df
->getFixedDecimal(30.0, status
);
698 TEST_ASSERT_STATUS(status
);
699 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
); // v
700 ASSERT_EQUAL(20, fd
.decimalDigits
); // f
701 ASSERT_EQUAL(2, fd
.decimalDigitsWithoutTrailingZeros
); // t
702 ASSERT_EQUAL(29, fd
.intValue
); // i
703 ASSERT_EQUAL(29.2, fd
.source
); // n
704 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
705 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
707 fd
= df
->getFixedDecimal(-30.0, status
);
708 TEST_ASSERT_STATUS(status
);
709 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
); // v
710 ASSERT_EQUAL(20, fd
.decimalDigits
); // f
711 ASSERT_EQUAL(2, fd
.decimalDigitsWithoutTrailingZeros
); // t
712 ASSERT_EQUAL(29, fd
.intValue
); // i
713 ASSERT_EQUAL(29.2, fd
.source
); // n
714 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
715 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
717 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status
), status
);
718 TEST_ASSERT_STATUS(status
);
719 fd
= df
->getFixedDecimal(123.456, status
);
720 TEST_ASSERT_STATUS(status
);
721 ASSERT_EQUAL(0, fd
.visibleDecimalDigitCount
);
722 ASSERT_EQUAL(0, fd
.decimalDigits
);
723 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
724 ASSERT_EQUAL(123, fd
.intValue
);
725 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
726 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
728 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
729 TEST_ASSERT_STATUS(status
);
730 fd
= df
->getFixedDecimal(123.01, status
);
731 TEST_ASSERT_STATUS(status
);
732 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
733 ASSERT_EQUAL(0, fd
.decimalDigits
);
734 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
735 ASSERT_EQUAL(123, fd
.intValue
);
736 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
737 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
739 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
740 TEST_ASSERT_STATUS(status
);
741 fd
= df
->getFixedDecimal(123.06, status
);
742 TEST_ASSERT_STATUS(status
);
743 ASSERT_EQUAL(1, fd
.visibleDecimalDigitCount
);
744 ASSERT_EQUAL(1, fd
.decimalDigits
);
745 ASSERT_EQUAL(1, fd
.decimalDigitsWithoutTrailingZeros
);
746 ASSERT_EQUAL(123, fd
.intValue
);
747 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
748 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
750 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
751 TEST_ASSERT_STATUS(status
);
752 fd
= df
->getFixedDecimal(123, status
);
753 TEST_ASSERT_STATUS(status
);
754 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
755 ASSERT_EQUAL(0, fd
.decimalDigits
);
756 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
757 ASSERT_EQUAL(123, fd
.intValue
);
758 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
759 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
761 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
762 TEST_ASSERT_STATUS(status
);
763 fd
= df
->getFixedDecimal(1.23, status
);
764 TEST_ASSERT_STATUS(status
);
765 ASSERT_EQUAL(4, fd
.visibleDecimalDigitCount
);
766 ASSERT_EQUAL(2300, fd
.decimalDigits
);
767 ASSERT_EQUAL(23, fd
.decimalDigitsWithoutTrailingZeros
);
768 ASSERT_EQUAL(1, fd
.intValue
);
769 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
770 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
772 fd
= df
->getFixedDecimal(uprv_getInfinity(), status
);
773 TEST_ASSERT_STATUS(status
);
774 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
775 fd
= df
->getFixedDecimal(0.0, status
);
776 ASSERT_EQUAL(FALSE
, fd
.isNanOrInfinity
);
777 fd
= df
->getFixedDecimal(uprv_getNaN(), status
);
778 ASSERT_EQUAL(TRUE
, fd
.isNanOrInfinity
);
779 TEST_ASSERT_STATUS(status
);
781 // Test Big Decimal input.
782 // 22 digits before and after decimal, will exceed the precision of a double
783 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
784 df
.adoptInsteadAndCheckErrorCode(
785 new DecimalFormat("#####################0.00####################", status
), status
);
786 TEST_ASSERT_STATUS(status
);
787 Formattable
fable("12.34", status
);
788 TEST_ASSERT_STATUS(status
);
789 fd
= df
->getFixedDecimal(fable
, status
);
790 TEST_ASSERT_STATUS(status
);
791 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
792 ASSERT_EQUAL(34, fd
.decimalDigits
);
793 ASSERT_EQUAL(34, fd
.decimalDigitsWithoutTrailingZeros
);
794 ASSERT_EQUAL(12, fd
.intValue
);
795 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
796 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
798 fable
.setDecimalNumber("12.345678901234567890123456789", status
);
799 TEST_ASSERT_STATUS(status
);
800 fd
= df
->getFixedDecimal(fable
, status
);
801 TEST_ASSERT_STATUS(status
);
802 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
803 ASSERT_EQUAL(345678901234567890LL, fd
.decimalDigits
);
804 ASSERT_EQUAL(34567890123456789LL, fd
.decimalDigitsWithoutTrailingZeros
);
805 ASSERT_EQUAL(12, fd
.intValue
);
806 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
807 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
809 // On field overflow, Integer part is truncated on the left, fraction part on the right.
810 fable
.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status
);
811 TEST_ASSERT_STATUS(status
);
812 fd
= df
->getFixedDecimal(fable
, status
);
813 TEST_ASSERT_STATUS(status
);
814 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
815 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigits
);
816 ASSERT_EQUAL(123456789012345678LL, fd
.decimalDigitsWithoutTrailingZeros
);
817 ASSERT_EQUAL(345678901234567890LL, fd
.intValue
);
818 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
819 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
821 // Digits way to the right of the decimal but within the format's precision aren't truncated
822 fable
.setDecimalNumber("1.0000000000000000000012", status
);
823 TEST_ASSERT_STATUS(status
);
824 fd
= df
->getFixedDecimal(fable
, status
);
825 TEST_ASSERT_STATUS(status
);
826 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
827 ASSERT_EQUAL(12, fd
.decimalDigits
);
828 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
829 ASSERT_EQUAL(1, fd
.intValue
);
830 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
831 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
833 // Digits beyond the precision of the format are rounded away
834 fable
.setDecimalNumber("1.000000000000000000000012", status
);
835 TEST_ASSERT_STATUS(status
);
836 fd
= df
->getFixedDecimal(fable
, status
);
837 TEST_ASSERT_STATUS(status
);
838 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
839 ASSERT_EQUAL(0, fd
.decimalDigits
);
840 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
841 ASSERT_EQUAL(1, fd
.intValue
);
842 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
843 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
845 // Negative numbers come through
846 fable
.setDecimalNumber("-1.0000000000000000000012", status
);
847 TEST_ASSERT_STATUS(status
);
848 fd
= df
->getFixedDecimal(fable
, status
);
849 TEST_ASSERT_STATUS(status
);
850 ASSERT_EQUAL(22, fd
.visibleDecimalDigitCount
);
851 ASSERT_EQUAL(12, fd
.decimalDigits
);
852 ASSERT_EQUAL(12, fd
.decimalDigitsWithoutTrailingZeros
);
853 ASSERT_EQUAL(1, fd
.intValue
);
854 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
855 ASSERT_EQUAL(TRUE
, fd
.isNegative
);
857 // MinFractionDigits from format larger than from number.
858 fable
.setDecimalNumber("1000000000000000000000.3", status
);
859 TEST_ASSERT_STATUS(status
);
860 fd
= df
->getFixedDecimal(fable
, status
);
861 TEST_ASSERT_STATUS(status
);
862 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
863 ASSERT_EQUAL(30, fd
.decimalDigits
);
864 ASSERT_EQUAL(3, fd
.decimalDigitsWithoutTrailingZeros
);
865 ASSERT_EQUAL(100000000000000000LL, fd
.intValue
);
866 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
867 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
869 fable
.setDecimalNumber("1000000000000000050000.3", status
);
870 TEST_ASSERT_STATUS(status
);
871 fd
= df
->getFixedDecimal(fable
, status
);
872 TEST_ASSERT_STATUS(status
);
873 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
874 ASSERT_EQUAL(30, fd
.decimalDigits
);
875 ASSERT_EQUAL(3, fd
.decimalDigitsWithoutTrailingZeros
);
876 ASSERT_EQUAL(50000LL, fd
.intValue
);
877 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue
);
878 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
880 // Test some int64_t values that are out of the range of a double
881 fable
.setInt64(4503599627370496LL);
882 TEST_ASSERT_STATUS(status
);
883 fd
= df
->getFixedDecimal(fable
, status
);
884 TEST_ASSERT_STATUS(status
);
885 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
886 ASSERT_EQUAL(0, fd
.decimalDigits
);
887 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
888 ASSERT_EQUAL(4503599627370496LL, fd
.intValue
);
889 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
890 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
892 fable
.setInt64(4503599627370497LL);
893 TEST_ASSERT_STATUS(status
);
894 fd
= df
->getFixedDecimal(fable
, status
);
895 TEST_ASSERT_STATUS(status
);
896 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
897 ASSERT_EQUAL(0, fd
.decimalDigits
);
898 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
899 ASSERT_EQUAL(4503599627370497LL, fd
.intValue
);
900 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
901 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
903 fable
.setInt64(9223372036854775807LL);
904 TEST_ASSERT_STATUS(status
);
905 fd
= df
->getFixedDecimal(fable
, status
);
906 TEST_ASSERT_STATUS(status
);
907 ASSERT_EQUAL(2, fd
.visibleDecimalDigitCount
);
908 ASSERT_EQUAL(0, fd
.decimalDigits
);
909 ASSERT_EQUAL(0, fd
.decimalDigitsWithoutTrailingZeros
);
910 // note: going through DigitList path to FixedDecimal, which is trimming
911 // int64_t fields to 18 digits. See ticket Ticket #10374
912 // ASSERT_EQUAL(223372036854775807LL, fd.intValue);
913 if (!(fd
.intValue
== 223372036854775807LL || fd
.intValue
== 9223372036854775807LL)) {
914 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__
, __LINE__
, fd
.intValue
);
916 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue
);
917 ASSERT_EQUAL(FALSE
, fd
.isNegative
);
921 void IntlTestDecimalFormatAPI::TestBadFastpath() {
922 UErrorCode status
= U_ZERO_ERROR
;
924 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
925 if (U_FAILURE(status
)) {
926 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
932 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
933 df
->setGroupingUsed(FALSE
);
935 assertEquals("Format 1234", "1234", df
->format(1234, fmt
));
936 df
->setGroupingUsed(TRUE
);
937 df
->setGroupingSize(3);
939 assertEquals("Format 1234 w/ grouping", "1,234", df
->format(1234, fmt
));
942 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
943 UErrorCode status
= U_ZERO_ERROR
;
944 UnicodeString
text("99");
946 UnicodeString
pat1("##.0000");
947 UnicodeString
pat2("00.0");
949 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pat1
, status
), status
);
950 if (U_FAILURE(status
)) {
951 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
955 status
= U_ZERO_ERROR
;
956 df
->applyPattern(pat1
, status
);
957 if(U_FAILURE(status
)) {
958 errln((UnicodeString
)"ERROR: applyPattern() failed");
960 df
->parse(text
, result1
, status
);
961 if(U_FAILURE(status
)) {
962 errln((UnicodeString
)"ERROR: parse() failed");
964 df
->setDecimalPatternMatchRequired(TRUE
);
965 df
->parse(text
, result1
, status
);
966 if(U_SUCCESS(status
)) {
967 errln((UnicodeString
)"ERROR: unexpected parse()");
971 status
= U_ZERO_ERROR
;
972 df
->applyPattern(pat2
, status
);
973 df
->setDecimalPatternMatchRequired(FALSE
);
974 if(U_FAILURE(status
)) {
975 errln((UnicodeString
)"ERROR: applyPattern(2) failed");
977 df
->parse(text
, result1
, status
);
978 if(U_FAILURE(status
)) {
979 errln((UnicodeString
)"ERROR: parse(2) failed - " + u_errorName(status
));
981 df
->setDecimalPatternMatchRequired(TRUE
);
982 df
->parse(text
, result1
, status
);
983 if(U_SUCCESS(status
)) {
984 errln((UnicodeString
)"ERROR: unexpected parse(2)");
988 #endif /* #if !UCONFIG_NO_FORMATTING */