1 /***********************************************************************
2 * Copyright (c) 1997-2012, International Business Machines Corporation
3 * and others. All Rights Reserved.
4 ***********************************************************************/
6 #include "unicode/utypes.h"
8 #if !UCONFIG_NO_FORMATTING
12 #include <float.h> // DBL_MIN, DBL_MAX
15 #include "unicode/dcfmtsym.h"
16 #include "unicode/decimfmt.h"
17 #include "unicode/locid.h"
18 #include "unicode/resbund.h"
19 #include "unicode/calendar.h"
20 #include "unicode/datefmt.h"
21 #include "unicode/ucurr.h"
24 class MyNumberFormatTest
: public NumberFormat
28 virtual UClassID
getDynamicClassID(void) const;
30 virtual UnicodeString
& format( double number
,
31 UnicodeString
& toAppendTo
,
33 UErrorCode
& status
) const
35 return NumberFormat::format(number
, toAppendTo
, pos
, status
);
38 /* Just keep this here to make some of the compilers happy */
39 virtual UnicodeString
& format(const Formattable
& obj
,
40 UnicodeString
& toAppendTo
,
42 UErrorCode
& status
) const
44 return NumberFormat::format(obj
, toAppendTo
, pos
, status
);
47 /* Just use one of the format functions */
48 virtual UnicodeString
& format( double /* number */,
49 UnicodeString
& toAppendTo
,
50 FieldPosition
& /* pos */) const
57 public Number parse(String text, ParsePosition parsePosition)
58 { return new Integer(0); }
61 /* Just use one of the parse functions */
62 virtual void parse( const UnicodeString
& /* text */,
64 ParsePosition
& /* parsePosition */) const
66 result
.setLong((int32_t)0);
69 virtual void parse( const UnicodeString
& text
,
71 UErrorCode
& status
) const
73 NumberFormat::parse(text
, result
, status
);
75 virtual Format
* clone() const
78 virtual UnicodeString
& format(int32_t,
81 { return foo
.remove(); }
83 virtual UnicodeString
& format(int64_t,
86 { return foo
.remove(); }
88 virtual void applyPattern(const UnicodeString
&, UParseError
&, UErrorCode
&){
92 int32_t gMyNumberFormatTestClassID
;
93 UClassID
MyNumberFormatTest::getDynamicClassID() const
95 return (UClassID
)&gMyNumberFormatTestClassID
;
99 // *****************************************************************************
100 // class NumberFormatRegressionTest
101 // *****************************************************************************
103 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
106 NumberFormatRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
108 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
120 CASE(10,Test4086575
);
121 CASE(11,Test4068693
);
122 CASE(12,Test4069754
);
123 CASE(13,Test4087251
);
124 CASE(14,Test4090489
);
125 CASE(15,Test4090504
);
126 CASE(16,Test4095713
);
127 CASE(17,Test4092561
);
128 CASE(18,Test4092480
);
129 CASE(19,Test4087244
);
130 CASE(20,Test4070798
);
131 CASE(21,Test4071005
);
132 CASE(22,Test4071014
);
133 CASE(23,Test4071859
);
134 CASE(24,Test4093610
);
135 CASE(25,Test4098741
);
136 CASE(26,Test4074454
);
137 CASE(27,Test4099404
);
138 CASE(28,Test4101481
);
139 CASE(29,Test4052223
);
140 CASE(30,Test4061302
);
141 CASE(31,Test4062486
);
142 CASE(32,Test4108738
);
143 CASE(33,Test4106658
);
144 CASE(34,Test4106662
);
145 CASE(35,Test4114639
);
146 CASE(36,Test4106664
);
147 CASE(37,Test4106667
);
148 CASE(38,Test4110936
);
149 CASE(39,Test4122840
);
150 CASE(40,Test4125885
);
151 CASE(41,Test4134034
);
152 CASE(42,Test4134300
);
153 CASE(43,Test4140009
);
154 CASE(44,Test4141750
);
155 CASE(45,Test4145457
);
156 CASE(46,Test4147295
);
157 CASE(47,Test4147706
);
158 CASE(48,Test4162198
);
159 CASE(49,Test4162852
);
160 CASE(50,Test4167494
);
161 CASE(51,Test4170798
);
162 CASE(52,Test4176114
);
163 CASE(53,Test4179818
);
164 CASE(54,Test4212072
);
165 CASE(55,Test4216742
);
166 CASE(56,Test4217661
);
167 CASE(57,Test4161100
);
168 CASE(58,Test4243011
);
169 CASE(59,Test4243108
);
174 default: name
= ""; break;
179 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
181 if(U_FAILURE(status
)) {
182 if (possibleDataError
) {
183 dataerrln(UnicodeString("FAIL: ", "") + msg
184 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
186 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
187 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
196 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
198 if(U_FAILURE(status
)) {
199 if (possibleDataError
) {
200 dataerrln(UnicodeString("FAIL: ", "") + msg
201 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
203 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
204 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
213 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
215 if(U_FAILURE(status
)) {
216 if (possibleDataError
) {
217 dataerrln(UnicodeString("FAIL: ", "") + msg
218 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
220 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
221 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
230 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
232 inline UnicodeString
str(const char *input
)
234 return CharsToUnicodeString(input
);
238 * NumberFormat.equals comparing with null should always return false.
240 // {sfb} kind of silly in C++, just checking for new success
241 void NumberFormatRegressionTest::Test4075713(void)
244 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
246 logln("NumberFormat.equals passed");
247 /*} catch (NullPointerException e) {
248 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
255 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
258 void NumberFormatRegressionTest::Test4074620(void)
261 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
262 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
264 nf1
->setGroupingUsed(FALSE
);
265 nf2
->setGroupingUsed(TRUE
);
268 errln("Test for bug 4074620 failed");
270 logln("Test for bug 4074620 passed.");
278 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
281 void NumberFormatRegressionTest::Test4088161 (void)
283 UErrorCode status
= U_ZERO_ERROR
;
284 DecimalFormat
*df
= new DecimalFormat(status
);
285 if (!failure(status
, "new DecimalFormat", "")) {
287 df
->setMinimumFractionDigits(0);
288 df
->setMaximumFractionDigits(16);
290 FieldPosition
fp1(0);
291 logln(UnicodeString("d = ") + d
);
292 logln("maxFractionDigits = " + df
->getMaximumFractionDigits());
294 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
295 df
->setMaximumFractionDigits(17);
297 FieldPosition
fp2(0);
298 logln("maxFractionDigits = " + df
->getMaximumFractionDigits());
299 sBuf2
= df
->format(d
, sBuf2
, fp2
);
301 errln(" format(d) = '" + sBuf2
+ "'");
308 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
309 * DecimalFormat(String, DecimalFormatSymbols).
311 void NumberFormatRegressionTest::Test4087245 (void)
313 UErrorCode status
= U_ZERO_ERROR
;
314 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
315 failure(status
, "new DecimalFormatSymbols", "");
316 // {sfb} One note about this test: if you pass in a pointer
317 // to the symbols, they are adopted and this test will fail,
318 // even though that is the correct behavior. To test the cloning
319 // of the symbols, it is necessary to pass in a reference to the symbols
320 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
321 failure(status
, "new DecimalFormat with symbols", "");
325 FieldPosition
pos(FieldPosition::DONT_CARE
);
326 logln(UnicodeString("format(") + n
+ ") = " +
327 df
->format(n
, buf1
, pos
));
328 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
329 logln(UnicodeString("format(") + n
+ ") = " +
330 df
->format(n
, buf2
, pos
));
332 errln("Test for bug 4087245 failed");
339 * DecimalFormat.format() incorrectly formats 0.0
341 void NumberFormatRegressionTest::Test4087535 (void)
343 UErrorCode status
= U_ZERO_ERROR
;
344 DecimalFormat
*df
= new DecimalFormat(status
);
345 failure(status
, "new DecimalFormat", "");
346 df
->setMinimumIntegerDigits(0);
349 UnicodeString buffer
;
350 FieldPosition
pos(FieldPosition::DONT_CARE
);
351 buffer
= df
->format(n
, buffer
, pos
);
352 if (buffer
.length() == 0)
353 errln(/*n + */": '" + buffer
+ "'");
355 buffer
= df
->format(n
, buffer
, pos
);
356 if (buffer
.length() == 0)
357 errln(/*n + */": '" + buffer
+ "'");
363 * DecimalFormat.format fails when groupingSize is set to 0.
365 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
366 void NumberFormatRegressionTest::Test4088503 (void)
368 UErrorCode status
= U_ZERO_ERROR
;
369 DecimalFormat
*df
= new DecimalFormat(status
);
370 failure(status
, "new DecimalFormat", "");
371 df
->setGroupingSize(0);
373 FieldPosition
fp(FieldPosition::DONT_CARE
);
375 logln(df
->format((int32_t)123, sBuf
, fp
));
376 //if(fp == FieldPosition(0))
377 // errln("Test for bug 4088503 failed.");
378 /*} catch (Exception foo) {
379 errln("Test for bug 4088503 failed.");
385 * NumberFormat.getCurrencyInstance is wrong.
387 void NumberFormatRegressionTest::Test4066646 (void)
389 assignFloatValue(2.04f
);
390 assignFloatValue(2.03f
);
391 assignFloatValue(2.02f
);
392 assignFloatValue(0.0f
);
396 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
398 logln(UnicodeString(" VALUE ") + returnfloat
);
399 UErrorCode status
= U_ZERO_ERROR
;
400 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
401 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
405 nfcommon
->setGroupingUsed(FALSE
);
407 UnicodeString stringValue
;
408 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
409 logln(" DISPLAYVALUE " + stringValue
);
411 nfcommon
->parse(stringValue
, result
, status
);
412 failure(status
, "nfcommon->parse", Locale::getUS());
413 float floatResult
= (float) (result
.getType() == Formattable::kDouble
414 ? result
.getDouble() : result
.getLong());
415 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
416 //String stringValue = nfcommon.format(returnfloat).substring(1);
417 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
418 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
422 } // End Of assignFloatValue()
425 * DecimalFormat throws exception when parsing "0"
427 void NumberFormatRegressionTest::Test4059870(void)
429 UErrorCode status
= U_ZERO_ERROR
;
430 DecimalFormat
*format
= new DecimalFormat("00", status
);
431 failure(status
, "new Decimalformat", Locale::getUS());
435 format
->parse(UnicodeString("0"), result
, status
);
436 failure(status
, "format->parse", Locale::getUS());
439 catch (Exception e) {
440 errln("Test for bug 4059870 failed : " + e);
446 * DecimalFormatSymbol.equals should always return false when
447 * comparing with null.
449 // {sfb} this is silly in C++
450 void NumberFormatRegressionTest::Test4083018 (void)
452 UErrorCode status
= U_ZERO_ERROR
;
453 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
454 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
457 logln("Test Passed!");
459 errln("Test for bug 4083018 failed");
460 /*} catch (Exception foo) {
461 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
468 * DecimalFormat does not round up correctly.
470 void NumberFormatRegressionTest::Test4071492 (void)
472 double x
= 0.00159999;
473 UErrorCode status
= U_ZERO_ERROR
;
474 NumberFormat
*nf
= NumberFormat::createInstance(status
);
475 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
479 nf
->setMaximumFractionDigits(4);
481 FieldPosition
pos(FieldPosition::DONT_CARE
);
482 out
= nf
->format(x
, out
, pos
);
483 logln("0.00159999 formats with 4 fractional digits to " + out
);
484 UnicodeString
expected("0.0016");
486 errln("FAIL: Expected " + expected
);
492 * A space as a group separator for localized pattern causes
493 * wrong format. WorkAround : use non-breaking space.
495 void NumberFormatRegressionTest::Test4086575(void)
497 UErrorCode status
= U_ZERO_ERROR
;
498 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
500 // TODO: There is not a good way to find out that the creation of this number format has
501 // failed. Major rewiring of format construction proposed.
502 if(U_FAILURE(status
)) {
503 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
507 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
509 // C++ workaround to make sure cast works
510 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
512 errln("NumberFormat::createInstance returned incorrect type.");
517 logln("nf toPattern1: " + nf
->toPattern(temp
));
518 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
520 // No group separator
521 logln("...applyLocalizedPattern ###,00;(###,00) ");
522 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
523 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
524 logln("nf toPattern2: " + nf
->toPattern(temp
));
525 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
527 FieldPosition
pos(FieldPosition::DONT_CARE
);
528 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
529 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
531 // Space as group separator
533 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
535 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
537 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
538 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
540 UnicodeString
pat(patChars
, 19, 19);
541 nf
->applyLocalizedPattern(pat
, status
);
542 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
543 logln("nf toPattern2: " + nf
->toPattern(temp
));
544 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
545 UnicodeString buffer
;
546 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
547 //if (buffer != UnicodeString("1\u00a0234,00"))
549 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
551 UnicodeString
cc(c
, 8, 8);
553 errln("nf : " + buffer
); // Expect 1 234,00
556 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
558 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
560 UnicodeString
cc1(c1
, 10, 10);
562 errln("nf : " + buffer
); // Expect (1 234,00)
564 // Erroneously prints:
571 * DecimalFormat.parse returns wrong value
573 // {sfb} slightly converted into a round-trip test, since in C++
574 // there is no Double.toString()
575 void NumberFormatRegressionTest::Test4068693(void)
577 logln("----- Test Application -----");
578 ParsePosition
pos(0);
579 UErrorCode status
= U_ZERO_ERROR
;
580 DecimalFormat
*df
= new DecimalFormat(status
);
581 if(U_FAILURE(status
)) {
582 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
586 failure(status
, "new DecimalFormat");
588 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
589 df
->parse(UnicodeString("123.55456"), d
, pos
);
590 //if (!d.toString().equals("123.55456")) {
592 df
->setMaximumFractionDigits(999);
593 df
->setMaximumIntegerDigits(999);
594 FieldPosition
fp(FieldPosition::DONT_CARE
);
595 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
596 if (dstr
!= UnicodeString("123.55456")) {
597 errln(UnicodeString("Result -> ") + d
.getDouble());
603 /* @bug 4069754, 4067878
604 * null pointer thrown when accessing a deserialized DecimalFormat
607 // {sfb} doesn't apply in C++
608 void NumberFormatRegressionTest::Test4069754(void)
611 myformat it = new myformat();
613 FileOutputStream ostream = new FileOutputStream("t.tmp");
614 ObjectOutputStream p = new ObjectOutputStream(ostream);
619 FileInputStream istream = new FileInputStream("t.tmp");
620 ObjectInputStream p2 = new ObjectInputStream(istream);
621 myformat it2 = (myformat)p2.readObject();
625 } catch (Exception foo) {
626 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
631 * DecimalFormat.applyPattern(String) allows illegal patterns
633 void NumberFormatRegressionTest::Test4087251 (void)
635 UErrorCode status
= U_ZERO_ERROR
;
636 DecimalFormat
*df
= new DecimalFormat(status
);
637 if(U_FAILURE(status
)) {
638 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
642 failure(status
, "new DecimalFormat");
644 df
->applyPattern(UnicodeString("#.#.#"), status
);
645 if( ! U_FAILURE(status
))
646 errln("df->applyPattern with illegal pattern didn't fail");
648 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
649 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
650 /*} catch (IllegalArgumentException e) {
651 logln("Caught Illegal Argument Error !");
653 // Second test; added 5/11/98 when reported to fail on 1.2b3
655 df
->applyPattern("#0.0#0#0", status
);
656 if( ! U_FAILURE(status
))
657 errln("df->applyPattern with illegal pattern didn't fail");
658 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
659 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
660 /*} catch (IllegalArgumentException e) {
661 logln("Ok - IllegalArgumentException for #0.0#0#0");
668 * DecimalFormat.format() loses precision
670 void NumberFormatRegressionTest::Test4090489 (void)
672 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
673 // that NumberFormat can do. For some reason, it does not format the last 1.
675 /* UErrorCode status = U_ZERO_ERROR;
676 DecimalFormat *df = new DecimalFormat(status);
677 failure(status, "new DecimalFormat");
678 df->setMinimumFractionDigits(10);
679 df->setMaximumFractionDigits(999);
680 df->setGroupingUsed(FALSE);
681 double d = 1.000000000000001E7;
682 //BigDecimal bd = new BigDecimal(d);
685 logln(UnicodeString("d = ") + d);
686 //logln("BigDecimal.toString(): " + bd.toString());
687 df->format(d, sb, fp);
688 if (sb != "10000000.0000000100") {
689 errln("DecimalFormat.format(): " + sb);
695 * DecimalFormat.format() loses precision
697 void NumberFormatRegressionTest::Test4090504 (void)
700 logln(UnicodeString("d = ") + d
);
701 UErrorCode status
= U_ZERO_ERROR
;
702 DecimalFormat
*df
= new DecimalFormat(status
);
703 if(U_FAILURE(status
)) {
704 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
708 failure(status
, "new DecimalFormat");
710 FieldPosition
fp(FieldPosition::DONT_CARE
);
712 for (int i
= 17; i
<= 20; i
++) {
713 df
->setMaximumFractionDigits(i
);
714 //sb = new StringBuffer("");
716 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
717 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
719 /*} catch (Exception foo) {
720 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
726 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
728 void NumberFormatRegressionTest::Test4095713 (void)
730 UErrorCode status
= U_ZERO_ERROR
;
731 DecimalFormat
*df
= new DecimalFormat(status
);
732 if(U_FAILURE(status
)) {
733 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
737 failure(status
, "new DecimalFormat");
738 UnicodeString
str("0.1234");
740 //Double d1 = new Double(str);
741 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
744 df
->parse(str
, d2
, pp
);
745 logln(UnicodeString("") + d1
);
746 if (d2
.getDouble() != d1
)
747 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
752 * DecimalFormat.parse() fails when multiplier is not set to 1
754 // {sfb} not sure what to do with this one
755 void NumberFormatRegressionTest::Test4092561 (void)
757 UErrorCode status
= U_ZERO_ERROR
;
758 DecimalFormat
*df
= new DecimalFormat(status
);
759 if(U_FAILURE(status
)) {
760 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
764 failure(status
, "new DecimalFormat");
766 // {sfb} going to cheat here and use sprintf ??
768 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
769 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
770 df.setMultiplier(100);
771 Number num = df.parse(str, new ParsePosition(0));
772 if (num.doubleValue() != -9.223372036854776E16)
773 errln("Bug 4092561 test failed when multiplier is set to not 1.");
779 * DecimalFormat: Negative format ignored.
781 void NumberFormatRegressionTest::Test4092480 (void)
783 UErrorCode status
= U_ZERO_ERROR
;
784 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
785 if(U_FAILURE(status
)) {
786 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
790 failure(status
, "new DecimalFormat");
793 dfFoo
->applyPattern("0000;-000", status
);
794 failure(status
, "dfFoo->applyPattern");
796 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
797 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
798 FieldPosition
pos(FieldPosition::DONT_CARE
);
799 logln(dfFoo
->format((int32_t)42, temp
, pos
));
800 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
801 dfFoo
->applyPattern("000;-000", status
);
802 failure(status
, "dfFoo->applyPattern");
803 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
804 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
805 logln(dfFoo
->format((int32_t)42,temp
, pos
));
806 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
808 dfFoo
->applyPattern("000;-0000", status
);
809 failure(status
, "dfFoo->applyPattern");
810 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
811 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
812 logln(dfFoo
->format((int32_t)42, temp
, pos
));
813 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
815 dfFoo
->applyPattern("0000;-000", status
);
816 failure(status
, "dfFoo->applyPattern");
817 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
818 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
819 logln(dfFoo
->format((int32_t)42, temp
, pos
));
820 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
821 /*} catch (Exception foo) {
822 errln("Message " + foo.getMessage());
828 * NumberFormat.getCurrencyInstance() produces format that uses
829 * decimal separator instead of monetary decimal separator.
831 * Rewrote this test not to depend on the actual pattern. Pattern should
832 * never contain the monetary separator! Decimal separator in pattern is
833 * interpreted as monetary separator if currency symbol is seen!
835 void NumberFormatRegressionTest::Test4087244 (void) {
836 UErrorCode status
= U_ZERO_ERROR
;
838 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
839 Locale
*de
= new Locale(loc
);
840 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
841 if(U_FAILURE(status
)) {
842 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
846 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
848 errln("expected DecimalFormat!");
851 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
852 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
853 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
854 if (decSep
== monSep
) {
855 errln("ERROR in test: want decimal sep != monetary sep");
858 df
->setMinimumIntegerDigits(1);
859 df
->setMinimumFractionDigits(2);
862 df
->format(1.23, str
, pos
);
863 UnicodeString
monStr("1x23");
864 monStr
.replace((int32_t)1, 1, monSep
);
865 UnicodeString
decStr("1x23");
866 decStr
.replace((int32_t)1, 1, decSep
);
867 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
868 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
869 monStr
+ "\" and not \"" + decStr
+ '"');
871 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
873 "\" and not \"" + decStr
+ '"');
879 * Number format data rounding errors for locale FR
881 void NumberFormatRegressionTest::Test4070798 (void)
883 NumberFormat
*formatter
;
884 UnicodeString tempString
;
887 String expectedDefault = "-5\u00a0789,987";
888 String expectedCurrency = "5\u00a0789,98\u00a0F";
889 String expectedPercent = "-578\u00a0998%";
892 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
895 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
898 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
900 UnicodeString
expectedDefault(chars1
, 10, 10);
901 UnicodeString
expectedCurrency(chars2
, 10, 10);
902 UnicodeString
expectedPercent(chars3
, 10, 10);
904 UErrorCode status
= U_ZERO_ERROR
;
906 int len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
907 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
908 if(U_FAILURE(status
)) {
909 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
913 failure(status
, "NumberFormat::createNumberInstance", loc
);
914 tempString
= formatter
->format (-5789.9876, tempString
);
916 if (tempString
== expectedDefault
) {
917 logln ("Bug 4070798 default test passed.");
919 errln(UnicodeString("Failed:") +
920 " Expected " + expectedDefault
+
921 " Received " + tempString
);
924 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
925 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
926 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
928 tempString
= formatter
->format( 5789.9876, tempString
);
930 if (tempString
== expectedCurrency
) {
931 logln ("Bug 4070798 currency test passed.");
933 errln(UnicodeString("Failed:") +
934 " Expected " + expectedCurrency
+
935 " Received " + tempString
);
939 uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
940 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
941 failure(status
, "NumberFormat::createPercentInstance", loc
);
943 tempString
= formatter
->format (-5789.9876, tempString
);
945 if (tempString
== expectedPercent
) {
946 logln ("Bug 4070798 percentage test passed.");
948 errln(UnicodeString("Failed:") +
949 " Expected " + expectedPercent
+
950 " Received " + tempString
);
956 * Data rounding errors for French (Canada) locale
958 void NumberFormatRegressionTest::Test4071005 (void)
960 NumberFormat
*formatter
;
961 UnicodeString tempString
;
963 String expectedDefault = "-5\u00a0789,987";
964 String expectedCurrency = "5\u00a0789,98\u00a0$";
965 String expectedPercent = "-578\u00a0998%";
968 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
971 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
974 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
976 UnicodeString
expectedDefault(chars1
, 10, 10);
977 UnicodeString
expectedCurrency(chars2
, 10, 10);
978 UnicodeString
expectedPercent(chars3
, 10, 10);
980 UErrorCode status
= U_ZERO_ERROR
;
981 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
982 if (failure(status
, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE
)){
986 tempString
= formatter
->format (-5789.9876, tempString
);
988 if (tempString
== expectedDefault
) {
989 logln ("Bug 4071005 default test passed.");
991 errln(UnicodeString("Failed:") +
992 " Expected " + expectedDefault
+
993 " Received " + tempString
);
997 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
998 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1000 tempString
= formatter
->format( 5789.9876, tempString
);
1002 if (tempString
== expectedCurrency
) {
1003 logln ("Bug 4071005 currency test assed.");
1005 errln(UnicodeString("Failed:") +
1006 " Expected " + expectedCurrency
+
1007 " Received " + tempString
);
1011 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1012 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1013 tempString
.remove();
1014 tempString
= formatter
->format (-5789.9876, tempString
);
1016 if (tempString
== expectedPercent
) {
1017 logln ("Bug 4071005 percentage test passed.");
1019 errln(UnicodeString("Failed:") +
1020 " Expected " + expectedPercent
+
1021 " Received " + tempString
);
1028 * Data rounding errors for German (Germany) locale
1030 void NumberFormatRegressionTest::Test4071014 (void)
1032 NumberFormat
*formatter
;
1033 UnicodeString tempString
;
1035 String expectedDefault = "-5.789,987";
1036 String expectedCurrency = "5.789,98 DEM";
1037 String expectedPercent = "-578.998%";
1039 UnicodeString
expectedDefault("-5.789,988");
1040 UnicodeString
expectedCurrency("5.789,99\\u00A0DEM");
1041 UnicodeString
expectedPercent("-578.999\\u00A0%");
1043 expectedCurrency
= expectedCurrency
.unescape();
1044 expectedPercent
= expectedPercent
.unescape();
1046 UErrorCode status
= U_ZERO_ERROR
;
1048 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1049 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1050 if (failure(status
, "NumberFormat::createNumberInstance", loc
, TRUE
)){
1054 tempString
.remove();
1055 tempString
= formatter
->format (-5789.9876, tempString
);
1057 if (tempString
== expectedDefault
) {
1058 logln ("Bug 4071014 default test passed.");
1060 errln(UnicodeString("Failed:") +
1061 " Expected " + expectedDefault
+
1062 " Received " + tempString
);
1065 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1066 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1067 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1068 tempString
.remove();
1069 tempString
= formatter
->format( 5789.9876, tempString
);
1071 if (tempString
== expectedCurrency
) {
1072 logln ("Bug 4071014 currency test assed.");
1074 errln(UnicodeString("Failed:") +
1075 " Expected " + expectedCurrency
+
1076 " Received " + tempString
);
1080 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1081 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1082 tempString
.remove();
1083 tempString
= formatter
->format (-5789.9876, tempString
);
1085 if (tempString
== expectedPercent
) {
1086 logln ("Bug 4071014 percentage test passed.");
1088 errln(UnicodeString("Failed:") +
1089 " Expected " + expectedPercent
+
1090 " Received " + tempString
);
1096 * Data rounding errors for Italian locale number formats
1098 void NumberFormatRegressionTest::Test4071859 (void)
1100 NumberFormat
*formatter
;
1101 UnicodeString tempString
;
1103 String expectedDefault = "-5.789,987";
1104 String expectedCurrency = "-L.\\u00A05.789,98";
1105 String expectedPercent = "-578.998%";
1107 UnicodeString
expectedDefault("-5.789,988");
1108 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1109 UnicodeString
expectedPercent("-578.999%");
1110 expectedCurrency
= expectedCurrency
.unescape();
1112 UErrorCode status
= U_ZERO_ERROR
;
1114 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1115 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1116 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1120 tempString
= formatter
->format (-5789.9876, tempString
);
1122 if (tempString
== expectedDefault
) {
1123 logln ("Bug 4071859 default test passed.");
1125 errln(UnicodeString("Failed:") +
1126 " Expected " + expectedDefault
+
1127 " Received " + tempString
);
1130 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1131 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1132 failure(status
, "NumberFormat::createCurrencyInstance");
1133 tempString
.remove();
1134 tempString
= formatter
->format( -5789.9876, tempString
);
1136 if (tempString
== expectedCurrency
) {
1137 logln ("Bug 4071859 currency test assed.");
1139 errln(UnicodeString("Failed:") +
1140 " Expected " + expectedCurrency
+
1141 " Received " + tempString
);
1144 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1145 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1146 failure(status
, "NumberFormat::createPercentInstance");
1147 tempString
.remove();
1148 tempString
= formatter
->format (-5789.9876, tempString
);
1150 if (tempString
== expectedPercent
) {
1151 logln ("Bug 4071859 percentage test passed.");
1153 errln(UnicodeString("Failed:") +
1154 " Expected " + expectedPercent
+
1155 " Received " + tempString
);
1161 * Test rounding for nearest even.
1163 void NumberFormatRegressionTest::Test4093610(void)
1165 UErrorCode status
= U_ZERO_ERROR
;
1166 DecimalFormat
*df
= new DecimalFormat("#0.#", status
);
1167 if (!failure(status
, "new DecimalFormat")) {
1168 UnicodeString
s("12.4");
1169 roundingTest(df
, 12.35, s
);
1170 roundingTest(df
, 12.45, s
);
1172 roundingTest(df
, 12.452,s
);
1174 roundingTest(df
, 12.55, s
);
1175 roundingTest(df
, 12.65, s
);
1177 roundingTest(df
, 12.652,s
);
1179 roundingTest(df
, 12.75, s
);
1180 roundingTest(df
, 12.752,s
);
1181 roundingTest(df
, 12.85, s
);
1183 roundingTest(df
, 12.852,s
);
1185 roundingTest(df
, 12.95, s
);
1186 roundingTest(df
, 12.952,s
);
1192 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1195 FieldPosition
pos(FieldPosition::DONT_CARE
);
1196 out
= df
->format(x
, out
, pos
);
1197 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1198 if (out
!= expected
)
1199 errln("FAIL: Expected " + expected
);
1202 * Tests the setMaximumFractionDigits limit.
1204 void NumberFormatRegressionTest::Test4098741(void)
1207 UErrorCode status
= U_ZERO_ERROR
;
1208 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1209 if (U_FAILURE(status
)) {
1210 dataerrln("Error calling NumberFormat::createPercentInstance");
1215 fmt
->setMaximumFractionDigits(20);
1217 logln(fmt
->format(.001, temp
));
1218 /*} catch (Exception foo) {
1219 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1224 * Tests illegal pattern exception.
1225 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1226 * Part2 has been fixed.
1228 void NumberFormatRegressionTest::Test4074454(void)
1231 UErrorCode status
= U_ZERO_ERROR
;
1232 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1233 if(U_FAILURE(status
)) {
1234 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1238 failure(status
, "new DecimalFormat");
1239 logln("Inconsistent negative pattern is fine.");
1240 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1241 failure(status
, "new DecimalFormat");
1242 UnicodeString tempString
;
1243 FieldPosition
pos(FieldPosition::DONT_CARE
);
1244 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1245 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1246 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1247 /*} catch (Exception foo) {
1248 errln("An exception was thrown for any inconsistent negative pattern.");
1255 * Tests all different comments.
1256 * Response to some comments :
1257 * [1] DecimalFormat.parse API documentation is more than just one line.
1258 * This is not a reproducable doc error in 116 source code.
1259 * [2] See updated javadoc.
1261 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1262 * a null object will be returned. The unchanged parse position also
1263 * reflects an error.
1264 * NumberFormat.parse(String) : If parsing fails, an ParseException
1266 * See updated javadoc for more details.
1267 * [5] See updated javadoc.
1268 * [6] See updated javadoc.
1269 * [7] This is a correct behavior if the DateFormat object is linient.
1270 * Otherwise, an IllegalArgumentException will be thrown when formatting
1271 * "January 35". See GregorianCalendar class javadoc for more details.
1273 void NumberFormatRegressionTest::Test4099404(void)
1276 UErrorCode status
= U_ZERO_ERROR
;
1277 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1278 if(! U_FAILURE(status
))
1279 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1280 /*} catch (Exception foo) {
1281 logln("Bug 4099404 pattern \"000.0#0\" passed");
1286 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1287 if( !U_FAILURE(status
))
1288 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1289 /*} catch (Exception foo) {
1290 logln("Bug 4099404 pattern \"0#0.000\" passed");
1296 * DecimalFormat.applyPattern doesn't set minimum integer digits
1298 void NumberFormatRegressionTest::Test4101481(void)
1300 UErrorCode status
= U_ZERO_ERROR
;
1301 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1302 if(U_FAILURE(status
)) {
1303 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1307 failure(status
, "new DecimalFormat");
1308 if (sdf
->getMinimumIntegerDigits() != 1)
1309 errln("Minimum integer digits : " + sdf
->getMinimumIntegerDigits());
1312 /* @bug 4052223 (API addition request A27)
1313 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1315 void NumberFormatRegressionTest::Test4052223(void)
1318 UErrorCode status
= U_ZERO_ERROR
;
1319 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1320 if(U_FAILURE(status
)) {
1321 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1325 failure(status
, "new DecimalFormat");
1327 fmt
->parse(UnicodeString("abc3"), num
, status
);
1328 if(! U_FAILURE(status
))
1329 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1330 /*} catch (ParseException foo) {
1331 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1336 * API tests for API addition request A9.
1338 void NumberFormatRegressionTest::Test4061302(void)
1340 UErrorCode status
= U_ZERO_ERROR
;
1341 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1342 failure(status
, "new DecimalFormatSymbols");
1343 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1344 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1345 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1346 if (currency
== UnicodeString("") ||
1347 intlCurrency
== UnicodeString("") ||
1348 monDecSeparator
== UnicodeString(""))
1350 errln("getCurrencySymbols failed, got empty string.");
1352 UnicodeString monDecSeparatorStr
;
1353 monDecSeparatorStr
.append(monDecSeparator
);
1354 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1355 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1356 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1357 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1358 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1359 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1360 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1361 if (currency
!= UnicodeString("XYZ") ||
1362 intlCurrency
!= UnicodeString("ABC") ||
1363 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1364 errln("setCurrencySymbols failed.");
1366 monDecSeparatorStr
.remove();
1367 monDecSeparatorStr
.append(monDecSeparator
);
1368 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1373 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1374 * FieldPosition.getEndIndex.
1376 void NumberFormatRegressionTest::Test4062486(void)
1378 UErrorCode status
= U_ZERO_ERROR
;
1379 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1380 failure(status
, "new DecimalFormat");
1381 UnicodeString formatted
;
1382 FieldPosition
field(0);
1383 double num
= 1234.5;
1384 fmt
->format(num
, formatted
, field
);
1385 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1386 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1387 field
.setBeginIndex(7);
1388 field
.setEndIndex(4);
1389 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1390 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1396 * DecimalFormat.parse incorrectly works with a group separator.
1398 void NumberFormatRegressionTest::Test4108738(void)
1400 UErrorCode status
= U_ZERO_ERROR
;
1401 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1402 failure(status
, "new DecimalFormatSymbols");
1403 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1404 if(U_FAILURE(status
)) {
1405 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1409 failure(status
, "new DecimalFormat");
1410 UnicodeString
text("1.222,111");
1412 ParsePosition
pp(0);
1413 df
->parse(text
, num
, pp
);
1415 // {sfb} how to do this (again) ?
1416 // shouldn't just be another round-trip test, should it?
1418 FieldPosition
pos(FieldPosition::DONT_CARE
);
1419 temp
= df
->format(num
.getDouble(), temp
, pos
);
1420 //if (!num.toString().equals("1.222"))
1421 if (temp
!= UnicodeString("1.222"))
1422 //errln("\"" + text + "\" is parsed as " + num);
1423 errln("\"" + text
+ "\" is parsed as " + temp
);
1424 text
= UnicodeString("1.222x111");
1425 pp
= ParsePosition(0);
1426 df
->parse(text
, num
, pp
);
1428 temp
= df
->format(num
.getDouble(), temp
, pos
);
1429 //if (!num.toString().equals("1.222"))
1430 if (temp
!= UnicodeString("1.222"))
1431 errln("\"" + text
+ "\" is parsed as " + temp
);
1437 * DecimalFormat.format() incorrectly formats negative doubles.
1439 void NumberFormatRegressionTest::Test4106658(void)
1441 UErrorCode status
= U_ZERO_ERROR
;
1442 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1443 if(U_FAILURE(status
)) {
1444 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1448 failure(status
, "new DecimalFormat");
1449 volatile double d1
= 0.0; // volatile to prevent code optimization
1450 double d2
= -0.0001;
1451 UnicodeString buffer
;
1453 FieldPosition
pos(FieldPosition::DONT_CARE
);
1455 #if U_PLATFORM == U_PF_HPUX
1456 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1458 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1460 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1461 df
->format(d1
, buffer
, pos
);
1462 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1463 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1465 df
->format(d2
, buffer
, pos
);
1466 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1467 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1473 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1475 void NumberFormatRegressionTest::Test4106662(void)
1477 UErrorCode status
= U_ZERO_ERROR
;
1478 DecimalFormat
*df
= new DecimalFormat(status
);
1479 if(U_FAILURE(status
)) {
1480 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1484 failure(status
, "new DecimalFormat");
1485 UnicodeString
text("x");
1486 ParsePosition
pos1(0), pos2(0);
1489 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1491 df
->parse(text
, num
, pos1
);
1492 if (pos1
== ParsePosition(0)/*num != null*/) {
1493 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1496 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1497 failure(status
, "new DecimalFormat");
1498 df
->parse(UnicodeString("$"), num
, pos2
);
1499 if (pos2
== ParsePosition(0) /*num != null*/){
1500 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1506 /* @bug 4114639 (duplicate of 4106662)
1507 * NumberFormat.parse doesn't return null
1509 void NumberFormatRegressionTest::Test4114639(void)
1511 UErrorCode status
= U_ZERO_ERROR
;
1512 NumberFormat
*format
= NumberFormat::createInstance(status
);
1513 if(U_FAILURE(status
)) {
1514 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1518 failure(status
, "NumberFormat::createInstance");
1519 UnicodeString
text("time 10:x");
1520 ParsePosition
pos(8);
1522 format
->parse(text
, result
, pos
);
1523 if (/*result != null*/pos
.getErrorIndex() != 8)
1524 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1530 * TODO: this test does not work because we need to use a 64 bit number and a
1531 * a double only MAY only have 52 bits of precision.
1532 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1534 void NumberFormatRegressionTest::Test4106664(void)
1536 UErrorCode status
= U_ZERO_ERROR
;
1537 DecimalFormat
*df
= new DecimalFormat(status
);
1538 if(U_FAILURE(status
)) {
1539 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1543 failure(status
, "new DecimalFormat");
1544 // {sfb} long in java is 64 bits
1545 /*long*/double n
= 1234567890123456.0;
1546 /*int*/int32_t m
= 12345678;
1547 // {sfb} will this work?
1548 //BigInteger bigN = BigInteger.valueOf(n);
1549 //bigN = bigN.multiply(BigInteger.valueOf(m));
1550 double bigN
= n
* m
;
1551 df
->setMultiplier(m
);
1552 df
->setGroupingUsed(FALSE
);
1554 FieldPosition
pos(FieldPosition::DONT_CARE
);
1555 logln("formated: " +
1556 df
->format(n
, temp
, pos
));
1559 sprintf(buf
, "%g", bigN
);
1560 //logln("expected: " + bigN.toString());
1561 logln(UnicodeString("expected: ") + buf
);
1565 /* @bug 4106667 (duplicate of 4106658)
1566 * DecimalFormat.format incorrectly formats -0.0.
1568 void NumberFormatRegressionTest::Test4106667(void)
1570 UErrorCode status
= U_ZERO_ERROR
;
1571 DecimalFormat
*df
= new DecimalFormat(status
);
1572 if(U_FAILURE(status
)) {
1573 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1577 failure(status
, "new DecimalFormat");
1578 UChar foo
[] = { 0x002B };
1579 UnicodeString
bar(foo
, 1, 1);
1580 volatile double d
= 0.0; // volatile to prevent code optimization
1582 UnicodeString buffer
;
1583 FieldPosition
pos(FieldPosition::DONT_CARE
);
1585 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1586 #if U_PLATFORM == U_PF_HPUX
1587 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1589 d
*= -1.0; // Some compilers have a problem with defining -0.0
1591 df
->setPositivePrefix(/*"+"*/bar
);
1592 df
->format(d
, buffer
, pos
);
1593 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1594 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1600 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1602 #if U_PLATFORM == U_PF_OS390
1603 # define MAX_INT_DIGITS 70
1605 # define MAX_INT_DIGITS 128
1608 void NumberFormatRegressionTest::Test4110936(void)
1610 UErrorCode status
= U_ZERO_ERROR
;
1611 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1612 if(U_FAILURE(status
)) {
1613 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1617 failure(status
, "NumberFormat::createInstance");
1618 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1619 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1620 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1621 errln("getMaximumIntegerDigits() returns " +
1622 nf
->getMaximumIntegerDigits());
1628 * Locale data should use generic currency symbol
1630 * 1) Make sure that all currency formats use the generic currency symbol.
1631 * 2) Make sure we get the same results using the generic symbol or a
1634 void NumberFormatRegressionTest::Test4122840(void)
1637 const Locale
*locales
= Locale::getAvailableLocales(count
);
1639 for (int i
= 0; i
< count
; i
++) {
1640 UErrorCode status
= U_ZERO_ERROR
;
1641 ResourceBundle
*rb
= new ResourceBundle(
1642 NULL
/*"java.text.resources.LocaleElements"*/,
1643 locales
[i
], status
);
1644 failure(status
, "new ResourceBundle");
1645 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1646 failure(status
, "rb.get(NumberElements)");
1647 numPat
= numPat
.getWithFallback("latn",status
);
1648 failure(status
, "rb.get(latn)");
1649 numPat
= numPat
.getWithFallback("patterns",status
);
1650 failure(status
, "rb.get(patterns)");
1651 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1652 failure(status
, "rb.get(currencyFormat)");
1654 // Get the currency pattern for this locale. We have to fish it
1655 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1656 // will return the localized symbol, not \00a4
1658 UnicodeString pattern
= numPat
.getString(status
);
1659 failure(status
, "rb->getString()");
1661 UChar fo
[] = { 0x00A4 };
1662 UnicodeString
foo(fo
, 1, 1);
1664 //if (pattern.indexOf("\u00A4") == -1 ) {
1665 if (pattern
.indexOf(foo
) == -1 ) {
1666 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1667 " does not contain generic currency symbol:" +
1671 // Create a DecimalFormat using the pattern we got and format a number
1672 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1673 failure(status
, "new DecimalFormatSymbols");
1674 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1675 failure(status
, "new DecimalFormat");
1677 UnicodeString result1
;
1678 FieldPosition
pos(FieldPosition::DONT_CARE
);
1679 result1
= fmt1
->format(1.111, result1
, pos
);
1682 // Now substitute in the locale's currency symbol and create another
1683 // pattern. We have to skip locales where the currency symbol
1684 // contains decimal separators, because that confuses things
1686 UChar ba
[] = { 0x002E/*'.'*/ };
1687 UnicodeString
bar(ba
, 1, 1);
1689 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1690 // {sfb} Also, switch the decimal separator to the monetary decimal
1691 // separator to mimic the behavior of a currency format
1692 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1693 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1695 UnicodeString
buf(pattern
);
1696 for (int j
= 0; j
< buf
.length(); j
++) {
1697 if (buf
[j
] == 0x00a4 ) {
1698 if(buf
[j
+ 1] == 0x00a4) {
1699 // {sfb} added to support double currency marker (intl currency sign)
1700 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1701 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1704 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1705 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1710 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1711 failure(status
, "new DecimalFormat");
1713 // Get the currency (if there is one) so we can set the rounding and fraction
1714 const UChar
*currency
= fmt1
->getCurrency();
1715 if (*currency
!= 0) {
1716 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1717 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1718 if (U_SUCCESS(status
)) {
1719 fmt2
->setRoundingIncrement(rounding
);
1720 fmt2
->setMinimumFractionDigits(frac
);
1721 fmt2
->setMaximumFractionDigits(frac
);
1724 failure(status
, "Fetching currency rounding/fractions");
1728 UnicodeString result2
;
1729 fmt2
->format(1.111, result2
, pos
);
1731 if (result1
!= result2
) {
1732 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1733 result1
+ " vs " + result2
);
1746 * DecimalFormat.format() delivers wrong string.
1748 void NumberFormatRegressionTest::Test4125885(void)
1750 UErrorCode status
= U_ZERO_ERROR
;
1751 double rate
= 12.34;
1752 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1753 if(U_FAILURE(status
)) {
1754 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1758 failure(status
, "new DecimalFormat");
1760 logln("toPattern: " + formatDec
->toPattern(temp
));
1761 UnicodeString rateString
;
1762 FieldPosition
pos(FieldPosition::DONT_CARE
);
1763 rateString
= formatDec
->format(rate
, rateString
, pos
);
1764 if (rateString
!= UnicodeString("012.34"))
1765 errln("result : " + rateString
+ " expected : 012.34");
1767 delete formatDec
;// = null;
1768 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1769 failure(status
, "new DecimalFormat");
1770 logln("toPattern: " + formatDec
->toPattern(temp
));
1771 rateString
.remove();
1772 rateString
= formatDec
->format(rate
, rateString
, pos
);
1773 if (rateString
!= UnicodeString("+012.34%"))
1774 errln("result : " + rateString
+ " expected : +012.34%");
1781 * DecimalFormat produces extra zeros when formatting numbers.
1783 void NumberFormatRegressionTest::Test4134034(void)
1785 UErrorCode status
= U_ZERO_ERROR
;
1786 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1787 if (!failure(status
, "new DecimalFormat")) {
1789 FieldPosition
pos(FieldPosition::DONT_CARE
);
1790 f
= nf
->format(9.02, f
, pos
);
1791 if (f
== UnicodeString("9.02"))
1794 errln("9.02 -> " + f
+ "; want 9.02");
1797 f
= nf
->format((int32_t)0, f
, pos
);
1798 if (f
== UnicodeString(".00"))
1801 errln("0 -> " + f
+ "; want .00");
1809 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1810 * a duplicate of 4134034.
1812 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1813 * Possibly related to bug 4125885.
1815 * This class demonstrates a regression in version 1.1.6
1816 * of DecimalFormat class.
1819 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1820 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1821 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1822 * Value 1.2 Format #0.0# Result '1.2'
1823 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1826 * Value 1.2 Format #.00 Result '1.20'
1827 * Value 1.2 Format 0.00 Result '1.20'
1828 * Value 1.2 Format 00.00 Result '01.20'
1829 * Value 1.2 Format #0.0# Result '1.2'
1830 * Value 1.2 Format #0.00 Result '1.20'
1832 void NumberFormatRegressionTest::Test4134300(void) {
1833 UnicodeString DATA
[] = {
1834 // Pattern Expected string
1835 UnicodeString("#.00"), UnicodeString("1.20"),
1836 UnicodeString("0.00"), UnicodeString("1.20"),
1837 UnicodeString("00.00"), UnicodeString("01.20"),
1838 UnicodeString("#0.0#"), UnicodeString("1.2"),
1839 UnicodeString("#0.00"), UnicodeString("1.20")
1842 for (int i
=0; i
< 10; i
+=2) {
1843 UnicodeString result
;
1844 UErrorCode status
= U_ZERO_ERROR
;
1845 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1846 if (!failure(status
, "new DecimalFormat")) {
1847 FieldPosition
pos(FieldPosition::DONT_CARE
);
1848 result
= df
->format(1.2, result
, pos
);
1849 if (result
!= DATA
[i
+1]) {
1850 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1851 "; want " + DATA
[i
+1]);
1854 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1864 * Empty pattern produces double negative prefix.
1866 void NumberFormatRegressionTest::Test4140009(void)
1868 UErrorCode status
= U_ZERO_ERROR
;
1869 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
1870 failure(status
, "new DecimalFormatSymbols");
1871 DecimalFormat
*f
= new DecimalFormat(UnicodeString(""), syms
, status
);
1872 if (!failure(status
, "new DecimalFormat")) {
1874 FieldPosition
pos(FieldPosition::DONT_CARE
);
1875 s
= f
->format(123.456, s
, pos
);
1876 if (s
!= UnicodeString("123.456"))
1877 errln("Fail: Format empty pattern x 123.456 => " + s
);
1879 s
= f
->format(-123.456, s
, pos
);
1880 if (s
!= UnicodeString("-123.456"))
1881 errln("Fail: Format empty pattern x -123.456 => " + s
);
1888 * BigDecimal numbers get their fractions truncated by NumberFormat.
1890 // {sfb} not pertinent in C++ ??
1891 void NumberFormatRegressionTest::Test4141750(void) {
1893 UnicodeString str("12345.67");
1894 BigDecimal bd = new BigDecimal(str);
1895 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1896 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1898 catch (Exception e) {
1899 errln(e.toString());
1900 e.printStackTrace();
1906 * DecimalFormat toPattern() doesn't quote special characters or handle
1909 void NumberFormatRegressionTest::Test4145457() {
1911 UErrorCode status
= U_ZERO_ERROR
;
1912 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1913 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1917 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1919 errln("DecimalFormat needed to continue");
1923 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1924 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1925 nf
->setDecimalFormatSymbols(*sym
);
1926 double pi
= 3.14159;
1928 UnicodeString PATS
[] = {
1929 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1932 for (int32_t i
=0; i
<2; ++i
) {
1933 nf
->applyPattern(PATS
[i
], status
);
1934 failure(status
, "nf->applyPattern");
1936 FieldPosition
pos(FieldPosition::DONT_CARE
);
1937 out
= nf
->format(pi
, out
, pos
);
1939 pat
= nf
->toPattern(pat
);
1941 ParsePosition
pp(0);
1942 nf
->parse(out
, num
, pp
);
1943 double val
= num
.getDouble();
1945 nf
->applyPattern(pat
, status
);
1946 failure(status
, "nf->applyPattern");
1948 out2
= nf
->format(pi
, out2
, pos
);
1950 pat2
= nf
->toPattern(pat2
);
1952 nf
->parse(out2
, num
, pp
);
1953 double val2
= num
.getDouble();
1956 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1957 pat
+ "\" vs. \"" + pat2
+ "\"");
1959 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1961 if (val
== val2
&& out
== out2
) {
1962 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1963 out
+ "\" -> " + val
+ " -> \"" +
1964 out2
+ "\" -> " + val2
);
1967 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1968 out
+ "\" -> " + val
+ " -> \"" +
1969 out2
+ "\" -> " + val2
);
1973 catch (ParseException e) {
1974 errln("Fail: " + e);
1975 e.printStackTrace();
1983 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
1985 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
1987 void NumberFormatRegressionTest::Test4147295(void)
1989 UErrorCode status
= U_ZERO_ERROR
;
1990 DecimalFormat
*sdf
= new DecimalFormat(status
);
1991 UnicodeString
pattern("#,###");
1992 logln("Applying pattern \"" + pattern
+ "\"");
1993 sdf
->applyPattern(pattern
, status
);
1994 if (!failure(status
, "sdf->applyPattern")) {
1995 int minIntDig
= sdf
->getMinimumIntegerDigits();
1996 if (minIntDig
!= 0) {
1997 errln("Test failed");
1998 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2000 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2002 logln("Test passed");
2003 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2011 * DecimalFormat formats -0.0 as +0.0
2012 * See also older related bug 4106658, 4106667
2014 void NumberFormatRegressionTest::Test4147706(void)
2016 UErrorCode status
= U_ZERO_ERROR
;
2017 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2018 failure(status
, "new DecimalFormat");
2019 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2020 if (!failure(status
, "new DecimalFormatSymbols")) {
2022 UnicodeString f2
, temp
;
2023 FieldPosition
pos(FieldPosition::DONT_CARE
);
2024 volatile double d1
= 0.0; // volatile to prevent code optimization
2025 double d2
= -0.0001;
2027 #if U_PLATFORM == U_PF_HPUX
2028 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2030 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2032 df
->adoptDecimalFormatSymbols(syms
);
2033 f1
= df
->format(d1
, f1
, pos
);
2034 f2
= df
->format(d2
, f2
, pos
);
2035 if (f1
!= UnicodeString("-0.0")) {
2036 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2038 if (f2
!= UnicodeString("-0.0")) {
2039 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2047 // Not applicable, since no serialization in C++
2048 /*class myformat implements Serializable
2050 DateFormat _dateFormat = DateFormat.getDateInstance();
2054 GregorianCalendar calendar = new GregorianCalendar();
2055 Date t = calendar.getTime();
2056 String nowStr = _dateFormat.format(t);
2063 * NumberFormat cannot format Double.MAX_VALUE
2065 // TODO: make this test actually test something
2067 NumberFormatRegressionTest::Test4162198(void)
2069 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2070 double dbl
= INT32_MAX
* 1000.0;
2071 UErrorCode status
= U_ZERO_ERROR
;
2072 NumberFormat
*f
= NumberFormat::createInstance(status
);
2073 if(U_FAILURE(status
)) {
2074 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2077 f
->setMaximumFractionDigits(INT32_MAX
);
2078 f
->setMaximumIntegerDigits(INT32_MAX
);
2081 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2084 f
->parse(s
, n
, status
);
2085 if(U_FAILURE(status
))
2086 errln("Couldn't parse!");
2087 //} catch (java.text.ParseException e) {
2088 // errln("Caught a ParseException:");
2089 // e.printStackTrace();
2092 //logln("The string " + s + " parsed as " + n);
2094 // {dlf} The old code assumes n is a double, but it isn't any more...
2095 // Formattable apparently does not and never did interconvert... too bad.
2096 //if(n.getDouble() != dbl) {
2097 // errln("Round trip failure");
2099 if (n
.getInt64() != dbl
) {
2100 errln("Round trip failure");
2108 * NumberFormat does not parse negative zero.
2111 NumberFormatRegressionTest::Test4162852(void)
2113 UErrorCode status
= U_ZERO_ERROR
;
2114 for(int32_t i
=0; i
< 2; ++i
) {
2115 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2116 : NumberFormat::createPercentInstance(status
);
2117 if(U_FAILURE(status
)) {
2118 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2126 f
->parse(s
, n
, status
);
2127 if(U_FAILURE(status
))
2128 errln("Couldn't parse!");
2129 double e
= n
.getDouble();
2130 logln(UnicodeString("") +
2132 '"' + s
+ '"' + " -> " + e
);
2133 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2136 if (e
!= 0.0 || 1.0/e
> 0.0) {
2138 logln("Failed to parse negative zero");
2144 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2147 * May 17 1999 sync up - liu
2149 * NumberFormat truncates data
2151 void NumberFormatRegressionTest::Test4167494(void) {
2152 UErrorCode status
= U_ZERO_ERROR
;
2153 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2154 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2159 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2163 fmt
->parse(s
, num
, status
);
2164 failure(status
, "Parse");
2165 if (num
.getType() == Formattable::kDouble
&&
2166 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2167 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2168 toString(num
) + " ok");
2170 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2171 toString(num
) + " FAIL");
2174 // We don't test Double.MIN_VALUE because the locale data for the US
2175 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2176 // This is correct for now; however, we leave this here as a reminder
2177 // in case we want to address this later.
2183 * May 17 1999 sync up - liu
2185 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2187 void NumberFormatRegressionTest::Test4170798(void) {
2188 UErrorCode status
= U_ZERO_ERROR
;
2189 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2190 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2194 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2196 errln("DecimalFormat needed to continue");
2199 df
->setParseIntegerOnly(TRUE
);
2201 ParsePosition
pos(0);
2202 df
->parse("-0.0", n
, pos
);
2203 if (n
.getType() != Formattable::kLong
2204 || n
.getLong() != 0) {
2205 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n
));
2211 * May 17 1999 sync up - liu
2212 * toPattern only puts the first grouping separator in.
2214 void NumberFormatRegressionTest::Test4176114(void) {
2215 const char* DATA
[] = {
2217 "000", "#000", // No grouping
2218 "#000", "#000", // No grouping
2222 "00,000", "#00,000",
2223 "000,000", "#,000,000",
2224 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2226 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2227 UErrorCode status
= U_ZERO_ERROR
;
2229 for (int i
=0; i
<DATA_length
; i
+=2) {
2230 DecimalFormat
df(DATA
[i
], status
);
2231 if (!failure(status
, "DecimalFormat constructor")) {
2233 UnicodeString
exp(DATA
[i
+1]);
2235 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2236 s
+ ", want " + exp
);
2243 * May 17 1999 sync up - liu
2245 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2247 void NumberFormatRegressionTest::Test4179818(void) {
2248 const char* DATA
[] = {
2249 // Input Pattern Expected output
2250 "1.2511", "#.#", "1.3",
2251 "1.2501", "#.#", "1.3",
2254 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2260 UErrorCode status
= U_ZERO_ERROR
;
2261 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2262 failure(status
, "Construct DecimalFormatSymbols");
2263 DecimalFormat
fmt("#", sym
, status
);
2264 if (!failure(status
, "Construct DecimalFormat")) {
2265 for (int i
=0; i
<DATA_length
; i
+=3) {
2266 double in
= DOUBLE
[i
/3];
2267 UnicodeString
pat(DATA
[i
+1]);
2268 UnicodeString
exp(DATA
[i
+2]);
2269 fmt
.applyPattern(pat
, status
);
2270 failure(status
, "applyPattern");
2273 fmt
.format(in
, out
, pos
);
2275 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2277 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2278 ", expected " + exp
);
2285 * May 17 1999 sync up - liu
2286 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2287 * This includes the minus sign, currency symbol, international currency
2288 * symbol, percent, and permille. This is filed as bugs 4212072 and
2291 void NumberFormatRegressionTest::Test4212072(void) {
2292 UErrorCode status
= U_ZERO_ERROR
;
2293 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2295 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2296 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2297 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2304 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2305 fmt
.setDecimalFormatSymbols(sym
);
2307 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2308 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2312 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2313 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2316 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2318 fmt
.applyPattern(UnicodeString("#%"), status
);
2319 failure(status
, "applyPattern percent");
2320 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2321 fmt
.setDecimalFormatSymbols(sym
);
2323 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2324 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2328 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2329 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2332 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2334 fmt
.applyPattern(str("#\\u2030"), status
);
2335 failure(status
, "applyPattern permill");
2336 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2337 fmt
.setDecimalFormatSymbols(sym
);
2339 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2340 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2344 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2345 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2348 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2350 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2351 failure(status
, "applyPattern currency");
2352 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2353 fmt
.setDecimalFormatSymbols(sym
);
2355 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) {
2356 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2360 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2361 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2364 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2366 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2367 failure(status
, "applyPattern intl currency");
2368 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2369 fmt
.setDecimalFormatSymbols(sym
);
2371 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) {
2372 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2376 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2377 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2380 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2382 // Since the pattern logic has changed, make sure that patterns round
2383 // trip properly. Test stream in/out integrity too.
2385 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2386 static const char* type
[] = {
2391 for (int i
=0; i
<n
; ++i
) {
2392 for (int j
=0; j
<3; ++j
) {
2393 status
= U_ZERO_ERROR
;
2397 nf
= NumberFormat::createInstance(avail
[i
], status
);
2398 failure(status
, "createInstance", avail
[i
]);
2401 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2402 failure(status
, "createCurrencyInstance", avail
[i
]);
2405 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2406 failure(status
, "createPercentInstance", avail
[i
]);
2409 if (U_FAILURE(status
)) {
2412 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2414 // Test toPattern/applyPattern round trip
2417 DecimalFormatSymbols
symb(avail
[i
], status
);
2418 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2419 DecimalFormat
f2(pat
, symb
, status
);
2421 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2426 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2428 "\" -> \"" + f2
.toPattern(p
) + "\"");
2431 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2436 // Test toLocalizedPattern/applyLocalizedPattern round trip
2437 df
->toLocalizedPattern(pat
);
2438 f2
.applyLocalizedPattern(pat
, status
);
2440 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2441 if (U_FAILURE(status
)) {
2445 // Make sure we set the currency attributes appropriately
2446 if (j
== 1) { // Currency format
2447 f2
.setCurrency(f2
.getCurrency(), status
);
2450 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2451 if (U_FAILURE(status
)) {
2457 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2458 " -> localized \"" + pat
+
2459 "\" -> \"" + f2
.toPattern(p
) + "\"");
2464 // Test writeObject/readObject round trip
2465 // NOT ON ICU -- Java only
2471 * May 17 1999 sync up - liu
2472 * DecimalFormat.parse() fails for mulipliers 2^n.
2474 void NumberFormatRegressionTest::Test4216742(void) {
2475 UErrorCode status
= U_ZERO_ERROR
;
2476 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2477 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2481 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2482 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2483 for (int i
=0; i
<DATA_length
; ++i
) {
2484 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2485 for (int m
= 1; m
<= 100; m
++) {
2486 fmt
->setMultiplier(m
);
2488 fmt
->parse(str
, num
, status
);
2489 failure(status
, "parse", Locale::getUS());
2490 if (num
.getType() != Formattable::kLong
&&
2491 num
.getType() != Formattable::kDouble
) {
2492 errln(UnicodeString("FAIL: Wanted number, got ") +
2495 double d
= num
.getType() == Formattable::kDouble
?
2496 num
.getDouble() : (double) num
.getLong();
2497 if ((d
> 0) != (DATA
[i
] > 0)) {
2498 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2499 fmt
->getMultiplier() +
2500 ") => " + toString(num
));
2509 * May 17 1999 sync up - liu
2510 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2513 void NumberFormatRegressionTest::Test4217661(void) {
2514 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2515 const char* S
[] = { "0", "1", "0.01", "1.01" };
2516 int D_length
= (int)(sizeof(D
) / sizeof(D
[0]));
2517 UErrorCode status
= U_ZERO_ERROR
;
2518 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2519 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2523 fmt
->setMaximumFractionDigits(2);
2524 for (int i
=0; i
<D_length
; i
++) {
2526 fmt
->format(D
[i
], s
);
2527 if (s
!= UnicodeString(S
[i
])) {
2528 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2535 * alphaWorks upgrade
2537 void NumberFormatRegressionTest::Test4161100(void) {
2538 UErrorCode status
= U_ZERO_ERROR
;
2539 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2540 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2544 nf
->setMinimumFractionDigits(1);
2545 nf
->setMaximumFractionDigits(1);
2550 logln(UnicodeString() + a
+ " x " +
2551 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2552 if (s
!= UnicodeString("-0.1")) {
2559 * June 16 1999 sync up - liu
2560 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2562 void NumberFormatRegressionTest::Test4243011(void) {
2563 UErrorCode status
= U_ZERO_ERROR
;
2564 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2565 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2566 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2568 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2569 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2570 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2571 int32_t N
= (int32_t)(sizeof(NUM
) / sizeof(NUM
[0]));
2573 for (int32_t i
=0; i
<N
; ++i
) {
2575 UnicodeString
exp(STR
[i
]);
2577 fmt
.format(NUM
[i
], str
, pos
);
2579 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2581 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2589 * June 16 1999 sync up - liu
2590 * format(0.0) gives "0.1" if preceded by parse("99.99").
2591 * (Regression in 1.2.2 RC1)
2593 void NumberFormatRegressionTest::Test4243108(void) {
2594 UErrorCode status
= U_ZERO_ERROR
;
2595 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2596 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2597 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2598 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2605 fmt
.format(0.0, str
, pos
);
2606 UnicodeString
exp("0");
2608 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2610 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2616 fmt
.parse(str
, val
, status
);
2617 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2618 if (val
.getType() == Formattable::kDouble
&&
2619 val
.getDouble() == 99.99) {
2620 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2622 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2627 fmt
.format(0.0, str
, pos
);
2629 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2631 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2638 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2639 * NumberFormat objects.
2641 void NumberFormatRegressionTest::TestJ691(void) {
2642 UErrorCode status
= U_ZERO_ERROR
;
2643 Locale
loc("fr", "CH");
2645 // set up the input date string & expected output
2646 UnicodeString
udt("11.10.2000", "");
2647 UnicodeString
exp("11.10.00", "");
2649 // create a Calendar for this locale
2650 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2651 if (U_FAILURE(status
)) {
2652 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2656 // create a NumberFormat for this locale
2657 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2658 if (U_FAILURE(status
)) {
2659 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2663 // *** Here's the key: We don't want to have to do THIS:
2664 // nf->setParseIntegerOnly(TRUE);
2666 // create the DateFormat
2667 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2668 if (U_FAILURE(status
)) {
2669 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2673 df
->adoptCalendar(cal
);
2674 df
->adoptNumberFormat(nf
);
2676 // set parsing to lenient & parse
2677 df
->setLenient(TRUE
);
2678 UDate ulocdat
= df
->parse(udt
, status
);
2680 // format back to a string
2681 UnicodeString outString
;
2682 df
->format(ulocdat
, outString
);
2684 if (outString
!= exp
) {
2685 errln("FAIL: " + udt
+ " => " + outString
);
2691 //---------------------------------------------------------------------------
2693 // Error Checking / Reporting macros
2695 //---------------------------------------------------------------------------
2696 #define TEST_CHECK_STATUS(status) \
2697 if (U_FAILURE(status)) {\
2698 errln("File %s, Line %d. status=%s\n", __FILE__, __LINE__, u_errorName(status));\
2702 #define TEST_ASSERT(expr) \
2703 if ((expr)==FALSE) {\
2704 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2708 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2710 void NumberFormatRegressionTest::Test8199(void) {
2711 UErrorCode status
= U_ZERO_ERROR
;
2712 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2714 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2717 TEST_CHECK_STATUS(status
);
2719 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2720 // should always truncate, no other rounding scheme.
2722 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2724 nf
->parse(numStr
, val
, status
);
2725 TEST_CHECK_STATUS(status
);
2726 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2727 TEST_ASSERT(1000000000 == val
.getInt64(status
));
2728 TEST_CHECK_STATUS(status
);
2729 TEST_ASSERT(1000000000.6 == val
.getDouble(status
));
2730 TEST_CHECK_STATUS(status
);
2732 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2733 // than int64 because of the fraction
2734 // even though int64 is more precise.
2735 nf
->parse(numStr
, val
, status
);
2736 TEST_CHECK_STATUS(status
);
2737 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2738 TEST_ASSERT(100000000000000001LL == val
.getInt64(status
));
2739 TEST_CHECK_STATUS(status
);
2740 TEST_ASSERT(100000000000000000.0 == val
.getDouble(status
));
2741 TEST_CHECK_STATUS(status
);
2743 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2744 nf
->parse(numStr
, val
, status
);
2745 TEST_CHECK_STATUS(status
);
2746 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2747 TEST_ASSERT(100000000000000000LL == val
.getInt64());
2748 TEST_ASSERT(1.0E17
== val
.getDouble(status
));
2749 TEST_CHECK_STATUS(status
);
2751 numStr
= "9223372036854775807"; // largest int64_t
2752 nf
->parse(numStr
, val
, status
);
2753 TEST_CHECK_STATUS(status
);
2754 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2755 TEST_ASSERT(9223372036854775807LL == val
.getInt64());
2756 // In the following check, note that a substantial range of integers will
2757 // convert to the same double value. There are also platform variations
2758 // in the rounding at compile time of double constants.
2759 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2760 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2761 TEST_CHECK_STATUS(status
);
2763 numStr
= "-9223372036854775808"; // smallest int64_t
2764 nf
->parse(numStr
, val
, status
);
2765 TEST_CHECK_STATUS(status
);
2766 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2767 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2768 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64());
2769 TEST_ASSERT(-9223372036854775808.0 == val
.getDouble(status
));
2770 TEST_CHECK_STATUS(status
);
2772 numStr
= "9223372036854775808"; // largest int64_t + 1
2773 nf
->parse(numStr
, val
, status
);
2774 TEST_CHECK_STATUS(status
);
2775 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2776 TEST_ASSERT(9223372036854775807LL == val
.getInt64(status
));
2777 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2778 status
= U_ZERO_ERROR
;
2779 TEST_ASSERT(9223372036854775810.0 == val
.getDouble(status
));
2780 TEST_CHECK_STATUS(status
);
2782 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2783 nf
->parse(numStr
, val
, status
);
2784 TEST_CHECK_STATUS(status
);
2785 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2786 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings
2787 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64(status
));
2788 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2789 status
= U_ZERO_ERROR
;
2790 TEST_ASSERT(-9223372036854775810.0 == val
.getDouble(status
));
2791 TEST_CHECK_STATUS(status
);
2793 // Test values near the limit of where doubles can represent all integers.
2794 // The implementation strategy of getInt64() changes at this boundary.
2795 // Strings to be parsed include a decimal fraction to force them to be
2796 // parsed as doubles rather than ints. The fraction is discarded
2797 // from the parsed double value because it is beyond what can be represented.
2799 status
= U_ZERO_ERROR
;
2800 numStr
= "9007199254740991.1"; // largest 53 bit int
2801 nf
->parse(numStr
, val
, status
);
2802 TEST_CHECK_STATUS(status
);
2803 // printf("getInt64() returns %lld\n", val.getInt64(status));
2804 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2805 TEST_ASSERT(9007199254740991LL == val
.getInt64(status
));
2806 TEST_ASSERT(9007199254740991.0 == val
.getDouble(status
));
2807 TEST_CHECK_STATUS(status
);
2809 status
= U_ZERO_ERROR
;
2810 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2811 nf
->parse(numStr
, val
, status
);
2812 TEST_CHECK_STATUS(status
);
2813 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2814 TEST_ASSERT(9007199254740992LL == val
.getInt64(status
));
2815 TEST_ASSERT(9007199254740992.0 == val
.getDouble(status
));
2816 TEST_CHECK_STATUS(status
);
2818 status
= U_ZERO_ERROR
;
2819 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2820 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2821 TEST_CHECK_STATUS(status
);
2822 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2823 TEST_ASSERT(9007199254740993LL == val
.getInt64(status
));
2824 TEST_ASSERT(9007199254740994.0 == val
.getDouble(status
));
2825 TEST_CHECK_STATUS(status
);
2830 void NumberFormatRegressionTest::Test9109(void) {
2831 UErrorCode status
= U_ZERO_ERROR
;
2834 DecimalFormat
fmt("+##", status
);
2835 fmt
.setLenient(TRUE
);
2837 if (U_FAILURE(status
)) {
2838 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2841 UnicodeString
text("123");
2842 int32_t expected
= 123;
2845 fmt
.parse(text
, val
, pos
);
2846 if (pos
.getErrorIndex() >= 0) {
2847 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2848 } else if (val
.getLong() != 123) {
2849 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2850 } else if (pos
.getIndex() != 3) {
2851 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2855 #endif /* #if !UCONFIG_NO_FORMATTING */