1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "dcfmapts.h"
12
13 #include "unicode/currpinf.h"
14 #include "unicode/dcfmtsym.h"
15 #include "unicode/decimfmt.h"
16 #include "unicode/fmtable.h"
17 #include "unicode/localpointer.h"
18 #include "unicode/parseerr.h"
19 #include "unicode/stringpiece.h"
20
21 #include "putilimp.h"
22 #include "plurrule_impl.h"
23 #include <stdio.h>
24
25 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
26 // try to test the full functionality. It just calls each function in the class and
27 // verifies that it works on a basic level.
28
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)29 void IntlTestDecimalFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
30 {
31 if (exec) logln((UnicodeString)"TestSuite DecimalFormatAPI");
32 switch (index) {
33 case 0: name = "DecimalFormat API test";
34 if (exec) {
35 logln((UnicodeString)"DecimalFormat API test---"); logln((UnicodeString)"");
36 UErrorCode status = U_ZERO_ERROR;
37 Locale saveLocale;
38 Locale::setDefault(Locale::getEnglish(), status);
39 if(U_FAILURE(status)) {
40 errln((UnicodeString)"ERROR: Could not set default locale, test may not give correct results");
41 }
42 testAPI(/*par*/);
43 Locale::setDefault(saveLocale, status);
44 }
45 break;
46 case 1: name = "Rounding test";
47 if(exec) {
48 logln((UnicodeString)"DecimalFormat Rounding test---");
49 testRounding(/*par*/);
50 }
51 break;
52 case 2: name = "Test6354";
53 if(exec) {
54 logln((UnicodeString)"DecimalFormat Rounding Increment test---");
55 testRoundingInc(/*par*/);
56 }
57 break;
58 case 3: name = "TestCurrencyPluralInfo";
59 if(exec) {
60 logln((UnicodeString)"CurrencyPluralInfo API test---");
61 TestCurrencyPluralInfo();
62 }
63 break;
64 case 4: name = "TestScale";
65 if(exec) {
66 logln((UnicodeString)"Scale test---");
67 TestScale();
68 }
69 break;
70 case 5: name = "TestFixedDecimal";
71 if(exec) {
72 logln((UnicodeString)"TestFixedDecimal ---");
73 TestFixedDecimal();
74 }
75 break;
76 case 6: name = "TestBadFastpath";
77 if(exec) {
78 logln((UnicodeString)"TestBadFastpath ---");
79 TestBadFastpath();
80 }
81 break;
82 case 7: name = "TestRequiredDecimalPoint";
83 if(exec) {
84 logln((UnicodeString)"TestRequiredDecimalPoint ---");
85 TestRequiredDecimalPoint();
86 }
87 break;
88 default: name = ""; break;
89 }
90 }
91
92 /**
93 * This test checks various generic API methods in DecimalFormat to achieve 100%
94 * API coverage.
95 */
testAPI()96 void IntlTestDecimalFormatAPI::testAPI(/*char *par*/)
97 {
98 UErrorCode status = U_ZERO_ERROR;
99
100 // ======= Test constructors
101
102 logln((UnicodeString)"Testing DecimalFormat constructors");
103
104 DecimalFormat def(status);
105 if(U_FAILURE(status)) {
106 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
107 return;
108 }
109
110 // bug 10864
111 status = U_ZERO_ERROR;
112 DecimalFormat noGrouping("###0.##", status);
113 if (noGrouping.getGroupingSize() != 0) {
114 errln("Grouping size should be 0 for no grouping.");
115 }
116 noGrouping.setGroupingUsed(TRUE);
117 if (noGrouping.getGroupingSize() != 0) {
118 errln("Grouping size should still be 0.");
119 }
120 // end bug 10864
121
122 status = U_ZERO_ERROR;
123 const UnicodeString pattern("#,##0.# FF");
124 DecimalFormat pat(pattern, status);
125 if(U_FAILURE(status)) {
126 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern)");
127 return;
128 }
129
130 status = U_ZERO_ERROR;
131 DecimalFormatSymbols *symbols = new DecimalFormatSymbols(Locale::getFrench(), status);
132 if(U_FAILURE(status)) {
133 errln((UnicodeString)"ERROR: Could not create DecimalFormatSymbols (French)");
134 return;
135 }
136
137 status = U_ZERO_ERROR;
138 DecimalFormat cust1(pattern, symbols, status);
139 if(U_FAILURE(status)) {
140 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols*)");
141 }
142
143 status = U_ZERO_ERROR;
144 DecimalFormat cust2(pattern, *symbols, status);
145 if(U_FAILURE(status)) {
146 errln((UnicodeString)"ERROR: Could not create DecimalFormat (pattern, symbols)");
147 }
148
149 DecimalFormat copy(pat);
150
151 // ======= Test clone(), assignment, and equality
152
153 logln((UnicodeString)"Testing clone(), assignment and equality operators");
154
155 if( ! (copy == pat) || copy != pat) {
156 errln((UnicodeString)"ERROR: Copy constructor or == failed");
157 }
158
159 copy = cust1;
160 if(copy != cust1) {
161 errln((UnicodeString)"ERROR: Assignment (or !=) failed");
162 }
163
164 Format *clone = def.clone();
165 if( ! (*clone == def) ) {
166 errln((UnicodeString)"ERROR: Clone() failed");
167 }
168 delete clone;
169
170 // ======= Test various format() methods
171
172 logln((UnicodeString)"Testing various format() methods");
173
174 double d = -10456.0037;
175 int32_t l = 100000000;
176 Formattable fD(d);
177 Formattable fL(l);
178
179 UnicodeString res1, res2, res3, res4;
180 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0);
181
182 res1 = def.format(d, res1, pos1);
183 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1);
184
185 res2 = pat.format(l, res2, pos2);
186 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2);
187
188 status = U_ZERO_ERROR;
189 res3 = cust1.format(fD, res3, pos3, status);
190 if(U_FAILURE(status)) {
191 errln((UnicodeString)"ERROR: format(Formattable [double]) failed");
192 }
193 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res3);
194
195 status = U_ZERO_ERROR;
196 res4 = cust2.format(fL, res4, pos4, status);
197 if(U_FAILURE(status)) {
198 errln((UnicodeString)"ERROR: format(Formattable [long]) failed");
199 }
200 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res4);
201
202 // ======= Test parse()
203
204 logln((UnicodeString)"Testing parse()");
205
206 UnicodeString text("-10,456.0037");
207 Formattable result1, result2;
208 ParsePosition pos(0);
209 UnicodeString patt("#,##0.#");
210 status = U_ZERO_ERROR;
211 pat.applyPattern(patt, status);
212 if(U_FAILURE(status)) {
213 errln((UnicodeString)"ERROR: applyPattern() failed");
214 }
215 pat.parse(text, result1, pos);
216 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) {
217 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
218 }
219 logln(text + " parsed into " + (int32_t) result1.getDouble());
220
221 status = U_ZERO_ERROR;
222 pat.parse(text, result2, status);
223 if(U_FAILURE(status)) {
224 errln((UnicodeString)"ERROR: parse() failed");
225 }
226 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) {
227 errln((UnicodeString)"ERROR: Roundtrip failed (via parse()) for " + text);
228 }
229 logln(text + " parsed into " + (int32_t) result2.getDouble());
230
231 // ======= Test getters and setters
232
233 logln((UnicodeString)"Testing getters and setters");
234
235 const DecimalFormatSymbols *syms = pat.getDecimalFormatSymbols();
236 DecimalFormatSymbols *newSyms = new DecimalFormatSymbols(*syms);
237 def.setDecimalFormatSymbols(*newSyms);
238 def.adoptDecimalFormatSymbols(newSyms); // don't use newSyms after this
239 if( *(pat.getDecimalFormatSymbols()) != *(def.getDecimalFormatSymbols())) {
240 errln((UnicodeString)"ERROR: adopt or set DecimalFormatSymbols() failed");
241 }
242
243 UnicodeString posPrefix;
244 pat.setPositivePrefix("+");
245 posPrefix = pat.getPositivePrefix(posPrefix);
246 logln((UnicodeString)"Positive prefix (should be +): " + posPrefix);
247 if(posPrefix != "+") {
248 errln((UnicodeString)"ERROR: setPositivePrefix() failed");
249 }
250
251 UnicodeString negPrefix;
252 pat.setNegativePrefix("-");
253 negPrefix = pat.getNegativePrefix(negPrefix);
254 logln((UnicodeString)"Negative prefix (should be -): " + negPrefix);
255 if(negPrefix != "-") {
256 errln((UnicodeString)"ERROR: setNegativePrefix() failed");
257 }
258
259 UnicodeString posSuffix;
260 pat.setPositiveSuffix("_");
261 posSuffix = pat.getPositiveSuffix(posSuffix);
262 logln((UnicodeString)"Positive suffix (should be _): " + posSuffix);
263 if(posSuffix != "_") {
264 errln((UnicodeString)"ERROR: setPositiveSuffix() failed");
265 }
266
267 UnicodeString negSuffix;
268 pat.setNegativeSuffix("~");
269 negSuffix = pat.getNegativeSuffix(negSuffix);
270 logln((UnicodeString)"Negative suffix (should be ~): " + negSuffix);
271 if(negSuffix != "~") {
272 errln((UnicodeString)"ERROR: setNegativeSuffix() failed");
273 }
274
275 int32_t multiplier = 0;
276 pat.setMultiplier(8);
277 multiplier = pat.getMultiplier();
278 logln((UnicodeString)"Multiplier (should be 8): " + multiplier);
279 if(multiplier != 8) {
280 errln((UnicodeString)"ERROR: setMultiplier() failed");
281 }
282
283 int32_t groupingSize = 0;
284 pat.setGroupingSize(2);
285 groupingSize = pat.getGroupingSize();
286 logln((UnicodeString)"Grouping size (should be 2): " + (int32_t) groupingSize);
287 if(groupingSize != 2) {
288 errln((UnicodeString)"ERROR: setGroupingSize() failed");
289 }
290
291 pat.setDecimalSeparatorAlwaysShown(TRUE);
292 UBool tf = pat.isDecimalSeparatorAlwaysShown();
293 logln((UnicodeString)"DecimalSeparatorIsAlwaysShown (should be TRUE) is " + (UnicodeString) (tf ? "TRUE" : "FALSE"));
294 if(tf != TRUE) {
295 errln((UnicodeString)"ERROR: setDecimalSeparatorAlwaysShown() failed");
296 }
297 // Added by Ken Liu testing set/isExponentSignAlwaysShown
298 pat.setExponentSignAlwaysShown(TRUE);
299 UBool esas = pat.isExponentSignAlwaysShown();
300 logln((UnicodeString)"ExponentSignAlwaysShown (should be TRUE) is " + (UnicodeString) (esas ? "TRUE" : "FALSE"));
301 if(esas != TRUE) {
302 errln((UnicodeString)"ERROR: ExponentSignAlwaysShown() failed");
303 }
304
305 // Added by Ken Liu testing set/isScientificNotation
306 pat.setScientificNotation(TRUE);
307 UBool sn = pat.isScientificNotation();
308 logln((UnicodeString)"isScientificNotation (should be TRUE) is " + (UnicodeString) (sn ? "TRUE" : "FALSE"));
309 if(sn != TRUE) {
310 errln((UnicodeString)"ERROR: setScientificNotation() failed");
311 }
312
313 // Added by Ken Liu testing set/getMinimumExponentDigits
314 int8_t MinimumExponentDigits = 0;
315 pat.setMinimumExponentDigits(2);
316 MinimumExponentDigits = pat.getMinimumExponentDigits();
317 logln((UnicodeString)"MinimumExponentDigits (should be 2) is " + (int8_t) MinimumExponentDigits);
318 if(MinimumExponentDigits != 2) {
319 errln((UnicodeString)"ERROR: setMinimumExponentDigits() failed");
320 }
321
322 // Added by Ken Liu testing set/getRoundingIncrement
323 double RoundingIncrement = 0.0;
324 pat.setRoundingIncrement(2.0);
325 RoundingIncrement = pat.getRoundingIncrement();
326 logln((UnicodeString)"RoundingIncrement (should be 2.0) is " + (double) RoundingIncrement);
327 if(RoundingIncrement != 2.0) {
328 errln((UnicodeString)"ERROR: setRoundingIncrement() failed");
329 }
330 //end of Ken's Adding
331
332 UnicodeString funkyPat;
333 funkyPat = pat.toPattern(funkyPat);
334 logln((UnicodeString)"Pattern is " + funkyPat);
335
336 UnicodeString locPat;
337 locPat = pat.toLocalizedPattern(locPat);
338 logln((UnicodeString)"Localized pattern is " + locPat);
339
340 // ======= Test applyPattern()
341
342 logln((UnicodeString)"Testing applyPattern()");
343
344 UnicodeString p1("#,##0.0#;(#,##0.0#)");
345 logln((UnicodeString)"Applying pattern " + p1);
346 status = U_ZERO_ERROR;
347 pat.applyPattern(p1, status);
348 if(U_FAILURE(status)) {
349 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
350 }
351 UnicodeString s2;
352 s2 = pat.toPattern(s2);
353 logln((UnicodeString)"Extracted pattern is " + s2);
354 if(s2 != p1) {
355 errln((UnicodeString)"ERROR: toPattern() result did not match pattern applied");
356 }
357
358 if(pat.getSecondaryGroupingSize() != 0) {
359 errln("FAIL: Secondary Grouping Size should be 0, not %d\n", pat.getSecondaryGroupingSize());
360 }
361
362 if(pat.getGroupingSize() != 3) {
363 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
364 }
365
366 UnicodeString p2("#,##,##0.0# FF;(#,##,##0.0# FF)");
367 logln((UnicodeString)"Applying pattern " + p2);
368 status = U_ZERO_ERROR;
369 pat.applyLocalizedPattern(p2, status);
370 if(U_FAILURE(status)) {
371 errln((UnicodeString)"ERROR: applyPattern() failed with " + (int32_t) status);
372 }
373 UnicodeString s3;
374 s3 = pat.toLocalizedPattern(s3);
375 logln((UnicodeString)"Extracted pattern is " + s3);
376 if(s3 != p2) {
377 errln((UnicodeString)"ERROR: toLocalizedPattern() result did not match pattern applied");
378 }
379
380 status = U_ZERO_ERROR;
381 UParseError pe;
382 pat.applyLocalizedPattern(p2, pe, status);
383 if(U_FAILURE(status)) {
384 errln((UnicodeString)"ERROR: applyPattern((with ParseError)) failed with " + (int32_t) status);
385 }
386 UnicodeString s4;
387 s4 = pat.toLocalizedPattern(s3);
388 logln((UnicodeString)"Extracted pattern is " + s4);
389 if(s4 != p2) {
390 errln((UnicodeString)"ERROR: toLocalizedPattern(with ParseErr) result did not match pattern applied");
391 }
392
393 if(pat.getSecondaryGroupingSize() != 2) {
394 errln("FAIL: Secondary Grouping Size should be 2, not %d\n", pat.getSecondaryGroupingSize());
395 }
396
397 if(pat.getGroupingSize() != 3) {
398 errln("FAIL: Primary Grouping Size should be 3, not %d\n", pat.getGroupingSize());
399 }
400
401 // ======= Test getStaticClassID()
402
403 logln((UnicodeString)"Testing getStaticClassID()");
404
405 status = U_ZERO_ERROR;
406 NumberFormat *test = new DecimalFormat(status);
407 if(U_FAILURE(status)) {
408 errln((UnicodeString)"ERROR: Couldn't create a DecimalFormat");
409 }
410
411 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
412 errln((UnicodeString)"ERROR: getDynamicClassID() didn't return the expected value");
413 }
414
415 delete test;
416 }
417
TestCurrencyPluralInfo()418 void IntlTestDecimalFormatAPI::TestCurrencyPluralInfo(){
419 UErrorCode status = U_ZERO_ERROR;
420
421 CurrencyPluralInfo *cpi = new CurrencyPluralInfo(status);
422 if(U_FAILURE(status)) {
423 errln((UnicodeString)"ERROR: CurrencyPluralInfo(UErrorCode) could not be created");
424 }
425
426 CurrencyPluralInfo cpi1 = *cpi;
427
428 if(cpi->getDynamicClassID() != CurrencyPluralInfo::getStaticClassID()){
429 errln((UnicodeString)"ERROR: CurrencyPluralInfo::getDynamicClassID() didn't return the expected value");
430 }
431
432 cpi->setCurrencyPluralPattern("","",status);
433 if(U_FAILURE(status)) {
434 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setCurrencyPluralPattern");
435 }
436
437 cpi->setLocale(Locale::getCanada(), status);
438 if(U_FAILURE(status)) {
439 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setLocale");
440 }
441
442 cpi->setPluralRules("",status);
443 if(U_FAILURE(status)) {
444 errln((UnicodeString)"ERROR: CurrencyPluralInfo::setPluralRules");
445 }
446
447 DecimalFormat *df = new DecimalFormat(status);
448 if(U_FAILURE(status)) {
449 errcheckln(status, "ERROR: Could not create DecimalFormat - %s", u_errorName(status));
450 return;
451 }
452
453 df->adoptCurrencyPluralInfo(cpi);
454
455 df->getCurrencyPluralInfo();
456
457 df->setCurrencyPluralInfo(cpi1);
458
459 delete df;
460 }
461
testRounding()462 void IntlTestDecimalFormatAPI::testRounding(/*char *par*/)
463 {
464 UErrorCode status = U_ZERO_ERROR;
465 double Roundingnumber = 2.55;
466 double Roundingnumber1 = -2.55;
467 //+2.55 results -2.55 results
468 double result[]={ 3.0, -2.0, // kRoundCeiling 0,
469 2.0, -3.0, // kRoundFloor 1,
470 2.0, -2.0, // kRoundDown 2,
471 3.0, -3.0, // kRoundUp 3,
472 3.0, -3.0, // kRoundHalfEven 4,
473 3.0, -3.0, // kRoundHalfDown 5,
474 3.0, -3.0 // kRoundHalfUp 6
475 };
476 DecimalFormat pat(status);
477 if(U_FAILURE(status)) {
478 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
479 return;
480 }
481 uint16_t mode;
482 uint16_t i=0;
483 UnicodeString message;
484 UnicodeString resultStr;
485 for(mode=0;mode < 7;mode++){
486 pat.setRoundingMode((DecimalFormat::ERoundingMode)mode);
487 if(pat.getRoundingMode() != (DecimalFormat::ERoundingMode)mode){
488 errln((UnicodeString)"SetRoundingMode or GetRoundingMode failed for mode=" + mode);
489 }
490
491
492 //for +2.55 with RoundingIncrement=1.0
493 pat.setRoundingIncrement(1.0);
494 pat.format(Roundingnumber, resultStr);
495 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
496 verify(message, resultStr, result[i++]);
497 message.remove();
498 resultStr.remove();
499
500 //for -2.55 with RoundingIncrement=1.0
501 pat.format(Roundingnumber1, resultStr);
502 message= (UnicodeString)"Round() failed: round(" + (double)Roundingnumber1 + UnicodeString(",") + mode + UnicodeString(",FALSE) with RoundingIncrement=1.0==>");
503 verify(message, resultStr, result[i++]);
504 message.remove();
505 resultStr.remove();
506 }
507
508 }
verify(const UnicodeString & message,const UnicodeString & got,double expected)509 void IntlTestDecimalFormatAPI::verify(const UnicodeString& message, const UnicodeString& got, double expected){
510 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
511 UnicodeString expectedStr("");
512 expectedStr=expectedStr + expected;
513 if(got != expectedStr ) {
514 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expectedStr);
515 }
516 }
517
verifyString(const UnicodeString & message,const UnicodeString & got,UnicodeString & expected)518 void IntlTestDecimalFormatAPI::verifyString(const UnicodeString& message, const UnicodeString& got, UnicodeString& expected){
519 logln((UnicodeString)message + got + (UnicodeString)" Expected : " + expected);
520 if(got != expected ) {
521 errln((UnicodeString)"ERROR: " + message + got + (UnicodeString)" Expected : " + expected);
522 }
523 }
524
testRoundingInc()525 void IntlTestDecimalFormatAPI::testRoundingInc(/*char *par*/)
526 {
527 UErrorCode status = U_ZERO_ERROR;
528 DecimalFormat pat(UnicodeString("#,##0.00"),status);
529 if(U_FAILURE(status)) {
530 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
531 return;
532 }
533
534 // get default rounding increment
535 double roundingInc = pat.getRoundingIncrement();
536 if (roundingInc != 0.0) {
537 errln((UnicodeString)"ERROR: Rounding increment not zero");
538 return;
539 }
540
541 // With rounding now being handled by decNumber, we no longer
542 // set a rounding increment to enable non-default mode rounding,
543 // checking of which was the original point of this test.
544
545 // set rounding mode with zero increment. Rounding
546 // increment should not be set by this operation
547 pat.setRoundingMode((DecimalFormat::ERoundingMode)0);
548 roundingInc = pat.getRoundingIncrement();
549 if (roundingInc != 0.0) {
550 errln((UnicodeString)"ERROR: Rounding increment not zero after setRoundingMode");
551 return;
552 }
553 }
554
TestScale()555 void IntlTestDecimalFormatAPI::TestScale()
556 {
557 typedef struct TestData {
558 double inputValue;
559 int inputScale;
560 const char *expectedOutput;
561 } TestData;
562
563 static TestData testData[] = {
564 { 100.0, 3, "100,000" },
565 { 10034.0, -2, "100.34" },
566 { 0.86, -3, "0.0009" },
567 { -0.000455, 1, "-0%" },
568 { -0.000555, 1, "-1%" },
569 { 0.000455, 1, "0%" },
570 { 0.000555, 1, "1%" },
571 };
572
573 UErrorCode status = U_ZERO_ERROR;
574 DecimalFormat pat(status);
575 if(U_FAILURE(status)) {
576 errcheckln(status, "ERROR: Could not create DecimalFormat (default) - %s", u_errorName(status));
577 return;
578 }
579
580 UnicodeString message;
581 UnicodeString resultStr;
582 UnicodeString exp;
583 UnicodeString percentPattern("#,##0%");
584 pat.setMaximumFractionDigits(4);
585
586 for(int32_t i=0; i < UPRV_LENGTHOF(testData); i++) {
587 if ( i > 2 ) {
588 pat.applyPattern(percentPattern,status);
589 }
590 pat.setAttribute(UNUM_SCALE,testData[i].inputScale,status);
591 pat.format(testData[i].inputValue, resultStr);
592 message = UnicodeString("Unexpected output for ") + testData[i].inputValue + UnicodeString(" and scale ") +
593 testData[i].inputScale + UnicodeString(". Got: ");
594 exp = testData[i].expectedOutput;
595 verifyString(message, resultStr, exp);
596 message.remove();
597 resultStr.remove();
598 exp.remove();
599 }
600 }
601
602
603 #define ASSERT_EQUAL(expect, actual) { char tmp[200]; sprintf(tmp, "(%g==%g)", (double)(expect), (double)(actual)); \
604 assertTrue(tmp, ((expect)==(actual)), FALSE, TRUE, __FILE__, __LINE__); }
605
TestFixedDecimal()606 void IntlTestDecimalFormatAPI::TestFixedDecimal() {
607 UErrorCode status = U_ZERO_ERROR;
608
609 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
610 TEST_ASSERT_STATUS(status);
611 if (status == U_MISSING_RESOURCE_ERROR) {
612 return;
613 }
614 FixedDecimal fd = df->getFixedDecimal(44, status);
615 TEST_ASSERT_STATUS(status);
616 ASSERT_EQUAL(44, fd.source);
617 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
618 ASSERT_EQUAL(FALSE, fd.isNegative);
619
620 fd = df->getFixedDecimal(-44, status);
621 TEST_ASSERT_STATUS(status);
622 ASSERT_EQUAL(44, fd.source);
623 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
624 ASSERT_EQUAL(TRUE, fd.isNegative);
625
626 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.00##", status), status);
627 TEST_ASSERT_STATUS(status);
628 fd = df->getFixedDecimal(123.456, status);
629 TEST_ASSERT_STATUS(status);
630 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
631 ASSERT_EQUAL(456, fd.decimalDigits); // f
632 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
633 ASSERT_EQUAL(123, fd.intValue); // i
634 ASSERT_EQUAL(123.456, fd.source); // n
635 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
636 ASSERT_EQUAL(FALSE, fd.isNegative);
637
638 fd = df->getFixedDecimal(-123.456, status);
639 TEST_ASSERT_STATUS(status);
640 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
641 ASSERT_EQUAL(456, fd.decimalDigits); // f
642 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
643 ASSERT_EQUAL(123, fd.intValue); // i
644 ASSERT_EQUAL(123.456, fd.source); // n
645 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
646 ASSERT_EQUAL(TRUE, fd.isNegative);
647
648 // test max int digits
649 df->setMaximumIntegerDigits(2);
650 fd = df->getFixedDecimal(123.456, status);
651 TEST_ASSERT_STATUS(status);
652 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
653 ASSERT_EQUAL(456, fd.decimalDigits); // f
654 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
655 ASSERT_EQUAL(23, fd.intValue); // i
656 ASSERT_EQUAL(23.456, fd.source); // n
657 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
658 ASSERT_EQUAL(FALSE, fd.isNegative);
659
660 fd = df->getFixedDecimal(-123.456, status);
661 TEST_ASSERT_STATUS(status);
662 ASSERT_EQUAL(3, fd.visibleDecimalDigitCount); // v
663 ASSERT_EQUAL(456, fd.decimalDigits); // f
664 ASSERT_EQUAL(456, fd.decimalDigitsWithoutTrailingZeros); // t
665 ASSERT_EQUAL(23, fd.intValue); // i
666 ASSERT_EQUAL(23.456, fd.source); // n
667 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
668 ASSERT_EQUAL(TRUE, fd.isNegative);
669
670 // test max fraction digits
671 df->setMaximumIntegerDigits(2000000000);
672 df->setMaximumFractionDigits(2);
673 fd = df->getFixedDecimal(123.456, status);
674 TEST_ASSERT_STATUS(status);
675 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
676 ASSERT_EQUAL(46, fd.decimalDigits); // f
677 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
678 ASSERT_EQUAL(123, fd.intValue); // i
679 ASSERT_EQUAL(123.46, fd.source); // n
680 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
681 ASSERT_EQUAL(FALSE, fd.isNegative);
682
683 fd = df->getFixedDecimal(-123.456, status);
684 TEST_ASSERT_STATUS(status);
685 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
686 ASSERT_EQUAL(46, fd.decimalDigits); // f
687 ASSERT_EQUAL(46, fd.decimalDigitsWithoutTrailingZeros); // t
688 ASSERT_EQUAL(123, fd.intValue); // i
689 ASSERT_EQUAL(123.46, fd.source); // n
690 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
691 ASSERT_EQUAL(TRUE, fd.isNegative);
692
693 // test esoteric rounding
694 df->setMaximumFractionDigits(6);
695 df->setRoundingIncrement(7.3);
696
697 fd = df->getFixedDecimal(30.0, status);
698 TEST_ASSERT_STATUS(status);
699 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
700 ASSERT_EQUAL(20, fd.decimalDigits); // f
701 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
702 ASSERT_EQUAL(29, fd.intValue); // i
703 ASSERT_EQUAL(29.2, fd.source); // n
704 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
705 ASSERT_EQUAL(FALSE, fd.isNegative);
706
707 fd = df->getFixedDecimal(-30.0, status);
708 TEST_ASSERT_STATUS(status);
709 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount); // v
710 ASSERT_EQUAL(20, fd.decimalDigits); // f
711 ASSERT_EQUAL(2, fd.decimalDigitsWithoutTrailingZeros); // t
712 ASSERT_EQUAL(29, fd.intValue); // i
713 ASSERT_EQUAL(29.2, fd.source); // n
714 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
715 ASSERT_EQUAL(TRUE, fd.isNegative);
716
717 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###", status), status);
718 TEST_ASSERT_STATUS(status);
719 fd = df->getFixedDecimal(123.456, status);
720 TEST_ASSERT_STATUS(status);
721 ASSERT_EQUAL(0, fd.visibleDecimalDigitCount);
722 ASSERT_EQUAL(0, fd.decimalDigits);
723 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
724 ASSERT_EQUAL(123, fd.intValue);
725 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
726 ASSERT_EQUAL(FALSE, fd.isNegative);
727
728 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
729 TEST_ASSERT_STATUS(status);
730 fd = df->getFixedDecimal(123.01, status);
731 TEST_ASSERT_STATUS(status);
732 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
733 ASSERT_EQUAL(0, fd.decimalDigits);
734 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
735 ASSERT_EQUAL(123, fd.intValue);
736 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
737 ASSERT_EQUAL(FALSE, fd.isNegative);
738
739 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("###.0", status), status);
740 TEST_ASSERT_STATUS(status);
741 fd = df->getFixedDecimal(123.06, status);
742 TEST_ASSERT_STATUS(status);
743 ASSERT_EQUAL(1, fd.visibleDecimalDigitCount);
744 ASSERT_EQUAL(1, fd.decimalDigits);
745 ASSERT_EQUAL(1, fd.decimalDigitsWithoutTrailingZeros);
746 ASSERT_EQUAL(123, fd.intValue);
747 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
748 ASSERT_EQUAL(FALSE, fd.isNegative);
749
750 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
751 TEST_ASSERT_STATUS(status);
752 fd = df->getFixedDecimal(123, status);
753 TEST_ASSERT_STATUS(status);
754 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
755 ASSERT_EQUAL(0, fd.decimalDigits);
756 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
757 ASSERT_EQUAL(123, fd.intValue);
758 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
759 ASSERT_EQUAL(FALSE, fd.isNegative);
760
761 df.adoptInsteadAndCheckErrorCode(new DecimalFormat("@@@@@", status), status); // Significant Digits
762 TEST_ASSERT_STATUS(status);
763 fd = df->getFixedDecimal(1.23, status);
764 TEST_ASSERT_STATUS(status);
765 ASSERT_EQUAL(4, fd.visibleDecimalDigitCount);
766 ASSERT_EQUAL(2300, fd.decimalDigits);
767 ASSERT_EQUAL(23, fd.decimalDigitsWithoutTrailingZeros);
768 ASSERT_EQUAL(1, fd.intValue);
769 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
770 ASSERT_EQUAL(FALSE, fd.isNegative);
771
772 fd = df->getFixedDecimal(uprv_getInfinity(), status);
773 TEST_ASSERT_STATUS(status);
774 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
775 fd = df->getFixedDecimal(0.0, status);
776 ASSERT_EQUAL(FALSE, fd.isNanOrInfinity);
777 fd = df->getFixedDecimal(uprv_getNaN(), status);
778 ASSERT_EQUAL(TRUE, fd.isNanOrInfinity);
779 TEST_ASSERT_STATUS(status);
780
781 // Test Big Decimal input.
782 // 22 digits before and after decimal, will exceed the precision of a double
783 // and force DecimalFormat::getFixedDecimal() to work with a digit list.
784 df.adoptInsteadAndCheckErrorCode(
785 new DecimalFormat("#####################0.00####################", status), status);
786 TEST_ASSERT_STATUS(status);
787 Formattable fable("12.34", status);
788 TEST_ASSERT_STATUS(status);
789 fd = df->getFixedDecimal(fable, status);
790 TEST_ASSERT_STATUS(status);
791 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
792 ASSERT_EQUAL(34, fd.decimalDigits);
793 ASSERT_EQUAL(34, fd.decimalDigitsWithoutTrailingZeros);
794 ASSERT_EQUAL(12, fd.intValue);
795 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
796 ASSERT_EQUAL(FALSE, fd.isNegative);
797
798 fable.setDecimalNumber("12.345678901234567890123456789", status);
799 TEST_ASSERT_STATUS(status);
800 fd = df->getFixedDecimal(fable, status);
801 TEST_ASSERT_STATUS(status);
802 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
803 ASSERT_EQUAL(345678901234567890LL, fd.decimalDigits);
804 ASSERT_EQUAL(34567890123456789LL, fd.decimalDigitsWithoutTrailingZeros);
805 ASSERT_EQUAL(12, fd.intValue);
806 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
807 ASSERT_EQUAL(FALSE, fd.isNegative);
808
809 // On field overflow, Integer part is truncated on the left, fraction part on the right.
810 fable.setDecimalNumber("123456789012345678901234567890.123456789012345678901234567890", status);
811 TEST_ASSERT_STATUS(status);
812 fd = df->getFixedDecimal(fable, status);
813 TEST_ASSERT_STATUS(status);
814 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
815 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigits);
816 ASSERT_EQUAL(123456789012345678LL, fd.decimalDigitsWithoutTrailingZeros);
817 ASSERT_EQUAL(345678901234567890LL, fd.intValue);
818 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
819 ASSERT_EQUAL(FALSE, fd.isNegative);
820
821 // Digits way to the right of the decimal but within the format's precision aren't truncated
822 fable.setDecimalNumber("1.0000000000000000000012", status);
823 TEST_ASSERT_STATUS(status);
824 fd = df->getFixedDecimal(fable, status);
825 TEST_ASSERT_STATUS(status);
826 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
827 ASSERT_EQUAL(12, fd.decimalDigits);
828 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
829 ASSERT_EQUAL(1, fd.intValue);
830 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
831 ASSERT_EQUAL(FALSE, fd.isNegative);
832
833 // Digits beyond the precision of the format are rounded away
834 fable.setDecimalNumber("1.000000000000000000000012", status);
835 TEST_ASSERT_STATUS(status);
836 fd = df->getFixedDecimal(fable, status);
837 TEST_ASSERT_STATUS(status);
838 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
839 ASSERT_EQUAL(0, fd.decimalDigits);
840 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
841 ASSERT_EQUAL(1, fd.intValue);
842 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
843 ASSERT_EQUAL(FALSE, fd.isNegative);
844
845 // Negative numbers come through
846 fable.setDecimalNumber("-1.0000000000000000000012", status);
847 TEST_ASSERT_STATUS(status);
848 fd = df->getFixedDecimal(fable, status);
849 TEST_ASSERT_STATUS(status);
850 ASSERT_EQUAL(22, fd.visibleDecimalDigitCount);
851 ASSERT_EQUAL(12, fd.decimalDigits);
852 ASSERT_EQUAL(12, fd.decimalDigitsWithoutTrailingZeros);
853 ASSERT_EQUAL(1, fd.intValue);
854 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
855 ASSERT_EQUAL(TRUE, fd.isNegative);
856
857 // MinFractionDigits from format larger than from number.
858 fable.setDecimalNumber("1000000000000000000000.3", status);
859 TEST_ASSERT_STATUS(status);
860 fd = df->getFixedDecimal(fable, status);
861 TEST_ASSERT_STATUS(status);
862 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
863 ASSERT_EQUAL(30, fd.decimalDigits);
864 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
865 ASSERT_EQUAL(100000000000000000LL, fd.intValue);
866 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
867 ASSERT_EQUAL(FALSE, fd.isNegative);
868
869 fable.setDecimalNumber("1000000000000000050000.3", status);
870 TEST_ASSERT_STATUS(status);
871 fd = df->getFixedDecimal(fable, status);
872 TEST_ASSERT_STATUS(status);
873 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
874 ASSERT_EQUAL(30, fd.decimalDigits);
875 ASSERT_EQUAL(3, fd.decimalDigitsWithoutTrailingZeros);
876 ASSERT_EQUAL(50000LL, fd.intValue);
877 ASSERT_EQUAL(FALSE, fd.hasIntegerValue);
878 ASSERT_EQUAL(FALSE, fd.isNegative);
879
880 // Test some int64_t values that are out of the range of a double
881 fable.setInt64(4503599627370496LL);
882 TEST_ASSERT_STATUS(status);
883 fd = df->getFixedDecimal(fable, status);
884 TEST_ASSERT_STATUS(status);
885 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
886 ASSERT_EQUAL(0, fd.decimalDigits);
887 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
888 ASSERT_EQUAL(4503599627370496LL, fd.intValue);
889 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
890 ASSERT_EQUAL(FALSE, fd.isNegative);
891
892 fable.setInt64(4503599627370497LL);
893 TEST_ASSERT_STATUS(status);
894 fd = df->getFixedDecimal(fable, status);
895 TEST_ASSERT_STATUS(status);
896 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
897 ASSERT_EQUAL(0, fd.decimalDigits);
898 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
899 ASSERT_EQUAL(4503599627370497LL, fd.intValue);
900 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
901 ASSERT_EQUAL(FALSE, fd.isNegative);
902
903 fable.setInt64(9223372036854775807LL);
904 TEST_ASSERT_STATUS(status);
905 fd = df->getFixedDecimal(fable, status);
906 TEST_ASSERT_STATUS(status);
907 ASSERT_EQUAL(2, fd.visibleDecimalDigitCount);
908 ASSERT_EQUAL(0, fd.decimalDigits);
909 ASSERT_EQUAL(0, fd.decimalDigitsWithoutTrailingZeros);
910 // note: going through DigitList path to FixedDecimal, which is trimming
911 // int64_t fields to 18 digits. See ticket Ticket #10374
912 // ASSERT_EQUAL(223372036854775807LL, fd.intValue);
913 if (!(fd.intValue == 223372036854775807LL || fd.intValue == 9223372036854775807LL)) {
914 dataerrln("File %s, Line %d, fd.intValue = %lld", __FILE__, __LINE__, fd.intValue);
915 }
916 ASSERT_EQUAL(TRUE, fd.hasIntegerValue);
917 ASSERT_EQUAL(FALSE, fd.isNegative);
918
919 }
920
TestBadFastpath()921 void IntlTestDecimalFormatAPI::TestBadFastpath() {
922 UErrorCode status = U_ZERO_ERROR;
923
924 LocalPointer<DecimalFormat> df(new DecimalFormat("###", status), status);
925 if (U_FAILURE(status)) {
926 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
927 return;
928 }
929
930 UnicodeString fmt;
931 fmt.remove();
932 assertEquals("Format 1234", "1234", df->format(1234, fmt));
933 df->setGroupingUsed(FALSE);
934 fmt.remove();
935 assertEquals("Format 1234", "1234", df->format(1234, fmt));
936 df->setGroupingUsed(TRUE);
937 df->setGroupingSize(3);
938 fmt.remove();
939 assertEquals("Format 1234 w/ grouping", "1,234", df->format(1234, fmt));
940 }
941
TestRequiredDecimalPoint()942 void IntlTestDecimalFormatAPI::TestRequiredDecimalPoint() {
943 UErrorCode status = U_ZERO_ERROR;
944 UnicodeString text("99");
945 Formattable result1;
946 UnicodeString pat1("##.0000");
947 UnicodeString pat2("00.0");
948
949 LocalPointer<DecimalFormat> df(new DecimalFormat(pat1, status), status);
950 if (U_FAILURE(status)) {
951 dataerrln("Error creating new DecimalFormat - %s", u_errorName(status));
952 return;
953 }
954
955 status = U_ZERO_ERROR;
956 df->applyPattern(pat1, status);
957 if(U_FAILURE(status)) {
958 errln((UnicodeString)"ERROR: applyPattern() failed");
959 }
960 df->parse(text, result1, status);
961 if(U_FAILURE(status)) {
962 errln((UnicodeString)"ERROR: parse() failed");
963 }
964 df->setDecimalPatternMatchRequired(TRUE);
965 df->parse(text, result1, status);
966 if(U_SUCCESS(status)) {
967 errln((UnicodeString)"ERROR: unexpected parse()");
968 }
969
970
971 status = U_ZERO_ERROR;
972 df->applyPattern(pat2, status);
973 df->setDecimalPatternMatchRequired(FALSE);
974 if(U_FAILURE(status)) {
975 errln((UnicodeString)"ERROR: applyPattern(2) failed");
976 }
977 df->parse(text, result1, status);
978 if(U_FAILURE(status)) {
979 errln((UnicodeString)"ERROR: parse(2) failed - " + u_errorName(status));
980 }
981 df->setDecimalPatternMatchRequired(TRUE);
982 df->parse(text, result1, status);
983 if(U_SUCCESS(status)) {
984 errln((UnicodeString)"ERROR: unexpected parse(2)");
985 }
986 }
987
988 #endif /* #if !UCONFIG_NO_FORMATTING */
989