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 <cmath> // std::signbit
15 #include <float.h> // DBL_MIN, DBL_MAX
18 #include "unicode/dcfmtsym.h"
19 #include "unicode/decimfmt.h"
20 #include "unicode/locid.h"
21 #include "unicode/resbund.h"
22 #include "unicode/calendar.h"
23 #include "unicode/datefmt.h"
24 #include "unicode/ucurr.h"
30 class MyNumberFormatTest
: public NumberFormat
34 virtual UClassID
getDynamicClassID(void) const;
36 virtual UnicodeString
& format( double number
,
37 UnicodeString
& toAppendTo
,
38 FieldPositionIterator
* posIter
,
39 UErrorCode
& status
) const
41 return NumberFormat::format(number
, toAppendTo
, posIter
, status
);
44 /* Just keep this here to make some of the compilers happy */
45 virtual UnicodeString
& format(const Formattable
& obj
,
46 UnicodeString
& toAppendTo
,
48 UErrorCode
& status
) const
50 return NumberFormat::format(obj
, toAppendTo
, pos
, status
);
53 /* Just use one of the format functions */
54 virtual UnicodeString
& format( double /* number */,
55 UnicodeString
& toAppendTo
,
56 FieldPosition
& /* pos */) const
63 public Number parse(String text, ParsePosition parsePosition)
64 { return new Integer(0); }
67 /* Just use one of the parse functions */
68 virtual void parse( const UnicodeString
& /* text */,
70 ParsePosition
& /* parsePosition */) const
72 result
.setLong((int32_t)0);
75 virtual void parse( const UnicodeString
& text
,
77 UErrorCode
& status
) const
79 NumberFormat::parse(text
, result
, status
);
81 virtual MyNumberFormatTest
* clone() const
84 virtual UnicodeString
& format(int32_t,
87 { return foo
.remove(); }
89 virtual UnicodeString
& format(int64_t,
92 { return foo
.remove(); }
94 virtual void applyPattern(const UnicodeString
&, UParseError
&, UErrorCode
&){
98 int32_t gMyNumberFormatTestClassID
;
99 UClassID
MyNumberFormatTest::getDynamicClassID() const
101 return (UClassID
)&gMyNumberFormatTestClassID
;
105 // *****************************************************************************
106 // class NumberFormatRegressionTest
107 // *****************************************************************************
109 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
112 NumberFormatRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
114 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
126 CASE(10,Test4086575
);
127 CASE(11,Test4068693
);
128 CASE(12,Test4069754
);
129 CASE(13,Test4087251
);
130 CASE(14,Test4090489
);
131 CASE(15,Test4090504
);
132 CASE(16,Test4095713
);
133 CASE(17,Test4092561
);
134 CASE(18,Test4092480
);
135 CASE(19,Test4087244
);
136 CASE(20,Test4070798
);
137 CASE(21,Test4071005
);
138 CASE(22,Test4071014
);
139 CASE(23,Test4071859
);
140 CASE(24,Test4093610
);
141 CASE(25,Test4098741
);
142 CASE(26,Test4074454
);
143 CASE(27,Test4099404
);
144 CASE(28,Test4101481
);
145 CASE(29,Test4052223
);
146 CASE(30,Test4061302
);
147 CASE(31,Test4062486
);
148 CASE(32,Test4108738
);
149 CASE(33,Test4106658
);
150 CASE(34,Test4106662
);
151 CASE(35,Test4114639
);
152 CASE(36,Test4106664
);
153 CASE(37,Test4106667
);
154 CASE(38,Test4110936
);
155 CASE(39,Test4122840
);
156 CASE(40,Test4125885
);
157 CASE(41,Test4134034
);
158 CASE(42,Test4134300
);
159 CASE(43,Test4140009
);
160 CASE(44,Test4141750
);
161 CASE(45,Test4145457
);
162 CASE(46,Test4147295
);
163 CASE(47,Test4147706
);
164 CASE(48,Test4162198
);
165 CASE(49,Test4162852
);
166 CASE(50,Test4167494
);
167 CASE(51,Test4170798
);
168 CASE(52,Test4176114
);
169 CASE(53,Test4179818
);
170 CASE(54,Test4212072
);
171 CASE(55,Test4216742
);
172 CASE(56,Test4217661
);
173 CASE(57,Test4161100
);
174 CASE(58,Test4243011
);
175 CASE(59,Test4243108
);
183 default: name
= ""; break;
188 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
190 if(U_FAILURE(status
)) {
191 if (possibleDataError
) {
192 dataerrln(UnicodeString("FAIL: ", "") + msg
193 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
195 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
196 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
205 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
207 if(U_FAILURE(status
)) {
208 if (possibleDataError
) {
209 dataerrln(UnicodeString("FAIL: ", "") + msg
210 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
212 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
213 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
222 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
224 if(U_FAILURE(status
)) {
225 if (possibleDataError
) {
226 dataerrln(UnicodeString("FAIL: ", "") + msg
227 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
229 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
230 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
239 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
241 inline UnicodeString
str(const char *input
)
243 return CharsToUnicodeString(input
);
247 * NumberFormat.equals comparing with null should always return false.
249 // {sfb} kind of silly in C++, just checking for new success
250 void NumberFormatRegressionTest::Test4075713(void)
253 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
255 logln("NumberFormat.equals passed");
256 /*} catch (NullPointerException e) {
257 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
264 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
267 void NumberFormatRegressionTest::Test4074620(void)
270 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
271 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
273 nf1
->setGroupingUsed(FALSE
);
274 nf2
->setGroupingUsed(TRUE
);
277 errln("Test for bug 4074620 failed");
279 logln("Test for bug 4074620 passed.");
287 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
290 void NumberFormatRegressionTest::Test4088161 (void)
292 UErrorCode status
= U_ZERO_ERROR
;
293 DecimalFormat
*df
= new DecimalFormat(status
);
294 if (!failure(status
, "new DecimalFormat", "")) {
296 df
->setMinimumFractionDigits(0);
297 df
->setMaximumFractionDigits(16);
299 FieldPosition
fp1(FieldPosition::DONT_CARE
);
300 logln(UnicodeString("d = ") + d
);
301 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
303 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
304 df
->setMaximumFractionDigits(17);
306 FieldPosition
fp2(FieldPosition::DONT_CARE
);
307 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
308 sBuf2
= df
->format(d
, sBuf2
, fp2
);
310 errln(" format(d) = '" + sBuf2
+ "'");
317 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
318 * DecimalFormat(String, DecimalFormatSymbols).
320 void NumberFormatRegressionTest::Test4087245 (void)
322 UErrorCode status
= U_ZERO_ERROR
;
323 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
324 failure(status
, "new DecimalFormatSymbols", "");
325 // {sfb} One note about this test: if you pass in a pointer
326 // to the symbols, they are adopted and this test will fail,
327 // even though that is the correct behavior. To test the cloning
328 // of the symbols, it is necessary to pass in a reference to the symbols
329 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
330 failure(status
, "new DecimalFormat with symbols", "");
334 FieldPosition
pos(FieldPosition::DONT_CARE
);
335 logln(UnicodeString("format(") + n
+ ") = " +
336 df
->format(n
, buf1
, pos
));
337 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
338 logln(UnicodeString("format(") + n
+ ") = " +
339 df
->format(n
, buf2
, pos
));
341 errln("Test for bug 4087245 failed");
348 * DecimalFormat.format() incorrectly formats 0.0
350 void NumberFormatRegressionTest::Test4087535 (void)
352 UErrorCode status
= U_ZERO_ERROR
;
353 DecimalFormat
*df
= new DecimalFormat(status
);
354 if (U_FAILURE(status
)) {
355 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
358 df
->setMinimumIntegerDigits(0);
361 UnicodeString buffer
;
362 FieldPosition
pos(FieldPosition::DONT_CARE
);
363 buffer
= df
->format(n
, buffer
, pos
);
364 if (buffer
.length() == 0)
365 errln(/*n + */": '" + buffer
+ "'");
367 buffer
= df
->format(n
, buffer
, pos
);
368 if (buffer
.length() == 0)
369 errln(/*n + */": '" + buffer
+ "'");
375 * DecimalFormat.format fails when groupingSize is set to 0.
377 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
378 void NumberFormatRegressionTest::Test4088503 (void)
380 UErrorCode status
= U_ZERO_ERROR
;
381 DecimalFormat
*df
= new DecimalFormat(status
);
382 if (U_FAILURE(status
)) {
383 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
386 df
->setGroupingSize(0);
388 FieldPosition
fp(FieldPosition::DONT_CARE
);
390 logln(df
->format((int32_t)123, sBuf
, fp
));
391 //if(fp == FieldPosition(FieldPosition::DONT_CARE))
392 // errln("Test for bug 4088503 failed.");
393 /*} catch (Exception foo) {
394 errln("Test for bug 4088503 failed.");
400 * NumberFormat.getCurrencyInstance is wrong.
402 void NumberFormatRegressionTest::Test4066646 (void)
404 assignFloatValue(2.04f
);
405 assignFloatValue(2.03f
);
406 assignFloatValue(2.02f
);
407 assignFloatValue(0.0f
);
411 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
413 logln(UnicodeString(" VALUE ") + returnfloat
);
414 UErrorCode status
= U_ZERO_ERROR
;
415 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
416 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
420 nfcommon
->setGroupingUsed(FALSE
);
422 UnicodeString stringValue
;
423 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
424 logln(" DISPLAYVALUE " + stringValue
);
426 nfcommon
->parse(stringValue
, result
, status
);
427 failure(status
, "nfcommon->parse", Locale::getUS());
428 float floatResult
= (float) (result
.getType() == Formattable::kDouble
429 ? result
.getDouble() : result
.getLong());
430 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
431 //String stringValue = nfcommon.format(returnfloat).substring(1);
432 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
433 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
437 } // End Of assignFloatValue()
440 * DecimalFormat throws exception when parsing "0"
442 void NumberFormatRegressionTest::Test4059870(void)
444 UErrorCode status
= U_ZERO_ERROR
;
445 DecimalFormat
*format
= new DecimalFormat("00", status
);
446 failure(status
, "new Decimalformat", Locale::getUS());
450 format
->parse(UnicodeString("0"), result
, status
);
451 failure(status
, "format->parse", Locale::getUS());
454 catch (Exception e) {
455 errln("Test for bug 4059870 failed : " + e);
461 * DecimalFormatSymbol.equals should always return false when
462 * comparing with null.
464 // {sfb} this is silly in C++
465 void NumberFormatRegressionTest::Test4083018 (void)
467 UErrorCode status
= U_ZERO_ERROR
;
468 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
469 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
472 logln("Test Passed!");
474 errln("Test for bug 4083018 failed");
475 /*} catch (Exception foo) {
476 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
483 * DecimalFormat does not round up correctly.
485 void NumberFormatRegressionTest::Test4071492 (void)
487 double x
= 0.00159999;
488 UErrorCode status
= U_ZERO_ERROR
;
489 NumberFormat
*nf
= NumberFormat::createInstance(status
);
490 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
494 nf
->setMaximumFractionDigits(4);
496 FieldPosition
pos(FieldPosition::DONT_CARE
);
497 out
= nf
->format(x
, out
, pos
);
498 logln("0.00159999 formats with 4 fractional digits to " + out
);
499 UnicodeString
expected("0.0016");
501 errln("FAIL: Expected " + expected
);
507 * A space as a group separator for localized pattern causes
508 * wrong format. WorkAround : use non-breaking space.
510 void NumberFormatRegressionTest::Test4086575(void)
512 UErrorCode status
= U_ZERO_ERROR
;
513 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
515 // TODO: There is not a good way to find out that the creation of this number format has
516 // failed. Major rewiring of format construction proposed.
517 if(U_FAILURE(status
)) {
518 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
522 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
524 // C++ workaround to make sure cast works
525 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
527 errln("NumberFormat::createInstance returned incorrect type.");
532 logln("nf toPattern1: " + nf
->toPattern(temp
));
533 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
535 // No group separator
536 logln("...applyLocalizedPattern ###,00;(###,00) ");
537 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
538 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
539 logln("nf toPattern2: " + nf
->toPattern(temp
));
540 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
542 FieldPosition
pos(FieldPosition::DONT_CARE
);
543 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
544 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
546 // Space as group separator
548 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
550 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
552 0x23, 0x202f, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
553 0x28, 0x23, 0x202f, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
555 UnicodeString
pat(patChars
, 19, 19);
556 nf
->applyLocalizedPattern(pat
, status
);
557 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
558 logln("nf toPattern2: " + nf
->toPattern(temp
));
559 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
560 UnicodeString buffer
;
561 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
562 //if (buffer != UnicodeString("1\u00a0234,00"))
564 0x31, 0x202f, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
566 UnicodeString
cc(c
, 8, 8);
568 errln("nf : " + buffer
); // Expect 1 234,00
571 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
573 0x28, 0x31, 0x202f, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
575 UnicodeString
cc1(c1
, 10, 10);
577 errln("nf : " + buffer
); // Expect (1 234,00)
579 // Erroneously prints:
586 * DecimalFormat.parse returns wrong value
588 // {sfb} slightly converted into a round-trip test, since in C++
589 // there is no Double.toString()
590 void NumberFormatRegressionTest::Test4068693(void)
592 logln("----- Test Application -----");
593 ParsePosition
pos(0);
594 UErrorCode status
= U_ZERO_ERROR
;
595 DecimalFormat
*df
= new DecimalFormat(status
);
596 if(U_FAILURE(status
)) {
597 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
601 failure(status
, "new DecimalFormat");
603 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
604 df
->parse(UnicodeString("123.55456"), d
, pos
);
605 //if (!d.toString().equals("123.55456")) {
607 df
->setMaximumFractionDigits(999);
608 df
->setMaximumIntegerDigits(999);
609 FieldPosition
fp(FieldPosition::DONT_CARE
);
610 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
611 if (dstr
!= UnicodeString("123.55456")) {
612 errln(UnicodeString("Result -> ") + d
.getDouble());
618 /* @bug 4069754, 4067878
619 * null pointer thrown when accessing a deserialized DecimalFormat
622 // {sfb} doesn't apply in C++
623 void NumberFormatRegressionTest::Test4069754(void)
626 myformat it = new myformat();
628 FileOutputStream ostream = new FileOutputStream("t.tmp");
629 ObjectOutputStream p = new ObjectOutputStream(ostream);
634 FileInputStream istream = new FileInputStream("t.tmp");
635 ObjectInputStream p2 = new ObjectInputStream(istream);
636 myformat it2 = (myformat)p2.readObject();
640 } catch (Exception foo) {
641 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
646 * DecimalFormat.applyPattern(String) allows illegal patterns
648 void NumberFormatRegressionTest::Test4087251 (void)
650 UErrorCode status
= U_ZERO_ERROR
;
651 DecimalFormat
*df
= new DecimalFormat(status
);
652 if(U_FAILURE(status
)) {
653 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
657 failure(status
, "new DecimalFormat");
659 df
->applyPattern(UnicodeString("#.#.#"), status
);
660 if( ! U_FAILURE(status
))
661 errln("df->applyPattern with illegal pattern didn't fail");
663 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
664 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
665 /*} catch (IllegalArgumentException e) {
666 logln("Caught Illegal Argument Error !");
668 // Second test; added 5/11/98 when reported to fail on 1.2b3
670 df
->applyPattern("#0.0#0#0", status
);
671 if( ! U_FAILURE(status
))
672 errln("df->applyPattern with illegal pattern didn't fail");
673 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
674 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
675 /*} catch (IllegalArgumentException e) {
676 logln("Ok - IllegalArgumentException for #0.0#0#0");
683 * DecimalFormat.format() loses precision
685 void NumberFormatRegressionTest::Test4090489 (void)
687 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
688 // that NumberFormat can do. For some reason, it does not format the last 1.
690 /* UErrorCode status = U_ZERO_ERROR;
691 DecimalFormat *df = new DecimalFormat(status);
692 failure(status, "new DecimalFormat");
693 df->setMinimumFractionDigits(10);
694 df->setMaximumFractionDigits(999);
695 df->setGroupingUsed(FALSE);
696 double d = 1.000000000000001E7;
697 //BigDecimal bd = new BigDecimal(d);
699 FieldPosition fp(FieldPosition::DONT_CARE);
700 logln(UnicodeString("d = ") + d);
701 //logln("BigDecimal.toString(): " + bd.toString());
702 df->format(d, sb, fp);
703 if (sb != "10000000.0000000100") {
704 errln("DecimalFormat.format(): " + sb);
710 * DecimalFormat.format() loses precision
712 void NumberFormatRegressionTest::Test4090504 (void)
715 logln(UnicodeString("d = ") + d
);
716 UErrorCode status
= U_ZERO_ERROR
;
717 DecimalFormat
*df
= new DecimalFormat(status
);
718 if(U_FAILURE(status
)) {
719 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
723 failure(status
, "new DecimalFormat");
725 FieldPosition
fp(FieldPosition::DONT_CARE
);
727 for (int i
= 17; i
<= 20; i
++) {
728 df
->setMaximumFractionDigits(i
);
729 //sb = new StringBuffer("");
731 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
732 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
734 /*} catch (Exception foo) {
735 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
741 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
743 void NumberFormatRegressionTest::Test4095713 (void)
745 UErrorCode status
= U_ZERO_ERROR
;
746 DecimalFormat
*df
= new DecimalFormat(status
);
747 if(U_FAILURE(status
)) {
748 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
752 failure(status
, "new DecimalFormat");
753 UnicodeString
str("0.1234");
755 //Double d1 = new Double(str);
756 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
759 df
->parse(str
, d2
, pp
);
760 logln(UnicodeString("") + d1
);
761 if (d2
.getDouble() != d1
)
762 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
767 * DecimalFormat.parse() fails when multiplier is not set to 1
769 // {sfb} not sure what to do with this one
770 void NumberFormatRegressionTest::Test4092561 (void)
772 UErrorCode status
= U_ZERO_ERROR
;
773 DecimalFormat
*df
= new DecimalFormat(status
);
774 if(U_FAILURE(status
)) {
775 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
779 failure(status
, "new DecimalFormat");
781 // {sfb} going to cheat here and use sprintf ??
783 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
784 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
785 df.setMultiplier(100);
786 Number num = df.parse(str, new ParsePosition(0));
787 if (num.doubleValue() != -9.223372036854776E16)
788 errln("Bug 4092561 test failed when multiplier is set to not 1.");
794 * DecimalFormat: Negative format ignored.
796 void NumberFormatRegressionTest::Test4092480 (void)
798 UErrorCode status
= U_ZERO_ERROR
;
799 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
800 if(U_FAILURE(status
)) {
801 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
805 failure(status
, "new DecimalFormat");
808 dfFoo
->applyPattern("0000;-000", status
);
809 failure(status
, "dfFoo->applyPattern");
811 if (dfFoo
->toPattern(temp
) != UnicodeString("0000"))
812 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
813 FieldPosition
pos(FieldPosition::DONT_CARE
);
814 logln(dfFoo
->format((int32_t)42, temp
, pos
));
815 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
816 dfFoo
->applyPattern("000;-000", status
);
817 failure(status
, "dfFoo->applyPattern");
818 if (dfFoo
->toPattern(temp
) != UnicodeString("000"))
819 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
820 logln(dfFoo
->format((int32_t)42,temp
, pos
));
821 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
823 dfFoo
->applyPattern("000;-0000", status
);
824 failure(status
, "dfFoo->applyPattern");
825 if (dfFoo
->toPattern(temp
) != UnicodeString("000"))
826 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
827 logln(dfFoo
->format((int32_t)42, temp
, pos
));
828 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
830 dfFoo
->applyPattern("0000;-000", status
);
831 failure(status
, "dfFoo->applyPattern");
832 if (dfFoo
->toPattern(temp
) != UnicodeString("0000"))
833 errln("ERROR: dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
834 logln(dfFoo
->format((int32_t)42, temp
, pos
));
835 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
836 /*} catch (Exception foo) {
837 errln("Message " + foo.getMessage());
843 * NumberFormat.getCurrencyInstance() produces format that uses
844 * decimal separator instead of monetary decimal separator.
846 * Rewrote this test not to depend on the actual pattern. Pattern should
847 * never contain the monetary separator! Decimal separator in pattern is
848 * interpreted as monetary separator if currency symbol is seen!
850 void NumberFormatRegressionTest::Test4087244 (void) {
851 UErrorCode status
= U_ZERO_ERROR
;
854 uloc_canonicalize("pt_PT@currency=PTE", loc
, 256, &status
);
856 LocalPointer
<NumberFormat
> nf(NumberFormat::createCurrencyInstance(de
, status
));
857 if(U_FAILURE(status
)) {
858 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
861 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
.getAlias());
863 errln("expected DecimalFormat!");
866 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
867 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
868 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
869 if (decSep
== monSep
) {
870 errln("ERROR in test: want decimal sep != monetary sep");
873 df
->setMinimumIntegerDigits(1);
874 df
->setMinimumFractionDigits(2);
877 df
->format(1.23, str
, pos
);
878 UnicodeString
monStr("1x23");
879 monStr
.replace((int32_t)1, 1, monSep
);
880 UnicodeString
decStr("1x23");
881 decStr
.replace((int32_t)1, 1, decSep
);
882 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
883 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
884 monStr
+ "\" and not \"" + decStr
+ '"');
886 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
888 "\" and not \"" + decStr
+ '"');
892 * Number format data rounding errors for locale FR
894 void NumberFormatRegressionTest::Test4070798 (void)
896 NumberFormat
*formatter
;
897 UnicodeString tempString
;
900 String expectedDefault = "-5\u202f789,987";
901 String expectedCurrency = "5\u202f789,98\u00a0F";
902 String expectedPercent = "-578\u202f998%";
905 0x2d, 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
908 0x35, 0x202f, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
911 0x2d, 0x35, 0x37, 0x38, 0x202f, 0x39, 0x39, 0x39, 0x00a0, 0x25
913 UnicodeString
expectedDefault(chars1
, 10, 10);
914 UnicodeString
expectedCurrency(chars2
, 10, 10);
915 UnicodeString
expectedPercent(chars3
, 10, 10);
917 UErrorCode status
= U_ZERO_ERROR
;
919 int len
= uloc_canonicalize("fr_FR@currency=FRF", loc
, 256, &status
);
920 (void)len
; // Suppress set but not used warning.
921 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
922 if(U_FAILURE(status
)) {
923 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
927 failure(status
, "NumberFormat::createInstance", loc
);
928 tempString
= formatter
->format (-5789.9876, tempString
);
930 if (tempString
== expectedDefault
) {
931 logln ("Bug 4070798 default test passed.");
933 errln(UnicodeString("Failed:") +
934 " Expected " + expectedDefault
+
935 " Received " + tempString
);
938 len
= uloc_canonicalize("fr_FR@currency=FRF", loc
, 256, &status
);
939 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
940 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
942 tempString
= formatter
->format( 5789.9876, tempString
);
944 if (tempString
== expectedCurrency
) {
945 logln ("Bug 4070798 currency test passed.");
947 errln(UnicodeString("Failed:") +
948 " Expected " + expectedCurrency
+
949 " Received " + tempString
);
953 uloc_canonicalize("fr_FR@currency=FRF", loc
, 256, &status
);
954 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
955 failure(status
, "NumberFormat::createPercentInstance", loc
);
957 tempString
= formatter
->format (-5789.9876, tempString
);
959 if (tempString
== expectedPercent
) {
960 logln ("Bug 4070798 percentage test passed.");
962 errln(UnicodeString("Failed:") +
963 " Expected " + expectedPercent
+
964 " Received " + tempString
);
970 * Data rounding errors for French (Canada) locale
972 void NumberFormatRegressionTest::Test4071005 (void)
974 NumberFormat
*formatter
;
975 UnicodeString tempString
;
977 String expectedDefault = "-5\u00a0789,987";
978 String expectedCurrency = "5\u00a0789,98\u00a0$";
979 String expectedPercent = "-578\u00a0998%";
982 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
985 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
988 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
990 UnicodeString
expectedDefault(chars1
, 10, 10);
991 UnicodeString
expectedCurrency(chars2
, 10, 10);
992 UnicodeString
expectedPercent(chars3
, 10, 10);
994 UErrorCode status
= U_ZERO_ERROR
;
995 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
996 if (failure(status
, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE
)){
1000 tempString
= formatter
->format (-5789.9876, tempString
);
1002 if (tempString
== expectedDefault
) {
1003 logln ("Bug 4071005 default test passed.");
1005 errln(UnicodeString("Failed:") +
1006 " Expected " + expectedDefault
+
1007 " Received " + tempString
);
1011 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
1012 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1013 tempString
.remove();
1014 tempString
= formatter
->format( 5789.9876, tempString
);
1016 if (tempString
== expectedCurrency
) {
1017 logln ("Bug 4071005 currency test assed.");
1019 errln(UnicodeString("Failed:") +
1020 " Expected " + expectedCurrency
+
1021 " Received " + tempString
);
1025 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1026 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1027 tempString
.remove();
1028 tempString
= formatter
->format (-5789.9876, tempString
);
1030 if (tempString
== expectedPercent
) {
1031 logln ("Bug 4071005 percentage test passed.");
1033 errln(UnicodeString("Failed:") +
1034 " Expected " + expectedPercent
+
1035 " Received " + tempString
);
1042 * Data rounding errors for German (Germany) locale
1044 void NumberFormatRegressionTest::Test4071014 (void)
1046 NumberFormat
*formatter
;
1047 UnicodeString tempString
;
1049 String expectedDefault = "-5.789,987";
1050 String expectedCurrency = "5.789,98 DM";
1051 String expectedPercent = "-578.998%";
1053 UnicodeString
expectedDefault("-5.789,988");
1054 UnicodeString
expectedCurrency("5.789,99\\u00A0DM");
1055 UnicodeString
expectedPercent("-578.999\\u00A0%");
1057 expectedCurrency
= expectedCurrency
.unescape();
1058 expectedPercent
= expectedPercent
.unescape();
1060 UErrorCode status
= U_ZERO_ERROR
;
1062 uloc_canonicalize("de_DE@currency=DEM", loc
, 256, &status
);
1063 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1064 if (failure(status
, "NumberFormat::createInstance", loc
, TRUE
)){
1068 tempString
.remove();
1069 tempString
= formatter
->format (-5789.9876, tempString
);
1071 if (tempString
== expectedDefault
) {
1072 logln ("Bug 4071014 default test passed.");
1074 errln(UnicodeString("Failed:") +
1075 " Expected " + expectedDefault
+
1076 " Received " + tempString
);
1079 uloc_canonicalize("de_DE@currency=DEM", loc
, 256, &status
);
1080 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1081 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1082 tempString
.remove();
1083 tempString
= formatter
->format( 5789.9876, tempString
);
1085 if (tempString
== expectedCurrency
) {
1086 logln ("Bug 4071014 currency test assed.");
1088 errln(UnicodeString("Failed:") +
1089 " Expected " + expectedCurrency
+
1090 " Received " + tempString
);
1094 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1095 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1096 tempString
.remove();
1097 tempString
= formatter
->format (-5789.9876, tempString
);
1099 if (tempString
== expectedPercent
) {
1100 logln ("Bug 4071014 percentage test passed.");
1102 errln(UnicodeString("Failed:") +
1103 " Expected " + expectedPercent
+
1104 " Received " + tempString
);
1110 * Data rounding errors for Italian locale number formats
1112 void NumberFormatRegressionTest::Test4071859 (void)
1114 NumberFormat
*formatter
;
1115 UnicodeString tempString
;
1117 String expectedDefault = "-5.789,987";
1118 String expectedCurrency = "-L.\\u00A05.789,98";
1119 String expectedPercent = "-578.998%";
1121 UnicodeString
expectedDefault("-5.789,988");
1122 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1123 UnicodeString
expectedPercent("-578.999%");
1124 expectedCurrency
= expectedCurrency
.unescape();
1126 UErrorCode status
= U_ZERO_ERROR
;
1128 uloc_canonicalize("it_IT@currency=ITL", loc
, 256, &status
);
1129 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1130 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1134 tempString
= formatter
->format (-5789.9876, tempString
);
1136 if (tempString
== expectedDefault
) {
1137 logln ("Bug 4071859 default test passed.");
1139 errln(UnicodeString("Failed:") +
1140 " Expected " + expectedDefault
+
1141 " Received " + tempString
);
1144 uloc_canonicalize("it_IT@currency=ITL", loc
, 256, &status
);
1145 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1146 failure(status
, "NumberFormat::createCurrencyInstance");
1147 tempString
.remove();
1148 tempString
= formatter
->format( -5789.9876, tempString
);
1150 if (tempString
== expectedCurrency
) {
1151 logln ("Bug 4071859 currency test assed.");
1153 errln(UnicodeString("Failed:") +
1154 " Expected " + expectedCurrency
+
1155 " Received " + tempString
);
1158 uloc_canonicalize("it_IT@currency=ITL", loc
, 256, &status
);
1159 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1160 failure(status
, "NumberFormat::createPercentInstance");
1161 tempString
.remove();
1162 tempString
= formatter
->format (-5789.9876, tempString
);
1164 if (tempString
== expectedPercent
) {
1165 logln ("Bug 4071859 percentage test passed.");
1167 errln(UnicodeString("Failed:") +
1168 " Expected " + expectedPercent
+
1169 " Received " + tempString
);
1175 * Test rounding for nearest even.
1177 void NumberFormatRegressionTest::Test4093610(void)
1179 UErrorCode status
= U_ZERO_ERROR
;
1180 DecimalFormat
df("#0.#", status
);
1181 if (!failure(status
, "new DecimalFormat")) {
1182 UnicodeString
s("12.4");
1183 roundingTest(&df
, 12.35, s
);
1184 roundingTest(&df
, 12.45, s
);
1186 roundingTest(&df
, 12.452,s
);
1188 roundingTest(&df
, 12.55, s
);
1189 roundingTest(&df
, 12.65, s
);
1191 roundingTest(&df
, 12.652,s
);
1193 roundingTest(&df
, 12.75, s
);
1194 roundingTest(&df
, 12.752,s
);
1195 roundingTest(&df
, 12.85, s
);
1197 roundingTest(&df
, 12.852,s
);
1199 roundingTest(&df
, 12.95, s
);
1200 roundingTest(&df
, 12.952,s
);
1204 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1207 FieldPosition
pos(FieldPosition::DONT_CARE
);
1208 out
= df
->format(x
, out
, pos
);
1209 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1210 if (out
!= expected
) {
1211 dataerrln("FAIL: Expected '%s'; got '%s'", CStr(expected
)(), CStr(out
)());
1215 * Tests the setMaximumFractionDigits limit.
1217 void NumberFormatRegressionTest::Test4098741(void)
1220 UErrorCode status
= U_ZERO_ERROR
;
1221 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1222 if (U_FAILURE(status
)) {
1223 dataerrln("Error calling NumberFormat::createPercentInstance");
1228 fmt
->setMaximumFractionDigits(20);
1230 logln(fmt
->format(.001, temp
));
1231 /*} catch (Exception foo) {
1232 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1237 * Tests illegal pattern exception.
1238 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1239 * Part2 has been fixed.
1241 void NumberFormatRegressionTest::Test4074454(void)
1244 UErrorCode status
= U_ZERO_ERROR
;
1245 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1246 if(U_FAILURE(status
)) {
1247 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1251 failure(status
, "new DecimalFormat");
1252 logln("Inconsistent negative pattern is fine.");
1253 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1254 failure(status
, "new DecimalFormat");
1255 UnicodeString tempString
;
1256 FieldPosition
pos(FieldPosition::DONT_CARE
);
1257 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1258 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1259 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1260 /*} catch (Exception foo) {
1261 errln("An exception was thrown for any inconsistent negative pattern.");
1268 * Tests all different comments.
1269 * Response to some comments :
1270 * [1] DecimalFormat.parse API documentation is more than just one line.
1271 * This is not a reproducable doc error in 116 source code.
1272 * [2] See updated javadoc.
1274 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1275 * a null object will be returned. The unchanged parse position also
1276 * reflects an error.
1277 * NumberFormat.parse(String) : If parsing fails, an ParseException
1279 * See updated javadoc for more details.
1280 * [5] See updated javadoc.
1281 * [6] See updated javadoc.
1282 * [7] This is a correct behavior if the DateFormat object is linient.
1283 * Otherwise, an IllegalArgumentException will be thrown when formatting
1284 * "January 35". See GregorianCalendar class javadoc for more details.
1286 void NumberFormatRegressionTest::Test4099404(void)
1289 UErrorCode status
= U_ZERO_ERROR
;
1290 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1291 if(! U_FAILURE(status
))
1292 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1293 /*} catch (Exception foo) {
1294 logln("Bug 4099404 pattern \"000.0#0\" passed");
1299 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1300 if( !U_FAILURE(status
))
1301 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1302 /*} catch (Exception foo) {
1303 logln("Bug 4099404 pattern \"0#0.000\" passed");
1309 * DecimalFormat.applyPattern doesn't set minimum integer digits
1311 void NumberFormatRegressionTest::Test4101481(void)
1313 UErrorCode status
= U_ZERO_ERROR
;
1314 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1315 if(U_FAILURE(status
)) {
1316 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1320 failure(status
, "new DecimalFormat");
1321 if (sdf
->getMinimumIntegerDigits() != 1)
1322 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1325 /* @bug 4052223 (API addition request A27)
1326 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1328 void NumberFormatRegressionTest::Test4052223(void)
1331 UErrorCode status
= U_ZERO_ERROR
;
1332 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1333 if(U_FAILURE(status
)) {
1334 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1338 failure(status
, "new DecimalFormat");
1340 fmt
->parse(UnicodeString("abc3"), num
, status
);
1341 if(! U_FAILURE(status
))
1342 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1343 /*} catch (ParseException foo) {
1344 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1349 * API tests for API addition request A9.
1351 void NumberFormatRegressionTest::Test4061302(void)
1353 UErrorCode status
= U_ZERO_ERROR
;
1354 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1355 if (U_FAILURE(status
)) {
1356 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status
));
1359 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1360 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1361 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1362 if (currency
== UnicodeString("") ||
1363 intlCurrency
== UnicodeString("") ||
1364 monDecSeparator
== UnicodeString(""))
1366 errln("getCurrencySymbols failed, got empty string.");
1368 UnicodeString monDecSeparatorStr
;
1369 monDecSeparatorStr
.append(monDecSeparator
);
1370 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1371 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1372 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1373 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1374 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1375 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1376 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1377 if (currency
!= UnicodeString("XYZ") ||
1378 intlCurrency
!= UnicodeString("ABC") ||
1379 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1380 errln("setCurrencySymbols failed.");
1382 monDecSeparatorStr
.remove();
1383 monDecSeparatorStr
.append(monDecSeparator
);
1384 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1389 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1390 * FieldPosition.getEndIndex.
1392 void NumberFormatRegressionTest::Test4062486(void)
1394 UErrorCode status
= U_ZERO_ERROR
;
1395 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1396 if (U_FAILURE(status
)) {
1397 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
1400 UnicodeString formatted
;
1401 FieldPosition
field(FieldPosition::DONT_CARE
);
1402 double num
= 1234.5;
1403 fmt
->format(num
, formatted
, field
);
1404 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1405 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1406 field
.setBeginIndex(7);
1407 field
.setEndIndex(4);
1408 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1409 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1415 * DecimalFormat.parse incorrectly works with a group separator.
1417 void NumberFormatRegressionTest::Test4108738(void)
1419 UErrorCode status
= U_ZERO_ERROR
;
1420 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1421 failure(status
, "new DecimalFormatSymbols");
1422 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1423 if(U_FAILURE(status
)) {
1424 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1428 failure(status
, "new DecimalFormat");
1429 UnicodeString
text("1.222,111");
1431 ParsePosition
pp(0);
1432 df
->parse(text
, num
, pp
);
1434 // {sfb} how to do this (again) ?
1435 // shouldn't just be another round-trip test, should it?
1437 FieldPosition
pos(FieldPosition::DONT_CARE
);
1438 temp
= df
->format(num
.getDouble(), temp
, pos
);
1439 //if (!num.toString().equals("1.222"))
1440 if (temp
!= UnicodeString("1.222"))
1441 //errln("\"" + text + "\" is parsed as " + num);
1442 errln("\"" + text
+ "\" is parsed as " + temp
);
1443 text
= UnicodeString("1.222x111");
1444 pp
= ParsePosition(0);
1445 df
->parse(text
, num
, pp
);
1447 temp
= df
->format(num
.getDouble(), temp
, pos
);
1448 //if (!num.toString().equals("1.222"))
1449 if (temp
!= UnicodeString("1.222"))
1450 errln("\"" + text
+ "\" is parsed as " + temp
);
1456 * DecimalFormat.format() incorrectly formats negative doubles.
1458 void NumberFormatRegressionTest::Test4106658(void)
1460 UErrorCode status
= U_ZERO_ERROR
;
1461 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1462 if(U_FAILURE(status
)) {
1463 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1467 failure(status
, "new DecimalFormat");
1468 volatile double d1
= 0.0; // volatile to prevent code optimization
1469 double d2
= -0.0001;
1470 UnicodeString buffer
;
1472 FieldPosition
pos(FieldPosition::DONT_CARE
);
1474 #if U_PLATFORM == U_PF_HPUX
1475 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1477 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1479 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1480 df
->format(d1
, buffer
, pos
);
1481 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1482 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1484 df
->format(d2
, buffer
, pos
);
1485 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1486 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1492 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1494 void NumberFormatRegressionTest::Test4106662(void)
1496 UErrorCode status
= U_ZERO_ERROR
;
1497 DecimalFormat
*df
= new DecimalFormat(status
);
1498 if(U_FAILURE(status
)) {
1499 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1503 failure(status
, "new DecimalFormat");
1504 UnicodeString
text("x");
1505 ParsePosition
pos1(0), pos2(0);
1508 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1510 df
->parse(text
, num
, pos1
);
1511 if (pos1
== ParsePosition(0)/*num != null*/) {
1512 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1515 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1516 failure(status
, "new DecimalFormat");
1517 df
->parse(UnicodeString("$"), num
, pos2
);
1518 if (pos2
== ParsePosition(0) /*num != null*/){
1519 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1525 /* @bug 4114639 (duplicate of 4106662)
1526 * NumberFormat.parse doesn't return null
1528 void NumberFormatRegressionTest::Test4114639(void)
1530 UErrorCode status
= U_ZERO_ERROR
;
1531 NumberFormat
*format
= NumberFormat::createInstance(status
);
1532 if(U_FAILURE(status
)) {
1533 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1537 failure(status
, "NumberFormat::createInstance");
1538 UnicodeString
text("time 10:x");
1539 ParsePosition
pos(8);
1541 format
->parse(text
, result
, pos
);
1542 if (/*result != null*/pos
.getErrorIndex() != 8)
1543 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1549 * TODO: this test does not work because we need to use a 64 bit number and a
1550 * a double only MAY only have 52 bits of precision.
1551 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1553 void NumberFormatRegressionTest::Test4106664(void)
1555 UErrorCode status
= U_ZERO_ERROR
;
1556 DecimalFormat
*df
= new DecimalFormat(status
);
1557 if(U_FAILURE(status
)) {
1558 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1562 failure(status
, "new DecimalFormat");
1563 // {sfb} long in java is 64 bits
1564 /*long*/double n
= 1234567890123456.0;
1565 /*int*/int32_t m
= 12345678;
1566 // {sfb} will this work?
1567 //BigInteger bigN = BigInteger.valueOf(n);
1568 //bigN = bigN.multiply(BigInteger.valueOf(m));
1569 double bigN
= n
* m
;
1570 df
->setMultiplier(m
);
1571 df
->setGroupingUsed(FALSE
);
1573 FieldPosition
pos(FieldPosition::DONT_CARE
);
1574 logln("formated: " +
1575 df
->format(n
, temp
, pos
));
1578 sprintf(buf
, "%g", bigN
);
1579 //logln("expected: " + bigN.toString());
1580 logln(UnicodeString("expected: ") + buf
);
1584 /* @bug 4106667 (duplicate of 4106658)
1585 * DecimalFormat.format incorrectly formats -0.0.
1587 void NumberFormatRegressionTest::Test4106667(void)
1589 UErrorCode status
= U_ZERO_ERROR
;
1590 DecimalFormat
*df
= new DecimalFormat(status
);
1591 if(U_FAILURE(status
)) {
1592 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1596 failure(status
, "new DecimalFormat");
1597 UChar foo
[] = { 0x002B };
1598 UnicodeString
bar(foo
, 1, 1);
1599 volatile double d
= 0.0; // volatile to prevent code optimization
1601 UnicodeString buffer
;
1602 FieldPosition
pos(FieldPosition::DONT_CARE
);
1604 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1605 #if U_PLATFORM == U_PF_HPUX
1606 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1608 d
*= -1.0; // Some compilers have a problem with defining -0.0
1610 df
->setPositivePrefix(/*"+"*/bar
);
1611 df
->format(d
, buffer
, pos
);
1612 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1613 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1619 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1621 #if U_PLATFORM == U_PF_OS390
1622 # define MAX_INT_DIGITS 70
1624 # define MAX_INT_DIGITS 128
1627 void NumberFormatRegressionTest::Test4110936(void)
1629 UErrorCode status
= U_ZERO_ERROR
;
1630 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1631 if(U_FAILURE(status
)) {
1632 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1636 failure(status
, "NumberFormat::createInstance");
1637 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1638 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1639 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1640 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1641 nf
->getMaximumIntegerDigits());
1647 * Locale data should use generic currency symbol
1649 * 1) Make sure that all currency formats use the generic currency symbol.
1650 * 2) Make sure we get the same results using the generic symbol or a
1653 void NumberFormatRegressionTest::Test4122840(void)
1656 const Locale
*locales
= Locale::getAvailableLocales(count
);
1658 for (int i
= 0; i
< count
; i
++) {
1659 UErrorCode status
= U_ZERO_ERROR
;
1660 ResourceBundle
*rb
= new ResourceBundle(
1661 NULL
/*"java.text.resources.LocaleElements"*/,
1662 locales
[i
], status
);
1663 failure(status
, "new ResourceBundle");
1664 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1665 failure(status
, "rb.get(NumberElements)");
1666 numPat
= numPat
.getWithFallback("latn",status
);
1667 failure(status
, "rb.get(latn)");
1668 numPat
= numPat
.getWithFallback("patterns",status
);
1669 failure(status
, "rb.get(patterns)");
1670 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1671 failure(status
, "rb.get(currencyFormat)");
1673 // Get the currency pattern for this locale. We have to fish it
1674 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1675 // will return the localized symbol, not \00a4
1677 UnicodeString pattern
= numPat
.getString(status
);
1678 failure(status
, "rb->getString()");
1680 UChar fo
[] = { 0x00A4 };
1681 UnicodeString
foo(fo
, 1, 1);
1683 //if (pattern.indexOf("\u00A4") == -1 ) {
1684 if (pattern
.indexOf(foo
) == -1 ) {
1685 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1686 " does not contain generic currency symbol:" +
1690 // Create a DecimalFormat using the pattern we got and format a number
1691 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1692 failure(status
, "new DecimalFormatSymbols");
1694 // Disable currency spacing for the purposes of this test.
1695 // To do this, set the spacing insert to the empty string both before and after the symbol.
1696 symbols
->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT
, FALSE
, u
"");
1697 symbols
->setPatternForCurrencySpacing(UNUM_CURRENCY_INSERT
, TRUE
, u
"");
1699 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1700 failure(status
, "new DecimalFormat");
1702 UnicodeString result1
;
1703 FieldPosition
pos(FieldPosition::DONT_CARE
);
1704 result1
= fmt1
->format(1.111, result1
, pos
);
1707 // Now substitute in the locale's currency symbol and create another
1708 // pattern. We have to skip locales where the currency symbol
1709 // contains decimal separators, because that confuses things
1711 UChar ba
[] = { 0x002E/*'.'*/ };
1712 UnicodeString
bar(ba
, 1, 1);
1714 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1715 // {sfb} Also, switch the decimal separator to the monetary decimal
1716 // separator to mimic the behavior of a currency format
1717 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1718 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1720 UnicodeString
buf(pattern
);
1721 for (int j
= 0; j
< buf
.length(); j
++) {
1722 if (buf
[j
] == 0x00a4 ) {
1723 if(buf
[j
+ 1] == 0x00a4) {
1724 // {sfb} added to support double currency marker (intl currency sign)
1725 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1726 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1729 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1730 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1735 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1736 failure(status
, "new DecimalFormat");
1738 // Get the currency (if there is one) so we can set the rounding and fraction
1739 const UChar
*currency
= fmt1
->getCurrency();
1740 if (*currency
!= 0) {
1741 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1742 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1743 if (U_SUCCESS(status
)) {
1744 fmt2
->setRoundingIncrement(rounding
);
1745 fmt2
->setMinimumFractionDigits(frac
);
1746 fmt2
->setMaximumFractionDigits(frac
);
1749 failure(status
, "Fetching currency rounding/fractions");
1753 UnicodeString result2
;
1754 fmt2
->format(1.111, result2
, pos
);
1756 if (result1
!= result2
) {
1757 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1758 result1
+ " vs " + result2
);
1771 * DecimalFormat.format() delivers wrong string.
1773 void NumberFormatRegressionTest::Test4125885(void)
1775 UErrorCode status
= U_ZERO_ERROR
;
1776 double rate
= 12.34;
1777 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1778 if(U_FAILURE(status
)) {
1779 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1783 failure(status
, "new DecimalFormat");
1785 logln("toPattern: " + formatDec
->toPattern(temp
));
1786 UnicodeString rateString
;
1787 FieldPosition
pos(FieldPosition::DONT_CARE
);
1788 rateString
= formatDec
->format(rate
, rateString
, pos
);
1789 if (rateString
!= UnicodeString("012.34"))
1790 errln("result : " + rateString
+ " expected : 012.34");
1792 delete formatDec
;// = null;
1793 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1794 failure(status
, "new DecimalFormat");
1795 logln("toPattern: " + formatDec
->toPattern(temp
));
1796 rateString
.remove();
1797 rateString
= formatDec
->format(rate
, rateString
, pos
);
1798 if (rateString
!= UnicodeString("+012.34%"))
1799 errln("result : " + rateString
+ " expected : +012.34%");
1806 * DecimalFormat produces extra zeros when formatting numbers.
1808 void NumberFormatRegressionTest::Test4134034(void)
1810 UErrorCode status
= U_ZERO_ERROR
;
1811 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1812 if (!failure(status
, "new DecimalFormat")) {
1814 FieldPosition
pos(FieldPosition::DONT_CARE
);
1815 f
= nf
->format(9.02, f
, pos
);
1816 if (f
== UnicodeString("9.02"))
1819 errln("9.02 -> " + f
+ "; want 9.02");
1822 f
= nf
->format((int32_t)0, f
, pos
);
1823 if (f
== UnicodeString(".00"))
1826 errln("0 -> " + f
+ "; want .00");
1834 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1835 * a duplicate of 4134034.
1837 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1838 * Possibly related to bug 4125885.
1840 * This class demonstrates a regression in version 1.1.6
1841 * of DecimalFormat class.
1844 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1845 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1846 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1847 * Value 1.2 Format #0.0# Result '1.2'
1848 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1851 * Value 1.2 Format #.00 Result '1.20'
1852 * Value 1.2 Format 0.00 Result '1.20'
1853 * Value 1.2 Format 00.00 Result '01.20'
1854 * Value 1.2 Format #0.0# Result '1.2'
1855 * Value 1.2 Format #0.00 Result '1.20'
1857 void NumberFormatRegressionTest::Test4134300(void) {
1858 UnicodeString DATA
[] = {
1859 // Pattern Expected string
1860 UnicodeString("#.00"), UnicodeString("1.20"),
1861 UnicodeString("0.00"), UnicodeString("1.20"),
1862 UnicodeString("00.00"), UnicodeString("01.20"),
1863 UnicodeString("#0.0#"), UnicodeString("1.2"),
1864 UnicodeString("#0.00"), UnicodeString("1.20")
1867 for (int i
=0; i
< 10; i
+=2) {
1868 UnicodeString result
;
1869 UErrorCode status
= U_ZERO_ERROR
;
1870 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1871 if (!failure(status
, "new DecimalFormat")) {
1872 FieldPosition
pos(FieldPosition::DONT_CARE
);
1873 result
= df
->format(1.2, result
, pos
);
1874 if (result
!= DATA
[i
+1]) {
1875 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1876 "; want " + DATA
[i
+1]);
1879 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1889 * Empty pattern produces double negative prefix.
1891 void NumberFormatRegressionTest::Test4140009(void)
1893 UErrorCode status
= U_ZERO_ERROR
;
1894 LocalPointer
<DecimalFormatSymbols
> syms(new DecimalFormatSymbols(Locale::getEnglish(), status
), status
);
1895 if (failure(status
, "new DecimalFormatSymbols")) {
1898 DecimalFormat
*f
= new DecimalFormat(UnicodeString(u
""), syms
.orphan(), status
);
1899 if (!failure(status
, "new DecimalFormat")) {
1901 FieldPosition
pos(FieldPosition::DONT_CARE
);
1902 s
= f
->format(123.456, s
, pos
);
1903 if (s
!= UnicodeString("123.456"))
1904 errln("Fail: Format empty pattern x 123.456 => " + s
);
1906 s
= f
->format(-123.456, s
, pos
);
1907 if (s
!= UnicodeString("-123.456"))
1908 errln("Fail: Format empty pattern x -123.456 => " + s
);
1915 * BigDecimal numbers get their fractions truncated by NumberFormat.
1917 // {sfb} not pertinent in C++ ??
1918 void NumberFormatRegressionTest::Test4141750(void) {
1920 UnicodeString str("12345.67");
1921 BigDecimal bd = new BigDecimal(str);
1922 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1923 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1925 catch (Exception e) {
1926 errln(e.toString());
1927 e.printStackTrace();
1933 * DecimalFormat toPattern() doesn't quote special characters or handle
1936 void NumberFormatRegressionTest::Test4145457() {
1938 UErrorCode status
= U_ZERO_ERROR
;
1939 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1940 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1944 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1946 errln("DecimalFormat needed to continue");
1950 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1951 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1952 nf
->setDecimalFormatSymbols(*sym
);
1953 double pi
= 3.14159;
1955 UnicodeString PATS
[] = {
1956 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1959 for (int32_t i
=0; i
<2; ++i
) {
1960 nf
->applyPattern(PATS
[i
], status
);
1961 failure(status
, "nf->applyPattern");
1963 FieldPosition
pos(FieldPosition::DONT_CARE
);
1964 out
= nf
->format(pi
, out
, pos
);
1966 pat
= nf
->toPattern(pat
);
1968 ParsePosition
pp(0);
1969 nf
->parse(out
, num
, pp
);
1970 double val
= num
.getDouble();
1972 nf
->applyPattern(pat
, status
);
1973 failure(status
, "nf->applyPattern");
1975 out2
= nf
->format(pi
, out2
, pos
);
1977 pat2
= nf
->toPattern(pat2
);
1979 nf
->parse(out2
, num
, pp
);
1980 double val2
= num
.getDouble();
1983 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1984 pat
+ "\" vs. \"" + pat2
+ "\"");
1986 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1988 if (val
== val2
&& out
== out2
) {
1989 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1990 out
+ "\" -> " + val
+ " -> \"" +
1991 out2
+ "\" -> " + val2
);
1994 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1995 out
+ "\" -> " + val
+ " -> \"" +
1996 out2
+ "\" -> " + val2
);
2000 catch (ParseException e) {
2001 errln("Fail: " + e);
2002 e.printStackTrace();
2010 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2012 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2014 * ICU 62: minInt is always at least one, and the getter should reflect that!
2016 void NumberFormatRegressionTest::Test4147295(void)
2018 UErrorCode status
= U_ZERO_ERROR
;
2019 DecimalFormat
*sdf
= new DecimalFormat(status
);
2020 UnicodeString
pattern("#,###");
2021 logln("Applying pattern \"" + pattern
+ "\"");
2022 sdf
->applyPattern(pattern
, status
);
2023 if (!failure(status
, "sdf->applyPattern")) {
2024 int minIntDig
= sdf
->getMinimumIntegerDigits();
2025 if (minIntDig
!= 1) {
2026 errln("Test failed");
2027 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2029 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2031 logln("Test passed");
2032 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2040 * DecimalFormat formats -0.0 as +0.0
2041 * See also older related bug 4106658, 4106667
2043 void NumberFormatRegressionTest::Test4147706(void)
2045 UErrorCode status
= U_ZERO_ERROR
;
2046 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2047 failure(status
, "new DecimalFormat");
2048 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2049 if (!failure(status
, "new DecimalFormatSymbols")) {
2051 UnicodeString f2
, temp
;
2052 FieldPosition
pos(FieldPosition::DONT_CARE
);
2053 volatile double d1
= 0.0; // volatile to prevent code optimization
2054 double d2
= -0.0001;
2056 #if U_PLATFORM == U_PF_HPUX
2057 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2059 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2061 df
->adoptDecimalFormatSymbols(syms
);
2062 f1
= df
->format(d1
, f1
, pos
);
2063 f2
= df
->format(d2
, f2
, pos
);
2064 if (f1
!= UnicodeString("-0.0")) {
2065 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2067 if (f2
!= UnicodeString("-0.0")) {
2068 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2076 // Not applicable, since no serialization in C++
2077 /*class myformat implements Serializable
2079 DateFormat _dateFormat = DateFormat.getDateInstance();
2083 GregorianCalendar calendar = new GregorianCalendar();
2084 Date t = calendar.getTime();
2085 String nowStr = _dateFormat.format(t);
2092 * NumberFormat cannot format Double.MAX_VALUE
2094 // TODO: make this test actually test something
2096 NumberFormatRegressionTest::Test4162198(void)
2098 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2099 double dbl
= INT32_MAX
* 1000.0;
2100 UErrorCode status
= U_ZERO_ERROR
;
2101 NumberFormat
*f
= NumberFormat::createInstance(status
);
2102 if(U_FAILURE(status
)) {
2103 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2106 f
->setMaximumFractionDigits(INT32_MAX
);
2107 f
->setMaximumIntegerDigits(INT32_MAX
);
2110 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2113 f
->parse(s
, n
, status
);
2114 if(U_FAILURE(status
))
2115 errln("Couldn't parse!");
2116 //} catch (java.text.ParseException e) {
2117 // errln("Caught a ParseException:");
2118 // e.printStackTrace();
2121 //logln("The string " + s + " parsed as " + n);
2123 // {dlf} The old code assumes n is a double, but it isn't any more...
2124 // Formattable apparently does not and never did interconvert... too bad.
2125 //if(n.getDouble() != dbl) {
2126 // errln("Round trip failure");
2128 if (n
.getInt64() != dbl
) {
2129 errln("Round trip failure");
2137 * NumberFormat does not parse negative zero.
2140 NumberFormatRegressionTest::Test4162852(void)
2142 UErrorCode status
= U_ZERO_ERROR
;
2143 for(int32_t i
=0; i
< 2; ++i
) {
2144 LocalPointer
<NumberFormat
> f(
2145 ((i
== 0) ? NumberFormat::createInstance(status
) : 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!");
2161 double e
= n
.getDouble();
2162 logln("%f -> \"%s\" -> %f", d
, CStr(s
)(), e
);
2163 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2166 if (e
!= 0.0 || (std::signbit(e
) == false)) {
2168 errln("Failed to parse negative zero");
2173 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2176 * May 17 1999 sync up - liu
2178 * NumberFormat truncates data
2180 void NumberFormatRegressionTest::Test4167494(void) {
2181 UErrorCode status
= U_ZERO_ERROR
;
2182 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2183 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2188 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2192 fmt
->parse(s
, num
, status
);
2193 failure(status
, "Parse");
2194 if (num
.getType() == Formattable::kDouble
&&
2195 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2196 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2197 toString(num
) + " ok");
2199 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2200 toString(num
) + " FAIL");
2203 // We don't test Double.MIN_VALUE because the locale data for the US
2204 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2205 // This is correct for now; however, we leave this here as a reminder
2206 // in case we want to address this later.
2212 * May 17 1999 sync up - liu
2214 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2216 void NumberFormatRegressionTest::Test4170798(void) {
2217 IcuTestErrorCode
status(*this, "Test4170798");
2218 LocalPointer
<DecimalFormat
> df(dynamic_cast<DecimalFormat
*>(
2219 NumberFormat::createInstance(Locale::getUS(), status
)), status
);
2220 if (!assertSuccess("", status
, true, __FILE__
, __LINE__
)) {
2225 ParsePosition
pos(0);
2226 df
->parse("-0.0", n
, pos
);
2227 if (n
.getType() != Formattable::kDouble
2228 || n
.getDouble() != -0.0) {
2229 errln(UnicodeString("FAIL: default parse(\"-0.0\") returns ") + toString(n
));
2232 df
->setParseIntegerOnly(TRUE
);
2235 ParsePosition
pos(0);
2236 df
->parse("-0.0", n
, pos
);
2237 if (n
.getType() != Formattable::kLong
2238 || n
.getLong() != 0) {
2239 errln(UnicodeString("FAIL: integer parse(\"-0.0\") returns ") + toString(n
));
2245 * May 17 1999 sync up - liu
2246 * toPattern only puts the first grouping separator in.
2248 void NumberFormatRegressionTest::Test4176114(void) {
2249 const char* DATA
[] = {
2251 "000", "000", // No grouping
2252 "#000", "000", // No grouping
2257 "000,000", "000,000",
2258 "0,000,000,000,000.0000", "0,000,000,000,000.0000", // Reported
2260 int DATA_length
= UPRV_LENGTHOF(DATA
);
2261 UErrorCode status
= U_ZERO_ERROR
;
2263 for (int i
=0; i
<DATA_length
; i
+=2) {
2264 DecimalFormat
df(DATA
[i
], status
);
2265 if (!failure(status
, "DecimalFormat constructor")) {
2267 UnicodeString
exp(DATA
[i
+1]);
2269 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2270 s
+ ", want " + exp
);
2277 * May 17 1999 sync up - liu
2279 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2281 void NumberFormatRegressionTest::Test4179818(void) {
2282 const char* DATA
[] = {
2283 // Input Pattern Expected output
2284 "1.2511", "#.#", "1.3",
2285 "1.2501", "#.#", "1.3",
2288 int DATA_length
= UPRV_LENGTHOF(DATA
);
2294 UErrorCode status
= U_ZERO_ERROR
;
2295 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2296 failure(status
, "Construct DecimalFormatSymbols");
2297 DecimalFormat
fmt("#", sym
, status
);
2298 if (!failure(status
, "Construct DecimalFormat")) {
2299 for (int i
=0; i
<DATA_length
; i
+=3) {
2300 double in
= DOUBLE
[i
/3];
2301 UnicodeString
pat(DATA
[i
+1]);
2302 UnicodeString
exp(DATA
[i
+2]);
2303 fmt
.applyPattern(pat
, status
);
2304 failure(status
, "applyPattern");
2307 fmt
.format(in
, out
, pos
);
2309 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2311 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2312 ", expected " + exp
);
2319 * May 17 1999 sync up - liu
2320 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2321 * This includes the minus sign, currency symbol, international currency
2322 * symbol, percent, and permille. This is filed as bugs 4212072 and
2325 void NumberFormatRegressionTest::Test4212072(void) {
2326 UErrorCode status
= U_ZERO_ERROR
;
2327 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2329 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2330 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2331 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2338 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2339 fmt
.setDecimalFormatSymbols(sym
);
2341 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2342 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2346 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2347 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2350 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2352 fmt
.applyPattern(UnicodeString("#%"), status
);
2353 failure(status
, "applyPattern percent");
2354 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2355 fmt
.setDecimalFormatSymbols(sym
);
2357 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2358 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2362 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2363 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2366 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2368 fmt
.applyPattern(str("#\\u2030"), status
);
2369 failure(status
, "applyPattern permill");
2370 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2371 fmt
.setDecimalFormatSymbols(sym
);
2373 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2374 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2378 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2379 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2382 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2384 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2385 failure(status
, "applyPattern currency");
2386 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2387 fmt
.setDecimalFormatSymbols(sym
);
2389 if (fmt
.format(12.5, s
, pos
) != UnicodeString(u
"usd\u00A012.50")) {
2390 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2391 u
", exp usd\u00A012.50");
2394 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2395 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2398 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2400 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2401 failure(status
, "applyPattern intl currency");
2402 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2403 fmt
.setDecimalFormatSymbols(sym
);
2405 if (fmt
.format(12.5, s
, pos
) != UnicodeString(u
"DOL\u00A012.50")) {
2406 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2407 u
", exp DOL\u00A012.50");
2410 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2411 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2414 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2416 // Since the pattern logic has changed, make sure that patterns round
2417 // trip properly. Test stream in/out integrity too.
2419 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2420 static const char* type
[] = {
2425 for (int i
=0; i
<n
; ++i
) {
2426 for (int j
=0; j
<3; ++j
) {
2427 status
= U_ZERO_ERROR
;
2431 nf
= NumberFormat::createInstance(avail
[i
], status
);
2432 failure(status
, "createInstance", avail
[i
]);
2435 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2436 failure(status
, "createCurrencyInstance", avail
[i
]);
2439 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2440 failure(status
, "createPercentInstance", avail
[i
]);
2443 if (U_FAILURE(status
)) {
2446 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2448 // Test toPattern/applyPattern round trip
2451 DecimalFormatSymbols
symb(avail
[i
], status
);
2452 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2453 DecimalFormat
f2(pat
, symb
, status
);
2455 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2460 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2462 "\" -> \"" + f2
.toPattern(p
) + "\"");
2465 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2470 // Test toLocalizedPattern/applyLocalizedPattern round trip
2471 // TODO(refactor): don't worry about localized patterns for now.
2472 // df->toLocalizedPattern(pat);
2473 // f2.applyLocalizedPattern(pat, status);
2475 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2476 if (U_FAILURE(status
)) {
2480 // TODO(refactor): don't worry about localized patterns for now.
2481 // Make sure we set the currency attributes appropriately
2482 // if (j == 1) { // Currency format
2483 // f2.setCurrency(f2.getCurrency(), status);
2486 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2487 if (U_FAILURE(status
)) {
2493 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2494 " -> localized \"" + pat
+
2495 "\" -> \"" + f2
.toPattern(p
) + "\"");
2500 // Test writeObject/readObject round trip
2501 // NOT ON ICU -- Java only
2507 * May 17 1999 sync up - liu
2508 * DecimalFormat.parse() fails for mulipliers 2^n.
2510 void NumberFormatRegressionTest::Test4216742(void) {
2511 UErrorCode status
= U_ZERO_ERROR
;
2512 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2513 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2517 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2518 int DATA_length
= UPRV_LENGTHOF(DATA
);
2519 for (int i
=0; i
<DATA_length
; ++i
) {
2520 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2521 for (int m
= 1; m
<= 100; m
++) {
2522 fmt
->setMultiplier(m
);
2524 fmt
->parse(str
, num
, status
);
2525 failure(status
, "parse", Locale::getUS());
2526 if (num
.getType() != Formattable::kLong
&&
2527 num
.getType() != Formattable::kDouble
) {
2528 errln(UnicodeString("FAIL: Wanted number, got ") +
2531 double d
= num
.getType() == Formattable::kDouble
?
2532 num
.getDouble() : (double) num
.getLong();
2533 if ((d
> 0) != (DATA
[i
] > 0)) {
2534 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2535 fmt
->getMultiplier() +
2536 ") => " + toString(num
));
2545 * May 17 1999 sync up - liu
2546 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2549 void NumberFormatRegressionTest::Test4217661(void) {
2550 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2551 const char* S
[] = { "0", "1", "0.01", "1.01" };
2552 int D_length
= UPRV_LENGTHOF(D
);
2553 UErrorCode status
= U_ZERO_ERROR
;
2554 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2555 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2559 fmt
->setMaximumFractionDigits(2);
2560 for (int i
=0; i
<D_length
; i
++) {
2562 fmt
->format(D
[i
], s
);
2563 if (s
!= UnicodeString(S
[i
])) {
2564 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2571 * alphaWorks upgrade
2573 void NumberFormatRegressionTest::Test4161100(void) {
2574 UErrorCode status
= U_ZERO_ERROR
;
2575 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2576 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2580 nf
->setMinimumFractionDigits(1);
2581 nf
->setMaximumFractionDigits(1);
2586 logln(UnicodeString() + a
+ " x " +
2587 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2588 if (s
!= UnicodeString("-0.1")) {
2595 * June 16 1999 sync up - liu
2596 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2598 void NumberFormatRegressionTest::Test4243011(void) {
2599 UErrorCode status
= U_ZERO_ERROR
;
2600 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2601 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2602 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2604 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2605 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2606 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2607 int32_t N
= UPRV_LENGTHOF(NUM
);
2609 for (int32_t i
=0; i
<N
; ++i
) {
2611 UnicodeString
exp(STR
[i
]);
2613 fmt
.format(NUM
[i
], str
, pos
);
2615 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2617 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2625 * June 16 1999 sync up - liu
2626 * format(0.0) gives "0.1" if preceded by parse("99.99").
2627 * (Regression in 1.2.2 RC1)
2629 void NumberFormatRegressionTest::Test4243108(void) {
2630 UErrorCode status
= U_ZERO_ERROR
;
2631 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2632 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2633 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2634 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2641 fmt
.format(0.0, str
, pos
);
2642 UnicodeString
exp("0");
2644 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2646 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2652 fmt
.parse(str
, val
, status
);
2653 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2654 if (val
.getType() == Formattable::kDouble
&&
2655 val
.getDouble() == 99.99) {
2656 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2658 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2663 fmt
.format(0.0, str
, pos
);
2665 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2667 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2674 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2675 * NumberFormat objects.
2677 void NumberFormatRegressionTest::TestJ691(void) {
2678 UErrorCode status
= U_ZERO_ERROR
;
2679 Locale
loc("fr", "CH");
2681 // set up the input date string & expected output
2682 UnicodeString
udt(u
"11.10.2000");
2683 UnicodeString
exp(u
"11.10.00");
2685 // create a Calendar for this locale
2686 LocalPointer
<Calendar
> cal(Calendar::createInstance(loc
, status
));
2687 if (U_FAILURE(status
)) {
2688 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2692 // create a NumberFormat for this locale
2693 LocalPointer
<NumberFormat
> nf(NumberFormat::createInstance(loc
, status
));
2694 if (U_FAILURE(status
)) {
2695 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2699 // *** Here's the key: We don't want to have to do THIS:
2700 // nf->setParseIntegerOnly(TRUE);
2701 // or this (with changes to fr_CH per cldrbug:9370):
2702 // nf->setGroupingUsed(FALSE);
2703 // so they are done in DateFormat::adoptNumberFormat
2705 // create the DateFormat
2706 LocalPointer
<DateFormat
> df(DateFormat::createDateInstance(DateFormat::kShort
, loc
));
2707 if (U_FAILURE(status
)) {
2708 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2712 df
->adoptCalendar(cal
.orphan());
2713 df
->adoptNumberFormat(nf
.orphan());
2715 // set parsing to lenient & parse
2716 df
->setLenient(TRUE
);
2717 UDate ulocdat
= df
->parse(udt
, status
);
2719 // format back to a string
2720 UnicodeString outString
;
2721 df
->format(ulocdat
, outString
);
2723 if (outString
!= exp
) {
2724 errln("FAIL: " + udt
+ " => " + outString
);
2728 //---------------------------------------------------------------------------
2730 // Error Checking / Reporting macros
2732 //---------------------------------------------------------------------------
2733 #define TEST_CHECK_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \
2734 if (U_FAILURE(status)) { \
2735 if (status == U_MISSING_RESOURCE_ERROR) { \
2736 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2738 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2741 } UPRV_BLOCK_MACRO_END
2743 #define TEST_ASSERT(expr) UPRV_BLOCK_MACRO_BEGIN { \
2744 if ((expr)==FALSE) {\
2745 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2747 } UPRV_BLOCK_MACRO_END
2748 #define TEST_ASSERT_EQUALS(x,y) UPRV_BLOCK_MACRO_BEGIN { \
2750 int32_t len = sprintf (_msg,"File %s, line %d: " #x "==" #y, __FILE__, __LINE__); \
2752 U_ASSERT(len < (int32_t) sizeof(_msg)); \
2753 assertEquals((const char*) _msg, x,y); \
2754 } UPRV_BLOCK_MACRO_END
2757 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2759 void NumberFormatRegressionTest::Test8199(void) {
2760 UErrorCode status
= U_ZERO_ERROR
;
2761 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2763 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2766 TEST_CHECK_STATUS(status
);
2768 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2769 // should always truncate, no other rounding scheme.
2771 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2773 nf
->parse(numStr
, val
, status
);
2774 TEST_CHECK_STATUS(status
);
2775 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2776 TEST_ASSERT_EQUALS(1000000000LL, val
.getInt64(status
));
2777 TEST_CHECK_STATUS(status
);
2778 TEST_ASSERT_EQUALS(1000000000.6, val
.getDouble(status
));
2779 TEST_CHECK_STATUS(status
);
2781 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2782 // than int64 because of the fraction
2783 // even though int64 is more precise.
2784 nf
->parse(numStr
, val
, status
);
2785 TEST_CHECK_STATUS(status
);
2786 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2787 TEST_ASSERT_EQUALS(100000000000000001LL, val
.getInt64(status
));
2788 TEST_CHECK_STATUS(status
);
2789 TEST_ASSERT_EQUALS(100000000000000000.0, val
.getDouble(status
));
2790 TEST_CHECK_STATUS(status
);
2792 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2793 nf
->parse(numStr
, val
, status
);
2794 TEST_CHECK_STATUS(status
);
2795 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2796 TEST_ASSERT_EQUALS(100000000000000000LL, val
.getInt64());
2797 TEST_ASSERT_EQUALS(1.0E17
, val
.getDouble(status
));
2798 TEST_CHECK_STATUS(status
);
2800 numStr
= "9223372036854775807"; // largest int64_t
2801 nf
->parse(numStr
, val
, status
);
2802 TEST_CHECK_STATUS(status
);
2803 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2804 TEST_ASSERT_EQUALS(9223372036854775807LL, val
.getInt64());
2805 // In the following check, note that a substantial range of integers will
2806 // convert to the same double value. There are also platform variations
2807 // in the rounding at compile time of double constants.
2808 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2809 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2810 TEST_CHECK_STATUS(status
);
2812 numStr
= "-9223372036854775808"; // smallest int64_t
2813 nf
->parse(numStr
, val
, status
);
2814 TEST_CHECK_STATUS(status
);
2815 TEST_ASSERT_EQUALS(Formattable::kInt64
, val
.getType());
2816 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64()); // Compiler chokes on constant.
2817 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL
, val
.getInt64());
2818 TEST_ASSERT_EQUALS(-9223372036854775808.0, val
.getDouble(status
));
2819 TEST_CHECK_STATUS(status
);
2821 numStr
= "9223372036854775808"; // largest int64_t + 1
2822 nf
->parse(numStr
, val
, status
);
2823 TEST_CHECK_STATUS(status
);
2824 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2825 TEST_ASSERT_EQUALS(9223372036854775807LL, val
.getInt64(status
));
2826 TEST_ASSERT_EQUALS(status
, U_INVALID_FORMAT_ERROR
);
2827 status
= U_ZERO_ERROR
;
2828 TEST_ASSERT_EQUALS(9223372036854775810.0, val
.getDouble(status
));
2829 TEST_CHECK_STATUS(status
);
2831 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2832 nf
->parse(numStr
, val
, status
);
2833 TEST_CHECK_STATUS(status
);
2834 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2835 // TEST_ASSERT_EQUALS(-9223372036854775808LL, val.getInt64(status)); // spurious compiler warnings
2836 TEST_ASSERT_EQUALS((int64_t)0x8000000000000000LL
, val
.getInt64(status
));
2837 TEST_ASSERT_EQUALS(status
, U_INVALID_FORMAT_ERROR
);
2838 status
= U_ZERO_ERROR
;
2839 TEST_ASSERT_EQUALS(-9223372036854775810.0, val
.getDouble(status
));
2840 TEST_CHECK_STATUS(status
);
2842 // Test values near the limit of where doubles can represent all integers.
2843 // The implementation strategy of getInt64() changes at this boundary.
2844 // Strings to be parsed include a decimal fraction to force them to be
2845 // parsed as doubles rather than ints. The fraction is discarded
2846 // from the parsed double value because it is beyond what can be represented.
2848 status
= U_ZERO_ERROR
;
2849 numStr
= "9007199254740991.1"; // largest 53 bit int
2850 nf
->parse(numStr
, val
, status
);
2851 TEST_CHECK_STATUS(status
);
2852 // printf("getInt64() returns %lld\n", val.getInt64(status));
2853 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2854 TEST_ASSERT_EQUALS(9007199254740991LL, val
.getInt64(status
));
2855 TEST_ASSERT_EQUALS(9007199254740991.0, val
.getDouble(status
));
2856 TEST_CHECK_STATUS(status
);
2858 status
= U_ZERO_ERROR
;
2859 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2860 nf
->parse(numStr
, val
, status
);
2861 TEST_CHECK_STATUS(status
);
2862 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2863 TEST_ASSERT_EQUALS(9007199254740992LL, val
.getInt64(status
));
2864 TEST_ASSERT_EQUALS(9007199254740992.0, val
.getDouble(status
));
2865 TEST_CHECK_STATUS(status
);
2867 status
= U_ZERO_ERROR
;
2868 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2869 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2870 TEST_CHECK_STATUS(status
);
2871 TEST_ASSERT_EQUALS(Formattable::kDouble
, val
.getType());
2872 TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val
.getInt64(status
));
2873 TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val
.getDouble(status
));
2874 TEST_CHECK_STATUS(status
);
2879 void NumberFormatRegressionTest::Test9109(void) {
2880 UErrorCode status
= U_ZERO_ERROR
;
2883 DecimalFormat
fmt("+##", status
);
2884 if (U_FAILURE(status
)) {
2885 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2889 fmt
.setLenient(TRUE
);
2890 UnicodeString
text("123");
2891 int32_t expected
= 123;
2894 fmt
.parse(text
, val
, pos
);
2895 if (pos
.getErrorIndex() >= 0) {
2896 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2897 } else if (val
.getLong() != 123) {
2898 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2899 } else if (pos
.getIndex() != 3) {
2900 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2905 void NumberFormatRegressionTest::Test9780(void) {
2906 UErrorCode status
= U_ZERO_ERROR
;
2907 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2908 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2912 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2914 errln("DecimalFormat needed to continue");
2917 df
->setParseIntegerOnly(TRUE
);
2921 ParsePosition
pos(0);
2922 UnicodeString
toParse("1,234","");
2923 df
->parse(toParse
, n
, pos
);
2924 if (n
.getType() != Formattable::kLong
2925 || n
.getLong() != 1234) {
2926 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2929 // should still work in lenient mode, just won't get fastpath
2930 df
->setLenient(TRUE
);
2933 ParsePosition
pos(0);
2934 UnicodeString
toParse("1,234","");
2935 df
->parse(toParse
, n
, pos
);
2936 if (n
.getType() != Formattable::kLong
2937 || n
.getLong() != 1234) {
2938 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2945 void NumberFormatRegressionTest::Test9677(void) {
2946 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2947 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2948 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2949 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2950 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2952 UErrorCode status
= U_ZERO_ERROR
;
2953 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2954 if (U_FAILURE(status
)) {
2955 dataerrln("Failure opening unum_open");
2959 if (U_SUCCESS(status
)) {
2960 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2961 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2962 assertSuccess("setting attributes", status
);
2965 if(U_SUCCESS(status
)) {
2966 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2967 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2969 if(U_FAILURE(status
)) {
2970 logln("Got expected parse error %s\n", u_errorName(status
));
2971 status
= U_ZERO_ERROR
;
2973 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2977 if (U_SUCCESS(status
)) {
2978 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2979 assertSuccess("setting attributes", status
);
2980 logln("removed positive prefix");
2983 if(U_SUCCESS(status
)) {
2984 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2985 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2987 if(U_FAILURE(status
)) {
2988 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2989 status
= U_ZERO_ERROR
;
2992 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2994 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
2999 if(U_SUCCESS(status
)) {
3000 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3001 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3003 if(U_FAILURE(status
)) {
3004 logln("text2: Got expected parse error %s\n", u_errorName(status
));
3005 status
= U_ZERO_ERROR
;
3007 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
3011 if (U_SUCCESS(status
)) {
3012 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
3013 assertSuccess("setting attributes", status
);
3014 logln("Set a different neg prefix prefix");
3017 if(U_SUCCESS(status
)) {
3018 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3019 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3021 if(U_FAILURE(status
)) {
3022 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
3023 status
= U_ZERO_ERROR
;
3026 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3028 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3034 void NumberFormatRegressionTest::Test10361(void) {
3035 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3036 // preventing formatting of big decimals.
3037 UErrorCode status
= U_ZERO_ERROR
;
3038 DecimalFormatSymbols
symbols(Locale::getEnglish(), status
);
3039 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###.##", symbols
, status
), status
);
3040 TEST_CHECK_STATUS(status
);
3042 // Create a decimal number with a million digits.
3043 const int32_t NUMSIZE
=1000000;
3044 char *num
= new char[NUMSIZE
];
3045 for (int32_t i
=0; i
<NUMSIZE
; i
++) {
3046 num
[i
] = '0' + (i
+1) % 10;
3048 num
[NUMSIZE
-3] = '.';
3052 Formattable fmtable
;
3053 fmtable
.setDecimalNumber(num
, status
);
3054 TEST_CHECK_STATUS(status
);
3056 FieldPosition
pos(UNUM_DECIMAL_SEPARATOR_FIELD
);
3057 df
->format(fmtable
, s
, pos
, status
);
3058 TEST_CHECK_STATUS(status
);
3059 TEST_ASSERT(999999 == s
.length());
3060 TEST_ASSERT(999997 == pos
.getBeginIndex());
3061 TEST_ASSERT(999998 == pos
.getEndIndex());
3063 UnicodeString
expected(num
, -1, US_INV
);
3064 TEST_ASSERT(expected
== s
);
3068 #endif /* #if !UCONFIG_NO_FORMATTING */