1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2015, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "dcfmapts.h"
14
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"
22
23 #include "putilimp.h"
24 #include "plurrule_impl.h"
25 #include <stdio.h>
26
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.
30
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)31 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
32 {
33 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI");
34 switch (index) {
35 case 0: name = "DecimalFormat API test";
36 if (exec) {
37 logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)"");
38 UErrorCode status = U_ZERO_ERROR;
39 Locale saveLocale;
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");
43 }
44 testAPI(/*par*/);
45 Locale::setDefault(saveLocale, status);
46 }
47 break;
48 case 1: name = "Rounding test";
49 if(exec) {
50 logln((UnicodeString)"DecimalFormat Rounding test---");
51 testRounding(/*par*/);
52 }
53 break;
54 case 2: name = "Test6354";
55 if(exec) {
56 logln((UnicodeString)"DecimalFormat Rounding Increment test---");
57 testRoundingInc(/*par*/);
58 }
59 break;
60 case 3: name = "TestCurrencyPluralInfo";
61 if(exec) {
62 logln((UnicodeString)"CurrencyPluralInfo API test---");
63 TestCurrencyPluralInfo();
64 }
65 break;
66 case 4: name = "TestScale";
67 if(exec) {
68 logln((UnicodeString)"Scale test---");
69 TestScale();
70 }
71 break;
72 case 5: name = "TestFixedDecimal";
73 if(exec) {
74 logln((UnicodeString)"TestFixedDecimal ---");
75 TestFixedDecimal();
76 }
77 break;
78 case 6: name = "TestBadFastpath";
79 if(exec) {
80 logln((UnicodeString)"TestBadFastpath ---");
81 TestBadFastpath();
82 }
83 break;
84 case 7: name = "TestRequiredDecimalPoint";
85 if(exec) {
86 logln((UnicodeString)"TestRequiredDecimalPoint ---");
87 TestRequiredDecimalPoint();
88 }
89 break;
90 default: name = ""; break;
91 }
92 }
93
94 /**
95 * This test checks various generic API methods in DecimalFormat to achieve 100%
96 * API coverage.
97 */
testAPI()98 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
99 {
100 UErrorCode status = U_ZERO_ERROR;
101
102 // ======= Test constructors
103
104 logln((UnicodeString)"Testing DecimalFormat constructors");
105
106 DecimalFormat def(status);
107 if(U_FAILURE(status)) {
108 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
109 return;
110 }
111
112 // bug 10864
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.");
117 }
118 noGrouping.setGroupingUsed(TRUE);
119 if (noGrouping.getGroupingSize() != 0) {
120 errln("Grouping size should still be 0.");
121 }
122 // end bug 10864
123
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)");
129 return;
130 }
131
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)");
136 return;
137 }
138
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*)");
143 }
144
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)");
149 }
150
151 DecimalFormat copy(pat);
152
153 // ======= Test clone(), assignment, and equality
154
155 logln((UnicodeString)"Testing clone(), assignment and equality operators");
156
157 if( ! (copy == pat) || copy != pat) {
158 errln((UnicodeString)"ERROR: Copy constructor or == failed");
159 }
160
161 copy = cust1;
162 if(copy != cust1) {
163 errln((UnicodeString)"ERROR: Assignment (or !=) failed");
164 }
165
166 Format *clone = def.clone();
167 if( ! (*clone == def) ) {
168 errln((UnicodeString)"ERROR: Clone() failed");
169 }
170 delete clone;
171
172 // ======= Test various format() methods
173
174 logln((UnicodeString)"Testing various format() methods");
175
176 double d = -10456.0037;
177 int32_t l = 100000000;
178 Formattable fD(d);
179 Formattable fL(l);
180
181 UnicodeString res1, res2, res3, res4;
182 FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE), pos3(FieldPosition::DONT_CARE), pos4(FieldPosition::DONT_CARE);
183
184 res1 = def.format(d, res1, pos1);
185 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1);
186
187 res2 = pat.format(l, res2, pos2);
188 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2);
189
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");
194 }
195 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3);
196
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");
201 }
202 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4);
203
204 // ======= Test parse()
205
206 logln((UnicodeString)"Testing parse()");
207
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");
216 }
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);
220 }
221 logln(text + " parsed into " + (int32_t) result1.getDouble());
222
223 status = U_ZERO_ERROR;
224 pat.parse(text, result2, status);
225 if(U_FAILURE(status)) {
226 errln((UnicodeString)"ERROR: parse() failed");
227 }
228 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) {
229 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
230 }
231 logln(text + " parsed into " + (int32_t) result2.getDouble());
232
233 // ======= Test getters and setters
234
235 logln((UnicodeString)"Testing getters and setters");
236
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");
243 }
244
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");
251 }
252
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");
259 }
260
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");
267 }
268
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");
275 }
276
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");
283 }
284
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");
291 }
292
293 pat.setDecimalSeparatorAlwaysShown(TRUE);
294 UBool tf = pat.isDecimalSeparatorAlwaysShown();
295 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE"));
296 if(tf != TRUE) {
297 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed");
298 }
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"));
303 if(esas != TRUE) {
304 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed");
305 }
306
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"));
311 if(sn != TRUE) {
312 errln((UnicodeString)"ERROR: setScientificNotation() failed");
313 }
314
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");
322 }
323
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");
331 }
332 //end of Ken's Adding
333
334 UnicodeString funkyPat;
335 funkyPat = pat.toPattern(funkyPat);
336 logln((UnicodeString)"Pattern is " + funkyPat);
337
338 UnicodeString locPat;
339 locPat = pat.toLocalizedPattern(locPat);
340 logln((UnicodeString)"Localized pattern is " + locPat);
341
342 // ======= Test applyPattern()
343
344 logln((UnicodeString)"Testing applyPattern()");
345
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);
352 }
353 UnicodeString s2;
354 s2 = pat.toPattern(s2);
355 logln((UnicodeString)"Extracted pattern is " + s2);
356 if(s2 != p1) {
357 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied");
358 }
359
360 if(pat.getSecondaryGroupingSize() != 0) {
361 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize());
362 }
363
364 if(pat.getGroupingSize() != 3) {
365 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
366 }
367
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);
374 }
375 UnicodeString s3;
376 s3 = pat.toLocalizedPattern(s3);
377 logln((UnicodeString)"Extracted pattern is " + s3);
378 if(s3 != p2) {
379 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied");
380 }
381
382 status = U_ZERO_ERROR;
383 UParseError pe;
384 pat.applyLocalizedPattern(p2, pe, status);
385 if(U_FAILURE(status)) {
386 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status);
387 }
388 UnicodeString s4;
389 s4 = pat.toLocalizedPattern(s3);
390 logln((UnicodeString)"Extracted pattern is " + s4);
391 if(s4 != p2) {
392 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
393 }
394
395 if(pat.getSecondaryGroupingSize() != 2) {
396 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize());
397 }
398
399 if(pat.getGroupingSize() != 3) {
400 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
401 }
402
403 // ======= Test getStaticClassID()
404
405 logln((UnicodeString)"Testing getStaticClassID()");
406
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");
411 }
412
413 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
414 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value");
415 }
416
417 delete test;
418 }
419
TestCurrencyPluralInfo()420 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
421 UErrorCode status = U_ZERO_ERROR;
422
423 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status);
424 if(U_FAILURE(status)) {
425 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
426 }
427
428 CurrencyPluralInfo cpi1 = *cpi;
429
430 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
431 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
432 }
433
434 cpi->setCurrencyPluralPattern("","",status);
435 if(U_FAILURE(status)) {
436 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
437 }
438
439 cpi->setLocale(Locale::getCanada(), status);
440 if(U_FAILURE(status)) {
441 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale");
442 }
443
444 cpi->setPluralRules("",status);
445 if(U_FAILURE(status)) {
446 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules");
447 }
448
449 DecimalFormat *df = new DecimalFormat(status);
450 if(U_FAILURE(status)) {
451 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status));
452 return;
453 }
454
455 df->adoptCurrencyPluralInfo(cpi);
456
457 df->getCurrencyPluralInfo();
458
459 df->setCurrencyPluralInfo(cpi1);
460
461 delete df;
462 }
463
testRounding()464 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
465 {
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
477 };
478 DecimalFormat pat(status);
479 if(U_FAILURE(status)) {
480 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
481 return;
482 }
483 uint16_t mode;
484 uint16_t i=0;
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);
491 }
492
493
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++]);
499 message.remove();
500 resultStr.remove();
501
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++]);
506 message.remove();
507 resultStr.remove();
508 }
509
510 }
verify(const UnicodeString & message,const UnicodeString & got,double expected)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);
517 }
518 }
519
verifyString(const UnicodeString & message,const UnicodeString & got,UnicodeString & expected)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);
524 }
525 }
526
testRoundingInc()527 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
528 {
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));
533 return;
534 }
535
536 // get default rounding increment
537 double roundingInc = pat.getRoundingIncrement();
538 if (roundingInc != 0.0) {
539 errln((UnicodeString)"ERROR: Rounding increment not zero");
540 return;
541 }
542
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.
546
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");
553 return;
554 }
555 }
556
TestScale()557 void IntlTestDecimalFormatAPI::TestScale()
558 {
559 typedef struct TestData {
560 double inputValue;
561 int inputScale;
562 const char *expectedOutput;
563 } TestData;
564
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%" },
573 };
574
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));
579 return;
580 }
581
582 UnicodeString message;
583 UnicodeString resultStr;
584 UnicodeString exp;
585 UnicodeString percentPattern("#,##0%");
586 pat.setMaximumFractionDigits(4);
587
588 for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) {
589 if ( i > 2 ) {
590 pat.applyPattern(percentPattern,status);
591 }
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);
598 message.remove();
599 resultStr.remove();
600 exp.remove();
601 }
602 }
603
604
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__); }
607
TestFixedDecimal()608 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
609 UErrorCode status = U_ZERO_ERROR;
610
611 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
612 TEST_ASSERT_STATUS(status);
613 if (status == U_MISSING_RESOURCE_ERROR) {
614 return;
615 }
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);
621
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);
627
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);
639
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);
649
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);
661
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);
671
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);
684
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);
694
695 // test esoteric rounding
696 df->setMaximumFractionDigits(6);
697 df->setRoundingIncrement(7.3);
698
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);
708
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);
718
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);
729
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);
740
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);
751
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);
762
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);
773
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);
782
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);
799
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);
810
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);
822
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);
834
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);
846
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);
858
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);
870
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);
881
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);
893
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);
904
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);
917 }
918 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
919 ASSERT_EQUAL(FALSE, fd.isNegative);
920
921 }
922
TestBadFastpath()923 void IntlTestDecimalFormatAPI::TestBadFastpath() {
924 UErrorCode status = U_ZERO_ERROR;
925
926 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
927 if (U_FAILURE(status)) {
928 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
929 return;
930 }
931
932 UnicodeString fmt;
933 fmt.remove();
934 assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
935 df->setGroupingUsed(FALSE);
936 fmt.remove();
937 assertEquals("Format 1234", "1234", df->format((int32_t)1234, fmt));
938 df->setGroupingUsed(TRUE);
939 df->setGroupingSize(3);
940 fmt.remove();
941 assertEquals("Format 1234 w/ grouping", "1,234", df->format((int32_t)1234, fmt));
942 }
943
TestRequiredDecimalPoint()944 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
945 UErrorCode status = U_ZERO_ERROR;
946 UnicodeString text("99");
947 Formattable result1;
948 UnicodeString pat1("##.0000");
949 UnicodeString pat2("00.0");
950
951 LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status);
952 if (U_FAILURE(status)) {
953 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
954 return;
955 }
956
957 status = U_ZERO_ERROR;
958 df->applyPattern(pat1, status);
959 if(U_FAILURE(status)) {
960 errln((UnicodeString)"ERROR: applyPattern() failed");
961 }
962 df->parse(text, result1, status);
963 if(U_FAILURE(status)) {
964 errln((UnicodeString)"ERROR: parse() failed");
965 }
966 df->setDecimalPatternMatchRequired(TRUE);
967 df->parse(text, result1, status);
968 if(U_SUCCESS(status)) {
969 errln((UnicodeString)"ERROR: unexpected parse()");
970 }
971
972
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");
978 }
979 df->parse(text, result1, status);
980 if(U_FAILURE(status)) {
981 errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status));
982 }
983 df->setDecimalPatternMatchRequired(TRUE);
984 df->parse(text, result1, status);
985 if(U_SUCCESS(status)) {
986 errln((UnicodeString)"ERROR: unexpected parse(2)");
987 }
988 }
989
990 #endif /* #if !UCONFIG_NO_FORMATTING */
991