1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
15 #include "unicode/currpinf.h"
16 #include "unicode/dcfmtsym.h"
17 #include "unicode/decimfmt.h"
18 #include "unicode/fmtable.h"
19 #include "unicode/localpointer.h"
20 #include "unicode/parseerr.h"
21 #include "unicode/stringpiece.h"
24 #include "plurrule_impl.h"
25 #include "number_decimalquantity.h"
29 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
30 // try to test the full functionality. It just calls each function in the class and
31 // verifies that it works on a basic level.
33 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
35 if (exec
) logln((UnicodeString
)"TestSuite DecimalFormatAPI");
37 case 0: name
= "DecimalFormat API test";
39 logln((UnicodeString
)"DecimalFormat API test---"); logln((UnicodeString
)"");
40 UErrorCode status
= U_ZERO_ERROR
;
42 Locale::setDefault(Locale::getEnglish(), status
);
43 if(U_FAILURE(status
)) {
44 errln((UnicodeString
)"ERROR: Could not set default locale, test may not give correct results");
47 Locale::setDefault(saveLocale
, status
);
50 case 1: name
= "Rounding test";
52 logln((UnicodeString
)"DecimalFormat Rounding test---");
53 testRounding(/*par*/);
56 case 2: name
= "Test6354";
58 logln((UnicodeString
)"DecimalFormat Rounding Increment test---");
59 testRoundingInc(/*par*/);
62 case 3: name
= "TestCurrencyPluralInfo";
64 logln((UnicodeString
)"CurrencyPluralInfo API test---");
65 TestCurrencyPluralInfo();
68 case 4: name
= "TestScale";
70 logln((UnicodeString
)"Scale test---");
74 case 5: name
= "TestFixedDecimal";
76 logln((UnicodeString
)"TestFixedDecimal ---");
80 case 6: name
= "TestBadFastpath";
82 logln((UnicodeString
)"TestBadFastpath ---");
86 case 7: name
= "TestRequiredDecimalPoint";
88 logln((UnicodeString
)"TestRequiredDecimalPoint ---");
89 TestRequiredDecimalPoint();
92 case 8: name
= "testErrorCode";
94 logln((UnicodeString
)"testErrorCode ---");
98 case 9: name
= "testInvalidObject";
100 logln((UnicodeString
) "testInvalidObject ---");
104 default: name
= ""; break;
109 * This test checks various generic API methods in DecimalFormat to achieve 100%
112 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
114 UErrorCode status
= U_ZERO_ERROR
;
116 // ======= Test constructors
118 logln((UnicodeString
)"Testing DecimalFormat constructors");
120 DecimalFormat
def(status
);
121 if(U_FAILURE(status
)) {
122 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
127 status
= U_ZERO_ERROR
;
128 DecimalFormat
noGrouping("###0.##", status
);
129 assertEquals("Grouping size should be 0 for no grouping.", 0, noGrouping
.getGroupingSize());
130 noGrouping
.setGroupingUsed(TRUE
);
131 assertEquals("Grouping size should still be 0.", 0, noGrouping
.getGroupingSize());
134 // bug 13442 comment 14
135 status
= U_ZERO_ERROR
;
137 DecimalFormat
df("0", {"en", status
}, status
);
138 UnicodeString result
;
139 assertEquals("pat 0: ", 0, df
.getGroupingSize());
140 assertEquals("pat 0: ", (UBool
) FALSE
, (UBool
) df
.isGroupingUsed());
141 df
.setGroupingUsed(false);
142 assertEquals("pat 0 then disabled: ", 0, df
.getGroupingSize());
143 assertEquals("pat 0 then disabled: ", u
"1111", df
.format(1111, result
.remove()));
144 df
.setGroupingUsed(true);
145 assertEquals("pat 0 then enabled: ", 0, df
.getGroupingSize());
146 assertEquals("pat 0 then enabled: ", u
"1111", df
.format(1111, result
.remove()));
149 DecimalFormat
df("#,##0", {"en", status
}, status
);
150 UnicodeString result
;
151 assertEquals("pat #,##0: ", 3, df
.getGroupingSize());
152 assertEquals("pat #,##0: ", (UBool
) TRUE
, (UBool
) df
.isGroupingUsed());
153 df
.setGroupingUsed(false);
154 assertEquals("pat #,##0 then disabled: ", 3, df
.getGroupingSize());
155 assertEquals("pat #,##0 then disabled: ", u
"1111", df
.format(1111, result
.remove()));
156 df
.setGroupingUsed(true);
157 assertEquals("pat #,##0 then enabled: ", 3, df
.getGroupingSize());
158 assertEquals("pat #,##0 then enabled: ", u
"1,111", df
.format(1111, result
.remove()));
160 // end bug 13442 comment 14
162 status
= U_ZERO_ERROR
;
163 const UnicodeString
pattern("#,##0.# FF");
164 DecimalFormat
pat(pattern
, status
);
165 if(U_FAILURE(status
)) {
166 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern)");
170 status
= U_ZERO_ERROR
;
171 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(Locale::getFrench(), status
);
172 if(U_FAILURE(status
)) {
173 errln((UnicodeString
)"ERROR: Could not create DecimalFormatSymbols (French)");
177 status
= U_ZERO_ERROR
;
178 DecimalFormat
cust1(pattern
, symbols
, status
);
179 if(U_FAILURE(status
)) {
180 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
183 status
= U_ZERO_ERROR
;
184 DecimalFormat
cust2(pattern
, *symbols
, status
);
185 if(U_FAILURE(status
)) {
186 errln((UnicodeString
)"ERROR: Could not create DecimalFormat (pattern, symbols)");
189 DecimalFormat
copy(pat
);
191 // ======= Test clone(), assignment, and equality
193 logln((UnicodeString
)"Testing clone(), assignment and equality operators");
195 if( ! (copy
== pat
) || copy
!= pat
) {
196 errln((UnicodeString
)"ERROR: Copy constructor or == failed");
201 errln((UnicodeString
)"ERROR: Assignment (or !=) failed");
204 Format
*clone
= def
.clone();
205 if( ! (*clone
== def
) ) {
206 errln((UnicodeString
)"ERROR: Clone() failed");
210 // ======= Test various format() methods
212 logln((UnicodeString
)"Testing various format() methods");
214 double d
= -10456.0037;
215 int32_t l
= 100000000;
219 UnicodeString res1
, res2
, res3
, res4
;
220 FieldPosition
pos1(FieldPosition::DONT_CARE
), pos2(FieldPosition::DONT_CARE
), pos3(FieldPosition::DONT_CARE
), pos4(FieldPosition::DONT_CARE
);
222 res1
= def
.format(d
, res1
, pos1
);
223 logln( (UnicodeString
) "" + (int32_t) d
+ " formatted to " + res1
);
225 res2
= pat
.format(l
, res2
, pos2
);
226 logln((UnicodeString
) "" + (int32_t) l
+ " formatted to " + res2
);
228 status
= U_ZERO_ERROR
;
229 res3
= cust1
.format(fD
, res3
, pos3
, status
);
230 if(U_FAILURE(status
)) {
231 errln((UnicodeString
)"ERROR: format(Formattable [double]) failed");
233 logln((UnicodeString
) "" + (int32_t) fD
.getDouble() + " formatted to " + res3
);
235 status
= U_ZERO_ERROR
;
236 res4
= cust2
.format(fL
, res4
, pos4
, status
);
237 if(U_FAILURE(status
)) {
238 errln((UnicodeString
)"ERROR: format(Formattable [long]) failed");
240 logln((UnicodeString
) "" + fL
.getLong() + " formatted to " + res4
);
242 // ======= Test parse()
244 logln((UnicodeString
)"Testing parse()");
246 UnicodeString
text("-10,456.0037");
247 Formattable result1
, result2
;
248 ParsePosition
pos(0);
249 UnicodeString
patt("#,##0.#");
250 status
= U_ZERO_ERROR
;
251 pat
.applyPattern(patt
, status
);
252 if(U_FAILURE(status
)) {
253 errln((UnicodeString
)"ERROR: applyPattern() failed");
255 pat
.parse(text
, result1
, pos
);
256 if(result1
.getType() != Formattable::kDouble
&& result1
.getDouble() != d
) {
257 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
259 logln(text
+ " parsed into " + (int32_t) result1
.getDouble());
261 status
= U_ZERO_ERROR
;
262 pat
.parse(text
, result2
, status
);
263 if(U_FAILURE(status
)) {
264 errln((UnicodeString
)"ERROR: parse() failed");
266 if(result2
.getType() != Formattable::kDouble
&& result2
.getDouble() != d
) {
267 errln((UnicodeString
)"ERROR: Roundtrip failed (via parse()) for " + text
);
269 logln(text
+ " parsed into " + (int32_t) result2
.getDouble());
271 // ======= Test getters and setters
273 logln((UnicodeString
)"Testing getters and setters");
275 const DecimalFormatSymbols
*syms
= pat
.getDecimalFormatSymbols();
276 DecimalFormatSymbols
*newSyms
= new DecimalFormatSymbols(*syms
);
277 def
.setDecimalFormatSymbols(*newSyms
);
278 def
.adoptDecimalFormatSymbols(newSyms
); // don't use newSyms after this
279 if( *(pat
.getDecimalFormatSymbols()) != *(def
.getDecimalFormatSymbols())) {
280 errln((UnicodeString
)"ERROR: adopt or set DecimalFormatSymbols() failed");
283 UnicodeString posPrefix
;
284 pat
.setPositivePrefix("+");
285 posPrefix
= pat
.getPositivePrefix(posPrefix
);
286 logln((UnicodeString
)"Positive prefix (should be +): " + posPrefix
);
287 if(posPrefix
!= "+") {
288 errln((UnicodeString
)"ERROR: setPositivePrefix() failed");
291 UnicodeString negPrefix
;
292 pat
.setNegativePrefix("-");
293 negPrefix
= pat
.getNegativePrefix(negPrefix
);
294 logln((UnicodeString
)"Negative prefix (should be -): " + negPrefix
);
295 if(negPrefix
!= "-") {
296 errln((UnicodeString
)"ERROR: setNegativePrefix() failed");
299 UnicodeString posSuffix
;
300 pat
.setPositiveSuffix("_");
301 posSuffix
= pat
.getPositiveSuffix(posSuffix
);
302 logln((UnicodeString
)"Positive suffix (should be _): " + posSuffix
);
303 if(posSuffix
!= "_") {
304 errln((UnicodeString
)"ERROR: setPositiveSuffix() failed");
307 UnicodeString negSuffix
;
308 pat
.setNegativeSuffix("~");
309 negSuffix
= pat
.getNegativeSuffix(negSuffix
);
310 logln((UnicodeString
)"Negative suffix (should be ~): " + negSuffix
);
311 if(negSuffix
!= "~") {
312 errln((UnicodeString
)"ERROR: setNegativeSuffix() failed");
315 int32_t multiplier
= 0;
316 pat
.setMultiplier(8);
317 multiplier
= pat
.getMultiplier();
318 logln((UnicodeString
)"Multiplier (should be 8): " + multiplier
);
319 if(multiplier
!= 8) {
320 errln((UnicodeString
)"ERROR: setMultiplier() failed");
323 int32_t groupingSize
= 0;
324 pat
.setGroupingSize(2);
325 groupingSize
= pat
.getGroupingSize();
326 logln((UnicodeString
)"Grouping size (should be 2): " + (int32_t) groupingSize
);
327 if(groupingSize
!= 2) {
328 errln((UnicodeString
)"ERROR: setGroupingSize() failed");
331 pat
.setDecimalSeparatorAlwaysShown(TRUE
);
332 UBool tf
= pat
.isDecimalSeparatorAlwaysShown();
333 logln((UnicodeString
)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString
) (tf
? "TRUE" : "FALSE"));
335 errln((UnicodeString
)"ERROR: setDecimalSeparatorAlwaysShown() failed");
337 // Added by Ken Liu testing set/isExponentSignAlwaysShown
338 pat
.setExponentSignAlwaysShown(TRUE
);
339 UBool esas
= pat
.isExponentSignAlwaysShown();
340 logln((UnicodeString
)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString
) (esas
? "TRUE" : "FALSE"));
342 errln((UnicodeString
)"ERROR: ExponentSignAlwaysShown() failed");
345 // Added by Ken Liu testing set/isScientificNotation
346 pat
.setScientificNotation(TRUE
);
347 UBool sn
= pat
.isScientificNotation();
348 logln((UnicodeString
)"isScientificNotation (should be TRUE) is " + (UnicodeString
) (sn
? "TRUE" : "FALSE"));
350 errln((UnicodeString
)"ERROR: setScientificNotation() failed");
353 // Added by Ken Liu testing set/getMinimumExponentDigits
354 int8_t MinimumExponentDigits
= 0;
355 pat
.setMinimumExponentDigits(2);
356 MinimumExponentDigits
= pat
.getMinimumExponentDigits();
357 logln((UnicodeString
)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits
);
358 if(MinimumExponentDigits
!= 2) {
359 errln((UnicodeString
)"ERROR: setMinimumExponentDigits() failed");
362 // Added by Ken Liu testing set/getRoundingIncrement
363 double RoundingIncrement
= 0.0;
364 pat
.setRoundingIncrement(2.0);
365 RoundingIncrement
= pat
.getRoundingIncrement();
366 logln((UnicodeString
)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement
);
367 if(RoundingIncrement
!= 2.0) {
368 errln((UnicodeString
)"ERROR: setRoundingIncrement() failed");
370 //end of Ken's Adding
372 UnicodeString funkyPat
;
373 funkyPat
= pat
.toPattern(funkyPat
);
374 logln((UnicodeString
)"Pattern is " + funkyPat
);
376 UnicodeString locPat
;
377 locPat
= pat
.toLocalizedPattern(locPat
);
378 logln((UnicodeString
)"Localized pattern is " + locPat
);
380 // ======= Test applyPattern()
382 logln((UnicodeString
)"Testing applyPattern()");
383 pat
= DecimalFormat(status
); // reset
385 UnicodeString
p1("#,##0.0#;(#,##0.0#)");
386 logln((UnicodeString
)"Applying pattern " + p1
);
387 status
= U_ZERO_ERROR
;
388 pat
.applyPattern(p1
, status
);
389 if(U_FAILURE(status
)) {
390 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
393 s2
= pat
.toPattern(s2
);
394 logln((UnicodeString
)"Extracted pattern is " + s2
);
395 assertEquals("toPattern() result did not match pattern applied", p1
, s2
);
397 if(pat
.getSecondaryGroupingSize() != 0) {
398 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat
.getSecondaryGroupingSize());
401 if(pat
.getGroupingSize() != 3) {
402 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
405 UnicodeString
p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
406 logln((UnicodeString
)"Applying pattern " + p2
);
407 status
= U_ZERO_ERROR
;
408 pat
.applyLocalizedPattern(p2
, status
);
409 if(U_FAILURE(status
)) {
410 errln((UnicodeString
)"ERROR: applyPattern() failed with " + (int32_t) status
);
413 s3
= pat
.toLocalizedPattern(s3
);
414 logln((UnicodeString
)"Extracted pattern is " + s3
);
415 assertEquals("toLocalizedPattern() result did not match pattern applied", p2
, s3
);
417 status
= U_ZERO_ERROR
;
419 pat
.applyLocalizedPattern(p2
, pe
, status
);
420 if(U_FAILURE(status
)) {
421 errln((UnicodeString
)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status
);
424 s4
= pat
.toLocalizedPattern(s3
);
425 logln((UnicodeString
)"Extracted pattern is " + s4
);
426 assertEquals("toLocalizedPattern(with ParseErr) result did not match pattern applied", p2
, s4
);
428 if(pat
.getSecondaryGroupingSize() != 2) {
429 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat
.getSecondaryGroupingSize());
432 if(pat
.getGroupingSize() != 3) {
433 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat
.getGroupingSize());
436 // ======= Test getStaticClassID()
438 logln((UnicodeString
)"Testing getStaticClassID()");
440 status
= U_ZERO_ERROR
;
441 NumberFormat
*test
= new DecimalFormat(status
);
442 if(U_FAILURE(status
)) {
443 errln((UnicodeString
)"ERROR: Couldn't create a DecimalFormat");
446 if(test
->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
447 errln((UnicodeString
)"ERROR: getDynamicClassID() didn't return the expected value");
453 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
454 UErrorCode status
= U_ZERO_ERROR
;
456 CurrencyPluralInfo
*cpi
= new CurrencyPluralInfo(status
);
457 if(U_FAILURE(status
)) {
458 errln((UnicodeString
)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
461 CurrencyPluralInfo cpi1
= *cpi
;
463 if(cpi
->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
464 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
467 cpi
->setCurrencyPluralPattern("","",status
);
468 if(U_FAILURE(status
)) {
469 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
472 cpi
->setLocale(Locale::getCanada(), status
);
473 if(U_FAILURE(status
)) {
474 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setLocale");
477 cpi
->setPluralRules("",status
);
478 if(U_FAILURE(status
)) {
479 errln((UnicodeString
)"ERROR: CurrencyPluralInfo::setPluralRules");
482 DecimalFormat
*df
= new DecimalFormat(status
);
483 if(U_FAILURE(status
)) {
484 errcheckln(status
, "ERROR: Could not create DecimalFormat - %s", u_errorName(status
));
488 df
->adoptCurrencyPluralInfo(cpi
);
490 df
->getCurrencyPluralInfo();
492 df
->setCurrencyPluralInfo(cpi1
);
497 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
499 UErrorCode status
= U_ZERO_ERROR
;
500 double Roundingnumber
= 2.55;
501 double Roundingnumber1
= -2.55;
502 //+2.55 results -2.55 results
503 double result
[]={ 3.0, -2.0, // kRoundCeiling 0,
504 2.0, -3.0, // kRoundFloor 1,
505 2.0, -2.0, // kRoundDown 2,
506 3.0, -3.0, // kRoundUp 3,
507 3.0, -3.0, // kRoundHalfEven 4,
508 3.0, -3.0, // kRoundHalfDown 5,
509 3.0, -3.0 // kRoundHalfUp 6
511 DecimalFormat
pat(status
);
512 if(U_FAILURE(status
)) {
513 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
518 UnicodeString message
;
519 UnicodeString resultStr
;
520 for(mode
=0;mode
< 7;mode
++){
521 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
522 if(pat
.getRoundingMode() != (DecimalFormat::ERoundingMode
)mode
){
523 errln((UnicodeString
)"SetRoundingMode or GetRoundingMode failed for mode=" + mode
);
527 //for +2.55 with RoundingIncrement=1.0
528 pat
.setRoundingIncrement(1.0);
529 pat
.format(Roundingnumber
, resultStr
);
530 message
= (UnicodeString
)"round(" + (double)Roundingnumber
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
531 verify(message
, resultStr
, result
[i
++]);
535 //for -2.55 with RoundingIncrement=1.0
536 pat
.format(Roundingnumber1
, resultStr
);
537 message
= (UnicodeString
)"round(" + (double)Roundingnumber1
+ UnicodeString(",") + mode
+ UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
538 verify(message
, resultStr
, result
[i
++]);
544 void IntlTestDecimalFormatAPI::verify(const UnicodeString
& message
, const UnicodeString
& got
, double expected
){
545 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
546 UnicodeString
expectedStr("");
547 expectedStr
=expectedStr
+ expected
;
548 if(got
!= expectedStr
) {
549 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expectedStr
);
553 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString
& message
, const UnicodeString
& got
, UnicodeString
& expected
){
554 logln((UnicodeString
)message
+ got
+ (UnicodeString
)" Expected : " + expected
);
555 if(got
!= expected
) {
556 errln((UnicodeString
)"ERROR: " + message
+ got
+ (UnicodeString
)" Expected : " + expected
);
560 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
562 UErrorCode status
= U_ZERO_ERROR
;
563 DecimalFormat
pat(UnicodeString("#,##0.00"),status
);
564 if(U_FAILURE(status
)) {
565 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
569 // get default rounding increment
570 double roundingInc
= pat
.getRoundingIncrement();
571 if (roundingInc
!= 0.0) {
572 errln((UnicodeString
)"ERROR: Rounding increment not zero");
576 // With rounding now being handled by decNumber, we no longer
577 // set a rounding increment to enable non-default mode rounding,
578 // checking of which was the original point of this test.
580 // set rounding mode with zero increment. Rounding
581 // increment should not be set by this operation
582 pat
.setRoundingMode((DecimalFormat::ERoundingMode
)0);
583 roundingInc
= pat
.getRoundingIncrement();
584 if (roundingInc
!= 0.0) {
585 errln((UnicodeString
)"ERROR: Rounding increment not zero after setRoundingMode");
590 void IntlTestDecimalFormatAPI::TestScale()
592 typedef struct TestData
{
595 const char *expectedOutput
;
598 static TestData testData
[] = {
599 { 100.0, 3, "100,000" },
600 { 10034.0, -2, "100.34" },
601 { 0.86, -3, "0.0009" },
602 { -0.000455, 1, "-0%" },
603 { -0.000555, 1, "-1%" },
604 { 0.000455, 1, "0%" },
605 { 0.000555, 1, "1%" },
608 UErrorCode status
= U_ZERO_ERROR
;
609 DecimalFormat
pat(status
);
610 if(U_FAILURE(status
)) {
611 errcheckln(status
, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status
));
615 UnicodeString message
;
616 UnicodeString resultStr
;
618 UnicodeString
percentPattern("#,##0%");
619 pat
.setMaximumFractionDigits(4);
621 for(int32_t i
=0; i
< UPRV_LENGTHOF(testData
); i
++) {
623 pat
.applyPattern(percentPattern
,status
);
625 // Test both the attribute and the setter
627 pat
.setAttribute(UNUM_SCALE
, testData
[i
].inputScale
,status
);
628 assertEquals("", testData
[i
].inputScale
, pat
.getMultiplierScale());
630 pat
.setMultiplierScale(testData
[i
].inputScale
);
631 assertEquals("", testData
[i
].inputScale
, pat
.getAttribute(UNUM_SCALE
, status
));
633 pat
.format(testData
[i
].inputValue
, resultStr
);
634 message
= UnicodeString("Unexpected output for ") + testData
[i
].inputValue
+ UnicodeString(" and scale ") +
635 testData
[i
].inputScale
+ UnicodeString(". Got: ");
636 exp
= testData
[i
].expectedOutput
;
637 verifyString(message
, resultStr
, exp
);
645 #define ASSERT_EQUAL(expect, actual) { \
646 /* ICU-20080: Use temporary variables to avoid strange compiler behaviour \
647 (with the nice side-effect of avoiding repeated function calls too). */ \
648 auto lhs = (expect); \
649 auto rhs = (actual); \
651 sprintf(tmp, "(%g==%g)", (double)lhs, (double)rhs); \
652 assertTrue(tmp, (lhs==rhs), FALSE, TRUE, __FILE__, __LINE__); }
654 #if defined(_MSC_VER)
655 // Ignore the noisy warning 4805 (comparisons between int and bool) in the function below as we use the ICU TRUE/FALSE macros
656 // which are int values, whereas some of the DecimalQuantity methods return C++ bools.
657 #pragma warning(push)
658 #pragma warning(disable: 4805)
660 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
661 UErrorCode status
= U_ZERO_ERROR
;
663 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
664 assertSuccess(WHERE
, status
);
665 if (status
== U_MISSING_RESOURCE_ERROR
) {
668 number::impl::DecimalQuantity fd
;
669 df
->formatToDecimalQuantity(44, fd
, status
);
670 assertSuccess(WHERE
, status
);
671 ASSERT_EQUAL(44, fd
.getPluralOperand(PLURAL_OPERAND_N
));
672 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_V
));
673 ASSERT_EQUAL(FALSE
, fd
.isNegative());
675 df
->formatToDecimalQuantity(-44, fd
, status
);
676 assertSuccess(WHERE
, status
);
677 ASSERT_EQUAL(44, fd
.getPluralOperand(PLURAL_OPERAND_N
));
678 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_V
));
679 ASSERT_EQUAL(TRUE
, fd
.isNegative());
681 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status
), status
);
682 assertSuccess(WHERE
, status
);
683 df
->formatToDecimalQuantity(123.456, fd
, status
);
684 assertSuccess(WHERE
, status
);
685 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
686 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
687 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
688 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
689 ASSERT_EQUAL(123.456, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
690 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
691 ASSERT_EQUAL(FALSE
, fd
.isNegative());
693 df
->formatToDecimalQuantity(-123.456, fd
, status
);
694 assertSuccess(WHERE
, status
);
695 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
696 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
697 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
698 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
699 ASSERT_EQUAL(123.456, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
700 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
701 ASSERT_EQUAL(TRUE
, fd
.isNegative());
703 // test max int digits
704 df
->setMaximumIntegerDigits(2);
705 df
->formatToDecimalQuantity(123.456, fd
, status
);
706 assertSuccess(WHERE
, status
);
707 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
708 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
709 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
710 ASSERT_EQUAL(23, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
711 ASSERT_EQUAL(23.456, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
712 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
713 ASSERT_EQUAL(FALSE
, fd
.isNegative());
715 df
->formatToDecimalQuantity(-123.456, fd
, status
);
716 assertSuccess(WHERE
, status
);
717 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
718 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
719 ASSERT_EQUAL(456, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
720 ASSERT_EQUAL(23, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
721 ASSERT_EQUAL(23.456, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
722 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
723 ASSERT_EQUAL(TRUE
, fd
.isNegative());
725 // test max fraction digits
726 df
->setMaximumIntegerDigits(2000000000);
727 df
->setMaximumFractionDigits(2);
728 df
->formatToDecimalQuantity(123.456, fd
, status
);
729 assertSuccess(WHERE
, status
);
730 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
731 ASSERT_EQUAL(46, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
732 ASSERT_EQUAL(46, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
733 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
734 ASSERT_EQUAL(123.46, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
735 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
736 ASSERT_EQUAL(FALSE
, fd
.isNegative());
738 df
->formatToDecimalQuantity(-123.456, fd
, status
);
739 assertSuccess(WHERE
, status
);
740 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
741 ASSERT_EQUAL(46, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
742 ASSERT_EQUAL(46, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
743 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
744 ASSERT_EQUAL(123.46, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
745 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
746 ASSERT_EQUAL(TRUE
, fd
.isNegative());
748 // test esoteric rounding
749 df
->setMaximumFractionDigits(6);
750 df
->setRoundingIncrement(7.3);
752 df
->formatToDecimalQuantity(30.0, fd
, status
);
753 assertSuccess(WHERE
, status
);
754 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
755 ASSERT_EQUAL(20, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
756 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
757 ASSERT_EQUAL(29, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
758 ASSERT_EQUAL(29.2, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
759 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
760 ASSERT_EQUAL(FALSE
, fd
.isNegative());
762 df
->formatToDecimalQuantity(-30.0, fd
, status
);
763 assertSuccess(WHERE
, status
);
764 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
)); // v
765 ASSERT_EQUAL(20, fd
.getPluralOperand(PLURAL_OPERAND_F
)); // f
766 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_T
)); // t
767 ASSERT_EQUAL(29, fd
.getPluralOperand(PLURAL_OPERAND_I
)); // i
768 ASSERT_EQUAL(29.2, fd
.getPluralOperand(PLURAL_OPERAND_N
)); // n
769 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
770 ASSERT_EQUAL(TRUE
, fd
.isNegative());
772 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status
), status
);
773 assertSuccess(WHERE
, status
);
774 df
->formatToDecimalQuantity(123.456, fd
, status
);
775 assertSuccess(WHERE
, status
);
776 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_V
));
777 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
778 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
779 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
));
780 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
781 ASSERT_EQUAL(FALSE
, fd
.isNegative());
783 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
784 assertSuccess(WHERE
, status
);
785 df
->formatToDecimalQuantity(123.01, fd
, status
);
786 assertSuccess(WHERE
, status
);
787 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_V
));
788 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
789 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
790 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
));
791 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
792 ASSERT_EQUAL(FALSE
, fd
.isNegative());
794 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status
), status
);
795 assertSuccess(WHERE
, status
);
796 df
->formatToDecimalQuantity(123.06, fd
, status
);
797 assertSuccess(WHERE
, status
);
798 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_V
));
799 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_F
));
800 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_T
));
801 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
));
802 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
803 ASSERT_EQUAL(FALSE
, fd
.isNegative());
805 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
806 assertSuccess(WHERE
, status
);
807 df
->formatToDecimalQuantity(123, fd
, status
);
808 assertSuccess(WHERE
, status
);
809 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
810 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
811 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
812 ASSERT_EQUAL(123, fd
.getPluralOperand(PLURAL_OPERAND_I
));
813 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
814 ASSERT_EQUAL(FALSE
, fd
.isNegative());
816 df
.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status
), status
); // Significant Digits
817 assertSuccess(WHERE
, status
);
818 df
->formatToDecimalQuantity(1.23, fd
, status
);
819 assertSuccess(WHERE
, status
);
820 ASSERT_EQUAL(4, fd
.getPluralOperand(PLURAL_OPERAND_V
));
821 ASSERT_EQUAL(2300, fd
.getPluralOperand(PLURAL_OPERAND_F
));
822 ASSERT_EQUAL(23, fd
.getPluralOperand(PLURAL_OPERAND_T
));
823 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_I
));
824 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
825 ASSERT_EQUAL(FALSE
, fd
.isNegative());
827 df
->formatToDecimalQuantity(uprv_getInfinity(), fd
, status
);
828 assertSuccess(WHERE
, status
);
829 ASSERT_EQUAL(TRUE
, fd
.isNaN() || fd
.isInfinite());
830 df
->formatToDecimalQuantity(0.0, fd
, status
);
831 ASSERT_EQUAL(FALSE
, fd
.isNaN() || fd
.isInfinite());
832 df
->formatToDecimalQuantity(uprv_getNaN(), fd
, status
);
833 ASSERT_EQUAL(TRUE
, fd
.isNaN() || fd
.isInfinite());
834 assertSuccess(WHERE
, status
);
836 // Test Big Decimal input.
837 // 22 digits before and after decimal, will exceed the precision of a double
838 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
839 df
.adoptInsteadAndCheckErrorCode(
840 new DecimalFormat("#####################0.00####################", status
), status
);
841 assertSuccess(WHERE
, status
);
842 Formattable
fable("12.34", status
);
843 assertSuccess(WHERE
, status
);
844 df
->formatToDecimalQuantity(fable
, fd
, status
);
845 assertSuccess(WHERE
, status
);
846 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
847 ASSERT_EQUAL(34, fd
.getPluralOperand(PLURAL_OPERAND_F
));
848 ASSERT_EQUAL(34, fd
.getPluralOperand(PLURAL_OPERAND_T
));
849 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_I
));
850 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
851 ASSERT_EQUAL(FALSE
, fd
.isNegative());
853 fable
.setDecimalNumber("12.3456789012345678900123456789", status
);
854 assertSuccess(WHERE
, status
);
855 df
->formatToDecimalQuantity(fable
, fd
, status
);
856 assertSuccess(WHERE
, status
);
857 ASSERT_EQUAL(22, fd
.getPluralOperand(PLURAL_OPERAND_V
));
858 ASSERT_EQUAL(3456789012345678900LL, fd
.getPluralOperand(PLURAL_OPERAND_F
));
859 ASSERT_EQUAL(34567890123456789LL, fd
.getPluralOperand(PLURAL_OPERAND_T
));
860 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_I
));
861 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
862 ASSERT_EQUAL(FALSE
, fd
.isNegative());
864 // On field overflow, Integer part is truncated on the left, fraction part on the right.
865 fable
.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status
);
866 assertSuccess(WHERE
, status
);
867 df
->formatToDecimalQuantity(fable
, fd
, status
);
868 assertSuccess(WHERE
, status
);
869 ASSERT_EQUAL(22, fd
.getPluralOperand(PLURAL_OPERAND_V
));
870 ASSERT_EQUAL(1234567890123456789LL, fd
.getPluralOperand(PLURAL_OPERAND_F
));
871 ASSERT_EQUAL(1234567890123456789LL, fd
.getPluralOperand(PLURAL_OPERAND_T
));
872 ASSERT_EQUAL(345678901234567890LL, fd
.getPluralOperand(PLURAL_OPERAND_I
));
873 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
874 ASSERT_EQUAL(FALSE
, fd
.isNegative());
876 // Digits way to the right of the decimal but within the format's precision aren't truncated
877 fable
.setDecimalNumber("1.0000000000000000000012", status
);
878 assertSuccess(WHERE
, status
);
879 df
->formatToDecimalQuantity(fable
, fd
, status
);
880 assertSuccess(WHERE
, status
);
881 ASSERT_EQUAL(22, fd
.getPluralOperand(PLURAL_OPERAND_V
));
882 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_F
));
883 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_T
));
884 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_I
));
885 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
886 ASSERT_EQUAL(FALSE
, fd
.isNegative());
888 // Digits beyond the precision of the format are rounded away
889 fable
.setDecimalNumber("1.000000000000000000000012", status
);
890 assertSuccess(WHERE
, status
);
891 df
->formatToDecimalQuantity(fable
, fd
, status
);
892 assertSuccess(WHERE
, status
);
893 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
894 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
895 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
896 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_I
));
897 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
898 ASSERT_EQUAL(FALSE
, fd
.isNegative());
900 // Negative numbers come through
901 fable
.setDecimalNumber("-1.0000000000000000000012", status
);
902 assertSuccess(WHERE
, status
);
903 df
->formatToDecimalQuantity(fable
, fd
, status
);
904 assertSuccess(WHERE
, status
);
905 ASSERT_EQUAL(22, fd
.getPluralOperand(PLURAL_OPERAND_V
));
906 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_F
));
907 ASSERT_EQUAL(12, fd
.getPluralOperand(PLURAL_OPERAND_T
));
908 ASSERT_EQUAL(1, fd
.getPluralOperand(PLURAL_OPERAND_I
));
909 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
910 ASSERT_EQUAL(TRUE
, fd
.isNegative());
912 // MinFractionDigits from format larger than from number.
913 fable
.setDecimalNumber("1000000000000000000000.3", status
);
914 assertSuccess(WHERE
, status
);
915 df
->formatToDecimalQuantity(fable
, fd
, status
);
916 assertSuccess(WHERE
, status
);
917 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
918 ASSERT_EQUAL(30, fd
.getPluralOperand(PLURAL_OPERAND_F
));
919 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_T
));
920 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_I
));
921 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
922 ASSERT_EQUAL(FALSE
, fd
.isNegative());
924 fable
.setDecimalNumber("1000000000000000050000.3", status
);
925 assertSuccess(WHERE
, status
);
926 df
->formatToDecimalQuantity(fable
, fd
, status
);
927 assertSuccess(WHERE
, status
);
928 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
929 ASSERT_EQUAL(30, fd
.getPluralOperand(PLURAL_OPERAND_F
));
930 ASSERT_EQUAL(3, fd
.getPluralOperand(PLURAL_OPERAND_T
));
931 ASSERT_EQUAL(50000LL, fd
.getPluralOperand(PLURAL_OPERAND_I
));
932 ASSERT_EQUAL(FALSE
, fd
.hasIntegerValue());
933 ASSERT_EQUAL(FALSE
, fd
.isNegative());
935 // Test some int64_t values that are out of the range of a double
936 fable
.setInt64(4503599627370496LL);
937 assertSuccess(WHERE
, status
);
938 df
->formatToDecimalQuantity(fable
, fd
, status
);
939 assertSuccess(WHERE
, status
);
940 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
941 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
942 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
943 ASSERT_EQUAL(4503599627370496LL, fd
.getPluralOperand(PLURAL_OPERAND_I
));
944 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
945 ASSERT_EQUAL(FALSE
, fd
.isNegative());
947 fable
.setInt64(4503599627370497LL);
948 assertSuccess(WHERE
, status
);
949 df
->formatToDecimalQuantity(fable
, fd
, status
);
950 assertSuccess(WHERE
, status
);
951 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
952 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
953 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
954 ASSERT_EQUAL(4503599627370497LL, fd
.getPluralOperand(PLURAL_OPERAND_I
));
955 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
956 ASSERT_EQUAL(FALSE
, fd
.isNegative());
958 fable
.setInt64(9223372036854775807LL);
959 assertSuccess(WHERE
, status
);
960 df
->formatToDecimalQuantity(fable
, fd
, status
);
961 assertSuccess(WHERE
, status
);
962 ASSERT_EQUAL(2, fd
.getPluralOperand(PLURAL_OPERAND_V
));
963 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_F
));
964 ASSERT_EQUAL(0, fd
.getPluralOperand(PLURAL_OPERAND_T
));
965 // note: going through DigitList path to FixedDecimal, which is trimming
966 // int64_t fields to 18 digits. See ticket Ticket #10374
967 ASSERT_EQUAL(223372036854775807LL, fd
.getPluralOperand(PLURAL_OPERAND_I
));
968 ASSERT_EQUAL(TRUE
, fd
.hasIntegerValue());
969 ASSERT_EQUAL(FALSE
, fd
.isNegative());
972 #if defined(_MSC_VER)
973 // Re-enable 4805 warnings (comparisons between int and bool).
977 void IntlTestDecimalFormatAPI::TestBadFastpath() {
978 UErrorCode status
= U_ZERO_ERROR
;
980 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###", status
), status
);
981 if (U_FAILURE(status
)) {
982 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
988 assertEquals("Format 1234", "1234", df
->format((int32_t)1234, fmt
));
989 df
->setGroupingUsed(FALSE
);
991 assertEquals("Format 1234", "1234", df
->format((int32_t)1234, fmt
));
992 df
->setGroupingUsed(TRUE
);
993 df
->setGroupingSize(3);
995 assertEquals("Format 1234 w/ grouping", "1,234", df
->format((int32_t)1234, fmt
));
998 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
999 UErrorCode status
= U_ZERO_ERROR
;
1000 UnicodeString
text("99");
1001 Formattable result1
;
1002 UnicodeString
pat1("##.0000");
1003 UnicodeString
pat2("00.0");
1005 LocalPointer
<DecimalFormat
> df(new DecimalFormat(pat1
, status
), status
);
1006 if (U_FAILURE(status
)) {
1007 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status
));
1011 status
= U_ZERO_ERROR
;
1012 df
->applyPattern(pat1
, status
);
1013 if(U_FAILURE(status
)) {
1014 errln((UnicodeString
)"ERROR: applyPattern() failed");
1016 df
->parse(text
, result1
, status
);
1017 if(U_FAILURE(status
)) {
1018 errln((UnicodeString
)"ERROR: parse() failed");
1020 df
->setDecimalPatternMatchRequired(TRUE
);
1021 df
->parse(text
, result1
, status
);
1022 if(U_SUCCESS(status
)) {
1023 errln((UnicodeString
)"ERROR: unexpected parse()");
1027 status
= U_ZERO_ERROR
;
1028 df
->applyPattern(pat2
, status
);
1029 df
->setDecimalPatternMatchRequired(FALSE
);
1030 if(U_FAILURE(status
)) {
1031 errln((UnicodeString
)"ERROR: applyPattern(2) failed");
1033 df
->parse(text
, result1
, status
);
1034 if(U_FAILURE(status
)) {
1035 errln((UnicodeString
)"ERROR: parse(2) failed - " + u_errorName(status
));
1037 df
->setDecimalPatternMatchRequired(TRUE
);
1038 df
->parse(text
, result1
, status
);
1039 if(U_SUCCESS(status
)) {
1040 errln((UnicodeString
)"ERROR: unexpected parse(2)");
1044 void IntlTestDecimalFormatAPI::testErrorCode() {
1045 // Try each DecimalFormat constructor with an errorCode set on input,
1046 // Verify no crashes or leaks, and that the errorCode is not altered.
1048 UErrorCode status
= U_ZERO_ERROR
;
1049 const UnicodeString
pattern(u
"0.###E0");
1051 DecimalFormatSymbols
symbols(Locale::getUS(), status
);
1052 assertSuccess(WHERE
, status
);
1055 status
= U_INTERNAL_PROGRAM_ERROR
;
1056 DecimalFormat
df(status
);
1057 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1060 status
= U_INTERNAL_PROGRAM_ERROR
;
1061 DecimalFormat
df(pattern
, status
);
1062 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1065 status
= U_INTERNAL_PROGRAM_ERROR
;
1066 DecimalFormat
df(pattern
, new DecimalFormatSymbols(symbols
), status
);
1067 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1070 status
= U_INTERNAL_PROGRAM_ERROR
;
1071 DecimalFormat
df(pattern
, new DecimalFormatSymbols(symbols
), UNUM_DECIMAL_COMPACT_LONG
, status
);
1072 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1075 status
= U_INTERNAL_PROGRAM_ERROR
;
1076 DecimalFormat
df(pattern
, new DecimalFormatSymbols(symbols
), pe
, status
);
1077 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1080 status
= U_INTERNAL_PROGRAM_ERROR
;
1081 DecimalFormat
df(pattern
, symbols
,status
);
1082 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1085 // Try each DecimalFormat method with an error code parameter, verifying that
1086 // an input error is not altered, and that no segmentation faults occur.
1088 status
= U_INTERNAL_PROGRAM_ERROR
;
1089 DecimalFormat
dfBogus(status
);
1090 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1092 status
= U_ZERO_ERROR
;
1093 DecimalFormat
dfGood(pattern
, new DecimalFormatSymbols(symbols
), status
);
1094 assertSuccess(WHERE
, status
);
1096 for (DecimalFormat
*df
: {&dfBogus
, &dfGood
}) {
1097 status
= U_INTERNAL_PROGRAM_ERROR
;
1098 df
->setAttribute(UNUM_PARSE_INT_ONLY
, 0, status
);
1099 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1101 status
= U_INTERNAL_PROGRAM_ERROR
;
1102 df
->getAttribute(UNUM_MAX_FRACTION_DIGITS
, status
);
1103 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1105 status
= U_INTERNAL_PROGRAM_ERROR
;
1108 df
->format(1.2, dest
, fp
, status
);
1109 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1111 status
= U_INTERNAL_PROGRAM_ERROR
;
1112 df
->format(1.2, dest
, nullptr, status
);
1113 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1115 status
= U_INTERNAL_PROGRAM_ERROR
;
1116 df
->format((int32_t)666, dest
, nullptr, status
);
1117 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1119 status
= U_INTERNAL_PROGRAM_ERROR
;
1120 df
->format((int64_t)666, dest
, nullptr, status
);
1121 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1123 status
= U_INTERNAL_PROGRAM_ERROR
;
1124 df
->format(StringPiece("3.1415926535897932384626"), dest
, nullptr, status
);
1125 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1127 status
= U_INTERNAL_PROGRAM_ERROR
;
1128 df
->applyPattern(pattern
, status
);
1129 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1131 status
= U_INTERNAL_PROGRAM_ERROR
;
1132 df
->applyLocalizedPattern(pattern
, pe
, status
);
1133 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1135 status
= U_INTERNAL_PROGRAM_ERROR
;
1136 df
->applyLocalizedPattern(pattern
, status
);
1137 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1139 status
= U_INTERNAL_PROGRAM_ERROR
;
1140 df
->setCurrency(u
"USD", status
);
1141 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1143 status
= U_INTERNAL_PROGRAM_ERROR
;
1144 df
->setCurrencyUsage(UCURR_USAGE_CASH
, &status
);
1145 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1149 void IntlTestDecimalFormatAPI::testInvalidObject() {
1151 UErrorCode status
= U_INTERNAL_PROGRAM_ERROR
;
1152 DecimalFormat
dfBogus(status
);
1153 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1155 status
= U_ZERO_ERROR
;
1156 DecimalFormat
dfGood(status
);
1157 assertSuccess(WHERE
, status
);
1159 // An invalid object should not be equal to a valid object.
1160 // This also tests that no segmentation fault occurs in the comparison operator due
1161 // to any dangling/nullptr pointers. (ICU-20381).
1162 assertTrue(WHERE
, dfGood
!= dfBogus
);
1164 status
= U_MEMORY_ALLOCATION_ERROR
;
1165 DecimalFormat
dfBogus2(status
);
1166 assertEquals(WHERE
, U_MEMORY_ALLOCATION_ERROR
, status
);
1168 // Two invalid objects should not be equal.
1169 // (Also verify that nullptr isn't t dereferenced in the comparision operator.)
1170 assertTrue(WHERE
, dfBogus
!= dfBogus2
);
1172 // Verify the comparison operator works for two valid objects.
1173 status
= U_ZERO_ERROR
;
1174 DecimalFormat
dfGood2(status
);
1175 assertSuccess(WHERE
, status
);
1176 assertTrue(WHERE
, dfGood
== dfGood2
);
1178 // Verify that the assignment operator sets the object to an invalid state, and
1179 // that no segmentation fault occurs due to any dangling/nullptr pointers.
1180 status
= U_INTERNAL_PROGRAM_ERROR
;
1181 DecimalFormat dfAssignmentBogus
= DecimalFormat(status
);
1182 // Verify comparison for the assigned object.
1183 assertTrue(WHERE
, dfAssignmentBogus
!= dfGood
);
1184 assertTrue(WHERE
, dfAssignmentBogus
!= dfGood2
);
1185 assertTrue(WHERE
, dfAssignmentBogus
!= dfBogus
);
1187 // Verify that cloning our original invalid object gives nullptr.
1188 auto dfBogusClone
= dfBogus
.clone();
1189 assertTrue(WHERE
, dfBogusClone
== nullptr);
1190 // Verify that cloning our assigned invalid object gives nullptr.
1191 auto dfBogusClone2
= dfAssignmentBogus
.clone();
1192 assertTrue(WHERE
, dfBogusClone2
== nullptr);
1194 // Verify copy constructing from an invalid object is also invalid.
1195 DecimalFormat
dfCopy(dfBogus
);
1196 assertTrue(WHERE
, dfCopy
!= dfGood
);
1197 assertTrue(WHERE
, dfCopy
!= dfGood2
);
1198 assertTrue(WHERE
, dfCopy
!= dfBogus
);
1199 DecimalFormat dfCopyAssign
= dfBogus
;
1200 assertTrue(WHERE
, dfCopyAssign
!= dfGood
);
1201 assertTrue(WHERE
, dfCopyAssign
!= dfGood2
);
1202 assertTrue(WHERE
, dfCopyAssign
!= dfBogus
);
1203 auto dfBogusCopyClone1
= dfCopy
.clone();
1204 auto dfBogusCopyClone2
= dfCopyAssign
.clone();
1205 assertTrue(WHERE
, dfBogusCopyClone1
== nullptr);
1206 assertTrue(WHERE
, dfBogusCopyClone2
== nullptr);
1210 // Try each DecimalFormat class method that lacks an error code parameter, verifying
1211 // we don't crash (segmentation fault) on invalid objects.
1213 UErrorCode status
= U_ZERO_ERROR
;
1214 const UnicodeString
pattern(u
"0.###E0");
1216 DecimalFormatSymbols
symbols(Locale::getUS(), status
);
1217 assertSuccess(WHERE
, status
);
1218 CurrencyPluralInfo
currencyPI(status
);
1219 assertSuccess(WHERE
, status
);
1221 status
= U_INTERNAL_PROGRAM_ERROR
;
1222 DecimalFormat
dfBogus1(status
);
1223 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1225 status
= U_INTERNAL_PROGRAM_ERROR
;
1226 DecimalFormat
dfBogus2(pattern
, status
);
1227 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1229 status
= U_INTERNAL_PROGRAM_ERROR
;
1230 DecimalFormat
dfBogus3(pattern
, new DecimalFormatSymbols(symbols
), status
);
1231 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1233 status
= U_INTERNAL_PROGRAM_ERROR
;
1234 DecimalFormat
dfBogus4(pattern
, new DecimalFormatSymbols(symbols
), UNumberFormatStyle::UNUM_CURRENCY
, status
);
1235 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1237 status
= U_INTERNAL_PROGRAM_ERROR
;
1238 DecimalFormat
dfBogus5(pattern
, new DecimalFormatSymbols(symbols
), pe
, status
);
1239 assertEquals(WHERE
, U_INTERNAL_PROGRAM_ERROR
, status
);
1241 for (DecimalFormat
*df
: {&dfBogus1
, &dfBogus2
, &dfBogus3
, &dfBogus4
, &dfBogus5
})
1243 df
->setGroupingUsed(true);
1245 df
->setParseIntegerOnly(false);
1247 df
->setLenient(true);
1249 auto dfClone
= df
->clone();
1250 assertTrue(WHERE
, dfClone
== nullptr);
1254 df
->format(1.2, dest
, fp
);
1255 df
->format(static_cast<int32_t>(1234), dest
, fp
);
1256 df
->format(static_cast<int64_t>(1234), dest
, fp
);
1258 UnicodeString
text("-1,234.00");
1260 ParsePosition
pos(0);
1261 df
->parse(text
, result
, pos
);
1263 CurrencyAmount
* ca
= df
->parseCurrency(text
, pos
);
1264 assertTrue(WHERE
, ca
== nullptr);
1266 const DecimalFormatSymbols
* dfs
= df
->getDecimalFormatSymbols();
1267 assertTrue(WHERE
, dfs
== nullptr);
1269 df
->adoptDecimalFormatSymbols(nullptr);
1271 df
->setDecimalFormatSymbols(symbols
);
1273 const CurrencyPluralInfo
* cpi
= df
->getCurrencyPluralInfo();
1274 assertTrue(WHERE
, cpi
== nullptr);
1276 df
->adoptCurrencyPluralInfo(nullptr);
1278 df
->setCurrencyPluralInfo(currencyPI
);
1280 UnicodeString
prefix("-123");
1281 df
->getPositivePrefix(dest
);
1282 df
->setPositivePrefix(prefix
);
1283 df
->getNegativePrefix(dest
);
1284 df
->setNegativePrefix(prefix
);
1285 df
->getPositiveSuffix(dest
);
1286 df
->setPositiveSuffix(prefix
);
1287 df
->getNegativeSuffix(dest
);
1288 df
->setNegativeSuffix(prefix
);
1290 df
->isSignAlwaysShown();
1292 df
->setSignAlwaysShown(true);
1294 df
->getMultiplier();
1295 df
->setMultiplier(10);
1297 df
->getMultiplierScale();
1298 df
->setMultiplierScale(2);
1300 df
->getRoundingIncrement();
1301 df
->setRoundingIncrement(1.2);
1303 df
->getRoundingMode();
1304 df
->setRoundingMode(DecimalFormat::ERoundingMode::kRoundDown
);
1306 df
->getFormatWidth();
1307 df
->setFormatWidth(0);
1309 UnicodeString
pad(" ");
1310 df
->getPadCharacterString();
1311 df
->setPadCharacter(pad
);
1313 df
->getPadPosition();
1314 df
->setPadPosition(DecimalFormat::EPadPosition::kPadBeforePrefix
);
1316 df
->isScientificNotation();
1317 df
->setScientificNotation(false);
1319 df
->getMinimumExponentDigits();
1320 df
->setMinimumExponentDigits(1);
1322 df
->isExponentSignAlwaysShown();
1323 df
->setExponentSignAlwaysShown(true);
1325 df
->getGroupingSize();
1326 df
->setGroupingSize(3);
1328 df
->getSecondaryGroupingSize();
1329 df
->setSecondaryGroupingSize(-1);
1331 df
->getMinimumGroupingDigits();
1332 df
->setMinimumGroupingDigits(-1);
1334 df
->isDecimalSeparatorAlwaysShown();
1335 df
->setDecimalSeparatorAlwaysShown(true);
1337 df
->isDecimalPatternMatchRequired();
1338 df
->setDecimalPatternMatchRequired(false);
1340 df
->isParseNoExponent();
1341 df
->setParseNoExponent(true);
1343 df
->isParseCaseSensitive();
1344 df
->setParseCaseSensitive(false);
1346 df
->isFormatFailIfMoreThanMaxDigits();
1347 df
->setFormatFailIfMoreThanMaxDigits(true);
1349 df
->toPattern(dest
);
1350 df
->toLocalizedPattern(dest
);
1352 df
->setMaximumIntegerDigits(10);
1353 df
->setMinimumIntegerDigits(0);
1355 df
->setMaximumFractionDigits(2);
1356 df
->setMinimumFractionDigits(0);
1358 df
->getMinimumSignificantDigits();
1359 df
->setMinimumSignificantDigits(0);
1361 df
->getMaximumSignificantDigits();
1362 df
->setMaximumSignificantDigits(5);
1364 df
->areSignificantDigitsUsed();
1365 df
->setSignificantDigitsUsed(true);
1367 df
->setCurrency(u
"USD");
1369 df
->getCurrencyUsage();
1371 const number::LocalizedNumberFormatter
* lnf
= df
->toNumberFormatter(status
);
1372 assertEquals("toNumberFormatter should return nullptr",
1373 (int64_t) nullptr, (int64_t) lnf
);
1375 // Should not crash when chaining to error code enabled methods on the LNF
1376 lnf
->formatInt(1, status
);
1377 lnf
->formatDouble(1.0, status
);
1378 lnf
->formatDecimal("1", status
);
1379 lnf
->toFormat(status
);
1380 lnf
->toSkeleton(status
);
1381 lnf
->copyErrorTo(status
);
1387 #endif /* #if !UCONFIG_NO_FORMATTING */