1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /***********************************************************************
4 * Copyright (c) 1997-2016, International Business Machines Corporation
5 * and others. All Rights Reserved.
6 ***********************************************************************/
8 #include "unicode/utypes.h"
10 #if !UCONFIG_NO_FORMATTING
14 #include <float.h> // DBL_MIN, DBL_MAX
17 #include "unicode/dcfmtsym.h"
18 #include "unicode/decimfmt.h"
19 #include "unicode/locid.h"
20 #include "unicode/resbund.h"
21 #include "unicode/calendar.h"
22 #include "unicode/datefmt.h"
23 #include "unicode/ucurr.h"
28 class MyNumberFormatTest
: public NumberFormat
32 virtual UClassID
getDynamicClassID(void) const;
34 virtual UnicodeString
& format( double number
,
35 UnicodeString
& toAppendTo
,
36 FieldPositionIterator
* posIter
,
37 UErrorCode
& status
) const
39 return NumberFormat::format(number
, toAppendTo
, posIter
, status
);
42 /* Just keep this here to make some of the compilers happy */
43 virtual UnicodeString
& format(const Formattable
& obj
,
44 UnicodeString
& toAppendTo
,
46 UErrorCode
& status
) const
48 return NumberFormat::format(obj
, toAppendTo
, pos
, status
);
51 /* Just use one of the format functions */
52 virtual UnicodeString
& format( double /* number */,
53 UnicodeString
& toAppendTo
,
54 FieldPosition
& /* pos */) const
61 public Number parse(String text, ParsePosition parsePosition)
62 { return new Integer(0); }
65 /* Just use one of the parse functions */
66 virtual void parse( const UnicodeString
& /* text */,
68 ParsePosition
& /* parsePosition */) const
70 result
.setLong((int32_t)0);
73 virtual void parse( const UnicodeString
& text
,
75 UErrorCode
& status
) const
77 NumberFormat::parse(text
, result
, status
);
79 virtual Format
* clone() const
82 virtual UnicodeString
& format(int32_t,
85 { return foo
.remove(); }
87 virtual UnicodeString
& format(int64_t,
90 { return foo
.remove(); }
92 virtual void applyPattern(const UnicodeString
&, UParseError
&, UErrorCode
&){
96 int32_t gMyNumberFormatTestClassID
;
97 UClassID
MyNumberFormatTest::getDynamicClassID() const
99 return (UClassID
)&gMyNumberFormatTestClassID
;
103 // *****************************************************************************
104 // class NumberFormatRegressionTest
105 // *****************************************************************************
107 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
110 NumberFormatRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
112 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
124 CASE(10,Test4086575
);
125 CASE(11,Test4068693
);
126 CASE(12,Test4069754
);
127 CASE(13,Test4087251
);
128 CASE(14,Test4090489
);
129 CASE(15,Test4090504
);
130 CASE(16,Test4095713
);
131 CASE(17,Test4092561
);
132 CASE(18,Test4092480
);
133 CASE(19,Test4087244
);
134 CASE(20,Test4070798
);
135 CASE(21,Test4071005
);
136 CASE(22,Test4071014
);
137 CASE(23,Test4071859
);
138 CASE(24,Test4093610
);
139 CASE(25,Test4098741
);
140 CASE(26,Test4074454
);
141 CASE(27,Test4099404
);
142 CASE(28,Test4101481
);
143 CASE(29,Test4052223
);
144 CASE(30,Test4061302
);
145 CASE(31,Test4062486
);
146 CASE(32,Test4108738
);
147 CASE(33,Test4106658
);
148 CASE(34,Test4106662
);
149 CASE(35,Test4114639
);
150 CASE(36,Test4106664
);
151 CASE(37,Test4106667
);
152 CASE(38,Test4110936
);
153 CASE(39,Test4122840
);
154 CASE(40,Test4125885
);
155 CASE(41,Test4134034
);
156 CASE(42,Test4134300
);
157 CASE(43,Test4140009
);
158 CASE(44,Test4141750
);
159 CASE(45,Test4145457
);
160 CASE(46,Test4147295
);
161 CASE(47,Test4147706
);
162 CASE(48,Test4162198
);
163 CASE(49,Test4162852
);
164 CASE(50,Test4167494
);
165 CASE(51,Test4170798
);
166 CASE(52,Test4176114
);
167 CASE(53,Test4179818
);
168 CASE(54,Test4212072
);
169 CASE(55,Test4216742
);
170 CASE(56,Test4217661
);
171 CASE(57,Test4161100
);
172 CASE(58,Test4243011
);
173 CASE(59,Test4243108
);
181 default: name
= ""; break;
186 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
188 if(U_FAILURE(status
)) {
189 if (possibleDataError
) {
190 dataerrln(UnicodeString("FAIL: ", "") + msg
191 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
193 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
194 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
203 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
205 if(U_FAILURE(status
)) {
206 if (possibleDataError
) {
207 dataerrln(UnicodeString("FAIL: ", "") + msg
208 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
210 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
211 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
220 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
222 if(U_FAILURE(status
)) {
223 if (possibleDataError
) {
224 dataerrln(UnicodeString("FAIL: ", "") + msg
225 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
227 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
228 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
237 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
239 inline UnicodeString
str(const char *input
)
241 return CharsToUnicodeString(input
);
245 * NumberFormat.equals comparing with null should always return false.
247 // {sfb} kind of silly in C++, just checking for new success
248 void NumberFormatRegressionTest::Test4075713(void)
251 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
253 logln("NumberFormat.equals passed");
254 /*} catch (NullPointerException e) {
255 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
262 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
265 void NumberFormatRegressionTest::Test4074620(void)
268 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
269 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
271 nf1
->setGroupingUsed(FALSE
);
272 nf2
->setGroupingUsed(TRUE
);
275 errln("Test for bug 4074620 failed");
277 logln("Test for bug 4074620 passed.");
285 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
288 void NumberFormatRegressionTest::Test4088161 (void)
290 UErrorCode status
= U_ZERO_ERROR
;
291 DecimalFormat
*df
= new DecimalFormat(status
);
292 if (!failure(status
, "new DecimalFormat", "")) {
294 df
->setMinimumFractionDigits(0);
295 df
->setMaximumFractionDigits(16);
297 FieldPosition
fp1(FieldPosition::DONT_CARE
);
298 logln(UnicodeString("d = ") + d
);
299 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
301 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
302 df
->setMaximumFractionDigits(17);
304 FieldPosition
fp2(FieldPosition::DONT_CARE
);
305 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
306 sBuf2
= df
->format(d
, sBuf2
, fp2
);
308 errln(" format(d) = '" + sBuf2
+ "'");
315 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
316 * DecimalFormat(String, DecimalFormatSymbols).
318 void NumberFormatRegressionTest::Test4087245 (void)
320 UErrorCode status
= U_ZERO_ERROR
;
321 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
322 failure(status
, "new DecimalFormatSymbols", "");
323 // {sfb} One note about this test: if you pass in a pointer
324 // to the symbols, they are adopted and this test will fail,
325 // even though that is the correct behavior. To test the cloning
326 // of the symbols, it is necessary to pass in a reference to the symbols
327 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
328 failure(status
, "new DecimalFormat with symbols", "");
332 FieldPosition
pos(FieldPosition::DONT_CARE
);
333 logln(UnicodeString("format(") + n
+ ") = " +
334 df
->format(n
, buf1
, pos
));
335 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
336 logln(UnicodeString("format(") + n
+ ") = " +
337 df
->format(n
, buf2
, pos
));
339 errln("Test for bug 4087245 failed");
346 * DecimalFormat.format() incorrectly formats 0.0
348 void NumberFormatRegressionTest::Test4087535 (void)
350 UErrorCode status
= U_ZERO_ERROR
;
351 DecimalFormat
*df
= new DecimalFormat(status
);
352 if (U_FAILURE(status
)) {
353 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
356 df
->setMinimumIntegerDigits(0);
359 UnicodeString buffer
;
360 FieldPosition
pos(FieldPosition::DONT_CARE
);
361 buffer
= df
->format(n
, buffer
, pos
);
362 if (buffer
.length() == 0)
363 errln(/*n + */": '" + buffer
+ "'");
365 buffer
= df
->format(n
, buffer
, pos
);
366 if (buffer
.length() == 0)
367 errln(/*n + */": '" + buffer
+ "'");
373 * DecimalFormat.format fails when groupingSize is set to 0.
375 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
376 void NumberFormatRegressionTest::Test4088503 (void)
378 UErrorCode status
= U_ZERO_ERROR
;
379 DecimalFormat
*df
= new DecimalFormat(status
);
380 if (U_FAILURE(status
)) {
381 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
384 df
->setGroupingSize(0);
386 FieldPosition
fp(FieldPosition::DONT_CARE
);
388 logln(df
->format((int32_t)123, sBuf
, fp
));
389 //if(fp == FieldPosition(FieldPosition::DONT_CARE))
390 // errln("Test for bug 4088503 failed.");
391 /*} catch (Exception foo) {
392 errln("Test for bug 4088503 failed.");
398 * NumberFormat.getCurrencyInstance is wrong.
400 void NumberFormatRegressionTest::Test4066646 (void)
402 assignFloatValue(2.04f
);
403 assignFloatValue(2.03f
);
404 assignFloatValue(2.02f
);
405 assignFloatValue(0.0f
);
409 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
411 logln(UnicodeString(" VALUE ") + returnfloat
);
412 UErrorCode status
= U_ZERO_ERROR
;
413 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
414 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
418 nfcommon
->setGroupingUsed(FALSE
);
420 UnicodeString stringValue
;
421 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
422 logln(" DISPLAYVALUE " + stringValue
);
424 nfcommon
->parse(stringValue
, result
, status
);
425 failure(status
, "nfcommon->parse", Locale::getUS());
426 float floatResult
= (float) (result
.getType() == Formattable::kDouble
427 ? result
.getDouble() : result
.getLong());
428 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
429 //String stringValue = nfcommon.format(returnfloat).substring(1);
430 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
431 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
435 } // End Of assignFloatValue()
438 * DecimalFormat throws exception when parsing "0"
440 void NumberFormatRegressionTest::Test4059870(void)
442 UErrorCode status
= U_ZERO_ERROR
;
443 DecimalFormat
*format
= new DecimalFormat("00", status
);
444 failure(status
, "new Decimalformat", Locale::getUS());
448 format
->parse(UnicodeString("0"), result
, status
);
449 failure(status
, "format->parse", Locale::getUS());
452 catch (Exception e) {
453 errln("Test for bug 4059870 failed : " + e);
459 * DecimalFormatSymbol.equals should always return false when
460 * comparing with null.
462 // {sfb} this is silly in C++
463 void NumberFormatRegressionTest::Test4083018 (void)
465 UErrorCode status
= U_ZERO_ERROR
;
466 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
467 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
470 logln("Test Passed!");
472 errln("Test for bug 4083018 failed");
473 /*} catch (Exception foo) {
474 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
481 * DecimalFormat does not round up correctly.
483 void NumberFormatRegressionTest::Test4071492 (void)
485 double x
= 0.00159999;
486 UErrorCode status
= U_ZERO_ERROR
;
487 NumberFormat
*nf
= NumberFormat::createInstance(status
);
488 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
492 nf
->setMaximumFractionDigits(4);
494 FieldPosition
pos(FieldPosition::DONT_CARE
);
495 out
= nf
->format(x
, out
, pos
);
496 logln("0.00159999 formats with 4 fractional digits to " + out
);
497 UnicodeString
expected("0.0016");
499 errln("FAIL: Expected " + expected
);
505 * A space as a group separator for localized pattern causes
506 * wrong format. WorkAround : use non-breaking space.
508 void NumberFormatRegressionTest::Test4086575(void)
510 UErrorCode status
= U_ZERO_ERROR
;
511 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
513 // TODO: There is not a good way to find out that the creation of this number format has
514 // failed. Major rewiring of format construction proposed.
515 if(U_FAILURE(status
)) {
516 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
520 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
522 // C++ workaround to make sure cast works
523 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
525 errln("NumberFormat::createInstance returned incorrect type.");
530 logln("nf toPattern1: " + nf
->toPattern(temp
));
531 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
533 // No group separator
534 logln("...applyLocalizedPattern ###,00;(###,00) ");
535 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
536 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
537 logln("nf toPattern2: " + nf
->toPattern(temp
));
538 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
540 FieldPosition
pos(FieldPosition::DONT_CARE
);
541 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
542 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
544 // Space as group separator
546 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
548 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
550 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
551 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
553 UnicodeString
pat(patChars
, 19, 19);
554 nf
->applyLocalizedPattern(pat
, status
);
555 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
556 logln("nf toPattern2: " + nf
->toPattern(temp
));
557 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
558 UnicodeString buffer
;
559 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
560 //if (buffer != UnicodeString("1\u00a0234,00"))
562 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
564 UnicodeString
cc(c
, 8, 8);
566 errln("nf : " + buffer
); // Expect 1 234,00
569 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
571 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
573 UnicodeString
cc1(c1
, 10, 10);
575 errln("nf : " + buffer
); // Expect (1 234,00)
577 // Erroneously prints:
584 * DecimalFormat.parse returns wrong value
586 // {sfb} slightly converted into a round-trip test, since in C++
587 // there is no Double.toString()
588 void NumberFormatRegressionTest::Test4068693(void)
590 logln("----- Test Application -----");
591 ParsePosition
pos(0);
592 UErrorCode status
= U_ZERO_ERROR
;
593 DecimalFormat
*df
= new DecimalFormat(status
);
594 if(U_FAILURE(status
)) {
595 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
599 failure(status
, "new DecimalFormat");
601 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
602 df
->parse(UnicodeString("123.55456"), d
, pos
);
603 //if (!d.toString().equals("123.55456")) {
605 df
->setMaximumFractionDigits(999);
606 df
->setMaximumIntegerDigits(999);
607 FieldPosition
fp(FieldPosition::DONT_CARE
);
608 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
609 if (dstr
!= UnicodeString("123.55456")) {
610 errln(UnicodeString("Result -> ") + d
.getDouble());
616 /* @bug 4069754, 4067878
617 * null pointer thrown when accessing a deserialized DecimalFormat
620 // {sfb} doesn't apply in C++
621 void NumberFormatRegressionTest::Test4069754(void)
624 myformat it = new myformat();
626 FileOutputStream ostream = new FileOutputStream("t.tmp");
627 ObjectOutputStream p = new ObjectOutputStream(ostream);
632 FileInputStream istream = new FileInputStream("t.tmp");
633 ObjectInputStream p2 = new ObjectInputStream(istream);
634 myformat it2 = (myformat)p2.readObject();
638 } catch (Exception foo) {
639 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
644 * DecimalFormat.applyPattern(String) allows illegal patterns
646 void NumberFormatRegressionTest::Test4087251 (void)
648 UErrorCode status
= U_ZERO_ERROR
;
649 DecimalFormat
*df
= new DecimalFormat(status
);
650 if(U_FAILURE(status
)) {
651 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
655 failure(status
, "new DecimalFormat");
657 df
->applyPattern(UnicodeString("#.#.#"), status
);
658 if( ! U_FAILURE(status
))
659 errln("df->applyPattern with illegal pattern didn't fail");
661 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
662 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
663 /*} catch (IllegalArgumentException e) {
664 logln("Caught Illegal Argument Error !");
666 // Second test; added 5/11/98 when reported to fail on 1.2b3
668 df
->applyPattern("#0.0#0#0", status
);
669 if( ! U_FAILURE(status
))
670 errln("df->applyPattern with illegal pattern didn't fail");
671 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
672 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
673 /*} catch (IllegalArgumentException e) {
674 logln("Ok - IllegalArgumentException for #0.0#0#0");
681 * DecimalFormat.format() loses precision
683 void NumberFormatRegressionTest::Test4090489 (void)
685 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
686 // that NumberFormat can do. For some reason, it does not format the last 1.
688 /* UErrorCode status = U_ZERO_ERROR;
689 DecimalFormat *df = new DecimalFormat(status);
690 failure(status, "new DecimalFormat");
691 df->setMinimumFractionDigits(10);
692 df->setMaximumFractionDigits(999);
693 df->setGroupingUsed(FALSE);
694 double d = 1.000000000000001E7;
695 //BigDecimal bd = new BigDecimal(d);
697 FieldPosition fp(FieldPosition::DONT_CARE);
698 logln(UnicodeString("d = ") + d);
699 //logln("BigDecimal.toString(): " + bd.toString());
700 df->format(d, sb, fp);
701 if (sb != "10000000.0000000100") {
702 errln("DecimalFormat.format(): " + sb);
708 * DecimalFormat.format() loses precision
710 void NumberFormatRegressionTest::Test4090504 (void)
713 logln(UnicodeString("d = ") + d
);
714 UErrorCode status
= U_ZERO_ERROR
;
715 DecimalFormat
*df
= new DecimalFormat(status
);
716 if(U_FAILURE(status
)) {
717 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
721 failure(status
, "new DecimalFormat");
723 FieldPosition
fp(FieldPosition::DONT_CARE
);
725 for (int i
= 17; i
<= 20; i
++) {
726 df
->setMaximumFractionDigits(i
);
727 //sb = new StringBuffer("");
729 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
730 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
732 /*} catch (Exception foo) {
733 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
739 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
741 void NumberFormatRegressionTest::Test4095713 (void)
743 UErrorCode status
= U_ZERO_ERROR
;
744 DecimalFormat
*df
= new DecimalFormat(status
);
745 if(U_FAILURE(status
)) {
746 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
750 failure(status
, "new DecimalFormat");
751 UnicodeString
str("0.1234");
753 //Double d1 = new Double(str);
754 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
757 df
->parse(str
, d2
, pp
);
758 logln(UnicodeString("") + d1
);
759 if (d2
.getDouble() != d1
)
760 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
765 * DecimalFormat.parse() fails when multiplier is not set to 1
767 // {sfb} not sure what to do with this one
768 void NumberFormatRegressionTest::Test4092561 (void)
770 UErrorCode status
= U_ZERO_ERROR
;
771 DecimalFormat
*df
= new DecimalFormat(status
);
772 if(U_FAILURE(status
)) {
773 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
777 failure(status
, "new DecimalFormat");
779 // {sfb} going to cheat here and use sprintf ??
781 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
782 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
783 df.setMultiplier(100);
784 Number num = df.parse(str, new ParsePosition(0));
785 if (num.doubleValue() != -9.223372036854776E16)
786 errln("Bug 4092561 test failed when multiplier is set to not 1.");
792 * DecimalFormat: Negative format ignored.
794 void NumberFormatRegressionTest::Test4092480 (void)
796 UErrorCode status
= U_ZERO_ERROR
;
797 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
798 if(U_FAILURE(status
)) {
799 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
803 failure(status
, "new DecimalFormat");
806 dfFoo
->applyPattern("0000;-000", status
);
807 failure(status
, "dfFoo->applyPattern");
809 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
810 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
811 FieldPosition
pos(FieldPosition::DONT_CARE
);
812 logln(dfFoo
->format((int32_t)42, temp
, pos
));
813 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
814 dfFoo
->applyPattern("000;-000", status
);
815 failure(status
, "dfFoo->applyPattern");
816 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
817 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
818 logln(dfFoo
->format((int32_t)42,temp
, pos
));
819 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
821 dfFoo
->applyPattern("000;-0000", status
);
822 failure(status
, "dfFoo->applyPattern");
823 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
824 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
825 logln(dfFoo
->format((int32_t)42, temp
, pos
));
826 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
828 dfFoo
->applyPattern("0000;-000", status
);
829 failure(status
, "dfFoo->applyPattern");
830 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
831 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
832 logln(dfFoo
->format((int32_t)42, temp
, pos
));
833 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
834 /*} catch (Exception foo) {
835 errln("Message " + foo.getMessage());
841 * NumberFormat.getCurrencyInstance() produces format that uses
842 * decimal separator instead of monetary decimal separator.
844 * Rewrote this test not to depend on the actual pattern. Pattern should
845 * never contain the monetary separator! Decimal separator in pattern is
846 * interpreted as monetary separator if currency symbol is seen!
848 void NumberFormatRegressionTest::Test4087244 (void) {
849 UErrorCode status
= U_ZERO_ERROR
;
851 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
852 Locale
*de
= new Locale(loc
);
853 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
854 if(U_FAILURE(status
)) {
855 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
859 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
861 errln("expected DecimalFormat!");
864 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
865 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
866 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
867 if (decSep
== monSep
) {
868 errln("ERROR in test: want decimal sep != monetary sep");
871 df
->setMinimumIntegerDigits(1);
872 df
->setMinimumFractionDigits(2);
875 df
->format(1.23, str
, pos
);
876 UnicodeString
monStr("1x23");
877 monStr
.replace((int32_t)1, 1, monSep
);
878 UnicodeString
decStr("1x23");
879 decStr
.replace((int32_t)1, 1, decSep
);
880 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
881 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
882 monStr
+ "\" and not \"" + decStr
+ '"');
884 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
886 "\" 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\u00a0789,987";
901 String expectedCurrency = "5\u00a0789,98\u00a0F";
902 String expectedPercent = "-578\u00a0998%";
905 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
908 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
911 0x2d, 0x35, 0x37, 0x38, 0x00a0, 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_PREEURO", 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_PREEURO", 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_PREEURO", 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_PREEURO", 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_PREEURO", 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_PREEURO", 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_PREEURO", 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_PREEURO", 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
= new DecimalFormat("#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
);
1206 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1209 FieldPosition
pos(FieldPosition::DONT_CARE
);
1210 out
= df
->format(x
, out
, pos
);
1211 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1212 if (out
!= expected
)
1213 errln("FAIL: Expected " + expected
);
1216 * Tests the setMaximumFractionDigits limit.
1218 void NumberFormatRegressionTest::Test4098741(void)
1221 UErrorCode status
= U_ZERO_ERROR
;
1222 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1223 if (U_FAILURE(status
)) {
1224 dataerrln("Error calling NumberFormat::createPercentInstance");
1229 fmt
->setMaximumFractionDigits(20);
1231 logln(fmt
->format(.001, temp
));
1232 /*} catch (Exception foo) {
1233 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1238 * Tests illegal pattern exception.
1239 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1240 * Part2 has been fixed.
1242 void NumberFormatRegressionTest::Test4074454(void)
1245 UErrorCode status
= U_ZERO_ERROR
;
1246 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1247 if(U_FAILURE(status
)) {
1248 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1252 failure(status
, "new DecimalFormat");
1253 logln("Inconsistent negative pattern is fine.");
1254 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1255 failure(status
, "new DecimalFormat");
1256 UnicodeString tempString
;
1257 FieldPosition
pos(FieldPosition::DONT_CARE
);
1258 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1259 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1260 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1261 /*} catch (Exception foo) {
1262 errln("An exception was thrown for any inconsistent negative pattern.");
1269 * Tests all different comments.
1270 * Response to some comments :
1271 * [1] DecimalFormat.parse API documentation is more than just one line.
1272 * This is not a reproducable doc error in 116 source code.
1273 * [2] See updated javadoc.
1275 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1276 * a null object will be returned. The unchanged parse position also
1277 * reflects an error.
1278 * NumberFormat.parse(String) : If parsing fails, an ParseException
1280 * See updated javadoc for more details.
1281 * [5] See updated javadoc.
1282 * [6] See updated javadoc.
1283 * [7] This is a correct behavior if the DateFormat object is linient.
1284 * Otherwise, an IllegalArgumentException will be thrown when formatting
1285 * "January 35". See GregorianCalendar class javadoc for more details.
1287 void NumberFormatRegressionTest::Test4099404(void)
1290 UErrorCode status
= U_ZERO_ERROR
;
1291 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1292 if(! U_FAILURE(status
))
1293 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1294 /*} catch (Exception foo) {
1295 logln("Bug 4099404 pattern \"000.0#0\" passed");
1300 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1301 if( !U_FAILURE(status
))
1302 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1303 /*} catch (Exception foo) {
1304 logln("Bug 4099404 pattern \"0#0.000\" passed");
1310 * DecimalFormat.applyPattern doesn't set minimum integer digits
1312 void NumberFormatRegressionTest::Test4101481(void)
1314 UErrorCode status
= U_ZERO_ERROR
;
1315 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1316 if(U_FAILURE(status
)) {
1317 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1321 failure(status
, "new DecimalFormat");
1322 if (sdf
->getMinimumIntegerDigits() != 1)
1323 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1326 /* @bug 4052223 (API addition request A27)
1327 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1329 void NumberFormatRegressionTest::Test4052223(void)
1332 UErrorCode status
= U_ZERO_ERROR
;
1333 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1334 if(U_FAILURE(status
)) {
1335 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1339 failure(status
, "new DecimalFormat");
1341 fmt
->parse(UnicodeString("abc3"), num
, status
);
1342 if(! U_FAILURE(status
))
1343 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1344 /*} catch (ParseException foo) {
1345 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1350 * API tests for API addition request A9.
1352 void NumberFormatRegressionTest::Test4061302(void)
1354 UErrorCode status
= U_ZERO_ERROR
;
1355 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1356 if (U_FAILURE(status
)) {
1357 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status
));
1360 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1361 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1362 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1363 if (currency
== UnicodeString("") ||
1364 intlCurrency
== UnicodeString("") ||
1365 monDecSeparator
== UnicodeString(""))
1367 errln("getCurrencySymbols failed, got empty string.");
1369 UnicodeString monDecSeparatorStr
;
1370 monDecSeparatorStr
.append(monDecSeparator
);
1371 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1372 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1373 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1374 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1375 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1376 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1377 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1378 if (currency
!= UnicodeString("XYZ") ||
1379 intlCurrency
!= UnicodeString("ABC") ||
1380 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1381 errln("setCurrencySymbols failed.");
1383 monDecSeparatorStr
.remove();
1384 monDecSeparatorStr
.append(monDecSeparator
);
1385 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1390 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1391 * FieldPosition.getEndIndex.
1393 void NumberFormatRegressionTest::Test4062486(void)
1395 UErrorCode status
= U_ZERO_ERROR
;
1396 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1397 if (U_FAILURE(status
)) {
1398 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
1401 UnicodeString formatted
;
1402 FieldPosition
field(FieldPosition::DONT_CARE
);
1403 double num
= 1234.5;
1404 fmt
->format(num
, formatted
, field
);
1405 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1406 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1407 field
.setBeginIndex(7);
1408 field
.setEndIndex(4);
1409 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1410 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1416 * DecimalFormat.parse incorrectly works with a group separator.
1418 void NumberFormatRegressionTest::Test4108738(void)
1420 UErrorCode status
= U_ZERO_ERROR
;
1421 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1422 failure(status
, "new DecimalFormatSymbols");
1423 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1424 if(U_FAILURE(status
)) {
1425 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1429 failure(status
, "new DecimalFormat");
1430 UnicodeString
text("1.222,111");
1432 ParsePosition
pp(0);
1433 df
->parse(text
, num
, pp
);
1435 // {sfb} how to do this (again) ?
1436 // shouldn't just be another round-trip test, should it?
1438 FieldPosition
pos(FieldPosition::DONT_CARE
);
1439 temp
= df
->format(num
.getDouble(), temp
, pos
);
1440 //if (!num.toString().equals("1.222"))
1441 if (temp
!= UnicodeString("1.222"))
1442 //errln("\"" + text + "\" is parsed as " + num);
1443 errln("\"" + text
+ "\" is parsed as " + temp
);
1444 text
= UnicodeString("1.222x111");
1445 pp
= ParsePosition(0);
1446 df
->parse(text
, num
, pp
);
1448 temp
= df
->format(num
.getDouble(), temp
, pos
);
1449 //if (!num.toString().equals("1.222"))
1450 if (temp
!= UnicodeString("1.222"))
1451 errln("\"" + text
+ "\" is parsed as " + temp
);
1457 * DecimalFormat.format() incorrectly formats negative doubles.
1459 void NumberFormatRegressionTest::Test4106658(void)
1461 UErrorCode status
= U_ZERO_ERROR
;
1462 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1463 if(U_FAILURE(status
)) {
1464 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1468 failure(status
, "new DecimalFormat");
1469 volatile double d1
= 0.0; // volatile to prevent code optimization
1470 double d2
= -0.0001;
1471 UnicodeString buffer
;
1473 FieldPosition
pos(FieldPosition::DONT_CARE
);
1475 #if U_PLATFORM == U_PF_HPUX
1476 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1478 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1480 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1481 df
->format(d1
, buffer
, pos
);
1482 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1483 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1485 df
->format(d2
, buffer
, pos
);
1486 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1487 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1493 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1495 void NumberFormatRegressionTest::Test4106662(void)
1497 UErrorCode status
= U_ZERO_ERROR
;
1498 DecimalFormat
*df
= new DecimalFormat(status
);
1499 if(U_FAILURE(status
)) {
1500 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1504 failure(status
, "new DecimalFormat");
1505 UnicodeString
text("x");
1506 ParsePosition
pos1(0), pos2(0);
1509 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1511 df
->parse(text
, num
, pos1
);
1512 if (pos1
== ParsePosition(0)/*num != null*/) {
1513 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1516 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1517 failure(status
, "new DecimalFormat");
1518 df
->parse(UnicodeString("$"), num
, pos2
);
1519 if (pos2
== ParsePosition(0) /*num != null*/){
1520 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1526 /* @bug 4114639 (duplicate of 4106662)
1527 * NumberFormat.parse doesn't return null
1529 void NumberFormatRegressionTest::Test4114639(void)
1531 UErrorCode status
= U_ZERO_ERROR
;
1532 NumberFormat
*format
= NumberFormat::createInstance(status
);
1533 if(U_FAILURE(status
)) {
1534 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1538 failure(status
, "NumberFormat::createInstance");
1539 UnicodeString
text("time 10:x");
1540 ParsePosition
pos(8);
1542 format
->parse(text
, result
, pos
);
1543 if (/*result != null*/pos
.getErrorIndex() != 8)
1544 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1550 * TODO: this test does not work because we need to use a 64 bit number and a
1551 * a double only MAY only have 52 bits of precision.
1552 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1554 void NumberFormatRegressionTest::Test4106664(void)
1556 UErrorCode status
= U_ZERO_ERROR
;
1557 DecimalFormat
*df
= new DecimalFormat(status
);
1558 if(U_FAILURE(status
)) {
1559 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1563 failure(status
, "new DecimalFormat");
1564 // {sfb} long in java is 64 bits
1565 /*long*/double n
= 1234567890123456.0;
1566 /*int*/int32_t m
= 12345678;
1567 // {sfb} will this work?
1568 //BigInteger bigN = BigInteger.valueOf(n);
1569 //bigN = bigN.multiply(BigInteger.valueOf(m));
1570 double bigN
= n
* m
;
1571 df
->setMultiplier(m
);
1572 df
->setGroupingUsed(FALSE
);
1574 FieldPosition
pos(FieldPosition::DONT_CARE
);
1575 logln("formated: " +
1576 df
->format(n
, temp
, pos
));
1579 sprintf(buf
, "%g", bigN
);
1580 //logln("expected: " + bigN.toString());
1581 logln(UnicodeString("expected: ") + buf
);
1585 /* @bug 4106667 (duplicate of 4106658)
1586 * DecimalFormat.format incorrectly formats -0.0.
1588 void NumberFormatRegressionTest::Test4106667(void)
1590 UErrorCode status
= U_ZERO_ERROR
;
1591 DecimalFormat
*df
= new DecimalFormat(status
);
1592 if(U_FAILURE(status
)) {
1593 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1597 failure(status
, "new DecimalFormat");
1598 UChar foo
[] = { 0x002B };
1599 UnicodeString
bar(foo
, 1, 1);
1600 volatile double d
= 0.0; // volatile to prevent code optimization
1602 UnicodeString buffer
;
1603 FieldPosition
pos(FieldPosition::DONT_CARE
);
1605 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1606 #if U_PLATFORM == U_PF_HPUX
1607 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1609 d
*= -1.0; // Some compilers have a problem with defining -0.0
1611 df
->setPositivePrefix(/*"+"*/bar
);
1612 df
->format(d
, buffer
, pos
);
1613 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1614 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1620 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1622 #if U_PLATFORM == U_PF_OS390
1623 # define MAX_INT_DIGITS 70
1625 # define MAX_INT_DIGITS 128
1628 void NumberFormatRegressionTest::Test4110936(void)
1630 UErrorCode status
= U_ZERO_ERROR
;
1631 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1632 if(U_FAILURE(status
)) {
1633 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1637 failure(status
, "NumberFormat::createInstance");
1638 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1639 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1640 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1641 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1642 nf
->getMaximumIntegerDigits());
1648 * Locale data should use generic currency symbol
1650 * 1) Make sure that all currency formats use the generic currency symbol.
1651 * 2) Make sure we get the same results using the generic symbol or a
1654 void NumberFormatRegressionTest::Test4122840(void)
1657 const Locale
*locales
= Locale::getAvailableLocales(count
);
1659 for (int i
= 0; i
< count
; i
++) {
1660 UErrorCode status
= U_ZERO_ERROR
;
1661 ResourceBundle
*rb
= new ResourceBundle(
1662 NULL
/*"java.text.resources.LocaleElements"*/,
1663 locales
[i
], status
);
1664 failure(status
, "new ResourceBundle");
1665 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1666 failure(status
, "rb.get(NumberElements)");
1667 numPat
= numPat
.getWithFallback("latn",status
);
1668 failure(status
, "rb.get(latn)");
1669 numPat
= numPat
.getWithFallback("patterns",status
);
1670 failure(status
, "rb.get(patterns)");
1671 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1672 failure(status
, "rb.get(currencyFormat)");
1674 // Get the currency pattern for this locale. We have to fish it
1675 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1676 // will return the localized symbol, not \00a4
1678 UnicodeString pattern
= numPat
.getString(status
);
1679 failure(status
, "rb->getString()");
1681 UChar fo
[] = { 0x00A4 };
1682 UnicodeString
foo(fo
, 1, 1);
1684 //if (pattern.indexOf("\u00A4") == -1 ) {
1685 if (pattern
.indexOf(foo
) == -1 ) {
1686 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1687 " does not contain generic currency symbol:" +
1691 // Create a DecimalFormat using the pattern we got and format a number
1692 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1693 failure(status
, "new DecimalFormatSymbols");
1694 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1695 failure(status
, "new DecimalFormat");
1697 UnicodeString result1
;
1698 FieldPosition
pos(FieldPosition::DONT_CARE
);
1699 result1
= fmt1
->format(1.111, result1
, pos
);
1702 // Now substitute in the locale's currency symbol and create another
1703 // pattern. We have to skip locales where the currency symbol
1704 // contains decimal separators, because that confuses things
1706 UChar ba
[] = { 0x002E/*'.'*/ };
1707 UnicodeString
bar(ba
, 1, 1);
1709 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1710 // {sfb} Also, switch the decimal separator to the monetary decimal
1711 // separator to mimic the behavior of a currency format
1712 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1713 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1715 UnicodeString
buf(pattern
);
1716 for (int j
= 0; j
< buf
.length(); j
++) {
1717 if (buf
[j
] == 0x00a4 ) {
1718 if(buf
[j
+ 1] == 0x00a4) {
1719 // {sfb} added to support double currency marker (intl currency sign)
1720 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1721 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1724 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1725 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1730 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1731 failure(status
, "new DecimalFormat");
1733 // Get the currency (if there is one) so we can set the rounding and fraction
1734 const UChar
*currency
= fmt1
->getCurrency();
1735 if (*currency
!= 0) {
1736 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1737 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1738 if (U_SUCCESS(status
)) {
1739 fmt2
->setRoundingIncrement(rounding
);
1740 fmt2
->setMinimumFractionDigits(frac
);
1741 fmt2
->setMaximumFractionDigits(frac
);
1744 failure(status
, "Fetching currency rounding/fractions");
1748 UnicodeString result2
;
1749 fmt2
->format(1.111, result2
, pos
);
1751 if (result1
!= result2
) {
1752 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1753 result1
+ " vs " + result2
);
1766 * DecimalFormat.format() delivers wrong string.
1768 void NumberFormatRegressionTest::Test4125885(void)
1770 UErrorCode status
= U_ZERO_ERROR
;
1771 double rate
= 12.34;
1772 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1773 if(U_FAILURE(status
)) {
1774 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1778 failure(status
, "new DecimalFormat");
1780 logln("toPattern: " + formatDec
->toPattern(temp
));
1781 UnicodeString rateString
;
1782 FieldPosition
pos(FieldPosition::DONT_CARE
);
1783 rateString
= formatDec
->format(rate
, rateString
, pos
);
1784 if (rateString
!= UnicodeString("012.34"))
1785 errln("result : " + rateString
+ " expected : 012.34");
1787 delete formatDec
;// = null;
1788 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1789 failure(status
, "new DecimalFormat");
1790 logln("toPattern: " + formatDec
->toPattern(temp
));
1791 rateString
.remove();
1792 rateString
= formatDec
->format(rate
, rateString
, pos
);
1793 if (rateString
!= UnicodeString("+012.34%"))
1794 errln("result : " + rateString
+ " expected : +012.34%");
1801 * DecimalFormat produces extra zeros when formatting numbers.
1803 void NumberFormatRegressionTest::Test4134034(void)
1805 UErrorCode status
= U_ZERO_ERROR
;
1806 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1807 if (!failure(status
, "new DecimalFormat")) {
1809 FieldPosition
pos(FieldPosition::DONT_CARE
);
1810 f
= nf
->format(9.02, f
, pos
);
1811 if (f
== UnicodeString("9.02"))
1814 errln("9.02 -> " + f
+ "; want 9.02");
1817 f
= nf
->format((int32_t)0, f
, pos
);
1818 if (f
== UnicodeString(".00"))
1821 errln("0 -> " + f
+ "; want .00");
1829 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1830 * a duplicate of 4134034.
1832 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1833 * Possibly related to bug 4125885.
1835 * This class demonstrates a regression in version 1.1.6
1836 * of DecimalFormat class.
1839 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1840 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1841 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1842 * Value 1.2 Format #0.0# Result '1.2'
1843 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1846 * Value 1.2 Format #.00 Result '1.20'
1847 * Value 1.2 Format 0.00 Result '1.20'
1848 * Value 1.2 Format 00.00 Result '01.20'
1849 * Value 1.2 Format #0.0# Result '1.2'
1850 * Value 1.2 Format #0.00 Result '1.20'
1852 void NumberFormatRegressionTest::Test4134300(void) {
1853 UnicodeString DATA
[] = {
1854 // Pattern Expected string
1855 UnicodeString("#.00"), UnicodeString("1.20"),
1856 UnicodeString("0.00"), UnicodeString("1.20"),
1857 UnicodeString("00.00"), UnicodeString("01.20"),
1858 UnicodeString("#0.0#"), UnicodeString("1.2"),
1859 UnicodeString("#0.00"), UnicodeString("1.20")
1862 for (int i
=0; i
< 10; i
+=2) {
1863 UnicodeString result
;
1864 UErrorCode status
= U_ZERO_ERROR
;
1865 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1866 if (!failure(status
, "new DecimalFormat")) {
1867 FieldPosition
pos(FieldPosition::DONT_CARE
);
1868 result
= df
->format(1.2, result
, pos
);
1869 if (result
!= DATA
[i
+1]) {
1870 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1871 "; want " + DATA
[i
+1]);
1874 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1884 * Empty pattern produces double negative prefix.
1886 void NumberFormatRegressionTest::Test4140009(void)
1888 UErrorCode status
= U_ZERO_ERROR
;
1889 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
1890 failure(status
, "new DecimalFormatSymbols");
1891 DecimalFormat
*f
= new DecimalFormat(UnicodeString(""), syms
, status
);
1892 if (!failure(status
, "new DecimalFormat")) {
1894 FieldPosition
pos(FieldPosition::DONT_CARE
);
1895 s
= f
->format(123.456, s
, pos
);
1896 if (s
!= UnicodeString("123.456"))
1897 errln("Fail: Format empty pattern x 123.456 => " + s
);
1899 s
= f
->format(-123.456, s
, pos
);
1900 if (s
!= UnicodeString("-123.456"))
1901 errln("Fail: Format empty pattern x -123.456 => " + s
);
1908 * BigDecimal numbers get their fractions truncated by NumberFormat.
1910 // {sfb} not pertinent in C++ ??
1911 void NumberFormatRegressionTest::Test4141750(void) {
1913 UnicodeString str("12345.67");
1914 BigDecimal bd = new BigDecimal(str);
1915 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1916 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1918 catch (Exception e) {
1919 errln(e.toString());
1920 e.printStackTrace();
1926 * DecimalFormat toPattern() doesn't quote special characters or handle
1929 void NumberFormatRegressionTest::Test4145457() {
1931 UErrorCode status
= U_ZERO_ERROR
;
1932 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1933 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1937 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1939 errln("DecimalFormat needed to continue");
1943 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1944 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1945 nf
->setDecimalFormatSymbols(*sym
);
1946 double pi
= 3.14159;
1948 UnicodeString PATS
[] = {
1949 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1952 for (int32_t i
=0; i
<2; ++i
) {
1953 nf
->applyPattern(PATS
[i
], status
);
1954 failure(status
, "nf->applyPattern");
1956 FieldPosition
pos(FieldPosition::DONT_CARE
);
1957 out
= nf
->format(pi
, out
, pos
);
1959 pat
= nf
->toPattern(pat
);
1961 ParsePosition
pp(0);
1962 nf
->parse(out
, num
, pp
);
1963 double val
= num
.getDouble();
1965 nf
->applyPattern(pat
, status
);
1966 failure(status
, "nf->applyPattern");
1968 out2
= nf
->format(pi
, out2
, pos
);
1970 pat2
= nf
->toPattern(pat2
);
1972 nf
->parse(out2
, num
, pp
);
1973 double val2
= num
.getDouble();
1976 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1977 pat
+ "\" vs. \"" + pat2
+ "\"");
1979 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1981 if (val
== val2
&& out
== out2
) {
1982 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1983 out
+ "\" -> " + val
+ " -> \"" +
1984 out2
+ "\" -> " + val2
);
1987 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1988 out
+ "\" -> " + val
+ " -> \"" +
1989 out2
+ "\" -> " + val2
);
1993 catch (ParseException e) {
1994 errln("Fail: " + e);
1995 e.printStackTrace();
2003 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2005 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2007 void NumberFormatRegressionTest::Test4147295(void)
2009 UErrorCode status
= U_ZERO_ERROR
;
2010 DecimalFormat
*sdf
= new DecimalFormat(status
);
2011 UnicodeString
pattern("#,###");
2012 logln("Applying pattern \"" + pattern
+ "\"");
2013 sdf
->applyPattern(pattern
, status
);
2014 if (!failure(status
, "sdf->applyPattern")) {
2015 int minIntDig
= sdf
->getMinimumIntegerDigits();
2016 if (minIntDig
!= 0) {
2017 errln("Test failed");
2018 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2020 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2022 logln("Test passed");
2023 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2031 * DecimalFormat formats -0.0 as +0.0
2032 * See also older related bug 4106658, 4106667
2034 void NumberFormatRegressionTest::Test4147706(void)
2036 UErrorCode status
= U_ZERO_ERROR
;
2037 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2038 failure(status
, "new DecimalFormat");
2039 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2040 if (!failure(status
, "new DecimalFormatSymbols")) {
2042 UnicodeString f2
, temp
;
2043 FieldPosition
pos(FieldPosition::DONT_CARE
);
2044 volatile double d1
= 0.0; // volatile to prevent code optimization
2045 double d2
= -0.0001;
2047 #if U_PLATFORM == U_PF_HPUX
2048 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2050 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2052 df
->adoptDecimalFormatSymbols(syms
);
2053 f1
= df
->format(d1
, f1
, pos
);
2054 f2
= df
->format(d2
, f2
, pos
);
2055 if (f1
!= UnicodeString("-0.0")) {
2056 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2058 if (f2
!= UnicodeString("-0.0")) {
2059 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2067 // Not applicable, since no serialization in C++
2068 /*class myformat implements Serializable
2070 DateFormat _dateFormat = DateFormat.getDateInstance();
2074 GregorianCalendar calendar = new GregorianCalendar();
2075 Date t = calendar.getTime();
2076 String nowStr = _dateFormat.format(t);
2083 * NumberFormat cannot format Double.MAX_VALUE
2085 // TODO: make this test actually test something
2087 NumberFormatRegressionTest::Test4162198(void)
2089 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2090 double dbl
= INT32_MAX
* 1000.0;
2091 UErrorCode status
= U_ZERO_ERROR
;
2092 NumberFormat
*f
= NumberFormat::createInstance(status
);
2093 if(U_FAILURE(status
)) {
2094 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2097 f
->setMaximumFractionDigits(INT32_MAX
);
2098 f
->setMaximumIntegerDigits(INT32_MAX
);
2101 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2104 f
->parse(s
, n
, status
);
2105 if(U_FAILURE(status
))
2106 errln("Couldn't parse!");
2107 //} catch (java.text.ParseException e) {
2108 // errln("Caught a ParseException:");
2109 // e.printStackTrace();
2112 //logln("The string " + s + " parsed as " + n);
2114 // {dlf} The old code assumes n is a double, but it isn't any more...
2115 // Formattable apparently does not and never did interconvert... too bad.
2116 //if(n.getDouble() != dbl) {
2117 // errln("Round trip failure");
2119 if (n
.getInt64() != dbl
) {
2120 errln("Round trip failure");
2128 * NumberFormat does not parse negative zero.
2131 NumberFormatRegressionTest::Test4162852(void)
2133 UErrorCode status
= U_ZERO_ERROR
;
2134 for(int32_t i
=0; i
< 2; ++i
) {
2135 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2136 : NumberFormat::createPercentInstance(status
);
2137 if(U_FAILURE(status
)) {
2138 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2146 f
->parse(s
, n
, status
);
2147 if(U_FAILURE(status
))
2148 errln("Couldn't parse!");
2149 double e
= n
.getDouble();
2150 logln(UnicodeString("") +
2152 '"' + s
+ '"' + " -> " + e
);
2153 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2156 if (e
!= 0.0 || 1.0/e
> 0.0) {
2158 logln("Failed to parse negative zero");
2164 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2167 * May 17 1999 sync up - liu
2169 * NumberFormat truncates data
2171 void NumberFormatRegressionTest::Test4167494(void) {
2172 UErrorCode status
= U_ZERO_ERROR
;
2173 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2174 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2179 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2183 fmt
->parse(s
, num
, status
);
2184 failure(status
, "Parse");
2185 if (num
.getType() == Formattable::kDouble
&&
2186 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2187 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2188 toString(num
) + " ok");
2190 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2191 toString(num
) + " FAIL");
2194 // We don't test Double.MIN_VALUE because the locale data for the US
2195 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2196 // This is correct for now; however, we leave this here as a reminder
2197 // in case we want to address this later.
2203 * May 17 1999 sync up - liu
2205 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2207 void NumberFormatRegressionTest::Test4170798(void) {
2208 UErrorCode status
= U_ZERO_ERROR
;
2209 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2210 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2214 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2216 errln("DecimalFormat needed to continue");
2219 df
->setParseIntegerOnly(TRUE
);
2221 ParsePosition
pos(0);
2222 df
->parse("-0.0", n
, pos
);
2223 if (n
.getType() != Formattable::kLong
2224 || n
.getLong() != 0) {
2225 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n
));
2231 * May 17 1999 sync up - liu
2232 * toPattern only puts the first grouping separator in.
2234 void NumberFormatRegressionTest::Test4176114(void) {
2235 const char* DATA
[] = {
2237 "000", "#000", // No grouping
2238 "#000", "#000", // No grouping
2242 "00,000", "#00,000",
2243 "000,000", "#,000,000",
2244 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2246 int DATA_length
= UPRV_LENGTHOF(DATA
);
2247 UErrorCode status
= U_ZERO_ERROR
;
2249 for (int i
=0; i
<DATA_length
; i
+=2) {
2250 DecimalFormat
df(DATA
[i
], status
);
2251 if (!failure(status
, "DecimalFormat constructor")) {
2253 UnicodeString
exp(DATA
[i
+1]);
2255 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2256 s
+ ", want " + exp
);
2263 * May 17 1999 sync up - liu
2265 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2267 void NumberFormatRegressionTest::Test4179818(void) {
2268 const char* DATA
[] = {
2269 // Input Pattern Expected output
2270 "1.2511", "#.#", "1.3",
2271 "1.2501", "#.#", "1.3",
2274 int DATA_length
= UPRV_LENGTHOF(DATA
);
2280 UErrorCode status
= U_ZERO_ERROR
;
2281 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2282 failure(status
, "Construct DecimalFormatSymbols");
2283 DecimalFormat
fmt("#", sym
, status
);
2284 if (!failure(status
, "Construct DecimalFormat")) {
2285 for (int i
=0; i
<DATA_length
; i
+=3) {
2286 double in
= DOUBLE
[i
/3];
2287 UnicodeString
pat(DATA
[i
+1]);
2288 UnicodeString
exp(DATA
[i
+2]);
2289 fmt
.applyPattern(pat
, status
);
2290 failure(status
, "applyPattern");
2293 fmt
.format(in
, out
, pos
);
2295 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2297 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2298 ", expected " + exp
);
2305 * May 17 1999 sync up - liu
2306 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2307 * This includes the minus sign, currency symbol, international currency
2308 * symbol, percent, and permille. This is filed as bugs 4212072 and
2311 void NumberFormatRegressionTest::Test4212072(void) {
2312 UErrorCode status
= U_ZERO_ERROR
;
2313 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2315 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2316 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2317 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2324 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2325 fmt
.setDecimalFormatSymbols(sym
);
2327 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2328 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2332 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2333 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2336 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2338 fmt
.applyPattern(UnicodeString("#%"), status
);
2339 failure(status
, "applyPattern percent");
2340 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2341 fmt
.setDecimalFormatSymbols(sym
);
2343 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2344 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2348 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2349 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2352 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2354 fmt
.applyPattern(str("#\\u2030"), status
);
2355 failure(status
, "applyPattern permill");
2356 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2357 fmt
.setDecimalFormatSymbols(sym
);
2359 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2360 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2364 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2365 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2368 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2370 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2371 failure(status
, "applyPattern currency");
2372 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2373 fmt
.setDecimalFormatSymbols(sym
);
2375 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) {
2376 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2380 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2381 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2384 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2386 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2387 failure(status
, "applyPattern intl currency");
2388 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2389 fmt
.setDecimalFormatSymbols(sym
);
2391 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) {
2392 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2396 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2397 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2400 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2402 // Since the pattern logic has changed, make sure that patterns round
2403 // trip properly. Test stream in/out integrity too.
2405 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2406 static const char* type
[] = {
2411 for (int i
=0; i
<n
; ++i
) {
2412 for (int j
=0; j
<3; ++j
) {
2413 status
= U_ZERO_ERROR
;
2417 nf
= NumberFormat::createInstance(avail
[i
], status
);
2418 failure(status
, "createInstance", avail
[i
]);
2421 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2422 failure(status
, "createCurrencyInstance", avail
[i
]);
2425 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2426 failure(status
, "createPercentInstance", avail
[i
]);
2429 if (U_FAILURE(status
)) {
2432 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2434 // Test toPattern/applyPattern round trip
2437 DecimalFormatSymbols
symb(avail
[i
], status
);
2438 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2439 DecimalFormat
f2(pat
, symb
, status
);
2441 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2446 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2448 "\" -> \"" + f2
.toPattern(p
) + "\"");
2451 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2456 // Test toLocalizedPattern/applyLocalizedPattern round trip
2457 // TODO(refactor): don't worry about localized patterns for now.
2458 // df->toLocalizedPattern(pat);
2459 // f2.applyLocalizedPattern(pat, status);
2461 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2462 if (U_FAILURE(status
)) {
2466 // TODO(refactor): don't worry about localized patterns for now.
2467 // Make sure we set the currency attributes appropriately
2468 // if (j == 1) { // Currency format
2469 // f2.setCurrency(f2.getCurrency(), status);
2472 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2473 if (U_FAILURE(status
)) {
2479 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2480 " -> localized \"" + pat
+
2481 "\" -> \"" + f2
.toPattern(p
) + "\"");
2486 // Test writeObject/readObject round trip
2487 // NOT ON ICU -- Java only
2493 * May 17 1999 sync up - liu
2494 * DecimalFormat.parse() fails for mulipliers 2^n.
2496 void NumberFormatRegressionTest::Test4216742(void) {
2497 UErrorCode status
= U_ZERO_ERROR
;
2498 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2499 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2503 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2504 int DATA_length
= UPRV_LENGTHOF(DATA
);
2505 for (int i
=0; i
<DATA_length
; ++i
) {
2506 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2507 for (int m
= 1; m
<= 100; m
++) {
2508 fmt
->setMultiplier(m
);
2510 fmt
->parse(str
, num
, status
);
2511 failure(status
, "parse", Locale::getUS());
2512 if (num
.getType() != Formattable::kLong
&&
2513 num
.getType() != Formattable::kDouble
) {
2514 errln(UnicodeString("FAIL: Wanted number, got ") +
2517 double d
= num
.getType() == Formattable::kDouble
?
2518 num
.getDouble() : (double) num
.getLong();
2519 if ((d
> 0) != (DATA
[i
] > 0)) {
2520 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2521 fmt
->getMultiplier() +
2522 ") => " + toString(num
));
2531 * May 17 1999 sync up - liu
2532 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2535 void NumberFormatRegressionTest::Test4217661(void) {
2536 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2537 const char* S
[] = { "0", "1", "0.01", "1.01" };
2538 int D_length
= UPRV_LENGTHOF(D
);
2539 UErrorCode status
= U_ZERO_ERROR
;
2540 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2541 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2545 fmt
->setMaximumFractionDigits(2);
2546 for (int i
=0; i
<D_length
; i
++) {
2548 fmt
->format(D
[i
], s
);
2549 if (s
!= UnicodeString(S
[i
])) {
2550 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2557 * alphaWorks upgrade
2559 void NumberFormatRegressionTest::Test4161100(void) {
2560 UErrorCode status
= U_ZERO_ERROR
;
2561 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2562 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2566 nf
->setMinimumFractionDigits(1);
2567 nf
->setMaximumFractionDigits(1);
2572 logln(UnicodeString() + a
+ " x " +
2573 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2574 if (s
!= UnicodeString("-0.1")) {
2581 * June 16 1999 sync up - liu
2582 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2584 void NumberFormatRegressionTest::Test4243011(void) {
2585 UErrorCode status
= U_ZERO_ERROR
;
2586 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2587 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2588 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2590 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2591 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2592 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2593 int32_t N
= UPRV_LENGTHOF(NUM
);
2595 for (int32_t i
=0; i
<N
; ++i
) {
2597 UnicodeString
exp(STR
[i
]);
2599 fmt
.format(NUM
[i
], str
, pos
);
2601 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2603 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2611 * June 16 1999 sync up - liu
2612 * format(0.0) gives "0.1" if preceded by parse("99.99").
2613 * (Regression in 1.2.2 RC1)
2615 void NumberFormatRegressionTest::Test4243108(void) {
2616 UErrorCode status
= U_ZERO_ERROR
;
2617 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2618 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2619 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2620 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2627 fmt
.format(0.0, str
, pos
);
2628 UnicodeString
exp("0");
2630 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2632 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2638 fmt
.parse(str
, val
, status
);
2639 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2640 if (val
.getType() == Formattable::kDouble
&&
2641 val
.getDouble() == 99.99) {
2642 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2644 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2649 fmt
.format(0.0, str
, pos
);
2651 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2653 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2660 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2661 * NumberFormat objects.
2663 void NumberFormatRegressionTest::TestJ691(void) {
2664 UErrorCode status
= U_ZERO_ERROR
;
2665 Locale
loc("fr", "CH");
2667 // set up the input date string & expected output
2668 UnicodeString
udt("11.10.2000", "");
2669 UnicodeString
exp("11.10.00", "");
2671 // create a Calendar for this locale
2672 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2673 if (U_FAILURE(status
)) {
2674 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2678 // create a NumberFormat for this locale
2679 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2680 if (U_FAILURE(status
)) {
2681 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2685 // *** Here's the key: We don't want to have to do THIS:
2686 // nf->setParseIntegerOnly(TRUE);
2688 // create the DateFormat
2689 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2690 if (U_FAILURE(status
)) {
2691 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2695 df
->adoptCalendar(cal
);
2696 df
->adoptNumberFormat(nf
);
2698 // set parsing to lenient & parse
2699 df
->setLenient(TRUE
);
2700 UDate ulocdat
= df
->parse(udt
, status
);
2702 // format back to a string
2703 UnicodeString outString
;
2704 df
->format(ulocdat
, outString
);
2706 if (outString
!= exp
) {
2707 errln("FAIL: " + udt
+ " => " + outString
);
2713 //---------------------------------------------------------------------------
2715 // Error Checking / Reporting macros
2717 //---------------------------------------------------------------------------
2718 #define TEST_CHECK_STATUS(status) { \
2719 if (U_FAILURE(status)) { \
2720 if (status == U_MISSING_RESOURCE_ERROR) { \
2721 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2723 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2727 #define TEST_ASSERT(expr) \
2728 if ((expr)==FALSE) {\
2729 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2731 #define TEST_ASSERT_EQUALS(x,y) \
2734 int32_t len = sprintf (_msg,"File %s, line %d: Assertion Failed: " #x "==" #y "\n", __FILE__, __LINE__); \
2736 U_ASSERT(len < (int32_t) sizeof(_msg)); \
2737 assertEquals((const char*) _msg, x,y); \
2741 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2743 void NumberFormatRegressionTest::Test8199(void) {
2744 UErrorCode status
= U_ZERO_ERROR
;
2745 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2747 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2750 TEST_CHECK_STATUS(status
);
2752 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2753 // should always truncate, no other rounding scheme.
2755 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2757 nf
->parse(numStr
, val
, status
);
2758 TEST_CHECK_STATUS(status
);
2759 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2760 TEST_ASSERT(1000000000 == val
.getInt64(status
));
2761 TEST_CHECK_STATUS(status
);
2762 TEST_ASSERT(1000000000.6 == val
.getDouble(status
));
2763 TEST_CHECK_STATUS(status
);
2765 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2766 // than int64 because of the fraction
2767 // even though int64 is more precise.
2768 nf
->parse(numStr
, val
, status
);
2769 TEST_CHECK_STATUS(status
);
2770 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2771 TEST_ASSERT(100000000000000001LL == val
.getInt64(status
));
2772 TEST_CHECK_STATUS(status
);
2773 TEST_ASSERT(100000000000000000.0 == val
.getDouble(status
));
2774 TEST_CHECK_STATUS(status
);
2776 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2777 nf
->parse(numStr
, val
, status
);
2778 TEST_CHECK_STATUS(status
);
2779 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2780 TEST_ASSERT(100000000000000000LL == val
.getInt64());
2781 TEST_ASSERT(1.0E17
== val
.getDouble(status
));
2782 TEST_CHECK_STATUS(status
);
2784 numStr
= "9223372036854775807"; // largest int64_t
2785 nf
->parse(numStr
, val
, status
);
2786 TEST_CHECK_STATUS(status
);
2787 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2788 TEST_ASSERT(9223372036854775807LL == val
.getInt64());
2789 // In the following check, note that a substantial range of integers will
2790 // convert to the same double value. There are also platform variations
2791 // in the rounding at compile time of double constants.
2792 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2793 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2794 TEST_CHECK_STATUS(status
);
2796 numStr
= "-9223372036854775808"; // smallest int64_t
2797 nf
->parse(numStr
, val
, status
);
2798 TEST_CHECK_STATUS(status
);
2799 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2800 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2801 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64());
2802 TEST_ASSERT(-9223372036854775808.0 == val
.getDouble(status
));
2803 TEST_CHECK_STATUS(status
);
2805 numStr
= "9223372036854775808"; // largest int64_t + 1
2806 nf
->parse(numStr
, val
, status
);
2807 TEST_CHECK_STATUS(status
);
2808 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2809 TEST_ASSERT(9223372036854775807LL == val
.getInt64(status
));
2810 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2811 status
= U_ZERO_ERROR
;
2812 TEST_ASSERT(9223372036854775810.0 == val
.getDouble(status
));
2813 TEST_CHECK_STATUS(status
);
2815 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2816 nf
->parse(numStr
, val
, status
);
2817 TEST_CHECK_STATUS(status
);
2818 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2819 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings
2820 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64(status
));
2821 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2822 status
= U_ZERO_ERROR
;
2823 TEST_ASSERT(-9223372036854775810.0 == val
.getDouble(status
));
2824 TEST_CHECK_STATUS(status
);
2826 // Test values near the limit of where doubles can represent all integers.
2827 // The implementation strategy of getInt64() changes at this boundary.
2828 // Strings to be parsed include a decimal fraction to force them to be
2829 // parsed as doubles rather than ints. The fraction is discarded
2830 // from the parsed double value because it is beyond what can be represented.
2832 status
= U_ZERO_ERROR
;
2833 numStr
= "9007199254740991.1"; // largest 53 bit int
2834 nf
->parse(numStr
, val
, status
);
2835 TEST_CHECK_STATUS(status
);
2836 // printf("getInt64() returns %lld\n", val.getInt64(status));
2837 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2838 TEST_ASSERT(9007199254740991LL == val
.getInt64(status
));
2839 TEST_ASSERT(9007199254740991.0 == val
.getDouble(status
));
2840 TEST_CHECK_STATUS(status
);
2842 status
= U_ZERO_ERROR
;
2843 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2844 nf
->parse(numStr
, val
, status
);
2845 TEST_CHECK_STATUS(status
);
2846 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2847 TEST_ASSERT(9007199254740992LL == val
.getInt64(status
));
2848 TEST_ASSERT(9007199254740992.0 == val
.getDouble(status
));
2849 TEST_CHECK_STATUS(status
);
2851 status
= U_ZERO_ERROR
;
2852 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2853 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2854 TEST_CHECK_STATUS(status
);
2855 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2856 TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val
.getInt64(status
));
2857 TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val
.getDouble(status
));
2858 TEST_CHECK_STATUS(status
);
2863 void NumberFormatRegressionTest::Test9109(void) {
2864 UErrorCode status
= U_ZERO_ERROR
;
2867 DecimalFormat
fmt("+##", status
);
2868 if (U_FAILURE(status
)) {
2869 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2873 fmt
.setLenient(TRUE
);
2874 UnicodeString
text("123");
2875 int32_t expected
= 123;
2878 fmt
.parse(text
, val
, pos
);
2879 if (pos
.getErrorIndex() >= 0) {
2880 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2881 } else if (val
.getLong() != 123) {
2882 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2883 } else if (pos
.getIndex() != 3) {
2884 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2889 void NumberFormatRegressionTest::Test9780(void) {
2890 UErrorCode status
= U_ZERO_ERROR
;
2891 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2892 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2896 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2898 errln("DecimalFormat needed to continue");
2901 df
->setParseIntegerOnly(TRUE
);
2905 ParsePosition
pos(0);
2906 UnicodeString
toParse("1,234","");
2907 df
->parse(toParse
, n
, pos
);
2908 if (n
.getType() != Formattable::kLong
2909 || n
.getLong() != 1234) {
2910 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2913 // should still work in lenient mode, just won't get fastpath
2914 df
->setLenient(TRUE
);
2917 ParsePosition
pos(0);
2918 UnicodeString
toParse("1,234","");
2919 df
->parse(toParse
, n
, pos
);
2920 if (n
.getType() != Formattable::kLong
2921 || n
.getLong() != 1234) {
2922 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2929 void NumberFormatRegressionTest::Test9677(void) {
2930 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2931 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2932 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2933 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2934 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2936 UErrorCode status
= U_ZERO_ERROR
;
2937 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2938 if (U_FAILURE(status
)) {
2939 dataerrln("Failure opening unum_open");
2943 if (U_SUCCESS(status
)) {
2944 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2945 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2946 assertSuccess("setting attributes", status
);
2949 if(U_SUCCESS(status
)) {
2950 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2951 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2953 if(U_FAILURE(status
)) {
2954 logln("Got expected parse error %s\n", u_errorName(status
));
2955 status
= U_ZERO_ERROR
;
2957 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2961 if (U_SUCCESS(status
)) {
2962 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2963 assertSuccess("setting attributes", status
);
2964 logln("removed positive prefix");
2967 if(U_SUCCESS(status
)) {
2968 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2969 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2971 if(U_FAILURE(status
)) {
2972 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2973 status
= U_ZERO_ERROR
;
2976 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2978 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
2983 if(U_SUCCESS(status
)) {
2984 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2985 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2987 if(U_FAILURE(status
)) {
2988 logln("text2: Got expected parse error %s\n", u_errorName(status
));
2989 status
= U_ZERO_ERROR
;
2991 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2995 if (U_SUCCESS(status
)) {
2996 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
2997 assertSuccess("setting attributes", status
);
2998 logln("Set a different neg prefix prefix");
3001 if(U_SUCCESS(status
)) {
3002 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3003 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3005 if(U_FAILURE(status
)) {
3006 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
3007 status
= U_ZERO_ERROR
;
3011 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3013 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3019 void NumberFormatRegressionTest::Test10361(void) {
3020 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3021 // preventing formatting of big decimals.
3022 UErrorCode status
= U_ZERO_ERROR
;
3023 DecimalFormatSymbols
symbols(Locale::getEnglish(), status
);
3024 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###.##", symbols
, status
), status
);
3025 TEST_CHECK_STATUS(status
);
3027 // Create a decimal number with a million digits.
3028 const int32_t NUMSIZE
=1000000;
3029 char *num
= new char[NUMSIZE
];
3030 for (int32_t i
=0; i
<NUMSIZE
; i
++) {
3031 num
[i
] = '0' + (i
+1) % 10;
3033 num
[NUMSIZE
-3] = '.';
3037 Formattable fmtable
;
3038 fmtable
.setDecimalNumber(num
, status
);
3039 TEST_CHECK_STATUS(status
);
3041 FieldPosition
pos(UNUM_DECIMAL_SEPARATOR_FIELD
);
3042 df
->format(fmtable
, s
, pos
, status
);
3043 TEST_CHECK_STATUS(status
);
3044 TEST_ASSERT(999999 == s
.length());
3045 TEST_ASSERT(999997 == pos
.getBeginIndex());
3046 TEST_ASSERT(999998 == pos
.getEndIndex());
3048 UnicodeString
expected(num
, -1, US_INV
);
3049 TEST_ASSERT(expected
== s
);
3053 #endif /* #if !UCONFIG_NO_FORMATTING */