1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
15 #include "unicode/currpinf.h"
16 #include "unicode/dcfmtsym.h"
17 #include "unicode/decimfmt.h"
18 #include "unicode/fmtable.h"
19 #include "unicode/localpointer.h"
20 #include "unicode/parseerr.h"
21 #include "unicode/stringpiece.h"
24 #include "plurrule_impl.h"
27 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
28 // try to test the full functionality. It just calls each function in the class and
29 // verifies that it works on a basic level.
31 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
33 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI");
35 case 0: name = "DecimalFormat API test";
37 logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)"");
38 UErrorCode status = U_ZERO_ERROR;
40 Locale::setDefault(Locale::getEnglish(), status);
41 if(U_FAILURE(status)) {
42 errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results");
45 Locale::setDefault(saveLocale, status);
48 case 1: name = "Rounding test";
50 logln((UnicodeString)"DecimalFormat Rounding test---");
51 testRounding(/*par*/);
54 case 2: name = "Test6354";
56 logln((UnicodeString)"DecimalFormat Rounding Increment test---");
57 testRoundingInc(/*par*/);
60 case 3: name = "TestCurrencyPluralInfo";
62 logln((UnicodeString)"CurrencyPluralInfo API test---");
63 TestCurrencyPluralInfo();
66 case 4: name = "TestScale";
68 logln((UnicodeString)"Scale test---");
72 case 5: name = "TestFixedDecimal";
74 logln((UnicodeString)"TestFixedDecimal ---");
78 case 6: name = "TestBadFastpath";
80 logln((UnicodeString)"TestBadFastpath ---");
84 case 7: name = "TestRequiredDecimalPoint";
86 logln((UnicodeString)"TestRequiredDecimalPoint ---");
87 TestRequiredDecimalPoint();
90 default: name = ""; break;
95 * This test checks various generic API methods in DecimalFormat to achieve 100%
98 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
100 UErrorCode status = U_ZERO_ERROR;
102 // ======= Test constructors
104 logln((UnicodeString)"Testing DecimalFormat constructors");
106 DecimalFormat def(status);
107 if(U_FAILURE(status)) {
108 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
113 status = U_ZERO_ERROR;
114 DecimalFormat noGrouping("###0.##", status);
115 if (noGrouping.getGroupingSize() != 0) {
116 errln("Grouping size should be 0 for no grouping.");
118 noGrouping.setGroupingUsed(TRUE);
119 if (noGrouping.getGroupingSize() != 0) {
120 errln("Grouping size should still be 0.");
124 status = U_ZERO_ERROR;
125 const UnicodeString pattern("#,##0.# FF");
126 DecimalFormat pat(pattern, status);
127 if(U_FAILURE(status)) {
128 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)");
132 status = U_ZERO_ERROR;
133 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status);
134 if(U_FAILURE(status)) {
135 errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)");
139 status = U_ZERO_ERROR;
140 DecimalFormat cust1(pattern, symbols, status);
141 if(U_FAILURE(status)) {
142 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
145 status = U_ZERO_ERROR;
146 DecimalFormat cust2(pattern, *symbols, status);
147 if(U_FAILURE(status)) {
148 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)");
151 DecimalFormat copy(pat);
153 // ======= Test clone(), assignment, and equality
155 logln((UnicodeString)"Testing clone(), assignment and equality operators");
157 if( ! (copy == pat) || copy != pat) {
158 errln((UnicodeString)"ERROR: Copy constructor or == failed");
163 errln((UnicodeString)"ERROR: Assignment (or !=) failed");
166 Format *clone = def.clone();
167 if( ! (*clone == def) ) {
168 errln((UnicodeString)"ERROR: Clone() failed");
172 // ======= Test various format() methods
174 logln((UnicodeString)"Testing various format() methods");
176 double d = -10456.0037;
177 int32_t l = 100000000;
181 UnicodeString res1, res2, res3, res4;
182 FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE), pos3(FieldPosition::DONT_CARE), pos4(FieldPosition::DONT_CARE);
184 res1 = def.format(d, res1, pos1);
185 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1);
187 res2 = pat.format(l, res2, pos2);
188 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2);
190 status = U_ZERO_ERROR;
191 res3 = cust1.format(fD, res3, pos3, status);
192 if(U_FAILURE(status)) {
193 errln((UnicodeString)"ERROR: format(Formattable [double]) failed");
195 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3);
197 status = U_ZERO_ERROR;
198 res4 = cust2.format(fL, res4, pos4, status);
199 if(U_FAILURE(status)) {
200 errln((UnicodeString)"ERROR: format(Formattable [long]) failed");
202 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4);
204 // ======= Test parse()
206 logln((UnicodeString)"Testing parse()");
208 UnicodeString text("-10,456.0037");
209 Formattable result1, result2;
210 ParsePosition pos(0);
211 UnicodeString patt("#,##0.#");
212 status = U_ZERO_ERROR;
213 pat.applyPattern(patt, status);
214 if(U_FAILURE(status)) {
215 errln((UnicodeString)"ERROR: applyPattern() failed");
217 pat.parse(text, result1, pos);
218 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) {
219 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
221 logln(text + " parsed into " + (int32_t) result1.getDouble());
223 status = U_ZERO_ERROR;
224 pat.parse(text, result2, status);
225 if(U_FAILURE(status)) {
226 errln((UnicodeString)"ERROR: parse() failed");
228 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) {
229 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
231 logln(text + " parsed into " + (int32_t) result2.getDouble());
233 // ======= Test getters and setters
235 logln((UnicodeString)"Testing getters and setters");
237 const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols();
238 DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms);
239 def.setDecimalFormatSymbols(*newSyms);
240 def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this
241 if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) {
242 errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed");
245 UnicodeString posPrefix;
246 pat.setPositivePrefix("+");
247 posPrefix = pat.getPositivePrefix(posPrefix);
248 logln((UnicodeString)"Positive prefix (should be +): " + posPrefix);
249 if(posPrefix != "+") {
250 errln((UnicodeString)"ERROR: setPositivePrefix() failed");
253 UnicodeString negPrefix;
254 pat.setNegativePrefix("-");
255 negPrefix = pat.getNegativePrefix(negPrefix);
256 logln((UnicodeString)"Negative prefix (should be -): " + negPrefix);
257 if(negPrefix != "-") {
258 errln((UnicodeString)"ERROR: setNegativePrefix() failed");
261 UnicodeString posSuffix;
262 pat.setPositiveSuffix("_");
263 posSuffix = pat.getPositiveSuffix(posSuffix);
264 logln((UnicodeString)"Positive suffix (should be _): " + posSuffix);
265 if(posSuffix != "_") {
266 errln((UnicodeString)"ERROR: setPositiveSuffix() failed");
269 UnicodeString negSuffix;
270 pat.setNegativeSuffix("~");
271 negSuffix = pat.getNegativeSuffix(negSuffix);
272 logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix);
273 if(negSuffix != "~") {
274 errln((UnicodeString)"ERROR: setNegativeSuffix() failed");
277 int32_t multiplier = 0;
278 pat.setMultiplier(8);
279 multiplier = pat.getMultiplier();
280 logln((UnicodeString)"Multiplier (should be 8): " + multiplier);
281 if(multiplier != 8) {
282 errln((UnicodeString)"ERROR: setMultiplier() failed");
285 int32_t groupingSize = 0;
286 pat.setGroupingSize(2);
287 groupingSize = pat.getGroupingSize();
288 logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize);
289 if(groupingSize != 2) {
290 errln((UnicodeString)"ERROR: setGroupingSize() failed");
293 pat.setDecimalSeparatorAlwaysShown(TRUE);
294 UBool tf = pat.isDecimalSeparatorAlwaysShown();
295 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE"));
297 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed");
299 // Added by Ken Liu testing set/isExponentSignAlwaysShown
300 pat.setExponentSignAlwaysShown(TRUE);
301 UBool esas = pat.isExponentSignAlwaysShown();
302 logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE"));
304 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed");
307 // Added by Ken Liu testing set/isScientificNotation
308 pat.setScientificNotation(TRUE);
309 UBool sn = pat.isScientificNotation();
310 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE"));
312 errln((UnicodeString)"ERROR: setScientificNotation() failed");
315 // Added by Ken Liu testing set/getMinimumExponentDigits
316 int8_t MinimumExponentDigits = 0;
317 pat.setMinimumExponentDigits(2);
318 MinimumExponentDigits = pat.getMinimumExponentDigits();
319 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits);
320 if(MinimumExponentDigits != 2) {
321 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed");
324 // Added by Ken Liu testing set/getRoundingIncrement
325 double RoundingIncrement = 0.0;
326 pat.setRoundingIncrement(2.0);
327 RoundingIncrement = pat.getRoundingIncrement();
328 logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement);
329 if(RoundingIncrement != 2.0) {
330 errln((UnicodeString)"ERROR: setRoundingIncrement() failed");
332 //end of Ken's Adding
334 UnicodeString funkyPat;
335 funkyPat = pat.toPattern(funkyPat);
336 logln((UnicodeString)"Pattern is " + funkyPat);
338 UnicodeString locPat;
339 locPat = pat.toLocalizedPattern(locPat);
340 logln((UnicodeString)"Localized pattern is " + locPat);
342 // ======= Test applyPattern()
344 logln((UnicodeString)"Testing applyPattern()");
346 UnicodeString p1("#,##0.0#;(#,##0.0#)");
347 logln((UnicodeString)"Applying pattern " + p1);
348 status = U_ZERO_ERROR;
349 pat.applyPattern(p1, status);
350 if(U_FAILURE(status)) {
351 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
354 s2 = pat.toPattern(s2);
355 logln((UnicodeString)"Extracted pattern is " + s2);
357 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied");
360 if(pat.getSecondaryGroupingSize() != 0) {
361 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize());
364 if(pat.getGroupingSize() != 3) {
365 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
368 UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
369 logln((UnicodeString)"Applying pattern " + p2);
370 status = U_ZERO_ERROR;
371 pat.applyLocalizedPattern(p2, status);
372 if(U_FAILURE(status)) {
373 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
376 s3 = pat.toLocalizedPattern(s3);
377 logln((UnicodeString)"Extracted pattern is " + s3);
379 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied");
382 status = U_ZERO_ERROR;
384 pat.applyLocalizedPattern(p2, pe, status);
385 if(U_FAILURE(status)) {
386 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status);
389 s4 = pat.toLocalizedPattern(s3);
390 logln((UnicodeString)"Extracted pattern is " + s4);
392 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
395 if(pat.getSecondaryGroupingSize() != 2) {
396 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize());
399 if(pat.getGroupingSize() != 3) {
400 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
403 // ======= Test getStaticClassID()
405 logln((UnicodeString)"Testing getStaticClassID()");
407 status = U_ZERO_ERROR;
408 NumberFormat *test = new DecimalFormat(status);
409 if(U_FAILURE(status)) {
410 errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat");
413 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
414 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value");
420 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
421 UErrorCode status = U_ZERO_ERROR;
423 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status);
424 if(U_FAILURE(status)) {
425 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
428 CurrencyPluralInfo cpi1 = *cpi;
430 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
431 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
434 cpi->setCurrencyPluralPattern("","",status);
435 if(U_FAILURE(status)) {
436 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
439 cpi->setLocale(Locale::getCanada(), status);
440 if(U_FAILURE(status)) {
441 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale");
444 cpi->setPluralRules("",status);
445 if(U_FAILURE(status)) {
446 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules");
449 DecimalFormat *df = new DecimalFormat(status);
450 if(U_FAILURE(status)) {
451 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status));
455 df->adoptCurrencyPluralInfo(cpi);
457 df->getCurrencyPluralInfo();
459 df->setCurrencyPluralInfo(cpi1);
464 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
466 UErrorCode status = U_ZERO_ERROR;
467 double Roundingnumber = 2.55;
468 double Roundingnumber1 = -2.55;
469 //+2.55 results -2.55 results
470 double result[]={ 3.0, -2.0, // kRoundCeiling 0,
471 2.0, -3.0, // kRoundFloor 1,
472 2.0, -2.0, // kRoundDown 2,
473 3.0, -3.0, // kRoundUp 3,
474 3.0, -3.0, // kRoundHalfEven 4,
475 3.0, -3.0, // kRoundHalfDown 5,
476 3.0, -3.0 // kRoundHalfUp 6
478 DecimalFormat pat(status);
479 if(U_FAILURE(status)) {
480 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
485 UnicodeString message;
486 UnicodeString resultStr;
487 for(mode=0;mode < 7;mode++){
488 pat.setRoundingMode((DecimalFormat::ERoundingMode)mode);
489 if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){
490 errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode);
494 //for +2.55 with RoundingIncrement=1.0
495 pat.setRoundingIncrement(1.0);
496 pat.format(Roundingnumber, resultStr);
497 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
498 verify(message, resultStr, result[i++]);
502 //for -2.55 with RoundingIncrement=1.0
503 pat.format(Roundingnumber1, resultStr);
504 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
505 verify(message, resultStr, result[i++]);
511 void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){
512 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
513 UnicodeString expectedStr("");
514 expectedStr=expectedStr + expected;
515 if(got != expectedStr ) {
516 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr);
520 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){
521 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
522 if(got != expected ) {
523 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected);
527 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
529 UErrorCode status = U_ZERO_ERROR;
530 DecimalFormat pat(UnicodeString("#,##0.00"),status);
531 if(U_FAILURE(status)) {
532 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
536 // get default rounding increment
537 double roundingInc = pat.getRoundingIncrement();
538 if (roundingInc != 0.0) {
539 errln((UnicodeString)"ERROR: Rounding increment not zero");
543 // With rounding now being handled by decNumber, we no longer
544 // set a rounding increment to enable non-default mode rounding,
545 // checking of which was the original point of this test.
547 // set rounding mode with zero increment. Rounding
548 // increment should not be set by this operation
549 pat.setRoundingMode((DecimalFormat::ERoundingMode)0);
550 roundingInc = pat.getRoundingIncrement();
551 if (roundingInc != 0.0) {
552 errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode");
557 void IntlTestDecimalFormatAPI::TestScale()
559 typedef struct TestData {
562 const char *expectedOutput;
565 static TestData testData[] = {
566 { 100.0, 3, "100,000" },
567 { 10034.0, -2, "100.34" },
568 { 0.86, -3, "0.0009" },
569 { -0.000455, 1, "-0%" },
570 { -0.000555, 1, "-1%" },
571 { 0.000455, 1, "0%" },
572 { 0.000555, 1, "1%" },
575 UErrorCode status = U_ZERO_ERROR;
576 DecimalFormat pat(status);
577 if(U_FAILURE(status)) {
578 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
582 UnicodeString message;
583 UnicodeString resultStr;
585 UnicodeString percentPattern("#,##0%");
586 pat.setMaximumFractionDigits(4);
588 for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) {
590 pat.applyPattern(percentPattern,status);
592 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status);
593 pat.format(testData[i].inputValue, resultStr);
594 message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") +
595 testData[i].inputScale + UnicodeString(". Got: ");
596 exp = testData[i].expectedOutput;
597 verifyString(message, resultStr, exp);
605 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
606 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
608 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
609 UErrorCode status = U_ZERO_ERROR;
611 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
612 TEST_ASSERT_STATUS(status);
613 if (status == U_MISSING_RESOURCE_ERROR) {
616 FixedDecimal fd = df->getFixedDecimal(44, status);
617 TEST_ASSERT_STATUS(status);
618 ASSERT_EQUAL(44, fd.source);
619 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
620 ASSERT_EQUAL(FALSE, fd.isNegative);
622 fd = df->getFixedDecimal(-44, status);
623 TEST_ASSERT_STATUS(status);
624 ASSERT_EQUAL(44, fd.source);
625 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
626 ASSERT_EQUAL(TRUE, fd.isNegative);
628 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status);
629 TEST_ASSERT_STATUS(status);
630 fd = df->getFixedDecimal(123.456, status);
631 TEST_ASSERT_STATUS(status);
632 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
633 ASSERT_EQUAL(456, fd.decimalDigits); // f
634 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
635 ASSERT_EQUAL(123, fd.intValue); // i
636 ASSERT_EQUAL(123.456, fd.source); // n
637 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
638 ASSERT_EQUAL(FALSE, fd.isNegative);
640 fd = df->getFixedDecimal(-123.456, status);
641 TEST_ASSERT_STATUS(status);
642 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
643 ASSERT_EQUAL(456, fd.decimalDigits); // f
644 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
645 ASSERT_EQUAL(123, fd.intValue); // i
646 ASSERT_EQUAL(123.456, fd.source); // n
647 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
648 ASSERT_EQUAL(TRUE, fd.isNegative);
650 // test max int digits
651 df->setMaximumIntegerDigits(2);
652 fd = df->getFixedDecimal(123.456, status);
653 TEST_ASSERT_STATUS(status);
654 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
655 ASSERT_EQUAL(456, fd.decimalDigits); // f
656 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
657 ASSERT_EQUAL(23, fd.intValue); // i
658 ASSERT_EQUAL(23.456, fd.source); // n
659 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
660 ASSERT_EQUAL(FALSE, fd.isNegative);
662 fd = df->getFixedDecimal(-123.456, status);
663 TEST_ASSERT_STATUS(status);
664 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
665 ASSERT_EQUAL(456, fd.decimalDigits); // f
666 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
667 ASSERT_EQUAL(23, fd.intValue); // i
668 ASSERT_EQUAL(23.456, fd.source); // n
669 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
670 ASSERT_EQUAL(TRUE, fd.isNegative);
672 // test max fraction digits
673 df->setMaximumIntegerDigits(2000000000);
674 df->setMaximumFractionDigits(2);
675 fd = df->getFixedDecimal(123.456, status);
676 TEST_ASSERT_STATUS(status);
677 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
678 ASSERT_EQUAL(46, fd.decimalDigits); // f
679 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
680 ASSERT_EQUAL(123, fd.intValue); // i
681 ASSERT_EQUAL(123.46, fd.source); // n
682 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
683 ASSERT_EQUAL(FALSE, fd.isNegative);
685 fd = df->getFixedDecimal(-123.456, status);
686 TEST_ASSERT_STATUS(status);
687 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
688 ASSERT_EQUAL(46, fd.decimalDigits); // f
689 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
690 ASSERT_EQUAL(123, fd.intValue); // i
691 ASSERT_EQUAL(123.46, fd.source); // n
692 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
693 ASSERT_EQUAL(TRUE, fd.isNegative);
695 // test esoteric rounding
696 df->setMaximumFractionDigits(6);
697 df->setRoundingIncrement(7.3);
699 fd = df->getFixedDecimal(30.0, status);
700 TEST_ASSERT_STATUS(status);
701 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
702 ASSERT_EQUAL(20, fd.decimalDigits); // f
703 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
704 ASSERT_EQUAL(29, fd.intValue); // i
705 ASSERT_EQUAL(29.2, fd.source); // n
706 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
707 ASSERT_EQUAL(FALSE, fd.isNegative);
709 fd = df->getFixedDecimal(-30.0, status);
710 TEST_ASSERT_STATUS(status);
711 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
712 ASSERT_EQUAL(20, fd.decimalDigits); // f
713 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
714 ASSERT_EQUAL(29, fd.intValue); // i
715 ASSERT_EQUAL(29.2, fd.source); // n
716 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
717 ASSERT_EQUAL(TRUE, fd.isNegative);
719 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status);
720 TEST_ASSERT_STATUS(status);
721 fd = df->getFixedDecimal(123.456, status);
722 TEST_ASSERT_STATUS(status);
723 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
724 ASSERT_EQUAL(0, fd.decimalDigits);
725 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
726 ASSERT_EQUAL(123, fd.intValue);
727 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
728 ASSERT_EQUAL(FALSE, fd.isNegative);
730 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
731 TEST_ASSERT_STATUS(status);
732 fd = df->getFixedDecimal(123.01, status);
733 TEST_ASSERT_STATUS(status);
734 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
735 ASSERT_EQUAL(0, fd.decimalDigits);
736 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
737 ASSERT_EQUAL(123, fd.intValue);
738 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
739 ASSERT_EQUAL(FALSE, fd.isNegative);
741 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
742 TEST_ASSERT_STATUS(status);
743 fd = df->getFixedDecimal(123.06, status);
744 TEST_ASSERT_STATUS(status);
745 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
746 ASSERT_EQUAL(1, fd.decimalDigits);
747 ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros);
748 ASSERT_EQUAL(123, fd.intValue);
749 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
750 ASSERT_EQUAL(FALSE, fd.isNegative);
752 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
753 TEST_ASSERT_STATUS(status);
754 fd = df->getFixedDecimal(123, status);
755 TEST_ASSERT_STATUS(status);
756 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
757 ASSERT_EQUAL(0, fd.decimalDigits);
758 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
759 ASSERT_EQUAL(123, fd.intValue);
760 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
761 ASSERT_EQUAL(FALSE, fd.isNegative);
763 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
764 TEST_ASSERT_STATUS(status);
765 fd = df->getFixedDecimal(1.23, status);
766 TEST_ASSERT_STATUS(status);
767 ASSERT_EQUAL(4, fd.visibleDecimalDigitCount);
768 ASSERT_EQUAL(2300, fd.decimalDigits);
769 ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros);
770 ASSERT_EQUAL(1, fd.intValue);
771 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
772 ASSERT_EQUAL(FALSE, fd.isNegative);
774 fd = df->getFixedDecimal(uprv_getInfinity(), status);
775 TEST_ASSERT_STATUS(status);
776 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
777 fd = df->getFixedDecimal(0.0, status);
778 ASSERT_EQUAL(FALSE, fd.isNanOrInfinity);
779 fd = df->getFixedDecimal(uprv_getNaN(), status);
780 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
781 TEST_ASSERT_STATUS(status);
783 // Test Big Decimal input.
784 // 22 digits before and after decimal, will exceed the precision of a double
785 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
786 df.adoptInsteadAndCheckErrorCode(
787 new DecimalFormat("#####################0.00####################", status), status);
788 TEST_ASSERT_STATUS(status);
789 Formattable fable("12.34", status);
790 TEST_ASSERT_STATUS(status);
791 fd = df->getFixedDecimal(fable, status);
792 TEST_ASSERT_STATUS(status);
793 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
794 ASSERT_EQUAL(34, fd.decimalDigits);
795 ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros);
796 ASSERT_EQUAL(12, fd.intValue);
797 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
798 ASSERT_EQUAL(FALSE, fd.isNegative);
800 fable.setDecimalNumber("12.345678901234567890123456789", status);
801 TEST_ASSERT_STATUS(status);
802 fd = df->getFixedDecimal(fable, status);
803 TEST_ASSERT_STATUS(status);
804 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
805 ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits);
806 ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros);
807 ASSERT_EQUAL(12, fd.intValue);
808 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
809 ASSERT_EQUAL(FALSE, fd.isNegative);
811 // On field overflow, Integer part is truncated on the left, fraction part on the right.
812 fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status);
813 TEST_ASSERT_STATUS(status);
814 fd = df->getFixedDecimal(fable, status);
815 TEST_ASSERT_STATUS(status);
816 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
817 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits);
818 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros);
819 ASSERT_EQUAL(345678901234567890LL, fd.intValue);
820 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
821 ASSERT_EQUAL(FALSE, fd.isNegative);
823 // Digits way to the right of the decimal but within the format's precision aren't truncated
824 fable.setDecimalNumber("1.0000000000000000000012", status);
825 TEST_ASSERT_STATUS(status);
826 fd = df->getFixedDecimal(fable, status);
827 TEST_ASSERT_STATUS(status);
828 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
829 ASSERT_EQUAL(12, fd.decimalDigits);
830 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
831 ASSERT_EQUAL(1, fd.intValue);
832 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
833 ASSERT_EQUAL(FALSE, fd.isNegative);
835 // Digits beyond the precision of the format are rounded away
836 fable.setDecimalNumber("1.000000000000000000000012", status);
837 TEST_ASSERT_STATUS(status);
838 fd = df->getFixedDecimal(fable, status);
839 TEST_ASSERT_STATUS(status);
840 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
841 ASSERT_EQUAL(0, fd.decimalDigits);
842 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
843 ASSERT_EQUAL(1, fd.intValue);
844 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
845 ASSERT_EQUAL(FALSE, fd.isNegative);
847 // Negative numbers come through
848 fable.setDecimalNumber("-1.0000000000000000000012", status);
849 TEST_ASSERT_STATUS(status);
850 fd = df->getFixedDecimal(fable, status);
851 TEST_ASSERT_STATUS(status);
852 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
853 ASSERT_EQUAL(12, fd.decimalDigits);
854 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
855 ASSERT_EQUAL(1, fd.intValue);
856 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
857 ASSERT_EQUAL(TRUE, fd.isNegative);
859 // MinFractionDigits from format larger than from number.
860 fable.setDecimalNumber("1000000000000000000000.3", status);
861 TEST_ASSERT_STATUS(status);
862 fd = df->getFixedDecimal(fable, status);
863 TEST_ASSERT_STATUS(status);
864 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
865 ASSERT_EQUAL(30, fd.decimalDigits);
866 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
867 ASSERT_EQUAL(100000000000000000LL, fd.intValue);
868 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
869 ASSERT_EQUAL(FALSE, fd.isNegative);
871 fable.setDecimalNumber("1000000000000000050000.3", status);
872 TEST_ASSERT_STATUS(status);
873 fd = df->getFixedDecimal(fable, status);
874 TEST_ASSERT_STATUS(status);
875 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
876 ASSERT_EQUAL(30, fd.decimalDigits);
877 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
878 ASSERT_EQUAL(50000LL, fd.intValue);
879 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
880 ASSERT_EQUAL(FALSE, fd.isNegative);
882 // Test some int64_t values that are out of the range of a double
883 fable.setInt64(4503599627370496LL);
884 TEST_ASSERT_STATUS(status);
885 fd = df->getFixedDecimal(fable, status);
886 TEST_ASSERT_STATUS(status);
887 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
888 ASSERT_EQUAL(0, fd.decimalDigits);
889 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
890 ASSERT_EQUAL(4503599627370496LL, fd.intValue);
891 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
892 ASSERT_EQUAL(FALSE, fd.isNegative);
894 fable.setInt64(4503599627370497LL);
895 TEST_ASSERT_STATUS(status);
896 fd = df->getFixedDecimal(fable, status);
897 TEST_ASSERT_STATUS(status);
898 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
899 ASSERT_EQUAL(0, fd.decimalDigits);
900 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
901 ASSERT_EQUAL(4503599627370497LL, fd.intValue);
902 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
903 ASSERT_EQUAL(FALSE, fd.isNegative);
905 fable.setInt64(9223372036854775807LL);
906 TEST_ASSERT_STATUS(status);
907 fd = df->getFixedDecimal(fable, status);
908 TEST_ASSERT_STATUS(status);
909 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
910 ASSERT_EQUAL(0, fd.decimalDigits);
911 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
912 // note: going through DigitList path to FixedDecimal, which is trimming
913 // int64_t fields to 18 digits. See ticket Ticket #10374
914 // ASSERT_EQUAL(223372036854775807LL, fd.intValue);
915 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) {
916 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue);
918 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
919 ASSERT_EQUAL(FALSE, fd.isNegative);
923 void IntlTestDecimalFormatAPI::TestBadFastpath() {
924 UErrorCode status = U_ZERO_ERROR;
926 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
927 if (U_FAILURE(status)) {
928 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
934 assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
935 df->setGroupingUsed(FALSE);
937 assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
938 df->setGroupingUsed(TRUE);
939 df->setGroupingSize(3);
941 assertEquals("Format 1234 w/ grouping", "1,234", df->format((int32_t)1234, fmt));
944 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
945 UErrorCode status = U_ZERO_ERROR;
946 UnicodeString text("99");
948 UnicodeString pat1("##.0000");
949 UnicodeString pat2("00.0");
951 LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status);
952 if (U_FAILURE(status)) {
953 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
957 status = U_ZERO_ERROR;
958 df->applyPattern(pat1, status);
959 if(U_FAILURE(status)) {
960 errln((UnicodeString)"ERROR: applyPattern() failed");
962 df->parse(text, result1, status);
963 if(U_FAILURE(status)) {
964 errln((UnicodeString)"ERROR: parse() failed");
966 df->setDecimalPatternMatchRequired(TRUE);
967 df->parse(text, result1, status);
968 if(U_SUCCESS(status)) {
969 errln((UnicodeString)"ERROR: unexpected parse()");
973 status = U_ZERO_ERROR;
974 df->applyPattern(pat2, status);
975 df->setDecimalPatternMatchRequired(FALSE);
976 if(U_FAILURE(status)) {
977 errln((UnicodeString)"ERROR: applyPattern(2) failed");
979 df->parse(text, result1, status);
980 if(U_FAILURE(status)) {
981 errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status));
983 df->setDecimalPatternMatchRequired(TRUE);
984 df->parse(text, result1, status);
985 if(U_SUCCESS(status)) {
986 errln((UnicodeString)"ERROR: unexpected parse(2)");
990 #endif /* #if !UCONFIG_NO_FORMATTING */