1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /***********************************************************************
4 * Copyright (c) 1997-2016, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ***********************************************************************/
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
14 #include <float.h> // DBL_MIN, DBL_MAX
17 #include "unicode/dcfmtsym.h"
18 #include "unicode/decimfmt.h"
19 #include "unicode/locid.h"
20 #include "unicode/resbund.h"
21 #include "unicode/calendar.h"
22 #include "unicode/datefmt.h"
23 #include "unicode/ucurr.h"
29 class MyNumberFormatTest
: public NumberFormat
33 virtual UClassID
getDynamicClassID(void) const;
35 virtual UnicodeString
& format( double number
,
36 UnicodeString
& toAppendTo
,
37 FieldPositionIterator
* posIter
,
38 UErrorCode
& status
) const
40 return NumberFormat::format(number
, toAppendTo
, posIter
, status
);
43 /* Just keep this here to make some of the compilers happy */
44 virtual UnicodeString
& format(const Formattable
& obj
,
45 UnicodeString
& toAppendTo
,
47 UErrorCode
& status
) const
49 return NumberFormat::format(obj
, toAppendTo
, pos
, status
);
52 /* Just use one of the format functions */
53 virtual UnicodeString
& format( double /* number */,
54 UnicodeString
& toAppendTo
,
55 FieldPosition
& /* pos */) const
62 public Number parse(String text, ParsePosition parsePosition)
63 { return new Integer(0); }
66 /* Just use one of the parse functions */
67 virtual void parse( const UnicodeString
& /* text */,
69 ParsePosition
& /* parsePosition */) const
71 result
.setLong((int32_t)0);
74 virtual void parse( const UnicodeString
& text
,
76 UErrorCode
& status
) const
78 NumberFormat::parse(text
, result
, status
);
80 virtual Format
* clone() const
83 virtual UnicodeString
& format(int32_t,
86 { return foo
.remove(); }
88 virtual UnicodeString
& format(int64_t,
91 { return foo
.remove(); }
93 virtual void applyPattern(const UnicodeString
&, UParseError
&, UErrorCode
&){
97 int32_t gMyNumberFormatTestClassID
;
98 UClassID
MyNumberFormatTest::getDynamicClassID() const
100 return (UClassID
)&gMyNumberFormatTestClassID
;
104 // *****************************************************************************
105 // class NumberFormatRegressionTest
106 // *****************************************************************************
108 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
111 NumberFormatRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
113 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
125 CASE(10,Test4086575
);
126 CASE(11,Test4068693
);
127 CASE(12,Test4069754
);
128 CASE(13,Test4087251
);
129 CASE(14,Test4090489
);
130 CASE(15,Test4090504
);
131 CASE(16,Test4095713
);
132 CASE(17,Test4092561
);
133 CASE(18,Test4092480
);
134 CASE(19,Test4087244
);
135 CASE(20,Test4070798
);
136 CASE(21,Test4071005
);
137 CASE(22,Test4071014
);
138 CASE(23,Test4071859
);
139 CASE(24,Test4093610
);
140 CASE(25,Test4098741
);
141 CASE(26,Test4074454
);
142 CASE(27,Test4099404
);
143 CASE(28,Test4101481
);
144 CASE(29,Test4052223
);
145 CASE(30,Test4061302
);
146 CASE(31,Test4062486
);
147 CASE(32,Test4108738
);
148 CASE(33,Test4106658
);
149 CASE(34,Test4106662
);
150 CASE(35,Test4114639
);
151 CASE(36,Test4106664
);
152 CASE(37,Test4106667
);
153 CASE(38,Test4110936
);
154 CASE(39,Test4122840
);
155 CASE(40,Test4125885
);
156 CASE(41,Test4134034
);
157 CASE(42,Test4134300
);
158 CASE(43,Test4140009
);
159 CASE(44,Test4141750
);
160 CASE(45,Test4145457
);
161 CASE(46,Test4147295
);
162 CASE(47,Test4147706
);
163 CASE(48,Test4162198
);
164 CASE(49,Test4162852
);
165 CASE(50,Test4167494
);
166 CASE(51,Test4170798
);
167 CASE(52,Test4176114
);
168 CASE(53,Test4179818
);
169 CASE(54,Test4212072
);
170 CASE(55,Test4216742
);
171 CASE(56,Test4217661
);
172 CASE(57,Test4161100
);
173 CASE(58,Test4243011
);
174 CASE(59,Test4243108
);
182 default: name
= ""; break;
187 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
189 if(U_FAILURE(status
)) {
190 if (possibleDataError
) {
191 dataerrln(UnicodeString("FAIL: ", "") + msg
192 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
194 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
195 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
204 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
206 if(U_FAILURE(status
)) {
207 if (possibleDataError
) {
208 dataerrln(UnicodeString("FAIL: ", "") + msg
209 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
211 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
212 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
221 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
223 if(U_FAILURE(status
)) {
224 if (possibleDataError
) {
225 dataerrln(UnicodeString("FAIL: ", "") + msg
226 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
228 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
229 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
238 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
240 inline UnicodeString
str(const char *input
)
242 return CharsToUnicodeString(input
);
246 * NumberFormat.equals comparing with null should always return false.
248 // {sfb} kind of silly in C++, just checking for new success
249 void NumberFormatRegressionTest::Test4075713(void)
252 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
254 logln("NumberFormat.equals passed");
255 /*} catch (NullPointerException e) {
256 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
263 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
266 void NumberFormatRegressionTest::Test4074620(void)
269 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
270 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
272 nf1
->setGroupingUsed(FALSE
);
273 nf2
->setGroupingUsed(TRUE
);
276 errln("Test for bug 4074620 failed");
278 logln("Test for bug 4074620 passed.");
286 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
289 void NumberFormatRegressionTest::Test4088161 (void)
291 UErrorCode status
= U_ZERO_ERROR
;
292 DecimalFormat
*df
= new DecimalFormat(status
);
293 if (!failure(status
, "new DecimalFormat", "")) {
295 df
->setMinimumFractionDigits(0);
296 df
->setMaximumFractionDigits(16);
298 FieldPosition
fp1(FieldPosition::DONT_CARE
);
299 logln(UnicodeString("d = ") + d
);
300 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
302 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
303 df
->setMaximumFractionDigits(17);
305 FieldPosition
fp2(FieldPosition::DONT_CARE
);
306 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
307 sBuf2
= df
->format(d
, sBuf2
, fp2
);
309 errln(" format(d) = '" + sBuf2
+ "'");
316 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
317 * DecimalFormat(String, DecimalFormatSymbols).
319 void NumberFormatRegressionTest::Test4087245 (void)
321 UErrorCode status
= U_ZERO_ERROR
;
322 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
323 failure(status
, "new DecimalFormatSymbols", "");
324 // {sfb} One note about this test: if you pass in a pointer
325 // to the symbols, they are adopted and this test will fail,
326 // even though that is the correct behavior. To test the cloning
327 // of the symbols, it is necessary to pass in a reference to the symbols
328 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
329 failure(status
, "new DecimalFormat with symbols", "");
333 FieldPosition
pos(FieldPosition::DONT_CARE
);
334 logln(UnicodeString("format(") + n
+ ") = " +
335 df
->format(n
, buf1
, pos
));
336 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
337 logln(UnicodeString("format(") + n
+ ") = " +
338 df
->format(n
, buf2
, pos
));
340 errln("Test for bug 4087245 failed");
347 * DecimalFormat.format() incorrectly formats 0.0
349 void NumberFormatRegressionTest::Test4087535 (void)
351 UErrorCode status
= U_ZERO_ERROR
;
352 DecimalFormat
*df
= new DecimalFormat(status
);
353 if (U_FAILURE(status
)) {
354 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
357 df
->setMinimumIntegerDigits(0);
360 UnicodeString buffer
;
361 FieldPosition
pos(FieldPosition::DONT_CARE
);
362 buffer
= df
->format(n
, buffer
, pos
);
363 if (buffer
.length() == 0)
364 errln(/*n + */": '" + buffer
+ "'");
366 buffer
= df
->format(n
, buffer
, pos
);
367 if (buffer
.length() == 0)
368 errln(/*n + */": '" + buffer
+ "'");
374 * DecimalFormat.format fails when groupingSize is set to 0.
376 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
377 void NumberFormatRegressionTest::Test4088503 (void)
379 UErrorCode status
= U_ZERO_ERROR
;
380 DecimalFormat
*df
= new DecimalFormat(status
);
381 if (U_FAILURE(status
)) {
382 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
385 df
->setGroupingSize(0);
387 FieldPosition
fp(FieldPosition::DONT_CARE
);
389 logln(df
->format((int32_t)123, sBuf
, fp
));
390 //if(fp == FieldPosition(FieldPosition::DONT_CARE))
391 // errln("Test for bug 4088503 failed.");
392 /*} catch (Exception foo) {
393 errln("Test for bug 4088503 failed.");
399 * NumberFormat.getCurrencyInstance is wrong.
401 void NumberFormatRegressionTest::Test4066646 (void)
403 assignFloatValue(2.04f
);
404 assignFloatValue(2.03f
);
405 assignFloatValue(2.02f
);
406 assignFloatValue(0.0f
);
410 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
412 logln(UnicodeString(" VALUE ") + returnfloat
);
413 UErrorCode status
= U_ZERO_ERROR
;
414 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
415 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
419 nfcommon
->setGroupingUsed(FALSE
);
421 UnicodeString stringValue
;
422 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
423 logln(" DISPLAYVALUE " + stringValue
);
425 nfcommon
->parse(stringValue
, result
, status
);
426 failure(status
, "nfcommon->parse", Locale::getUS());
427 float floatResult
= (float) (result
.getType() == Formattable::kDouble
428 ? result
.getDouble() : result
.getLong());
429 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
430 //String stringValue = nfcommon.format(returnfloat).substring(1);
431 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
432 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
436 } // End Of assignFloatValue()
439 * DecimalFormat throws exception when parsing "0"
441 void NumberFormatRegressionTest::Test4059870(void)
443 UErrorCode status
= U_ZERO_ERROR
;
444 DecimalFormat
*format
= new DecimalFormat("00", status
);
445 failure(status
, "new Decimalformat", Locale::getUS());
449 format
->parse(UnicodeString("0"), result
, status
);
450 failure(status
, "format->parse", Locale::getUS());
453 catch (Exception e) {
454 errln("Test for bug 4059870 failed : " + e);
460 * DecimalFormatSymbol.equals should always return false when
461 * comparing with null.
463 // {sfb} this is silly in C++
464 void NumberFormatRegressionTest::Test4083018 (void)
466 UErrorCode status
= U_ZERO_ERROR
;
467 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
468 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
471 logln("Test Passed!");
473 errln("Test for bug 4083018 failed");
474 /*} catch (Exception foo) {
475 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
482 * DecimalFormat does not round up correctly.
484 void NumberFormatRegressionTest::Test4071492 (void)
486 double x
= 0.00159999;
487 UErrorCode status
= U_ZERO_ERROR
;
488 NumberFormat
*nf
= NumberFormat::createInstance(status
);
489 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
493 nf
->setMaximumFractionDigits(4);
495 FieldPosition
pos(FieldPosition::DONT_CARE
);
496 out
= nf
->format(x
, out
, pos
);
497 logln("0.00159999 formats with 4 fractional digits to " + out
);
498 UnicodeString
expected("0.0016");
500 errln("FAIL: Expected " + expected
);
506 * A space as a group separator for localized pattern causes
507 * wrong format. WorkAround : use non-breaking space.
509 void NumberFormatRegressionTest::Test4086575(void)
511 UErrorCode status
= U_ZERO_ERROR
;
512 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
514 // TODO: There is not a good way to find out that the creation of this number format has
515 // failed. Major rewiring of format construction proposed.
516 if(U_FAILURE(status
)) {
517 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
521 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
523 // C++ workaround to make sure cast works
524 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
526 errln("NumberFormat::createInstance returned incorrect type.");
531 logln("nf toPattern1: " + nf
->toPattern(temp
));
532 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
534 // No group separator
535 logln("...applyLocalizedPattern ###,00;(###,00) ");
536 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
537 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
538 logln("nf toPattern2: " + nf
->toPattern(temp
));
539 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
541 FieldPosition
pos(FieldPosition::DONT_CARE
);
542 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
543 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
545 // Space as group separator
547 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
549 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
551 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
552 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
554 UnicodeString
pat(patChars
, 19, 19);
555 nf
->applyLocalizedPattern(pat
, status
);
556 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
557 logln("nf toPattern2: " + nf
->toPattern(temp
));
558 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
559 UnicodeString buffer
;
560 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
561 //if (buffer != UnicodeString("1\u00a0234,00"))
563 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
565 UnicodeString
cc(c
, 8, 8);
567 errln("nf : " + buffer
); // Expect 1 234,00
570 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
572 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
574 UnicodeString
cc1(c1
, 10, 10);
576 errln("nf : " + buffer
); // Expect (1 234,00)
578 // Erroneously prints:
585 * DecimalFormat.parse returns wrong value
587 // {sfb} slightly converted into a round-trip test, since in C++
588 // there is no Double.toString()
589 void NumberFormatRegressionTest::Test4068693(void)
591 logln("----- Test Application -----");
592 ParsePosition
pos(0);
593 UErrorCode status
= U_ZERO_ERROR
;
594 DecimalFormat
*df
= new DecimalFormat(status
);
595 if(U_FAILURE(status
)) {
596 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
600 failure(status
, "new DecimalFormat");
602 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
603 df
->parse(UnicodeString("123.55456"), d
, pos
);
604 //if (!d.toString().equals("123.55456")) {
606 df
->setMaximumFractionDigits(999);
607 df
->setMaximumIntegerDigits(999);
608 FieldPosition
fp(FieldPosition::DONT_CARE
);
609 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
610 if (dstr
!= UnicodeString("123.55456")) {
611 errln(UnicodeString("Result -> ") + d
.getDouble());
617 /* @bug 4069754, 4067878
618 * null pointer thrown when accessing a deserialized DecimalFormat
621 // {sfb} doesn't apply in C++
622 void NumberFormatRegressionTest::Test4069754(void)
625 myformat it = new myformat();
627 FileOutputStream ostream = new FileOutputStream("t.tmp");
628 ObjectOutputStream p = new ObjectOutputStream(ostream);
633 FileInputStream istream = new FileInputStream("t.tmp");
634 ObjectInputStream p2 = new ObjectInputStream(istream);
635 myformat it2 = (myformat)p2.readObject();
639 } catch (Exception foo) {
640 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
645 * DecimalFormat.applyPattern(String) allows illegal patterns
647 void NumberFormatRegressionTest::Test4087251 (void)
649 UErrorCode status
= U_ZERO_ERROR
;
650 DecimalFormat
*df
= new DecimalFormat(status
);
651 if(U_FAILURE(status
)) {
652 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
656 failure(status
, "new DecimalFormat");
658 df
->applyPattern(UnicodeString("#.#.#"), status
);
659 if( ! U_FAILURE(status
))
660 errln("df->applyPattern with illegal pattern didn't fail");
662 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
663 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
664 /*} catch (IllegalArgumentException e) {
665 logln("Caught Illegal Argument Error !");
667 // Second test; added 5/11/98 when reported to fail on 1.2b3
669 df
->applyPattern("#0.0#0#0", status
);
670 if( ! U_FAILURE(status
))
671 errln("df->applyPattern with illegal pattern didn't fail");
672 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
673 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
674 /*} catch (IllegalArgumentException e) {
675 logln("Ok - IllegalArgumentException for #0.0#0#0");
682 * DecimalFormat.format() loses precision
684 void NumberFormatRegressionTest::Test4090489 (void)
686 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
687 // that NumberFormat can do. For some reason, it does not format the last 1.
689 /* UErrorCode status = U_ZERO_ERROR;
690 DecimalFormat *df = new DecimalFormat(status);
691 failure(status, "new DecimalFormat");
692 df->setMinimumFractionDigits(10);
693 df->setMaximumFractionDigits(999);
694 df->setGroupingUsed(FALSE);
695 double d = 1.000000000000001E7;
696 //BigDecimal bd = new BigDecimal(d);
698 FieldPosition fp(FieldPosition::DONT_CARE);
699 logln(UnicodeString("d = ") + d);
700 //logln("BigDecimal.toString(): " + bd.toString());
701 df->format(d, sb, fp);
702 if (sb != "10000000.0000000100") {
703 errln("DecimalFormat.format(): " + sb);
709 * DecimalFormat.format() loses precision
711 void NumberFormatRegressionTest::Test4090504 (void)
714 logln(UnicodeString("d = ") + d
);
715 UErrorCode status
= U_ZERO_ERROR
;
716 DecimalFormat
*df
= new DecimalFormat(status
);
717 if(U_FAILURE(status
)) {
718 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
722 failure(status
, "new DecimalFormat");
724 FieldPosition
fp(FieldPosition::DONT_CARE
);
726 for (int i
= 17; i
<= 20; i
++) {
727 df
->setMaximumFractionDigits(i
);
728 //sb = new StringBuffer("");
730 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
731 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
733 /*} catch (Exception foo) {
734 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
740 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
742 void NumberFormatRegressionTest::Test4095713 (void)
744 UErrorCode status
= U_ZERO_ERROR
;
745 DecimalFormat
*df
= new DecimalFormat(status
);
746 if(U_FAILURE(status
)) {
747 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
751 failure(status
, "new DecimalFormat");
752 UnicodeString
str("0.1234");
754 //Double d1 = new Double(str);
755 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
758 df
->parse(str
, d2
, pp
);
759 logln(UnicodeString("") + d1
);
760 if (d2
.getDouble() != d1
)
761 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
766 * DecimalFormat.parse() fails when multiplier is not set to 1
768 // {sfb} not sure what to do with this one
769 void NumberFormatRegressionTest::Test4092561 (void)
771 UErrorCode status
= U_ZERO_ERROR
;
772 DecimalFormat
*df
= new DecimalFormat(status
);
773 if(U_FAILURE(status
)) {
774 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
778 failure(status
, "new DecimalFormat");
780 // {sfb} going to cheat here and use sprintf ??
782 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
783 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
784 df.setMultiplier(100);
785 Number num = df.parse(str, new ParsePosition(0));
786 if (num.doubleValue() != -9.223372036854776E16)
787 errln("Bug 4092561 test failed when multiplier is set to not 1.");
793 * DecimalFormat: Negative format ignored.
795 void NumberFormatRegressionTest::Test4092480 (void)
797 UErrorCode status
= U_ZERO_ERROR
;
798 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
799 if(U_FAILURE(status
)) {
800 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
804 failure(status
, "new DecimalFormat");
807 dfFoo
->applyPattern("0000;-000", status
);
808 failure(status
, "dfFoo->applyPattern");
810 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
811 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
812 FieldPosition
pos(FieldPosition::DONT_CARE
);
813 logln(dfFoo
->format((int32_t)42, temp
, pos
));
814 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
815 dfFoo
->applyPattern("000;-000", status
);
816 failure(status
, "dfFoo->applyPattern");
817 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
818 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
819 logln(dfFoo
->format((int32_t)42,temp
, pos
));
820 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
822 dfFoo
->applyPattern("000;-0000", status
);
823 failure(status
, "dfFoo->applyPattern");
824 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
825 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
826 logln(dfFoo
->format((int32_t)42, temp
, pos
));
827 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
829 dfFoo
->applyPattern("0000;-000", status
);
830 failure(status
, "dfFoo->applyPattern");
831 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
832 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
833 logln(dfFoo
->format((int32_t)42, temp
, pos
));
834 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
835 /*} catch (Exception foo) {
836 errln("Message " + foo.getMessage());
842 * NumberFormat.getCurrencyInstance() produces format that uses
843 * decimal separator instead of monetary decimal separator.
845 * Rewrote this test not to depend on the actual pattern. Pattern should
846 * never contain the monetary separator! Decimal separator in pattern is
847 * interpreted as monetary separator if currency symbol is seen!
849 void NumberFormatRegressionTest::Test4087244 (void) {
850 UErrorCode status
= U_ZERO_ERROR
;
852 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
853 Locale
*de
= new Locale(loc
);
854 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
855 if(U_FAILURE(status
)) {
856 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
860 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
862 errln("expected DecimalFormat!");
865 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
866 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
867 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
868 if (decSep
== monSep
) {
869 errln("ERROR in test: want decimal sep != monetary sep");
872 df
->setMinimumIntegerDigits(1);
873 df
->setMinimumFractionDigits(2);
876 df
->format(1.23, str
, pos
);
877 UnicodeString
monStr("1x23");
878 monStr
.replace((int32_t)1, 1, monSep
);
879 UnicodeString
decStr("1x23");
880 decStr
.replace((int32_t)1, 1, decSep
);
881 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
882 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
883 monStr
+ "\" and not \"" + decStr
+ '"');
885 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
887 "\" and not \"" + decStr
+ '"');
893 * Number format data rounding errors for locale FR
895 void NumberFormatRegressionTest::Test4070798 (void)
897 NumberFormat
*formatter
;
898 UnicodeString tempString
;
901 String expectedDefault = "-5\u00a0789,987";
902 String expectedCurrency = "5\u00a0789,98\u00a0F";
903 String expectedPercent = "-578\u00a0998%";
906 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
909 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
912 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
914 UnicodeString
expectedDefault(chars1
, 10, 10);
915 UnicodeString
expectedCurrency(chars2
, 10, 10);
916 UnicodeString
expectedPercent(chars3
, 10, 10);
918 UErrorCode status
= U_ZERO_ERROR
;
920 int len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
921 (void)len
; // Suppress set but not used warning.
922 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
923 if(U_FAILURE(status
)) {
924 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
928 failure(status
, "NumberFormat::createInstance", loc
);
929 tempString
= formatter
->format (-5789.9876, tempString
);
931 if (tempString
== expectedDefault
) {
932 logln ("Bug 4070798 default test passed.");
934 errln(UnicodeString("Failed:") +
935 " Expected " + expectedDefault
+
936 " Received " + tempString
);
939 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
940 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
941 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
943 tempString
= formatter
->format( 5789.9876, tempString
);
945 if (tempString
== expectedCurrency
) {
946 logln ("Bug 4070798 currency test passed.");
948 errln(UnicodeString("Failed:") +
949 " Expected " + expectedCurrency
+
950 " Received " + tempString
);
954 uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
955 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
956 failure(status
, "NumberFormat::createPercentInstance", loc
);
958 tempString
= formatter
->format (-5789.9876, tempString
);
960 if (tempString
== expectedPercent
) {
961 logln ("Bug 4070798 percentage test passed.");
963 errln(UnicodeString("Failed:") +
964 " Expected " + expectedPercent
+
965 " Received " + tempString
);
971 * Data rounding errors for French (Canada) locale
973 void NumberFormatRegressionTest::Test4071005 (void)
975 NumberFormat
*formatter
;
976 UnicodeString tempString
;
978 String expectedDefault = "-5\u00a0789,987";
979 String expectedCurrency = "5\u00a0789,98\u00a0$";
980 String expectedPercent = "-578\u00a0998%";
983 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
986 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
989 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
991 UnicodeString
expectedDefault(chars1
, 10, 10);
992 UnicodeString
expectedCurrency(chars2
, 10, 10);
993 UnicodeString
expectedPercent(chars3
, 10, 10);
995 UErrorCode status
= U_ZERO_ERROR
;
996 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
997 if (failure(status
, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE
)){
1001 tempString
= formatter
->format (-5789.9876, tempString
);
1003 if (tempString
== expectedDefault
) {
1004 logln ("Bug 4071005 default test passed.");
1006 errln(UnicodeString("Failed:") +
1007 " Expected " + expectedDefault
+
1008 " Received " + tempString
);
1012 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
1013 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1014 tempString
.remove();
1015 tempString
= formatter
->format( 5789.9876, tempString
);
1017 if (tempString
== expectedCurrency
) {
1018 logln ("Bug 4071005 currency test assed.");
1020 errln(UnicodeString("Failed:") +
1021 " Expected " + expectedCurrency
+
1022 " Received " + tempString
);
1026 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1027 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1028 tempString
.remove();
1029 tempString
= formatter
->format (-5789.9876, tempString
);
1031 if (tempString
== expectedPercent
) {
1032 logln ("Bug 4071005 percentage test passed.");
1034 errln(UnicodeString("Failed:") +
1035 " Expected " + expectedPercent
+
1036 " Received " + tempString
);
1043 * Data rounding errors for German (Germany) locale
1045 void NumberFormatRegressionTest::Test4071014 (void)
1047 NumberFormat
*formatter
;
1048 UnicodeString tempString
;
1050 String expectedDefault = "-5.789,987";
1051 String expectedCurrency = "5.789,98 DM";
1052 String expectedPercent = "-578.998%";
1054 UnicodeString
expectedDefault("-5.789,988");
1055 UnicodeString
expectedCurrency("5.789,99\\u00A0DM");
1056 UnicodeString
expectedPercent("-578.999\\u00A0%");
1058 expectedCurrency
= expectedCurrency
.unescape();
1059 expectedPercent
= expectedPercent
.unescape();
1061 UErrorCode status
= U_ZERO_ERROR
;
1063 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1064 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1065 if (failure(status
, "NumberFormat::createInstance", loc
, TRUE
)){
1069 tempString
.remove();
1070 tempString
= formatter
->format (-5789.9876, tempString
);
1072 if (tempString
== expectedDefault
) {
1073 logln ("Bug 4071014 default test passed.");
1075 errln(UnicodeString("Failed:") +
1076 " Expected " + expectedDefault
+
1077 " Received " + tempString
);
1080 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1081 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1082 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1083 tempString
.remove();
1084 tempString
= formatter
->format( 5789.9876, tempString
);
1086 if (tempString
== expectedCurrency
) {
1087 logln ("Bug 4071014 currency test assed.");
1089 errln(UnicodeString("Failed:") +
1090 " Expected " + expectedCurrency
+
1091 " Received " + tempString
);
1095 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1096 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1097 tempString
.remove();
1098 tempString
= formatter
->format (-5789.9876, tempString
);
1100 if (tempString
== expectedPercent
) {
1101 logln ("Bug 4071014 percentage test passed.");
1103 errln(UnicodeString("Failed:") +
1104 " Expected " + expectedPercent
+
1105 " Received " + tempString
);
1111 * Data rounding errors for Italian locale number formats
1113 void NumberFormatRegressionTest::Test4071859 (void)
1115 NumberFormat
*formatter
;
1116 UnicodeString tempString
;
1118 String expectedDefault = "-5.789,987";
1119 String expectedCurrency = "-L.\\u00A05.789,98";
1120 String expectedPercent = "-578.998%";
1122 UnicodeString
expectedDefault("-5.789,988");
1123 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1124 UnicodeString
expectedPercent("-578.999%");
1125 expectedCurrency
= expectedCurrency
.unescape();
1127 UErrorCode status
= U_ZERO_ERROR
;
1129 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1130 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1131 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1135 tempString
= formatter
->format (-5789.9876, tempString
);
1137 if (tempString
== expectedDefault
) {
1138 logln ("Bug 4071859 default test passed.");
1140 errln(UnicodeString("Failed:") +
1141 " Expected " + expectedDefault
+
1142 " Received " + tempString
);
1145 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1146 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1147 failure(status
, "NumberFormat::createCurrencyInstance");
1148 tempString
.remove();
1149 tempString
= formatter
->format( -5789.9876, tempString
);
1151 if (tempString
== expectedCurrency
) {
1152 logln ("Bug 4071859 currency test assed.");
1154 errln(UnicodeString("Failed:") +
1155 " Expected " + expectedCurrency
+
1156 " Received " + tempString
);
1159 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1160 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1161 failure(status
, "NumberFormat::createPercentInstance");
1162 tempString
.remove();
1163 tempString
= formatter
->format (-5789.9876, tempString
);
1165 if (tempString
== expectedPercent
) {
1166 logln ("Bug 4071859 percentage test passed.");
1168 errln(UnicodeString("Failed:") +
1169 " Expected " + expectedPercent
+
1170 " Received " + tempString
);
1176 * Test rounding for nearest even.
1178 void NumberFormatRegressionTest::Test4093610(void)
1180 UErrorCode status
= U_ZERO_ERROR
;
1181 DecimalFormat
df("#0.#", status
);
1182 if (!failure(status
, "new DecimalFormat")) {
1183 UnicodeString
s("12.4");
1184 roundingTest(&df
, 12.35, s
);
1185 roundingTest(&df
, 12.45, s
);
1187 roundingTest(&df
, 12.452,s
);
1189 roundingTest(&df
, 12.55, s
);
1190 roundingTest(&df
, 12.65, s
);
1192 roundingTest(&df
, 12.652,s
);
1194 roundingTest(&df
, 12.75, s
);
1195 roundingTest(&df
, 12.752,s
);
1196 roundingTest(&df
, 12.85, s
);
1198 roundingTest(&df
, 12.852,s
);
1200 roundingTest(&df
, 12.95, s
);
1201 roundingTest(&df
, 12.952,s
);
1205 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1208 FieldPosition
pos(FieldPosition::DONT_CARE
);
1209 out
= df
->format(x
, out
, pos
);
1210 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1211 if (out
!= expected
) {
1212 dataerrln("FAIL: Expected '%s'; got '%s'", CStr(expected
)(), CStr(out
)());
1216 * Tests the setMaximumFractionDigits limit.
1218 void NumberFormatRegressionTest::Test4098741(void)
1221 UErrorCode status
= U_ZERO_ERROR
;
1222 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1223 if (U_FAILURE(status
)) {
1224 dataerrln("Error calling NumberFormat::createPercentInstance");
1229 fmt
->setMaximumFractionDigits(20);
1231 logln(fmt
->format(.001, temp
));
1232 /*} catch (Exception foo) {
1233 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1238 * Tests illegal pattern exception.
1239 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1240 * Part2 has been fixed.
1242 void NumberFormatRegressionTest::Test4074454(void)
1245 UErrorCode status
= U_ZERO_ERROR
;
1246 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1247 if(U_FAILURE(status
)) {
1248 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1252 failure(status
, "new DecimalFormat");
1253 logln("Inconsistent negative pattern is fine.");
1254 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1255 failure(status
, "new DecimalFormat");
1256 UnicodeString tempString
;
1257 FieldPosition
pos(FieldPosition::DONT_CARE
);
1258 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1259 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1260 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1261 /*} catch (Exception foo) {
1262 errln("An exception was thrown for any inconsistent negative pattern.");
1269 * Tests all different comments.
1270 * Response to some comments :
1271 * [1] DecimalFormat.parse API documentation is more than just one line.
1272 * This is not a reproducable doc error in 116 source code.
1273 * [2] See updated javadoc.
1275 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1276 * a null object will be returned. The unchanged parse position also
1277 * reflects an error.
1278 * NumberFormat.parse(String) : If parsing fails, an ParseException
1280 * See updated javadoc for more details.
1281 * [5] See updated javadoc.
1282 * [6] See updated javadoc.
1283 * [7] This is a correct behavior if the DateFormat object is linient.
1284 * Otherwise, an IllegalArgumentException will be thrown when formatting
1285 * "January 35". See GregorianCalendar class javadoc for more details.
1287 void NumberFormatRegressionTest::Test4099404(void)
1290 UErrorCode status
= U_ZERO_ERROR
;
1291 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1292 if(! U_FAILURE(status
))
1293 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1294 /*} catch (Exception foo) {
1295 logln("Bug 4099404 pattern \"000.0#0\" passed");
1300 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1301 if( !U_FAILURE(status
))
1302 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1303 /*} catch (Exception foo) {
1304 logln("Bug 4099404 pattern \"0#0.000\" passed");
1310 * DecimalFormat.applyPattern doesn't set minimum integer digits
1312 void NumberFormatRegressionTest::Test4101481(void)
1314 UErrorCode status
= U_ZERO_ERROR
;
1315 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1316 if(U_FAILURE(status
)) {
1317 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1321 failure(status
, "new DecimalFormat");
1322 if (sdf
->getMinimumIntegerDigits() != 1)
1323 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1326 /* @bug 4052223 (API addition request A27)
1327 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1329 void NumberFormatRegressionTest::Test4052223(void)
1332 UErrorCode status
= U_ZERO_ERROR
;
1333 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1334 if(U_FAILURE(status
)) {
1335 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1339 failure(status
, "new DecimalFormat");
1341 fmt
->parse(UnicodeString("abc3"), num
, status
);
1342 if(! U_FAILURE(status
))
1343 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1344 /*} catch (ParseException foo) {
1345 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1350 * API tests for API addition request A9.
1352 void NumberFormatRegressionTest::Test4061302(void)
1354 UErrorCode status
= U_ZERO_ERROR
;
1355 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1356 if (U_FAILURE(status
)) {
1357 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status
));
1360 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1361 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1362 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1363 if (currency
== UnicodeString("") ||
1364 intlCurrency
== UnicodeString("") ||
1365 monDecSeparator
== UnicodeString(""))
1367 errln("getCurrencySymbols failed, got empty string.");
1369 UnicodeString monDecSeparatorStr
;
1370 monDecSeparatorStr
.append(monDecSeparator
);
1371 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1372 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1373 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1374 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1375 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1376 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1377 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1378 if (currency
!= UnicodeString("XYZ") ||
1379 intlCurrency
!= UnicodeString("ABC") ||
1380 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1381 errln("setCurrencySymbols failed.");
1383 monDecSeparatorStr
.remove();
1384 monDecSeparatorStr
.append(monDecSeparator
);
1385 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1390 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1391 * FieldPosition.getEndIndex.
1393 void NumberFormatRegressionTest::Test4062486(void)
1395 UErrorCode status
= U_ZERO_ERROR
;
1396 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1397 if (U_FAILURE(status
)) {
1398 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
1401 UnicodeString formatted
;
1402 FieldPosition
field(FieldPosition::DONT_CARE
);
1403 double num
= 1234.5;
1404 fmt
->format(num
, formatted
, field
);
1405 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1406 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1407 field
.setBeginIndex(7);
1408 field
.setEndIndex(4);
1409 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1410 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1416 * DecimalFormat.parse incorrectly works with a group separator.
1418 void NumberFormatRegressionTest::Test4108738(void)
1420 UErrorCode status
= U_ZERO_ERROR
;
1421 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1422 failure(status
, "new DecimalFormatSymbols");
1423 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1424 if(U_FAILURE(status
)) {
1425 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1429 failure(status
, "new DecimalFormat");
1430 UnicodeString
text("1.222,111");
1432 ParsePosition
pp(0);
1433 df
->parse(text
, num
, pp
);
1435 // {sfb} how to do this (again) ?
1436 // shouldn't just be another round-trip test, should it?
1438 FieldPosition
pos(FieldPosition::DONT_CARE
);
1439 temp
= df
->format(num
.getDouble(), temp
, pos
);
1440 //if (!num.toString().equals("1.222"))
1441 if (temp
!= UnicodeString("1.222"))
1442 //errln("\"" + text + "\" is parsed as " + num);
1443 errln("\"" + text
+ "\" is parsed as " + temp
);
1444 text
= UnicodeString("1.222x111");
1445 pp
= ParsePosition(0);
1446 df
->parse(text
, num
, pp
);
1448 temp
= df
->format(num
.getDouble(), temp
, pos
);
1449 //if (!num.toString().equals("1.222"))
1450 if (temp
!= UnicodeString("1.222"))
1451 errln("\"" + text
+ "\" is parsed as " + temp
);
1457 * DecimalFormat.format() incorrectly formats negative doubles.
1459 void NumberFormatRegressionTest::Test4106658(void)
1461 UErrorCode status
= U_ZERO_ERROR
;
1462 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1463 if(U_FAILURE(status
)) {
1464 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1468 failure(status
, "new DecimalFormat");
1469 volatile double d1
= 0.0; // volatile to prevent code optimization
1470 double d2
= -0.0001;
1471 UnicodeString buffer
;
1473 FieldPosition
pos(FieldPosition::DONT_CARE
);
1475 #if U_PLATFORM == U_PF_HPUX
1476 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1478 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1480 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1481 df
->format(d1
, buffer
, pos
);
1482 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1483 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1485 df
->format(d2
, buffer
, pos
);
1486 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1487 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1493 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1495 void NumberFormatRegressionTest::Test4106662(void)
1497 UErrorCode status
= U_ZERO_ERROR
;
1498 DecimalFormat
*df
= new DecimalFormat(status
);
1499 if(U_FAILURE(status
)) {
1500 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1504 failure(status
, "new DecimalFormat");
1505 UnicodeString
text("x");
1506 ParsePosition
pos1(0), pos2(0);
1509 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1511 df
->parse(text
, num
, pos1
);
1512 if (pos1
== ParsePosition(0)/*num != null*/) {
1513 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1516 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1517 failure(status
, "new DecimalFormat");
1518 df
->parse(UnicodeString("$"), num
, pos2
);
1519 if (pos2
== ParsePosition(0) /*num != null*/){
1520 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1526 /* @bug 4114639 (duplicate of 4106662)
1527 * NumberFormat.parse doesn't return null
1529 void NumberFormatRegressionTest::Test4114639(void)
1531 UErrorCode status
= U_ZERO_ERROR
;
1532 NumberFormat
*format
= NumberFormat::createInstance(status
);
1533 if(U_FAILURE(status
)) {
1534 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1538 failure(status
, "NumberFormat::createInstance");
1539 UnicodeString
text("time 10:x");
1540 ParsePosition
pos(8);
1542 format
->parse(text
, result
, pos
);
1543 if (/*result != null*/pos
.getErrorIndex() != 8)
1544 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1550 * TODO: this test does not work because we need to use a 64 bit number and a
1551 * a double only MAY only have 52 bits of precision.
1552 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1554 void NumberFormatRegressionTest::Test4106664(void)
1556 UErrorCode status
= U_ZERO_ERROR
;
1557 DecimalFormat
*df
= new DecimalFormat(status
);
1558 if(U_FAILURE(status
)) {
1559 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1563 failure(status
, "new DecimalFormat");
1564 // {sfb} long in java is 64 bits
1565 /*long*/double n
= 1234567890123456.0;
1566 /*int*/int32_t m
= 12345678;
1567 // {sfb} will this work?
1568 //BigInteger bigN = BigInteger.valueOf(n);
1569 //bigN = bigN.multiply(BigInteger.valueOf(m));
1570 double bigN
= n
* m
;
1571 df
->setMultiplier(m
);
1572 df
->setGroupingUsed(FALSE
);
1574 FieldPosition
pos(FieldPosition::DONT_CARE
);
1575 logln("formated: " +
1576 df
->format(n
, temp
, pos
));
1579 sprintf(buf
, "%g", bigN
);
1580 //logln("expected: " + bigN.toString());
1581 logln(UnicodeString("expected: ") + buf
);
1585 /* @bug 4106667 (duplicate of 4106658)
1586 * DecimalFormat.format incorrectly formats -0.0.
1588 void NumberFormatRegressionTest::Test4106667(void)
1590 UErrorCode status
= U_ZERO_ERROR
;
1591 DecimalFormat
*df
= new DecimalFormat(status
);
1592 if(U_FAILURE(status
)) {
1593 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1597 failure(status
, "new DecimalFormat");
1598 UChar foo
[] = { 0x002B };
1599 UnicodeString
bar(foo
, 1, 1);
1600 volatile double d
= 0.0; // volatile to prevent code optimization
1602 UnicodeString buffer
;
1603 FieldPosition
pos(FieldPosition::DONT_CARE
);
1605 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1606 #if U_PLATFORM == U_PF_HPUX
1607 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1609 d
*= -1.0; // Some compilers have a problem with defining -0.0
1611 df
->setPositivePrefix(/*"+"*/bar
);
1612 df
->format(d
, buffer
, pos
);
1613 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1614 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1620 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1622 #if U_PLATFORM == U_PF_OS390
1623 # define MAX_INT_DIGITS 70
1625 # define MAX_INT_DIGITS 128
1628 void NumberFormatRegressionTest::Test4110936(void)
1630 UErrorCode status
= U_ZERO_ERROR
;
1631 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1632 if(U_FAILURE(status
)) {
1633 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1637 failure(status
, "NumberFormat::createInstance");
1638 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1639 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1640 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1641 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1642 nf
->getMaximumIntegerDigits());
1648 * Locale data should use generic currency symbol
1650 * 1) Make sure that all currency formats use the generic currency symbol.
1651 * 2) Make sure we get the same results using the generic symbol or a
1654 void NumberFormatRegressionTest::Test4122840(void)
1657 const Locale
*locales
= Locale::getAvailableLocales(count
);
1659 for (int i
= 0; i
< count
; i
++) {
1660 UErrorCode status
= U_ZERO_ERROR
;
1661 ResourceBundle
*rb
= new ResourceBundle(
1662 NULL
/*"java.text.resources.LocaleElements"*/,
1663 locales
[i
], status
);
1664 failure(status
, "new ResourceBundle");
1665 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1666 failure(status
, "rb.get(NumberElements)");
1667 numPat
= numPat
.getWithFallback("latn",status
);
1668 failure(status
, "rb.get(latn)");
1669 numPat
= numPat
.getWithFallback("patterns",status
);
1670 failure(status
, "rb.get(patterns)");
1671 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1672 failure(status
, "rb.get(currencyFormat)");
1674 // Get the currency pattern for this locale. We have to fish it
1675 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1676 // will return the localized symbol, not \00a4
1678 UnicodeString pattern
= numPat
.getString(status
);
1679 failure(status
, "rb->getString()");
1681 UChar fo
[] = { 0x00A4 };
1682 UnicodeString
foo(fo
, 1, 1);
1684 //if (pattern.indexOf("\u00A4") == -1 ) {
1685 if (pattern
.indexOf(foo
) == -1 ) {
1686 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1687 " does not contain generic currency symbol:" +
1691 // Create a DecimalFormat using the pattern we got and format a number
1692 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1693 failure(status
, "new DecimalFormatSymbols");
1695 // Disable currency spacing for the purposes of this test.
1696 // To do this, set the spacing insert to the empty string both before and after the symbol.
1697 symbols
->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT
, FALSE
, u
"");
1698 symbols
->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT
, TRUE
, u
"");
1700 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1701 failure(status
, "new DecimalFormat");
1703 UnicodeString result1
;
1704 FieldPosition
pos(FieldPosition::DONT_CARE
);
1705 result1
= fmt1
->format(1.111, result1
, pos
);
1708 // Now substitute in the locale's currency symbol and create another
1709 // pattern. We have to skip locales where the currency symbol
1710 // contains decimal separators, because that confuses things
1712 UChar ba
[] = { 0x002E/*'.'*/ };
1713 UnicodeString
bar(ba
, 1, 1);
1715 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1716 // {sfb} Also, switch the decimal separator to the monetary decimal
1717 // separator to mimic the behavior of a currency format
1718 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1719 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1721 UnicodeString
buf(pattern
);
1722 for (int j
= 0; j
< buf
.length(); j
++) {
1723 if (buf
[j
] == 0x00a4 ) {
1724 if(buf
[j
+ 1] == 0x00a4) {
1725 // {sfb} added to support double currency marker (intl currency sign)
1726 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1727 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1730 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1731 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1736 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1737 failure(status
, "new DecimalFormat");
1739 // Get the currency (if there is one) so we can set the rounding and fraction
1740 const UChar
*currency
= fmt1
->getCurrency();
1741 if (*currency
!= 0) {
1742 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1743 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1744 if (U_SUCCESS(status
)) {
1745 fmt2
->setRoundingIncrement(rounding
);
1746 fmt2
->setMinimumFractionDigits(frac
);
1747 fmt2
->setMaximumFractionDigits(frac
);
1750 failure(status
, "Fetching currency rounding/fractions");
1754 UnicodeString result2
;
1755 fmt2
->format(1.111, result2
, pos
);
1757 if (result1
!= result2
) {
1758 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1759 result1
+ " vs " + result2
);
1772 * DecimalFormat.format() delivers wrong string.
1774 void NumberFormatRegressionTest::Test4125885(void)
1776 UErrorCode status
= U_ZERO_ERROR
;
1777 double rate
= 12.34;
1778 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1779 if(U_FAILURE(status
)) {
1780 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1784 failure(status
, "new DecimalFormat");
1786 logln("toPattern: " + formatDec
->toPattern(temp
));
1787 UnicodeString rateString
;
1788 FieldPosition
pos(FieldPosition::DONT_CARE
);
1789 rateString
= formatDec
->format(rate
, rateString
, pos
);
1790 if (rateString
!= UnicodeString("012.34"))
1791 errln("result : " + rateString
+ " expected : 012.34");
1793 delete formatDec
;// = null;
1794 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1795 failure(status
, "new DecimalFormat");
1796 logln("toPattern: " + formatDec
->toPattern(temp
));
1797 rateString
.remove();
1798 rateString
= formatDec
->format(rate
, rateString
, pos
);
1799 if (rateString
!= UnicodeString("+012.34%"))
1800 errln("result : " + rateString
+ " expected : +012.34%");
1807 * DecimalFormat produces extra zeros when formatting numbers.
1809 void NumberFormatRegressionTest::Test4134034(void)
1811 UErrorCode status
= U_ZERO_ERROR
;
1812 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1813 if (!failure(status
, "new DecimalFormat")) {
1815 FieldPosition
pos(FieldPosition::DONT_CARE
);
1816 f
= nf
->format(9.02, f
, pos
);
1817 if (f
== UnicodeString("9.02"))
1820 errln("9.02 -> " + f
+ "; want 9.02");
1823 f
= nf
->format((int32_t)0, f
, pos
);
1824 if (f
== UnicodeString(".00"))
1827 errln("0 -> " + f
+ "; want .00");
1835 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1836 * a duplicate of 4134034.
1838 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1839 * Possibly related to bug 4125885.
1841 * This class demonstrates a regression in version 1.1.6
1842 * of DecimalFormat class.
1845 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1846 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1847 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1848 * Value 1.2 Format #0.0# Result '1.2'
1849 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1852 * Value 1.2 Format #.00 Result '1.20'
1853 * Value 1.2 Format 0.00 Result '1.20'
1854 * Value 1.2 Format 00.00 Result '01.20'
1855 * Value 1.2 Format #0.0# Result '1.2'
1856 * Value 1.2 Format #0.00 Result '1.20'
1858 void NumberFormatRegressionTest::Test4134300(void) {
1859 UnicodeString DATA
[] = {
1860 // Pattern Expected string
1861 UnicodeString("#.00"), UnicodeString("1.20"),
1862 UnicodeString("0.00"), UnicodeString("1.20"),
1863 UnicodeString("00.00"), UnicodeString("01.20"),
1864 UnicodeString("#0.0#"), UnicodeString("1.2"),
1865 UnicodeString("#0.00"), UnicodeString("1.20")
1868 for (int i
=0; i
< 10; i
+=2) {
1869 UnicodeString result
;
1870 UErrorCode status
= U_ZERO_ERROR
;
1871 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1872 if (!failure(status
, "new DecimalFormat")) {
1873 FieldPosition
pos(FieldPosition::DONT_CARE
);
1874 result
= df
->format(1.2, result
, pos
);
1875 if (result
!= DATA
[i
+1]) {
1876 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1877 "; want " + DATA
[i
+1]);
1880 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1890 * Empty pattern produces double negative prefix.
1892 void NumberFormatRegressionTest::Test4140009(void)
1894 UErrorCode status
= U_ZERO_ERROR
;
1895 LocalPointer
<DecimalFormatSymbols
> syms(new DecimalFormatSymbols(Locale::getEnglish(), status
), status
);
1896 if (failure(status
, "new DecimalFormatSymbols")) {
1899 DecimalFormat
*f
= new DecimalFormat(UnicodeString(u
""), syms
.orphan(), status
);
1900 if (!failure(status
, "new DecimalFormat")) {
1902 FieldPosition
pos(FieldPosition::DONT_CARE
);
1903 s
= f
->format(123.456, s
, pos
);
1904 if (s
!= UnicodeString("123.456"))
1905 errln("Fail: Format empty pattern x 123.456 => " + s
);
1907 s
= f
->format(-123.456, s
, pos
);
1908 if (s
!= UnicodeString("-123.456"))
1909 errln("Fail: Format empty pattern x -123.456 => " + s
);
1916 * BigDecimal numbers get their fractions truncated by NumberFormat.
1918 // {sfb} not pertinent in C++ ??
1919 void NumberFormatRegressionTest::Test4141750(void) {
1921 UnicodeString str("12345.67");
1922 BigDecimal bd = new BigDecimal(str);
1923 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1924 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1926 catch (Exception e) {
1927 errln(e.toString());
1928 e.printStackTrace();
1934 * DecimalFormat toPattern() doesn't quote special characters or handle
1937 void NumberFormatRegressionTest::Test4145457() {
1939 UErrorCode status
= U_ZERO_ERROR
;
1940 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1941 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1945 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1947 errln("DecimalFormat needed to continue");
1951 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1952 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1953 nf
->setDecimalFormatSymbols(*sym
);
1954 double pi
= 3.14159;
1956 UnicodeString PATS
[] = {
1957 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1960 for (int32_t i
=0; i
<2; ++i
) {
1961 nf
->applyPattern(PATS
[i
], status
);
1962 failure(status
, "nf->applyPattern");
1964 FieldPosition
pos(FieldPosition::DONT_CARE
);
1965 out
= nf
->format(pi
, out
, pos
);
1967 pat
= nf
->toPattern(pat
);
1969 ParsePosition
pp(0);
1970 nf
->parse(out
, num
, pp
);
1971 double val
= num
.getDouble();
1973 nf
->applyPattern(pat
, status
);
1974 failure(status
, "nf->applyPattern");
1976 out2
= nf
->format(pi
, out2
, pos
);
1978 pat2
= nf
->toPattern(pat2
);
1980 nf
->parse(out2
, num
, pp
);
1981 double val2
= num
.getDouble();
1984 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1985 pat
+ "\" vs. \"" + pat2
+ "\"");
1987 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1989 if (val
== val2
&& out
== out2
) {
1990 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1991 out
+ "\" -> " + val
+ " -> \"" +
1992 out2
+ "\" -> " + val2
);
1995 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1996 out
+ "\" -> " + val
+ " -> \"" +
1997 out2
+ "\" -> " + val2
);
2001 catch (ParseException e) {
2002 errln("Fail: " + e);
2003 e.printStackTrace();
2011 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2013 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2015 * ICU 62: minInt is always at least one, and the getter should reflect that!
2017 void NumberFormatRegressionTest::Test4147295(void)
2019 UErrorCode status
= U_ZERO_ERROR
;
2020 DecimalFormat
*sdf
= new DecimalFormat(status
);
2021 UnicodeString
pattern("#,###");
2022 logln("Applying pattern \"" + pattern
+ "\"");
2023 sdf
->applyPattern(pattern
, status
);
2024 if (!failure(status
, "sdf->applyPattern")) {
2025 int minIntDig
= sdf
->getMinimumIntegerDigits();
2026 if (minIntDig
!= 0) { // use ICU 61 behavior
2027 errln("Test failed");
2028 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2030 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2032 logln("Test passed");
2033 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2041 * DecimalFormat formats -0.0 as +0.0
2042 * See also older related bug 4106658, 4106667
2044 void NumberFormatRegressionTest::Test4147706(void)
2046 UErrorCode status
= U_ZERO_ERROR
;
2047 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2048 failure(status
, "new DecimalFormat");
2049 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2050 if (!failure(status
, "new DecimalFormatSymbols")) {
2052 UnicodeString f2
, temp
;
2053 FieldPosition
pos(FieldPosition::DONT_CARE
);
2054 volatile double d1
= 0.0; // volatile to prevent code optimization
2055 double d2
= -0.0001;
2057 #if U_PLATFORM == U_PF_HPUX
2058 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2060 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2062 df
->adoptDecimalFormatSymbols(syms
);
2063 f1
= df
->format(d1
, f1
, pos
);
2064 f2
= df
->format(d2
, f2
, pos
);
2065 if (f1
!= UnicodeString("-0.0")) {
2066 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2068 if (f2
!= UnicodeString("-0.0")) {
2069 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2077 // Not applicable, since no serialization in C++
2078 /*class myformat implements Serializable
2080 DateFormat _dateFormat = DateFormat.getDateInstance();
2084 GregorianCalendar calendar = new GregorianCalendar();
2085 Date t = calendar.getTime();
2086 String nowStr = _dateFormat.format(t);
2093 * NumberFormat cannot format Double.MAX_VALUE
2095 // TODO: make this test actually test something
2097 NumberFormatRegressionTest::Test4162198(void)
2099 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2100 double dbl
= INT32_MAX
* 1000.0;
2101 UErrorCode status
= U_ZERO_ERROR
;
2102 NumberFormat
*f
= NumberFormat::createInstance(status
);
2103 if(U_FAILURE(status
)) {
2104 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2107 f
->setMaximumFractionDigits(INT32_MAX
);
2108 f
->setMaximumIntegerDigits(INT32_MAX
);
2111 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2114 f
->parse(s
, n
, status
);
2115 if(U_FAILURE(status
))
2116 errln("Couldn't parse!");
2117 //} catch (java.text.ParseException e) {
2118 // errln("Caught a ParseException:");
2119 // e.printStackTrace();
2122 //logln("The string " + s + " parsed as " + n);
2124 // {dlf} The old code assumes n is a double, but it isn't any more...
2125 // Formattable apparently does not and never did interconvert... too bad.
2126 //if(n.getDouble() != dbl) {
2127 // errln("Round trip failure");
2129 if (n
.getInt64() != dbl
) {
2130 errln("Round trip failure");
2138 * NumberFormat does not parse negative zero.
2141 NumberFormatRegressionTest::Test4162852(void)
2143 UErrorCode status
= U_ZERO_ERROR
;
2144 for(int32_t i
=0; i
< 2; ++i
) {
2145 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2146 : NumberFormat::createPercentInstance(status
);
2147 if(U_FAILURE(status
)) {
2148 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2156 f
->parse(s
, n
, status
);
2157 if(U_FAILURE(status
))
2158 errln("Couldn't parse!");
2159 double e
= n
.getDouble();
2160 logln(UnicodeString("") +
2162 '"' + s
+ '"' + " -> " + e
);
2163 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2166 if (e
!= 0.0 || 1.0/e
> 0.0) {
2168 logln("Failed to parse negative zero");
2174 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2177 * May 17 1999 sync up - liu
2179 * NumberFormat truncates data
2181 void NumberFormatRegressionTest::Test4167494(void) {
2182 UErrorCode status
= U_ZERO_ERROR
;
2183 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2184 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2189 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2193 fmt
->parse(s
, num
, status
);
2194 failure(status
, "Parse");
2195 if (num
.getType() == Formattable::kDouble
&&
2196 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2197 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2198 toString(num
) + " ok");
2200 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2201 toString(num
) + " FAIL");
2204 // We don't test Double.MIN_VALUE because the locale data for the US
2205 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2206 // This is correct for now; however, we leave this here as a reminder
2207 // in case we want to address this later.
2213 * May 17 1999 sync up - liu
2215 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2217 void NumberFormatRegressionTest::Test4170798(void) {
2218 IcuTestErrorCode
status(*this, "Test4170798");
2219 LocalPointer
<DecimalFormat
> df(dynamic_cast<DecimalFormat
*>(
2220 NumberFormat::createInstance(Locale::getUS(), status
)), status
);
2221 if (!assertSuccess("", status
, true, __FILE__
, __LINE__
)) {
2226 ParsePosition
pos(0);
2227 df
->parse("-0.0", n
, pos
);
2228 if (n
.getType() != Formattable::kDouble
2229 || n
.getDouble() != -0.0) {
2230 errln(UnicodeString("FAIL: default parse(\"-0.0\") returns ") + toString(n
));
2233 df
->setParseIntegerOnly(TRUE
);
2236 ParsePosition
pos(0);
2237 df
->parse("-0.0", n
, pos
);
2238 if (n
.getType() != Formattable::kLong
2239 || n
.getLong() != 0) {
2240 errln(UnicodeString("FAIL: integer parse(\"-0.0\") returns ") + toString(n
));
2246 * May 17 1999 sync up - liu
2247 * toPattern only puts the first grouping separator in.
2249 void NumberFormatRegressionTest::Test4176114(void) {
2250 const char* DATA
[] = {
2252 "000", "#000", // No grouping
2253 "#000", "#000", // No grouping
2257 "00,000", "#00,000",
2258 "000,000", "#,000,000",
2259 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2261 int DATA_length
= UPRV_LENGTHOF(DATA
);
2262 UErrorCode status
= U_ZERO_ERROR
;
2264 for (int i
=0; i
<DATA_length
; i
+=2) {
2265 DecimalFormat
df(DATA
[i
], status
);
2266 if (!failure(status
, "DecimalFormat constructor")) {
2268 UnicodeString
exp(DATA
[i
+1]);
2270 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2271 s
+ ", want " + exp
);
2278 * May 17 1999 sync up - liu
2280 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2282 void NumberFormatRegressionTest::Test4179818(void) {
2283 const char* DATA
[] = {
2284 // Input Pattern Expected output
2285 "1.2511", "#.#", "1.3",
2286 "1.2501", "#.#", "1.3",
2289 int DATA_length
= UPRV_LENGTHOF(DATA
);
2295 UErrorCode status
= U_ZERO_ERROR
;
2296 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2297 failure(status
, "Construct DecimalFormatSymbols");
2298 DecimalFormat
fmt("#", sym
, status
);
2299 if (!failure(status
, "Construct DecimalFormat")) {
2300 for (int i
=0; i
<DATA_length
; i
+=3) {
2301 double in
= DOUBLE
[i
/3];
2302 UnicodeString
pat(DATA
[i
+1]);
2303 UnicodeString
exp(DATA
[i
+2]);
2304 fmt
.applyPattern(pat
, status
);
2305 failure(status
, "applyPattern");
2308 fmt
.format(in
, out
, pos
);
2310 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2312 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2313 ", expected " + exp
);
2320 * May 17 1999 sync up - liu
2321 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2322 * This includes the minus sign, currency symbol, international currency
2323 * symbol, percent, and permille. This is filed as bugs 4212072 and
2326 void NumberFormatRegressionTest::Test4212072(void) {
2327 UErrorCode status
= U_ZERO_ERROR
;
2328 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2330 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2331 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2332 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2339 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2340 fmt
.setDecimalFormatSymbols(sym
);
2342 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2343 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2347 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2348 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2351 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2353 fmt
.applyPattern(UnicodeString("#%"), status
);
2354 failure(status
, "applyPattern percent");
2355 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2356 fmt
.setDecimalFormatSymbols(sym
);
2358 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2359 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2363 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2364 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2367 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2369 fmt
.applyPattern(str("#\\u2030"), status
);
2370 failure(status
, "applyPattern permill");
2371 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2372 fmt
.setDecimalFormatSymbols(sym
);
2374 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2375 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2379 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2380 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2383 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2385 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2386 failure(status
, "applyPattern currency");
2387 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2388 fmt
.setDecimalFormatSymbols(sym
);
2390 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) { // ICU 61 behavior
2391 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2395 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2396 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2399 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2401 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2402 failure(status
, "applyPattern intl currency");
2403 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2404 fmt
.setDecimalFormatSymbols(sym
);
2406 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) { // ICU 61 behavior
2407 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2411 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2412 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2415 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2417 // Since the pattern logic has changed, make sure that patterns round
2418 // trip properly. Test stream in/out integrity too.
2420 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2421 static const char* type
[] = {
2426 for (int i
=0; i
<n
; ++i
) {
2427 for (int j
=0; j
<3; ++j
) {
2428 status
= U_ZERO_ERROR
;
2432 nf
= NumberFormat::createInstance(avail
[i
], status
);
2433 failure(status
, "createInstance", avail
[i
]);
2436 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2437 failure(status
, "createCurrencyInstance", avail
[i
]);
2440 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2441 failure(status
, "createPercentInstance", avail
[i
]);
2444 if (U_FAILURE(status
)) {
2447 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2449 // Test toPattern/applyPattern round trip
2452 DecimalFormatSymbols
symb(avail
[i
], status
);
2453 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2454 DecimalFormat
f2(pat
, symb
, status
);
2456 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2461 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2463 "\" -> \"" + f2
.toPattern(p
) + "\"");
2466 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2471 // Test toLocalizedPattern/applyLocalizedPattern round trip
2472 // TODO(refactor): don't worry about localized patterns for now.
2473 // df->toLocalizedPattern(pat);
2474 // f2.applyLocalizedPattern(pat, status);
2476 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2477 if (U_FAILURE(status
)) {
2481 // TODO(refactor): don't worry about localized patterns for now.
2482 // Make sure we set the currency attributes appropriately
2483 // if (j == 1) { // Currency format
2484 // f2.setCurrency(f2.getCurrency(), status);
2487 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2488 if (U_FAILURE(status
)) {
2494 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2495 " -> localized \"" + pat
+
2496 "\" -> \"" + f2
.toPattern(p
) + "\"");
2501 // Test writeObject/readObject round trip
2502 // NOT ON ICU -- Java only
2508 * May 17 1999 sync up - liu
2509 * DecimalFormat.parse() fails for mulipliers 2^n.
2511 void NumberFormatRegressionTest::Test4216742(void) {
2512 UErrorCode status
= U_ZERO_ERROR
;
2513 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2514 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2518 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2519 int DATA_length
= UPRV_LENGTHOF(DATA
);
2520 for (int i
=0; i
<DATA_length
; ++i
) {
2521 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2522 for (int m
= 1; m
<= 100; m
++) {
2523 fmt
->setMultiplier(m
);
2525 fmt
->parse(str
, num
, status
);
2526 failure(status
, "parse", Locale::getUS());
2527 if (num
.getType() != Formattable::kLong
&&
2528 num
.getType() != Formattable::kDouble
) {
2529 errln(UnicodeString("FAIL: Wanted number, got ") +
2532 double d
= num
.getType() == Formattable::kDouble
?
2533 num
.getDouble() : (double) num
.getLong();
2534 if ((d
> 0) != (DATA
[i
] > 0)) {
2535 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2536 fmt
->getMultiplier() +
2537 ") => " + toString(num
));
2546 * May 17 1999 sync up - liu
2547 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2550 void NumberFormatRegressionTest::Test4217661(void) {
2551 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2552 const char* S
[] = { "0", "1", "0.01", "1.01" };
2553 int D_length
= UPRV_LENGTHOF(D
);
2554 UErrorCode status
= U_ZERO_ERROR
;
2555 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2556 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2560 fmt
->setMaximumFractionDigits(2);
2561 for (int i
=0; i
<D_length
; i
++) {
2563 fmt
->format(D
[i
], s
);
2564 if (s
!= UnicodeString(S
[i
])) {
2565 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2572 * alphaWorks upgrade
2574 void NumberFormatRegressionTest::Test4161100(void) {
2575 UErrorCode status
= U_ZERO_ERROR
;
2576 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2577 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2581 nf
->setMinimumFractionDigits(1);
2582 nf
->setMaximumFractionDigits(1);
2587 logln(UnicodeString() + a
+ " x " +
2588 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2589 if (s
!= UnicodeString("-0.1")) {
2596 * June 16 1999 sync up - liu
2597 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2599 void NumberFormatRegressionTest::Test4243011(void) {
2600 UErrorCode status
= U_ZERO_ERROR
;
2601 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2602 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2603 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2605 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2606 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2607 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2608 int32_t N
= UPRV_LENGTHOF(NUM
);
2610 for (int32_t i
=0; i
<N
; ++i
) {
2612 UnicodeString
exp(STR
[i
]);
2614 fmt
.format(NUM
[i
], str
, pos
);
2616 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2618 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2626 * June 16 1999 sync up - liu
2627 * format(0.0) gives "0.1" if preceded by parse("99.99").
2628 * (Regression in 1.2.2 RC1)
2630 void NumberFormatRegressionTest::Test4243108(void) {
2631 UErrorCode status
= U_ZERO_ERROR
;
2632 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2633 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2634 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2635 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2642 fmt
.format(0.0, str
, pos
);
2643 UnicodeString
exp("0");
2645 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2647 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2653 fmt
.parse(str
, val
, status
);
2654 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2655 if (val
.getType() == Formattable::kDouble
&&
2656 val
.getDouble() == 99.99) {
2657 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2659 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2664 fmt
.format(0.0, str
, pos
);
2666 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2668 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2675 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2676 * NumberFormat objects.
2678 void NumberFormatRegressionTest::TestJ691(void) {
2679 UErrorCode status
= U_ZERO_ERROR
;
2680 Locale
loc("fr", "CH");
2682 // set up the input date string & expected output
2683 UnicodeString
udt("11.10.2000", "");
2684 UnicodeString
exp("11.10.00", "");
2686 // create a Calendar for this locale
2687 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2688 if (U_FAILURE(status
)) {
2689 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2693 // create a NumberFormat for this locale
2694 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2695 if (U_FAILURE(status
)) {
2696 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2700 // *** Here's the key: We don't want to have to do THIS:
2701 // nf->setParseIntegerOnly(TRUE);
2702 // or this (with changes to fr_CH per cldrbug:9370):
2703 // nf->setGroupingUsed(FALSE);
2704 // so they are done in DateFormat::adoptNumberFormat
2706 // create the DateFormat
2707 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2708 if (U_FAILURE(status
)) {
2709 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2713 df
->adoptCalendar(cal
);
2714 df
->adoptNumberFormat(nf
);
2716 // set parsing to lenient & parse
2717 df
->setLenient(TRUE
);
2718 UDate ulocdat
= df
->parse(udt
, status
);
2720 // format back to a string
2721 UnicodeString outString
;
2722 df
->format(ulocdat
, outString
);
2724 if (outString
!= exp
) {
2725 errln("FAIL: " + udt
+ " => " + outString
);
2731 //---------------------------------------------------------------------------
2733 // Error Checking / Reporting macros
2735 //---------------------------------------------------------------------------
2736 #define TEST_CHECK_STATUS(status) { \
2737 if (U_FAILURE(status)) { \
2738 if (status == U_MISSING_RESOURCE_ERROR) { \
2739 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2741 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2745 #define TEST_ASSERT(expr) \
2746 if ((expr)==FALSE) {\
2747 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2749 #define TEST_ASSERT_EQUALS(x,y) \
2752 int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \
2754 U_ASSERT(len < (int32_t) sizeof(_msg)); \
2755 assertEquals((const char*) _msg, x,y); \
2759 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2761 void NumberFormatRegressionTest::Test8199(void) {
2762 UErrorCode status
= U_ZERO_ERROR
;
2763 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2765 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2768 TEST_CHECK_STATUS(status
);
2770 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2771 // should always truncate, no other rounding scheme.
2773 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2775 nf
->parse(numStr
, val
, status
);
2776 TEST_CHECK_STATUS(status
);
2777 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2778 TEST_ASSERT_EQUALS(1000000000LL, val
.getInt64(status
));
2779 TEST_CHECK_STATUS(status
);
2780 TEST_ASSERT_EQUALS(1000000000.6, val
.getDouble(status
));
2781 TEST_CHECK_STATUS(status
);
2783 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2784 // than int64 because of the fraction
2785 // even though int64 is more precise.
2786 nf
->parse(numStr
, val
, status
);
2787 TEST_CHECK_STATUS(status
);
2788 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2789 TEST_ASSERT_EQUALS(100000000000000001LL, val
.getInt64(status
));
2790 TEST_CHECK_STATUS(status
);
2791 TEST_ASSERT_EQUALS(100000000000000000.0, val
.getDouble(status
));
2792 TEST_CHECK_STATUS(status
);
2794 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2795 nf
->parse(numStr
, val
, status
);
2796 TEST_CHECK_STATUS(status
);
2797 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2798 TEST_ASSERT_EQUALS(100000000000000000LL, val
.getInt64());
2799 TEST_ASSERT_EQUALS(1.0E17
, val
.getDouble(status
));
2800 TEST_CHECK_STATUS(status
);
2802 numStr
= "9223372036854775807"; // largest int64_t
2803 nf
->parse(numStr
, val
, status
);
2804 TEST_CHECK_STATUS(status
);
2805 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2806 TEST_ASSERT_EQUALS(9223372036854775807LL, val
.getInt64());
2807 // In the following check, note that a substantial range of integers will
2808 // convert to the same double value. There are also platform variations
2809 // in the rounding at compile time of double constants.
2810 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2811 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2812 TEST_CHECK_STATUS(status
);
2814 numStr
= "-9223372036854775808"; // smallest int64_t
2815 nf
->parse(numStr
, val
, status
);
2816 TEST_CHECK_STATUS(status
);
2817 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2818 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64()); // Compiler chokes on constant.
2819 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL
, val
.getInt64());
2820 TEST_ASSERT_EQUALS(-9223372036854775808.0, val
.getDouble(status
));
2821 TEST_CHECK_STATUS(status
);
2823 numStr
= "9223372036854775808"; // largest int64_t + 1
2824 nf
->parse(numStr
, val
, status
);
2825 TEST_CHECK_STATUS(status
);
2826 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2827 TEST_ASSERT_EQUALS(9223372036854775807LL, val
.getInt64(status
));
2828 TEST_ASSERT_EQUALS(status
, U_INVALID_FORMAT_ERROR
);
2829 status
= U_ZERO_ERROR
;
2830 TEST_ASSERT_EQUALS(9223372036854775810.0, val
.getDouble(status
));
2831 TEST_CHECK_STATUS(status
);
2833 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2834 nf
->parse(numStr
, val
, status
);
2835 TEST_CHECK_STATUS(status
);
2836 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2837 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64(status)); // spurious compiler warnings
2838 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL
, val
.getInt64(status
));
2839 TEST_ASSERT_EQUALS(status
, U_INVALID_FORMAT_ERROR
);
2840 status
= U_ZERO_ERROR
;
2841 TEST_ASSERT_EQUALS(-9223372036854775810.0, val
.getDouble(status
));
2842 TEST_CHECK_STATUS(status
);
2844 // Test values near the limit of where doubles can represent all integers.
2845 // The implementation strategy of getInt64() changes at this boundary.
2846 // Strings to be parsed include a decimal fraction to force them to be
2847 // parsed as doubles rather than ints. The fraction is discarded
2848 // from the parsed double value because it is beyond what can be represented.
2850 status
= U_ZERO_ERROR
;
2851 numStr
= "9007199254740991.1"; // largest 53 bit int
2852 nf
->parse(numStr
, val
, status
);
2853 TEST_CHECK_STATUS(status
);
2854 // printf("getInt64() returns %lld\n", val.getInt64(status));
2855 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2856 TEST_ASSERT_EQUALS(9007199254740991LL, val
.getInt64(status
));
2857 TEST_ASSERT_EQUALS(9007199254740991.0, val
.getDouble(status
));
2858 TEST_CHECK_STATUS(status
);
2860 status
= U_ZERO_ERROR
;
2861 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2862 nf
->parse(numStr
, val
, status
);
2863 TEST_CHECK_STATUS(status
);
2864 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2865 TEST_ASSERT_EQUALS(9007199254740992LL, val
.getInt64(status
));
2866 TEST_ASSERT_EQUALS(9007199254740992.0, val
.getDouble(status
));
2867 TEST_CHECK_STATUS(status
);
2869 status
= U_ZERO_ERROR
;
2870 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2871 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2872 TEST_CHECK_STATUS(status
);
2873 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2874 TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val
.getInt64(status
));
2875 TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val
.getDouble(status
));
2876 TEST_CHECK_STATUS(status
);
2881 void NumberFormatRegressionTest::Test9109(void) {
2882 UErrorCode status
= U_ZERO_ERROR
;
2885 DecimalFormat
fmt("+##", status
);
2886 if (U_FAILURE(status
)) {
2887 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2891 fmt
.setLenient(TRUE
);
2892 UnicodeString
text("123");
2893 int32_t expected
= 123;
2896 fmt
.parse(text
, val
, pos
);
2897 if (pos
.getErrorIndex() >= 0) {
2898 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2899 } else if (val
.getLong() != 123) {
2900 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2901 } else if (pos
.getIndex() != 3) {
2902 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2907 void NumberFormatRegressionTest::Test9780(void) {
2908 UErrorCode status
= U_ZERO_ERROR
;
2909 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2910 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2914 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2916 errln("DecimalFormat needed to continue");
2919 df
->setParseIntegerOnly(TRUE
);
2923 ParsePosition
pos(0);
2924 UnicodeString
toParse("1,234","");
2925 df
->parse(toParse
, n
, pos
);
2926 if (n
.getType() != Formattable::kLong
2927 || n
.getLong() != 1234) {
2928 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2931 // should still work in lenient mode, just won't get fastpath
2932 df
->setLenient(TRUE
);
2935 ParsePosition
pos(0);
2936 UnicodeString
toParse("1,234","");
2937 df
->parse(toParse
, n
, pos
);
2938 if (n
.getType() != Formattable::kLong
2939 || n
.getLong() != 1234) {
2940 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2947 void NumberFormatRegressionTest::Test9677(void) {
2948 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2949 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2950 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2951 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2952 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2954 UErrorCode status
= U_ZERO_ERROR
;
2955 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2956 if (U_FAILURE(status
)) {
2957 dataerrln("Failure opening unum_open");
2961 if (U_SUCCESS(status
)) {
2962 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2963 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2964 assertSuccess("setting attributes", status
);
2967 if(U_SUCCESS(status
)) {
2968 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2969 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2971 if(U_FAILURE(status
)) {
2972 logln("Got expected parse error %s\n", u_errorName(status
));
2973 status
= U_ZERO_ERROR
;
2975 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2979 if (U_SUCCESS(status
)) {
2980 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2981 assertSuccess("setting attributes", status
);
2982 logln("removed positive prefix");
2985 if(U_SUCCESS(status
)) {
2986 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2987 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2989 if(U_FAILURE(status
)) {
2990 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2991 status
= U_ZERO_ERROR
;
2994 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2996 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
3001 if(U_SUCCESS(status
)) {
3002 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3003 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3005 if(U_FAILURE(status
)) {
3006 logln("text2: Got expected parse error %s\n", u_errorName(status
));
3007 status
= U_ZERO_ERROR
;
3009 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
3013 if (U_SUCCESS(status
)) {
3014 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
3015 assertSuccess("setting attributes", status
);
3016 logln("Set a different neg prefix prefix");
3019 if(U_SUCCESS(status
)) {
3020 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3021 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3023 if(U_FAILURE(status
)) {
3024 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
3025 status
= U_ZERO_ERROR
;
3029 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3031 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3037 void NumberFormatRegressionTest::Test10361(void) {
3038 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3039 // preventing formatting of big decimals.
3040 UErrorCode status
= U_ZERO_ERROR
;
3041 DecimalFormatSymbols
symbols(Locale::getEnglish(), status
);
3042 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###.##", symbols
, status
), status
);
3043 TEST_CHECK_STATUS(status
);
3045 // Create a decimal number with a million digits.
3046 const int32_t NUMSIZE
=1000000;
3047 char *num
= new char[NUMSIZE
];
3048 for (int32_t i
=0; i
<NUMSIZE
; i
++) {
3049 num
[i
] = '0' + (i
+1) % 10;
3051 num
[NUMSIZE
-3] = '.';
3055 Formattable fmtable
;
3056 fmtable
.setDecimalNumber(num
, status
);
3057 TEST_CHECK_STATUS(status
);
3059 FieldPosition
pos(UNUM_DECIMAL_SEPARATOR_FIELD
);
3060 df
->format(fmtable
, s
, pos
, status
);
3061 TEST_CHECK_STATUS(status
);
3062 TEST_ASSERT(999999 == s
.length());
3063 TEST_ASSERT(999997 == pos
.getBeginIndex());
3064 TEST_ASSERT(999998 == pos
.getEndIndex());
3066 UnicodeString
expected(num
, -1, US_INV
);
3067 TEST_ASSERT(expected
== s
);
3071 #endif /* #if !UCONFIG_NO_FORMATTING */