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
,
32 FieldPositionIterator
* posIter
,
33 UErrorCode
& status
) const
35 return NumberFormat::format(number
, toAppendTo
, posIter
, 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
);
176 default: name
= ""; break;
181 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
183 if(U_FAILURE(status
)) {
184 if (possibleDataError
) {
185 dataerrln(UnicodeString("FAIL: ", "") + msg
186 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
188 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
189 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
198 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
200 if(U_FAILURE(status
)) {
201 if (possibleDataError
) {
202 dataerrln(UnicodeString("FAIL: ", "") + msg
203 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
205 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
206 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
215 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
217 if(U_FAILURE(status
)) {
218 if (possibleDataError
) {
219 dataerrln(UnicodeString("FAIL: ", "") + msg
220 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
222 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
223 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
232 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
234 inline UnicodeString
str(const char *input
)
236 return CharsToUnicodeString(input
);
240 * NumberFormat.equals comparing with null should always return false.
242 // {sfb} kind of silly in C++, just checking for new success
243 void NumberFormatRegressionTest::Test4075713(void)
246 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
248 logln("NumberFormat.equals passed");
249 /*} catch (NullPointerException e) {
250 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
257 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
260 void NumberFormatRegressionTest::Test4074620(void)
263 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
264 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
266 nf1
->setGroupingUsed(FALSE
);
267 nf2
->setGroupingUsed(TRUE
);
270 errln("Test for bug 4074620 failed");
272 logln("Test for bug 4074620 passed.");
280 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
283 void NumberFormatRegressionTest::Test4088161 (void)
285 UErrorCode status
= U_ZERO_ERROR
;
286 DecimalFormat
*df
= new DecimalFormat(status
);
287 if (!failure(status
, "new DecimalFormat", "")) {
289 df
->setMinimumFractionDigits(0);
290 df
->setMaximumFractionDigits(16);
292 FieldPosition
fp1(0);
293 logln(UnicodeString("d = ") + d
);
294 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
296 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
297 df
->setMaximumFractionDigits(17);
299 FieldPosition
fp2(0);
300 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
301 sBuf2
= df
->format(d
, sBuf2
, fp2
);
303 errln(" format(d) = '" + sBuf2
+ "'");
310 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
311 * DecimalFormat(String, DecimalFormatSymbols).
313 void NumberFormatRegressionTest::Test4087245 (void)
315 UErrorCode status
= U_ZERO_ERROR
;
316 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
317 failure(status
, "new DecimalFormatSymbols", "");
318 // {sfb} One note about this test: if you pass in a pointer
319 // to the symbols, they are adopted and this test will fail,
320 // even though that is the correct behavior. To test the cloning
321 // of the symbols, it is necessary to pass in a reference to the symbols
322 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
323 failure(status
, "new DecimalFormat with symbols", "");
327 FieldPosition
pos(FieldPosition::DONT_CARE
);
328 logln(UnicodeString("format(") + n
+ ") = " +
329 df
->format(n
, buf1
, pos
));
330 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
331 logln(UnicodeString("format(") + n
+ ") = " +
332 df
->format(n
, buf2
, pos
));
334 errln("Test for bug 4087245 failed");
341 * DecimalFormat.format() incorrectly formats 0.0
343 void NumberFormatRegressionTest::Test4087535 (void)
345 UErrorCode status
= U_ZERO_ERROR
;
346 DecimalFormat
*df
= new DecimalFormat(status
);
347 failure(status
, "new DecimalFormat", "");
348 df
->setMinimumIntegerDigits(0);
351 UnicodeString buffer
;
352 FieldPosition
pos(FieldPosition::DONT_CARE
);
353 buffer
= df
->format(n
, buffer
, pos
);
354 if (buffer
.length() == 0)
355 errln(/*n + */": '" + buffer
+ "'");
357 buffer
= df
->format(n
, buffer
, pos
);
358 if (buffer
.length() == 0)
359 errln(/*n + */": '" + buffer
+ "'");
365 * DecimalFormat.format fails when groupingSize is set to 0.
367 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
368 void NumberFormatRegressionTest::Test4088503 (void)
370 UErrorCode status
= U_ZERO_ERROR
;
371 DecimalFormat
*df
= new DecimalFormat(status
);
372 failure(status
, "new DecimalFormat", "");
373 df
->setGroupingSize(0);
375 FieldPosition
fp(FieldPosition::DONT_CARE
);
377 logln(df
->format((int32_t)123, sBuf
, fp
));
378 //if(fp == FieldPosition(0))
379 // errln("Test for bug 4088503 failed.");
380 /*} catch (Exception foo) {
381 errln("Test for bug 4088503 failed.");
387 * NumberFormat.getCurrencyInstance is wrong.
389 void NumberFormatRegressionTest::Test4066646 (void)
391 assignFloatValue(2.04f
);
392 assignFloatValue(2.03f
);
393 assignFloatValue(2.02f
);
394 assignFloatValue(0.0f
);
398 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
400 logln(UnicodeString(" VALUE ") + returnfloat
);
401 UErrorCode status
= U_ZERO_ERROR
;
402 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
403 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
407 nfcommon
->setGroupingUsed(FALSE
);
409 UnicodeString stringValue
;
410 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
411 logln(" DISPLAYVALUE " + stringValue
);
413 nfcommon
->parse(stringValue
, result
, status
);
414 failure(status
, "nfcommon->parse", Locale::getUS());
415 float floatResult
= (float) (result
.getType() == Formattable::kDouble
416 ? result
.getDouble() : result
.getLong());
417 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
418 //String stringValue = nfcommon.format(returnfloat).substring(1);
419 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
420 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
424 } // End Of assignFloatValue()
427 * DecimalFormat throws exception when parsing "0"
429 void NumberFormatRegressionTest::Test4059870(void)
431 UErrorCode status
= U_ZERO_ERROR
;
432 DecimalFormat
*format
= new DecimalFormat("00", status
);
433 failure(status
, "new Decimalformat", Locale::getUS());
437 format
->parse(UnicodeString("0"), result
, status
);
438 failure(status
, "format->parse", Locale::getUS());
441 catch (Exception e) {
442 errln("Test for bug 4059870 failed : " + e);
448 * DecimalFormatSymbol.equals should always return false when
449 * comparing with null.
451 // {sfb} this is silly in C++
452 void NumberFormatRegressionTest::Test4083018 (void)
454 UErrorCode status
= U_ZERO_ERROR
;
455 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
456 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
459 logln("Test Passed!");
461 errln("Test for bug 4083018 failed");
462 /*} catch (Exception foo) {
463 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
470 * DecimalFormat does not round up correctly.
472 void NumberFormatRegressionTest::Test4071492 (void)
474 double x
= 0.00159999;
475 UErrorCode status
= U_ZERO_ERROR
;
476 NumberFormat
*nf
= NumberFormat::createInstance(status
);
477 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
481 nf
->setMaximumFractionDigits(4);
483 FieldPosition
pos(FieldPosition::DONT_CARE
);
484 out
= nf
->format(x
, out
, pos
);
485 logln("0.00159999 formats with 4 fractional digits to " + out
);
486 UnicodeString
expected("0.0016");
488 errln("FAIL: Expected " + expected
);
494 * A space as a group separator for localized pattern causes
495 * wrong format. WorkAround : use non-breaking space.
497 void NumberFormatRegressionTest::Test4086575(void)
499 UErrorCode status
= U_ZERO_ERROR
;
500 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
502 // TODO: There is not a good way to find out that the creation of this number format has
503 // failed. Major rewiring of format construction proposed.
504 if(U_FAILURE(status
)) {
505 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
509 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
511 // C++ workaround to make sure cast works
512 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
514 errln("NumberFormat::createInstance returned incorrect type.");
519 logln("nf toPattern1: " + nf
->toPattern(temp
));
520 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
522 // No group separator
523 logln("...applyLocalizedPattern ###,00;(###,00) ");
524 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
525 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
526 logln("nf toPattern2: " + nf
->toPattern(temp
));
527 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
529 FieldPosition
pos(FieldPosition::DONT_CARE
);
530 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
531 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
533 // Space as group separator
535 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
537 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
539 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
540 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
542 UnicodeString
pat(patChars
, 19, 19);
543 nf
->applyLocalizedPattern(pat
, status
);
544 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
545 logln("nf toPattern2: " + nf
->toPattern(temp
));
546 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
547 UnicodeString buffer
;
548 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
549 //if (buffer != UnicodeString("1\u00a0234,00"))
551 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
553 UnicodeString
cc(c
, 8, 8);
555 errln("nf : " + buffer
); // Expect 1 234,00
558 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
560 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
562 UnicodeString
cc1(c1
, 10, 10);
564 errln("nf : " + buffer
); // Expect (1 234,00)
566 // Erroneously prints:
573 * DecimalFormat.parse returns wrong value
575 // {sfb} slightly converted into a round-trip test, since in C++
576 // there is no Double.toString()
577 void NumberFormatRegressionTest::Test4068693(void)
579 logln("----- Test Application -----");
580 ParsePosition
pos(0);
581 UErrorCode status
= U_ZERO_ERROR
;
582 DecimalFormat
*df
= new DecimalFormat(status
);
583 if(U_FAILURE(status
)) {
584 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
588 failure(status
, "new DecimalFormat");
590 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
591 df
->parse(UnicodeString("123.55456"), d
, pos
);
592 //if (!d.toString().equals("123.55456")) {
594 df
->setMaximumFractionDigits(999);
595 df
->setMaximumIntegerDigits(999);
596 FieldPosition
fp(FieldPosition::DONT_CARE
);
597 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
598 if (dstr
!= UnicodeString("123.55456")) {
599 errln(UnicodeString("Result -> ") + d
.getDouble());
605 /* @bug 4069754, 4067878
606 * null pointer thrown when accessing a deserialized DecimalFormat
609 // {sfb} doesn't apply in C++
610 void NumberFormatRegressionTest::Test4069754(void)
613 myformat it = new myformat();
615 FileOutputStream ostream = new FileOutputStream("t.tmp");
616 ObjectOutputStream p = new ObjectOutputStream(ostream);
621 FileInputStream istream = new FileInputStream("t.tmp");
622 ObjectInputStream p2 = new ObjectInputStream(istream);
623 myformat it2 = (myformat)p2.readObject();
627 } catch (Exception foo) {
628 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
633 * DecimalFormat.applyPattern(String) allows illegal patterns
635 void NumberFormatRegressionTest::Test4087251 (void)
637 UErrorCode status
= U_ZERO_ERROR
;
638 DecimalFormat
*df
= new DecimalFormat(status
);
639 if(U_FAILURE(status
)) {
640 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
644 failure(status
, "new DecimalFormat");
646 df
->applyPattern(UnicodeString("#.#.#"), status
);
647 if( ! U_FAILURE(status
))
648 errln("df->applyPattern with illegal pattern didn't fail");
650 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
651 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
652 /*} catch (IllegalArgumentException e) {
653 logln("Caught Illegal Argument Error !");
655 // Second test; added 5/11/98 when reported to fail on 1.2b3
657 df
->applyPattern("#0.0#0#0", status
);
658 if( ! U_FAILURE(status
))
659 errln("df->applyPattern with illegal pattern didn't fail");
660 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
661 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
662 /*} catch (IllegalArgumentException e) {
663 logln("Ok - IllegalArgumentException for #0.0#0#0");
670 * DecimalFormat.format() loses precision
672 void NumberFormatRegressionTest::Test4090489 (void)
674 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
675 // that NumberFormat can do. For some reason, it does not format the last 1.
677 /* UErrorCode status = U_ZERO_ERROR;
678 DecimalFormat *df = new DecimalFormat(status);
679 failure(status, "new DecimalFormat");
680 df->setMinimumFractionDigits(10);
681 df->setMaximumFractionDigits(999);
682 df->setGroupingUsed(FALSE);
683 double d = 1.000000000000001E7;
684 //BigDecimal bd = new BigDecimal(d);
687 logln(UnicodeString("d = ") + d);
688 //logln("BigDecimal.toString(): " + bd.toString());
689 df->format(d, sb, fp);
690 if (sb != "10000000.0000000100") {
691 errln("DecimalFormat.format(): " + sb);
697 * DecimalFormat.format() loses precision
699 void NumberFormatRegressionTest::Test4090504 (void)
702 logln(UnicodeString("d = ") + d
);
703 UErrorCode status
= U_ZERO_ERROR
;
704 DecimalFormat
*df
= new DecimalFormat(status
);
705 if(U_FAILURE(status
)) {
706 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
710 failure(status
, "new DecimalFormat");
712 FieldPosition
fp(FieldPosition::DONT_CARE
);
714 for (int i
= 17; i
<= 20; i
++) {
715 df
->setMaximumFractionDigits(i
);
716 //sb = new StringBuffer("");
718 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
719 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
721 /*} catch (Exception foo) {
722 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
728 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
730 void NumberFormatRegressionTest::Test4095713 (void)
732 UErrorCode status
= U_ZERO_ERROR
;
733 DecimalFormat
*df
= new DecimalFormat(status
);
734 if(U_FAILURE(status
)) {
735 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
739 failure(status
, "new DecimalFormat");
740 UnicodeString
str("0.1234");
742 //Double d1 = new Double(str);
743 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
746 df
->parse(str
, d2
, pp
);
747 logln(UnicodeString("") + d1
);
748 if (d2
.getDouble() != d1
)
749 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
754 * DecimalFormat.parse() fails when multiplier is not set to 1
756 // {sfb} not sure what to do with this one
757 void NumberFormatRegressionTest::Test4092561 (void)
759 UErrorCode status
= U_ZERO_ERROR
;
760 DecimalFormat
*df
= new DecimalFormat(status
);
761 if(U_FAILURE(status
)) {
762 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
766 failure(status
, "new DecimalFormat");
768 // {sfb} going to cheat here and use sprintf ??
770 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
771 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
772 df.setMultiplier(100);
773 Number num = df.parse(str, new ParsePosition(0));
774 if (num.doubleValue() != -9.223372036854776E16)
775 errln("Bug 4092561 test failed when multiplier is set to not 1.");
781 * DecimalFormat: Negative format ignored.
783 void NumberFormatRegressionTest::Test4092480 (void)
785 UErrorCode status
= U_ZERO_ERROR
;
786 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
787 if(U_FAILURE(status
)) {
788 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
792 failure(status
, "new DecimalFormat");
795 dfFoo
->applyPattern("0000;-000", status
);
796 failure(status
, "dfFoo->applyPattern");
798 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
799 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
800 FieldPosition
pos(FieldPosition::DONT_CARE
);
801 logln(dfFoo
->format((int32_t)42, temp
, pos
));
802 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
803 dfFoo
->applyPattern("000;-000", status
);
804 failure(status
, "dfFoo->applyPattern");
805 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
806 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
807 logln(dfFoo
->format((int32_t)42,temp
, pos
));
808 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
810 dfFoo
->applyPattern("000;-0000", status
);
811 failure(status
, "dfFoo->applyPattern");
812 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
813 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
814 logln(dfFoo
->format((int32_t)42, temp
, pos
));
815 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
817 dfFoo
->applyPattern("0000;-000", status
);
818 failure(status
, "dfFoo->applyPattern");
819 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
820 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
821 logln(dfFoo
->format((int32_t)42, temp
, pos
));
822 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
823 /*} catch (Exception foo) {
824 errln("Message " + foo.getMessage());
830 * NumberFormat.getCurrencyInstance() produces format that uses
831 * decimal separator instead of monetary decimal separator.
833 * Rewrote this test not to depend on the actual pattern. Pattern should
834 * never contain the monetary separator! Decimal separator in pattern is
835 * interpreted as monetary separator if currency symbol is seen!
837 void NumberFormatRegressionTest::Test4087244 (void) {
838 UErrorCode status
= U_ZERO_ERROR
;
840 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
841 Locale
*de
= new Locale(loc
);
842 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
843 if(U_FAILURE(status
)) {
844 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
848 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
850 errln("expected DecimalFormat!");
853 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
854 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
855 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
856 if (decSep
== monSep
) {
857 errln("ERROR in test: want decimal sep != monetary sep");
860 df
->setMinimumIntegerDigits(1);
861 df
->setMinimumFractionDigits(2);
864 df
->format(1.23, str
, pos
);
865 UnicodeString
monStr("1x23");
866 monStr
.replace((int32_t)1, 1, monSep
);
867 UnicodeString
decStr("1x23");
868 decStr
.replace((int32_t)1, 1, decSep
);
869 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
870 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
871 monStr
+ "\" and not \"" + decStr
+ '"');
873 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
875 "\" and not \"" + decStr
+ '"');
881 * Number format data rounding errors for locale FR
883 void NumberFormatRegressionTest::Test4070798 (void)
885 NumberFormat
*formatter
;
886 UnicodeString tempString
;
889 String expectedDefault = "-5\u00a0789,987";
890 String expectedCurrency = "5\u00a0789,98\u00a0F";
891 String expectedPercent = "-578\u00a0998%";
894 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
897 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
900 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
902 UnicodeString
expectedDefault(chars1
, 10, 10);
903 UnicodeString
expectedCurrency(chars2
, 10, 10);
904 UnicodeString
expectedPercent(chars3
, 10, 10);
906 UErrorCode status
= U_ZERO_ERROR
;
908 int len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
909 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
910 if(U_FAILURE(status
)) {
911 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
915 failure(status
, "NumberFormat::createNumberInstance", loc
);
916 tempString
= formatter
->format (-5789.9876, tempString
);
918 if (tempString
== expectedDefault
) {
919 logln ("Bug 4070798 default test passed.");
921 errln(UnicodeString("Failed:") +
922 " Expected " + expectedDefault
+
923 " Received " + tempString
);
926 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
927 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
928 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
930 tempString
= formatter
->format( 5789.9876, tempString
);
932 if (tempString
== expectedCurrency
) {
933 logln ("Bug 4070798 currency test passed.");
935 errln(UnicodeString("Failed:") +
936 " Expected " + expectedCurrency
+
937 " Received " + tempString
);
941 uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
942 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
943 failure(status
, "NumberFormat::createPercentInstance", loc
);
945 tempString
= formatter
->format (-5789.9876, tempString
);
947 if (tempString
== expectedPercent
) {
948 logln ("Bug 4070798 percentage test passed.");
950 errln(UnicodeString("Failed:") +
951 " Expected " + expectedPercent
+
952 " Received " + tempString
);
958 * Data rounding errors for French (Canada) locale
960 void NumberFormatRegressionTest::Test4071005 (void)
962 NumberFormat
*formatter
;
963 UnicodeString tempString
;
965 String expectedDefault = "-5\u00a0789,987";
966 String expectedCurrency = "5\u00a0789,98\u00a0$";
967 String expectedPercent = "-578\u00a0998%";
970 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
973 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
976 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
978 UnicodeString
expectedDefault(chars1
, 10, 10);
979 UnicodeString
expectedCurrency(chars2
, 10, 10);
980 UnicodeString
expectedPercent(chars3
, 10, 10);
982 UErrorCode status
= U_ZERO_ERROR
;
983 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
984 if (failure(status
, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE
)){
988 tempString
= formatter
->format (-5789.9876, tempString
);
990 if (tempString
== expectedDefault
) {
991 logln ("Bug 4071005 default test passed.");
993 errln(UnicodeString("Failed:") +
994 " Expected " + expectedDefault
+
995 " Received " + tempString
);
999 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
1000 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1001 tempString
.remove();
1002 tempString
= formatter
->format( 5789.9876, tempString
);
1004 if (tempString
== expectedCurrency
) {
1005 logln ("Bug 4071005 currency test assed.");
1007 errln(UnicodeString("Failed:") +
1008 " Expected " + expectedCurrency
+
1009 " Received " + tempString
);
1013 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1014 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1015 tempString
.remove();
1016 tempString
= formatter
->format (-5789.9876, tempString
);
1018 if (tempString
== expectedPercent
) {
1019 logln ("Bug 4071005 percentage test passed.");
1021 errln(UnicodeString("Failed:") +
1022 " Expected " + expectedPercent
+
1023 " Received " + tempString
);
1030 * Data rounding errors for German (Germany) locale
1032 void NumberFormatRegressionTest::Test4071014 (void)
1034 NumberFormat
*formatter
;
1035 UnicodeString tempString
;
1037 String expectedDefault = "-5.789,987";
1038 String expectedCurrency = "5.789,98 DEM";
1039 String expectedPercent = "-578.998%";
1041 UnicodeString
expectedDefault("-5.789,988");
1042 UnicodeString
expectedCurrency("5.789,99\\u00A0DEM");
1043 UnicodeString
expectedPercent("-578.999\\u00A0%");
1045 expectedCurrency
= expectedCurrency
.unescape();
1046 expectedPercent
= expectedPercent
.unescape();
1048 UErrorCode status
= U_ZERO_ERROR
;
1050 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1051 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1052 if (failure(status
, "NumberFormat::createNumberInstance", loc
, TRUE
)){
1056 tempString
.remove();
1057 tempString
= formatter
->format (-5789.9876, tempString
);
1059 if (tempString
== expectedDefault
) {
1060 logln ("Bug 4071014 default test passed.");
1062 errln(UnicodeString("Failed:") +
1063 " Expected " + expectedDefault
+
1064 " Received " + tempString
);
1067 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1068 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1069 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1070 tempString
.remove();
1071 tempString
= formatter
->format( 5789.9876, tempString
);
1073 if (tempString
== expectedCurrency
) {
1074 logln ("Bug 4071014 currency test assed.");
1076 errln(UnicodeString("Failed:") +
1077 " Expected " + expectedCurrency
+
1078 " Received " + tempString
);
1082 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1083 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1084 tempString
.remove();
1085 tempString
= formatter
->format (-5789.9876, tempString
);
1087 if (tempString
== expectedPercent
) {
1088 logln ("Bug 4071014 percentage test passed.");
1090 errln(UnicodeString("Failed:") +
1091 " Expected " + expectedPercent
+
1092 " Received " + tempString
);
1098 * Data rounding errors for Italian locale number formats
1100 void NumberFormatRegressionTest::Test4071859 (void)
1102 NumberFormat
*formatter
;
1103 UnicodeString tempString
;
1105 String expectedDefault = "-5.789,987";
1106 String expectedCurrency = "-L.\\u00A05.789,98";
1107 String expectedPercent = "-578.998%";
1109 UnicodeString
expectedDefault("-5.789,988");
1110 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1111 UnicodeString
expectedPercent("-578.999%");
1112 expectedCurrency
= expectedCurrency
.unescape();
1114 UErrorCode status
= U_ZERO_ERROR
;
1116 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1117 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1118 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1122 tempString
= formatter
->format (-5789.9876, tempString
);
1124 if (tempString
== expectedDefault
) {
1125 logln ("Bug 4071859 default test passed.");
1127 errln(UnicodeString("Failed:") +
1128 " Expected " + expectedDefault
+
1129 " Received " + tempString
);
1132 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1133 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1134 failure(status
, "NumberFormat::createCurrencyInstance");
1135 tempString
.remove();
1136 tempString
= formatter
->format( -5789.9876, tempString
);
1138 if (tempString
== expectedCurrency
) {
1139 logln ("Bug 4071859 currency test assed.");
1141 errln(UnicodeString("Failed:") +
1142 " Expected " + expectedCurrency
+
1143 " Received " + tempString
);
1146 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1147 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1148 failure(status
, "NumberFormat::createPercentInstance");
1149 tempString
.remove();
1150 tempString
= formatter
->format (-5789.9876, tempString
);
1152 if (tempString
== expectedPercent
) {
1153 logln ("Bug 4071859 percentage test passed.");
1155 errln(UnicodeString("Failed:") +
1156 " Expected " + expectedPercent
+
1157 " Received " + tempString
);
1163 * Test rounding for nearest even.
1165 void NumberFormatRegressionTest::Test4093610(void)
1167 UErrorCode status
= U_ZERO_ERROR
;
1168 DecimalFormat
*df
= new DecimalFormat("#0.#", status
);
1169 if (!failure(status
, "new DecimalFormat")) {
1170 UnicodeString
s("12.4");
1171 roundingTest(df
, 12.35, s
);
1172 roundingTest(df
, 12.45, s
);
1174 roundingTest(df
, 12.452,s
);
1176 roundingTest(df
, 12.55, s
);
1177 roundingTest(df
, 12.65, s
);
1179 roundingTest(df
, 12.652,s
);
1181 roundingTest(df
, 12.75, s
);
1182 roundingTest(df
, 12.752,s
);
1183 roundingTest(df
, 12.85, s
);
1185 roundingTest(df
, 12.852,s
);
1187 roundingTest(df
, 12.95, s
);
1188 roundingTest(df
, 12.952,s
);
1194 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1197 FieldPosition
pos(FieldPosition::DONT_CARE
);
1198 out
= df
->format(x
, out
, pos
);
1199 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1200 if (out
!= expected
)
1201 errln("FAIL: Expected " + expected
);
1204 * Tests the setMaximumFractionDigits limit.
1206 void NumberFormatRegressionTest::Test4098741(void)
1209 UErrorCode status
= U_ZERO_ERROR
;
1210 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1211 if (U_FAILURE(status
)) {
1212 dataerrln("Error calling NumberFormat::createPercentInstance");
1217 fmt
->setMaximumFractionDigits(20);
1219 logln(fmt
->format(.001, temp
));
1220 /*} catch (Exception foo) {
1221 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1226 * Tests illegal pattern exception.
1227 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1228 * Part2 has been fixed.
1230 void NumberFormatRegressionTest::Test4074454(void)
1233 UErrorCode status
= U_ZERO_ERROR
;
1234 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1235 if(U_FAILURE(status
)) {
1236 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1240 failure(status
, "new DecimalFormat");
1241 logln("Inconsistent negative pattern is fine.");
1242 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1243 failure(status
, "new DecimalFormat");
1244 UnicodeString tempString
;
1245 FieldPosition
pos(FieldPosition::DONT_CARE
);
1246 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1247 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1248 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1249 /*} catch (Exception foo) {
1250 errln("An exception was thrown for any inconsistent negative pattern.");
1257 * Tests all different comments.
1258 * Response to some comments :
1259 * [1] DecimalFormat.parse API documentation is more than just one line.
1260 * This is not a reproducable doc error in 116 source code.
1261 * [2] See updated javadoc.
1263 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1264 * a null object will be returned. The unchanged parse position also
1265 * reflects an error.
1266 * NumberFormat.parse(String) : If parsing fails, an ParseException
1268 * See updated javadoc for more details.
1269 * [5] See updated javadoc.
1270 * [6] See updated javadoc.
1271 * [7] This is a correct behavior if the DateFormat object is linient.
1272 * Otherwise, an IllegalArgumentException will be thrown when formatting
1273 * "January 35". See GregorianCalendar class javadoc for more details.
1275 void NumberFormatRegressionTest::Test4099404(void)
1278 UErrorCode status
= U_ZERO_ERROR
;
1279 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1280 if(! U_FAILURE(status
))
1281 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1282 /*} catch (Exception foo) {
1283 logln("Bug 4099404 pattern \"000.0#0\" passed");
1288 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1289 if( !U_FAILURE(status
))
1290 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1291 /*} catch (Exception foo) {
1292 logln("Bug 4099404 pattern \"0#0.000\" passed");
1298 * DecimalFormat.applyPattern doesn't set minimum integer digits
1300 void NumberFormatRegressionTest::Test4101481(void)
1302 UErrorCode status
= U_ZERO_ERROR
;
1303 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1304 if(U_FAILURE(status
)) {
1305 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1309 failure(status
, "new DecimalFormat");
1310 if (sdf
->getMinimumIntegerDigits() != 1)
1311 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1314 /* @bug 4052223 (API addition request A27)
1315 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1317 void NumberFormatRegressionTest::Test4052223(void)
1320 UErrorCode status
= U_ZERO_ERROR
;
1321 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1322 if(U_FAILURE(status
)) {
1323 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1327 failure(status
, "new DecimalFormat");
1329 fmt
->parse(UnicodeString("abc3"), num
, status
);
1330 if(! U_FAILURE(status
))
1331 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1332 /*} catch (ParseException foo) {
1333 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1338 * API tests for API addition request A9.
1340 void NumberFormatRegressionTest::Test4061302(void)
1342 UErrorCode status
= U_ZERO_ERROR
;
1343 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1344 failure(status
, "new DecimalFormatSymbols");
1345 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1346 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1347 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1348 if (currency
== UnicodeString("") ||
1349 intlCurrency
== UnicodeString("") ||
1350 monDecSeparator
== UnicodeString(""))
1352 errln("getCurrencySymbols failed, got empty string.");
1354 UnicodeString monDecSeparatorStr
;
1355 monDecSeparatorStr
.append(monDecSeparator
);
1356 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1357 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1358 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1359 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1360 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1361 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1362 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1363 if (currency
!= UnicodeString("XYZ") ||
1364 intlCurrency
!= UnicodeString("ABC") ||
1365 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1366 errln("setCurrencySymbols failed.");
1368 monDecSeparatorStr
.remove();
1369 monDecSeparatorStr
.append(monDecSeparator
);
1370 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1375 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1376 * FieldPosition.getEndIndex.
1378 void NumberFormatRegressionTest::Test4062486(void)
1380 UErrorCode status
= U_ZERO_ERROR
;
1381 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1382 failure(status
, "new DecimalFormat");
1383 UnicodeString formatted
;
1384 FieldPosition
field(0);
1385 double num
= 1234.5;
1386 fmt
->format(num
, formatted
, field
);
1387 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1388 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1389 field
.setBeginIndex(7);
1390 field
.setEndIndex(4);
1391 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1392 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1398 * DecimalFormat.parse incorrectly works with a group separator.
1400 void NumberFormatRegressionTest::Test4108738(void)
1402 UErrorCode status
= U_ZERO_ERROR
;
1403 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1404 failure(status
, "new DecimalFormatSymbols");
1405 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1406 if(U_FAILURE(status
)) {
1407 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1411 failure(status
, "new DecimalFormat");
1412 UnicodeString
text("1.222,111");
1414 ParsePosition
pp(0);
1415 df
->parse(text
, num
, pp
);
1417 // {sfb} how to do this (again) ?
1418 // shouldn't just be another round-trip test, should it?
1420 FieldPosition
pos(FieldPosition::DONT_CARE
);
1421 temp
= df
->format(num
.getDouble(), temp
, pos
);
1422 //if (!num.toString().equals("1.222"))
1423 if (temp
!= UnicodeString("1.222"))
1424 //errln("\"" + text + "\" is parsed as " + num);
1425 errln("\"" + text
+ "\" is parsed as " + temp
);
1426 text
= UnicodeString("1.222x111");
1427 pp
= ParsePosition(0);
1428 df
->parse(text
, num
, pp
);
1430 temp
= df
->format(num
.getDouble(), temp
, pos
);
1431 //if (!num.toString().equals("1.222"))
1432 if (temp
!= UnicodeString("1.222"))
1433 errln("\"" + text
+ "\" is parsed as " + temp
);
1439 * DecimalFormat.format() incorrectly formats negative doubles.
1441 void NumberFormatRegressionTest::Test4106658(void)
1443 UErrorCode status
= U_ZERO_ERROR
;
1444 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1445 if(U_FAILURE(status
)) {
1446 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1450 failure(status
, "new DecimalFormat");
1451 volatile double d1
= 0.0; // volatile to prevent code optimization
1452 double d2
= -0.0001;
1453 UnicodeString buffer
;
1455 FieldPosition
pos(FieldPosition::DONT_CARE
);
1457 #if U_PLATFORM == U_PF_HPUX
1458 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1460 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1462 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1463 df
->format(d1
, buffer
, pos
);
1464 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1465 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1467 df
->format(d2
, buffer
, pos
);
1468 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1469 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1475 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1477 void NumberFormatRegressionTest::Test4106662(void)
1479 UErrorCode status
= U_ZERO_ERROR
;
1480 DecimalFormat
*df
= new DecimalFormat(status
);
1481 if(U_FAILURE(status
)) {
1482 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1486 failure(status
, "new DecimalFormat");
1487 UnicodeString
text("x");
1488 ParsePosition
pos1(0), pos2(0);
1491 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1493 df
->parse(text
, num
, pos1
);
1494 if (pos1
== ParsePosition(0)/*num != null*/) {
1495 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1498 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1499 failure(status
, "new DecimalFormat");
1500 df
->parse(UnicodeString("$"), num
, pos2
);
1501 if (pos2
== ParsePosition(0) /*num != null*/){
1502 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1508 /* @bug 4114639 (duplicate of 4106662)
1509 * NumberFormat.parse doesn't return null
1511 void NumberFormatRegressionTest::Test4114639(void)
1513 UErrorCode status
= U_ZERO_ERROR
;
1514 NumberFormat
*format
= NumberFormat::createInstance(status
);
1515 if(U_FAILURE(status
)) {
1516 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1520 failure(status
, "NumberFormat::createInstance");
1521 UnicodeString
text("time 10:x");
1522 ParsePosition
pos(8);
1524 format
->parse(text
, result
, pos
);
1525 if (/*result != null*/pos
.getErrorIndex() != 8)
1526 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1532 * TODO: this test does not work because we need to use a 64 bit number and a
1533 * a double only MAY only have 52 bits of precision.
1534 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1536 void NumberFormatRegressionTest::Test4106664(void)
1538 UErrorCode status
= U_ZERO_ERROR
;
1539 DecimalFormat
*df
= new DecimalFormat(status
);
1540 if(U_FAILURE(status
)) {
1541 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1545 failure(status
, "new DecimalFormat");
1546 // {sfb} long in java is 64 bits
1547 /*long*/double n
= 1234567890123456.0;
1548 /*int*/int32_t m
= 12345678;
1549 // {sfb} will this work?
1550 //BigInteger bigN = BigInteger.valueOf(n);
1551 //bigN = bigN.multiply(BigInteger.valueOf(m));
1552 double bigN
= n
* m
;
1553 df
->setMultiplier(m
);
1554 df
->setGroupingUsed(FALSE
);
1556 FieldPosition
pos(FieldPosition::DONT_CARE
);
1557 logln("formated: " +
1558 df
->format(n
, temp
, pos
));
1561 sprintf(buf
, "%g", bigN
);
1562 //logln("expected: " + bigN.toString());
1563 logln(UnicodeString("expected: ") + buf
);
1567 /* @bug 4106667 (duplicate of 4106658)
1568 * DecimalFormat.format incorrectly formats -0.0.
1570 void NumberFormatRegressionTest::Test4106667(void)
1572 UErrorCode status
= U_ZERO_ERROR
;
1573 DecimalFormat
*df
= new DecimalFormat(status
);
1574 if(U_FAILURE(status
)) {
1575 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1579 failure(status
, "new DecimalFormat");
1580 UChar foo
[] = { 0x002B };
1581 UnicodeString
bar(foo
, 1, 1);
1582 volatile double d
= 0.0; // volatile to prevent code optimization
1584 UnicodeString buffer
;
1585 FieldPosition
pos(FieldPosition::DONT_CARE
);
1587 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1588 #if U_PLATFORM == U_PF_HPUX
1589 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1591 d
*= -1.0; // Some compilers have a problem with defining -0.0
1593 df
->setPositivePrefix(/*"+"*/bar
);
1594 df
->format(d
, buffer
, pos
);
1595 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1596 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1602 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1604 #if U_PLATFORM == U_PF_OS390
1605 # define MAX_INT_DIGITS 70
1607 # define MAX_INT_DIGITS 128
1610 void NumberFormatRegressionTest::Test4110936(void)
1612 UErrorCode status
= U_ZERO_ERROR
;
1613 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1614 if(U_FAILURE(status
)) {
1615 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1619 failure(status
, "NumberFormat::createInstance");
1620 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1621 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1622 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1623 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1624 nf
->getMaximumIntegerDigits());
1630 * Locale data should use generic currency symbol
1632 * 1) Make sure that all currency formats use the generic currency symbol.
1633 * 2) Make sure we get the same results using the generic symbol or a
1636 void NumberFormatRegressionTest::Test4122840(void)
1639 const Locale
*locales
= Locale::getAvailableLocales(count
);
1641 for (int i
= 0; i
< count
; i
++) {
1642 UErrorCode status
= U_ZERO_ERROR
;
1643 ResourceBundle
*rb
= new ResourceBundle(
1644 NULL
/*"java.text.resources.LocaleElements"*/,
1645 locales
[i
], status
);
1646 failure(status
, "new ResourceBundle");
1647 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1648 failure(status
, "rb.get(NumberElements)");
1649 numPat
= numPat
.getWithFallback("latn",status
);
1650 failure(status
, "rb.get(latn)");
1651 numPat
= numPat
.getWithFallback("patterns",status
);
1652 failure(status
, "rb.get(patterns)");
1653 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1654 failure(status
, "rb.get(currencyFormat)");
1656 // Get the currency pattern for this locale. We have to fish it
1657 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1658 // will return the localized symbol, not \00a4
1660 UnicodeString pattern
= numPat
.getString(status
);
1661 failure(status
, "rb->getString()");
1663 UChar fo
[] = { 0x00A4 };
1664 UnicodeString
foo(fo
, 1, 1);
1666 //if (pattern.indexOf("\u00A4") == -1 ) {
1667 if (pattern
.indexOf(foo
) == -1 ) {
1668 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1669 " does not contain generic currency symbol:" +
1673 // Create a DecimalFormat using the pattern we got and format a number
1674 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1675 failure(status
, "new DecimalFormatSymbols");
1676 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1677 failure(status
, "new DecimalFormat");
1679 UnicodeString result1
;
1680 FieldPosition
pos(FieldPosition::DONT_CARE
);
1681 result1
= fmt1
->format(1.111, result1
, pos
);
1684 // Now substitute in the locale's currency symbol and create another
1685 // pattern. We have to skip locales where the currency symbol
1686 // contains decimal separators, because that confuses things
1688 UChar ba
[] = { 0x002E/*'.'*/ };
1689 UnicodeString
bar(ba
, 1, 1);
1691 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1692 // {sfb} Also, switch the decimal separator to the monetary decimal
1693 // separator to mimic the behavior of a currency format
1694 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1695 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1697 UnicodeString
buf(pattern
);
1698 for (int j
= 0; j
< buf
.length(); j
++) {
1699 if (buf
[j
] == 0x00a4 ) {
1700 if(buf
[j
+ 1] == 0x00a4) {
1701 // {sfb} added to support double currency marker (intl currency sign)
1702 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1703 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1706 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1707 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1712 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1713 failure(status
, "new DecimalFormat");
1715 // Get the currency (if there is one) so we can set the rounding and fraction
1716 const UChar
*currency
= fmt1
->getCurrency();
1717 if (*currency
!= 0) {
1718 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1719 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1720 if (U_SUCCESS(status
)) {
1721 fmt2
->setRoundingIncrement(rounding
);
1722 fmt2
->setMinimumFractionDigits(frac
);
1723 fmt2
->setMaximumFractionDigits(frac
);
1726 failure(status
, "Fetching currency rounding/fractions");
1730 UnicodeString result2
;
1731 fmt2
->format(1.111, result2
, pos
);
1733 if (result1
!= result2
) {
1734 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1735 result1
+ " vs " + result2
);
1748 * DecimalFormat.format() delivers wrong string.
1750 void NumberFormatRegressionTest::Test4125885(void)
1752 UErrorCode status
= U_ZERO_ERROR
;
1753 double rate
= 12.34;
1754 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1755 if(U_FAILURE(status
)) {
1756 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1760 failure(status
, "new DecimalFormat");
1762 logln("toPattern: " + formatDec
->toPattern(temp
));
1763 UnicodeString rateString
;
1764 FieldPosition
pos(FieldPosition::DONT_CARE
);
1765 rateString
= formatDec
->format(rate
, rateString
, pos
);
1766 if (rateString
!= UnicodeString("012.34"))
1767 errln("result : " + rateString
+ " expected : 012.34");
1769 delete formatDec
;// = null;
1770 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1771 failure(status
, "new DecimalFormat");
1772 logln("toPattern: " + formatDec
->toPattern(temp
));
1773 rateString
.remove();
1774 rateString
= formatDec
->format(rate
, rateString
, pos
);
1775 if (rateString
!= UnicodeString("+012.34%"))
1776 errln("result : " + rateString
+ " expected : +012.34%");
1783 * DecimalFormat produces extra zeros when formatting numbers.
1785 void NumberFormatRegressionTest::Test4134034(void)
1787 UErrorCode status
= U_ZERO_ERROR
;
1788 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1789 if (!failure(status
, "new DecimalFormat")) {
1791 FieldPosition
pos(FieldPosition::DONT_CARE
);
1792 f
= nf
->format(9.02, f
, pos
);
1793 if (f
== UnicodeString("9.02"))
1796 errln("9.02 -> " + f
+ "; want 9.02");
1799 f
= nf
->format((int32_t)0, f
, pos
);
1800 if (f
== UnicodeString(".00"))
1803 errln("0 -> " + f
+ "; want .00");
1811 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1812 * a duplicate of 4134034.
1814 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1815 * Possibly related to bug 4125885.
1817 * This class demonstrates a regression in version 1.1.6
1818 * of DecimalFormat class.
1821 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1822 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1823 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1824 * Value 1.2 Format #0.0# Result '1.2'
1825 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1828 * Value 1.2 Format #.00 Result '1.20'
1829 * Value 1.2 Format 0.00 Result '1.20'
1830 * Value 1.2 Format 00.00 Result '01.20'
1831 * Value 1.2 Format #0.0# Result '1.2'
1832 * Value 1.2 Format #0.00 Result '1.20'
1834 void NumberFormatRegressionTest::Test4134300(void) {
1835 UnicodeString DATA
[] = {
1836 // Pattern Expected string
1837 UnicodeString("#.00"), UnicodeString("1.20"),
1838 UnicodeString("0.00"), UnicodeString("1.20"),
1839 UnicodeString("00.00"), UnicodeString("01.20"),
1840 UnicodeString("#0.0#"), UnicodeString("1.2"),
1841 UnicodeString("#0.00"), UnicodeString("1.20")
1844 for (int i
=0; i
< 10; i
+=2) {
1845 UnicodeString result
;
1846 UErrorCode status
= U_ZERO_ERROR
;
1847 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1848 if (!failure(status
, "new DecimalFormat")) {
1849 FieldPosition
pos(FieldPosition::DONT_CARE
);
1850 result
= df
->format(1.2, result
, pos
);
1851 if (result
!= DATA
[i
+1]) {
1852 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1853 "; want " + DATA
[i
+1]);
1856 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1866 * Empty pattern produces double negative prefix.
1868 void NumberFormatRegressionTest::Test4140009(void)
1870 UErrorCode status
= U_ZERO_ERROR
;
1871 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
1872 failure(status
, "new DecimalFormatSymbols");
1873 DecimalFormat
*f
= new DecimalFormat(UnicodeString(""), syms
, status
);
1874 if (!failure(status
, "new DecimalFormat")) {
1876 FieldPosition
pos(FieldPosition::DONT_CARE
);
1877 s
= f
->format(123.456, s
, pos
);
1878 if (s
!= UnicodeString("123.456"))
1879 errln("Fail: Format empty pattern x 123.456 => " + s
);
1881 s
= f
->format(-123.456, s
, pos
);
1882 if (s
!= UnicodeString("-123.456"))
1883 errln("Fail: Format empty pattern x -123.456 => " + s
);
1890 * BigDecimal numbers get their fractions truncated by NumberFormat.
1892 // {sfb} not pertinent in C++ ??
1893 void NumberFormatRegressionTest::Test4141750(void) {
1895 UnicodeString str("12345.67");
1896 BigDecimal bd = new BigDecimal(str);
1897 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1898 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1900 catch (Exception e) {
1901 errln(e.toString());
1902 e.printStackTrace();
1908 * DecimalFormat toPattern() doesn't quote special characters or handle
1911 void NumberFormatRegressionTest::Test4145457() {
1913 UErrorCode status
= U_ZERO_ERROR
;
1914 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1915 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1919 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1921 errln("DecimalFormat needed to continue");
1925 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1926 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1927 nf
->setDecimalFormatSymbols(*sym
);
1928 double pi
= 3.14159;
1930 UnicodeString PATS
[] = {
1931 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1934 for (int32_t i
=0; i
<2; ++i
) {
1935 nf
->applyPattern(PATS
[i
], status
);
1936 failure(status
, "nf->applyPattern");
1938 FieldPosition
pos(FieldPosition::DONT_CARE
);
1939 out
= nf
->format(pi
, out
, pos
);
1941 pat
= nf
->toPattern(pat
);
1943 ParsePosition
pp(0);
1944 nf
->parse(out
, num
, pp
);
1945 double val
= num
.getDouble();
1947 nf
->applyPattern(pat
, status
);
1948 failure(status
, "nf->applyPattern");
1950 out2
= nf
->format(pi
, out2
, pos
);
1952 pat2
= nf
->toPattern(pat2
);
1954 nf
->parse(out2
, num
, pp
);
1955 double val2
= num
.getDouble();
1958 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1959 pat
+ "\" vs. \"" + pat2
+ "\"");
1961 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1963 if (val
== val2
&& out
== out2
) {
1964 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1965 out
+ "\" -> " + val
+ " -> \"" +
1966 out2
+ "\" -> " + val2
);
1969 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1970 out
+ "\" -> " + val
+ " -> \"" +
1971 out2
+ "\" -> " + val2
);
1975 catch (ParseException e) {
1976 errln("Fail: " + e);
1977 e.printStackTrace();
1985 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
1987 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
1989 void NumberFormatRegressionTest::Test4147295(void)
1991 UErrorCode status
= U_ZERO_ERROR
;
1992 DecimalFormat
*sdf
= new DecimalFormat(status
);
1993 UnicodeString
pattern("#,###");
1994 logln("Applying pattern \"" + pattern
+ "\"");
1995 sdf
->applyPattern(pattern
, status
);
1996 if (!failure(status
, "sdf->applyPattern")) {
1997 int minIntDig
= sdf
->getMinimumIntegerDigits();
1998 if (minIntDig
!= 0) {
1999 errln("Test failed");
2000 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2002 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2004 logln("Test passed");
2005 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2013 * DecimalFormat formats -0.0 as +0.0
2014 * See also older related bug 4106658, 4106667
2016 void NumberFormatRegressionTest::Test4147706(void)
2018 UErrorCode status
= U_ZERO_ERROR
;
2019 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2020 failure(status
, "new DecimalFormat");
2021 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2022 if (!failure(status
, "new DecimalFormatSymbols")) {
2024 UnicodeString f2
, temp
;
2025 FieldPosition
pos(FieldPosition::DONT_CARE
);
2026 volatile double d1
= 0.0; // volatile to prevent code optimization
2027 double d2
= -0.0001;
2029 #if U_PLATFORM == U_PF_HPUX
2030 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2032 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2034 df
->adoptDecimalFormatSymbols(syms
);
2035 f1
= df
->format(d1
, f1
, pos
);
2036 f2
= df
->format(d2
, f2
, pos
);
2037 if (f1
!= UnicodeString("-0.0")) {
2038 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2040 if (f2
!= UnicodeString("-0.0")) {
2041 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2049 // Not applicable, since no serialization in C++
2050 /*class myformat implements Serializable
2052 DateFormat _dateFormat = DateFormat.getDateInstance();
2056 GregorianCalendar calendar = new GregorianCalendar();
2057 Date t = calendar.getTime();
2058 String nowStr = _dateFormat.format(t);
2065 * NumberFormat cannot format Double.MAX_VALUE
2067 // TODO: make this test actually test something
2069 NumberFormatRegressionTest::Test4162198(void)
2071 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2072 double dbl
= INT32_MAX
* 1000.0;
2073 UErrorCode status
= U_ZERO_ERROR
;
2074 NumberFormat
*f
= NumberFormat::createInstance(status
);
2075 if(U_FAILURE(status
)) {
2076 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2079 f
->setMaximumFractionDigits(INT32_MAX
);
2080 f
->setMaximumIntegerDigits(INT32_MAX
);
2083 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2086 f
->parse(s
, n
, status
);
2087 if(U_FAILURE(status
))
2088 errln("Couldn't parse!");
2089 //} catch (java.text.ParseException e) {
2090 // errln("Caught a ParseException:");
2091 // e.printStackTrace();
2094 //logln("The string " + s + " parsed as " + n);
2096 // {dlf} The old code assumes n is a double, but it isn't any more...
2097 // Formattable apparently does not and never did interconvert... too bad.
2098 //if(n.getDouble() != dbl) {
2099 // errln("Round trip failure");
2101 if (n
.getInt64() != dbl
) {
2102 errln("Round trip failure");
2110 * NumberFormat does not parse negative zero.
2113 NumberFormatRegressionTest::Test4162852(void)
2115 UErrorCode status
= U_ZERO_ERROR
;
2116 for(int32_t i
=0; i
< 2; ++i
) {
2117 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2118 : NumberFormat::createPercentInstance(status
);
2119 if(U_FAILURE(status
)) {
2120 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2128 f
->parse(s
, n
, status
);
2129 if(U_FAILURE(status
))
2130 errln("Couldn't parse!");
2131 double e
= n
.getDouble();
2132 logln(UnicodeString("") +
2134 '"' + s
+ '"' + " -> " + e
);
2135 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2138 if (e
!= 0.0 || 1.0/e
> 0.0) {
2140 logln("Failed to parse negative zero");
2146 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2149 * May 17 1999 sync up - liu
2151 * NumberFormat truncates data
2153 void NumberFormatRegressionTest::Test4167494(void) {
2154 UErrorCode status
= U_ZERO_ERROR
;
2155 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2156 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2161 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2165 fmt
->parse(s
, num
, status
);
2166 failure(status
, "Parse");
2167 if (num
.getType() == Formattable::kDouble
&&
2168 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2169 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2170 toString(num
) + " ok");
2172 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2173 toString(num
) + " FAIL");
2176 // We don't test Double.MIN_VALUE because the locale data for the US
2177 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2178 // This is correct for now; however, we leave this here as a reminder
2179 // in case we want to address this later.
2185 * May 17 1999 sync up - liu
2187 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2189 void NumberFormatRegressionTest::Test4170798(void) {
2190 UErrorCode status
= U_ZERO_ERROR
;
2191 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2192 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2196 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2198 errln("DecimalFormat needed to continue");
2201 df
->setParseIntegerOnly(TRUE
);
2203 ParsePosition
pos(0);
2204 df
->parse("-0.0", n
, pos
);
2205 if (n
.getType() != Formattable::kLong
2206 || n
.getLong() != 0) {
2207 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n
));
2213 * May 17 1999 sync up - liu
2214 * toPattern only puts the first grouping separator in.
2216 void NumberFormatRegressionTest::Test4176114(void) {
2217 const char* DATA
[] = {
2219 "000", "#000", // No grouping
2220 "#000", "#000", // No grouping
2224 "00,000", "#00,000",
2225 "000,000", "#,000,000",
2226 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2228 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2229 UErrorCode status
= U_ZERO_ERROR
;
2231 for (int i
=0; i
<DATA_length
; i
+=2) {
2232 DecimalFormat
df(DATA
[i
], status
);
2233 if (!failure(status
, "DecimalFormat constructor")) {
2235 UnicodeString
exp(DATA
[i
+1]);
2237 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2238 s
+ ", want " + exp
);
2245 * May 17 1999 sync up - liu
2247 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2249 void NumberFormatRegressionTest::Test4179818(void) {
2250 const char* DATA
[] = {
2251 // Input Pattern Expected output
2252 "1.2511", "#.#", "1.3",
2253 "1.2501", "#.#", "1.3",
2256 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2262 UErrorCode status
= U_ZERO_ERROR
;
2263 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2264 failure(status
, "Construct DecimalFormatSymbols");
2265 DecimalFormat
fmt("#", sym
, status
);
2266 if (!failure(status
, "Construct DecimalFormat")) {
2267 for (int i
=0; i
<DATA_length
; i
+=3) {
2268 double in
= DOUBLE
[i
/3];
2269 UnicodeString
pat(DATA
[i
+1]);
2270 UnicodeString
exp(DATA
[i
+2]);
2271 fmt
.applyPattern(pat
, status
);
2272 failure(status
, "applyPattern");
2275 fmt
.format(in
, out
, pos
);
2277 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2279 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2280 ", expected " + exp
);
2287 * May 17 1999 sync up - liu
2288 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2289 * This includes the minus sign, currency symbol, international currency
2290 * symbol, percent, and permille. This is filed as bugs 4212072 and
2293 void NumberFormatRegressionTest::Test4212072(void) {
2294 UErrorCode status
= U_ZERO_ERROR
;
2295 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2297 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2298 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2299 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2306 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2307 fmt
.setDecimalFormatSymbols(sym
);
2309 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2310 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2314 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2315 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2318 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2320 fmt
.applyPattern(UnicodeString("#%"), status
);
2321 failure(status
, "applyPattern percent");
2322 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2323 fmt
.setDecimalFormatSymbols(sym
);
2325 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2326 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2330 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2331 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2334 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2336 fmt
.applyPattern(str("#\\u2030"), status
);
2337 failure(status
, "applyPattern permill");
2338 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2339 fmt
.setDecimalFormatSymbols(sym
);
2341 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2342 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2346 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2347 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2350 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2352 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2353 failure(status
, "applyPattern currency");
2354 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2355 fmt
.setDecimalFormatSymbols(sym
);
2357 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) {
2358 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2362 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2363 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2366 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2368 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2369 failure(status
, "applyPattern intl currency");
2370 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2371 fmt
.setDecimalFormatSymbols(sym
);
2373 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) {
2374 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2378 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2379 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2382 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2384 // Since the pattern logic has changed, make sure that patterns round
2385 // trip properly. Test stream in/out integrity too.
2387 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2388 static const char* type
[] = {
2393 for (int i
=0; i
<n
; ++i
) {
2394 for (int j
=0; j
<3; ++j
) {
2395 status
= U_ZERO_ERROR
;
2399 nf
= NumberFormat::createInstance(avail
[i
], status
);
2400 failure(status
, "createInstance", avail
[i
]);
2403 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2404 failure(status
, "createCurrencyInstance", avail
[i
]);
2407 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2408 failure(status
, "createPercentInstance", avail
[i
]);
2411 if (U_FAILURE(status
)) {
2414 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2416 // Test toPattern/applyPattern round trip
2419 DecimalFormatSymbols
symb(avail
[i
], status
);
2420 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2421 DecimalFormat
f2(pat
, symb
, status
);
2423 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2428 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2430 "\" -> \"" + f2
.toPattern(p
) + "\"");
2433 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2438 // Test toLocalizedPattern/applyLocalizedPattern round trip
2439 df
->toLocalizedPattern(pat
);
2440 f2
.applyLocalizedPattern(pat
, status
);
2442 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2443 if (U_FAILURE(status
)) {
2447 // Make sure we set the currency attributes appropriately
2448 if (j
== 1) { // Currency format
2449 f2
.setCurrency(f2
.getCurrency(), status
);
2452 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2453 if (U_FAILURE(status
)) {
2459 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2460 " -> localized \"" + pat
+
2461 "\" -> \"" + f2
.toPattern(p
) + "\"");
2466 // Test writeObject/readObject round trip
2467 // NOT ON ICU -- Java only
2473 * May 17 1999 sync up - liu
2474 * DecimalFormat.parse() fails for mulipliers 2^n.
2476 void NumberFormatRegressionTest::Test4216742(void) {
2477 UErrorCode status
= U_ZERO_ERROR
;
2478 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2479 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2483 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2484 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2485 for (int i
=0; i
<DATA_length
; ++i
) {
2486 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2487 for (int m
= 1; m
<= 100; m
++) {
2488 fmt
->setMultiplier(m
);
2490 fmt
->parse(str
, num
, status
);
2491 failure(status
, "parse", Locale::getUS());
2492 if (num
.getType() != Formattable::kLong
&&
2493 num
.getType() != Formattable::kDouble
) {
2494 errln(UnicodeString("FAIL: Wanted number, got ") +
2497 double d
= num
.getType() == Formattable::kDouble
?
2498 num
.getDouble() : (double) num
.getLong();
2499 if ((d
> 0) != (DATA
[i
] > 0)) {
2500 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2501 fmt
->getMultiplier() +
2502 ") => " + toString(num
));
2511 * May 17 1999 sync up - liu
2512 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2515 void NumberFormatRegressionTest::Test4217661(void) {
2516 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2517 const char* S
[] = { "0", "1", "0.01", "1.01" };
2518 int D_length
= (int)(sizeof(D
) / sizeof(D
[0]));
2519 UErrorCode status
= U_ZERO_ERROR
;
2520 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2521 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2525 fmt
->setMaximumFractionDigits(2);
2526 for (int i
=0; i
<D_length
; i
++) {
2528 fmt
->format(D
[i
], s
);
2529 if (s
!= UnicodeString(S
[i
])) {
2530 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2537 * alphaWorks upgrade
2539 void NumberFormatRegressionTest::Test4161100(void) {
2540 UErrorCode status
= U_ZERO_ERROR
;
2541 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2542 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2546 nf
->setMinimumFractionDigits(1);
2547 nf
->setMaximumFractionDigits(1);
2552 logln(UnicodeString() + a
+ " x " +
2553 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2554 if (s
!= UnicodeString("-0.1")) {
2561 * June 16 1999 sync up - liu
2562 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2564 void NumberFormatRegressionTest::Test4243011(void) {
2565 UErrorCode status
= U_ZERO_ERROR
;
2566 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2567 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2568 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2570 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2571 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2572 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2573 int32_t N
= (int32_t)(sizeof(NUM
) / sizeof(NUM
[0]));
2575 for (int32_t i
=0; i
<N
; ++i
) {
2577 UnicodeString
exp(STR
[i
]);
2579 fmt
.format(NUM
[i
], str
, pos
);
2581 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2583 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2591 * June 16 1999 sync up - liu
2592 * format(0.0) gives "0.1" if preceded by parse("99.99").
2593 * (Regression in 1.2.2 RC1)
2595 void NumberFormatRegressionTest::Test4243108(void) {
2596 UErrorCode status
= U_ZERO_ERROR
;
2597 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2598 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2599 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2600 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2607 fmt
.format(0.0, str
, pos
);
2608 UnicodeString
exp("0");
2610 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2612 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2618 fmt
.parse(str
, val
, status
);
2619 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2620 if (val
.getType() == Formattable::kDouble
&&
2621 val
.getDouble() == 99.99) {
2622 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2624 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2629 fmt
.format(0.0, str
, pos
);
2631 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2633 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2640 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2641 * NumberFormat objects.
2643 void NumberFormatRegressionTest::TestJ691(void) {
2644 UErrorCode status
= U_ZERO_ERROR
;
2645 Locale
loc("fr", "CH");
2647 // set up the input date string & expected output
2648 UnicodeString
udt("11.10.2000", "");
2649 UnicodeString
exp("11.10.00", "");
2651 // create a Calendar for this locale
2652 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2653 if (U_FAILURE(status
)) {
2654 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2658 // create a NumberFormat for this locale
2659 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2660 if (U_FAILURE(status
)) {
2661 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2665 // *** Here's the key: We don't want to have to do THIS:
2666 // nf->setParseIntegerOnly(TRUE);
2668 // create the DateFormat
2669 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2670 if (U_FAILURE(status
)) {
2671 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2675 df
->adoptCalendar(cal
);
2676 df
->adoptNumberFormat(nf
);
2678 // set parsing to lenient & parse
2679 df
->setLenient(TRUE
);
2680 UDate ulocdat
= df
->parse(udt
, status
);
2682 // format back to a string
2683 UnicodeString outString
;
2684 df
->format(ulocdat
, outString
);
2686 if (outString
!= exp
) {
2687 errln("FAIL: " + udt
+ " => " + outString
);
2693 //---------------------------------------------------------------------------
2695 // Error Checking / Reporting macros
2697 //---------------------------------------------------------------------------
2698 #define TEST_CHECK_STATUS(status) \
2699 if (U_FAILURE(status)) {\
2700 errln("File %s, Line %d. status=%s\n", __FILE__, __LINE__, u_errorName(status));\
2704 #define TEST_ASSERT(expr) \
2705 if ((expr)==FALSE) {\
2706 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2710 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2712 void NumberFormatRegressionTest::Test8199(void) {
2713 UErrorCode status
= U_ZERO_ERROR
;
2714 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2716 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2719 TEST_CHECK_STATUS(status
);
2721 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2722 // should always truncate, no other rounding scheme.
2724 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2726 nf
->parse(numStr
, val
, status
);
2727 TEST_CHECK_STATUS(status
);
2728 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2729 TEST_ASSERT(1000000000 == val
.getInt64(status
));
2730 TEST_CHECK_STATUS(status
);
2731 TEST_ASSERT(1000000000.6 == val
.getDouble(status
));
2732 TEST_CHECK_STATUS(status
);
2734 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2735 // than int64 because of the fraction
2736 // even though int64 is more precise.
2737 nf
->parse(numStr
, val
, status
);
2738 TEST_CHECK_STATUS(status
);
2739 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2740 TEST_ASSERT(100000000000000001LL == val
.getInt64(status
));
2741 TEST_CHECK_STATUS(status
);
2742 TEST_ASSERT(100000000000000000.0 == val
.getDouble(status
));
2743 TEST_CHECK_STATUS(status
);
2745 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2746 nf
->parse(numStr
, val
, status
);
2747 TEST_CHECK_STATUS(status
);
2748 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2749 TEST_ASSERT(100000000000000000LL == val
.getInt64());
2750 TEST_ASSERT(1.0E17
== val
.getDouble(status
));
2751 TEST_CHECK_STATUS(status
);
2753 numStr
= "9223372036854775807"; // largest int64_t
2754 nf
->parse(numStr
, val
, status
);
2755 TEST_CHECK_STATUS(status
);
2756 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2757 TEST_ASSERT(9223372036854775807LL == val
.getInt64());
2758 // In the following check, note that a substantial range of integers will
2759 // convert to the same double value. There are also platform variations
2760 // in the rounding at compile time of double constants.
2761 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2762 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2763 TEST_CHECK_STATUS(status
);
2765 numStr
= "-9223372036854775808"; // smallest int64_t
2766 nf
->parse(numStr
, val
, status
);
2767 TEST_CHECK_STATUS(status
);
2768 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2769 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2770 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64());
2771 TEST_ASSERT(-9223372036854775808.0 == val
.getDouble(status
));
2772 TEST_CHECK_STATUS(status
);
2774 numStr
= "9223372036854775808"; // largest int64_t + 1
2775 nf
->parse(numStr
, val
, status
);
2776 TEST_CHECK_STATUS(status
);
2777 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2778 TEST_ASSERT(9223372036854775807LL == val
.getInt64(status
));
2779 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2780 status
= U_ZERO_ERROR
;
2781 TEST_ASSERT(9223372036854775810.0 == val
.getDouble(status
));
2782 TEST_CHECK_STATUS(status
);
2784 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2785 nf
->parse(numStr
, val
, status
);
2786 TEST_CHECK_STATUS(status
);
2787 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2788 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings
2789 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64(status
));
2790 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2791 status
= U_ZERO_ERROR
;
2792 TEST_ASSERT(-9223372036854775810.0 == val
.getDouble(status
));
2793 TEST_CHECK_STATUS(status
);
2795 // Test values near the limit of where doubles can represent all integers.
2796 // The implementation strategy of getInt64() changes at this boundary.
2797 // Strings to be parsed include a decimal fraction to force them to be
2798 // parsed as doubles rather than ints. The fraction is discarded
2799 // from the parsed double value because it is beyond what can be represented.
2801 status
= U_ZERO_ERROR
;
2802 numStr
= "9007199254740991.1"; // largest 53 bit int
2803 nf
->parse(numStr
, val
, status
);
2804 TEST_CHECK_STATUS(status
);
2805 // printf("getInt64() returns %lld\n", val.getInt64(status));
2806 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2807 TEST_ASSERT(9007199254740991LL == val
.getInt64(status
));
2808 TEST_ASSERT(9007199254740991.0 == val
.getDouble(status
));
2809 TEST_CHECK_STATUS(status
);
2811 status
= U_ZERO_ERROR
;
2812 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2813 nf
->parse(numStr
, val
, status
);
2814 TEST_CHECK_STATUS(status
);
2815 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2816 TEST_ASSERT(9007199254740992LL == val
.getInt64(status
));
2817 TEST_ASSERT(9007199254740992.0 == val
.getDouble(status
));
2818 TEST_CHECK_STATUS(status
);
2820 status
= U_ZERO_ERROR
;
2821 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2822 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2823 TEST_CHECK_STATUS(status
);
2824 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2825 TEST_ASSERT(9007199254740993LL == val
.getInt64(status
));
2826 TEST_ASSERT(9007199254740994.0 == val
.getDouble(status
));
2827 TEST_CHECK_STATUS(status
);
2832 void NumberFormatRegressionTest::Test9109(void) {
2833 UErrorCode status
= U_ZERO_ERROR
;
2836 DecimalFormat
fmt("+##", status
);
2837 fmt
.setLenient(TRUE
);
2839 if (U_FAILURE(status
)) {
2840 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2843 UnicodeString
text("123");
2844 int32_t expected
= 123;
2847 fmt
.parse(text
, val
, pos
);
2848 if (pos
.getErrorIndex() >= 0) {
2849 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2850 } else if (val
.getLong() != 123) {
2851 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2852 } else if (pos
.getIndex() != 3) {
2853 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2858 void NumberFormatRegressionTest::Test9780(void) {
2859 UErrorCode status
= U_ZERO_ERROR
;
2860 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2861 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2865 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2867 errln("DecimalFormat needed to continue");
2870 df
->setParseIntegerOnly(TRUE
);
2874 ParsePosition
pos(0);
2875 UnicodeString
toParse("1,234","");
2876 df
->parse(toParse
, n
, pos
);
2877 if (n
.getType() != Formattable::kLong
2878 || n
.getLong() != 1234) {
2879 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2882 // should still work in lenient mode, just won't get fastpath
2883 df
->setLenient(TRUE
);
2886 ParsePosition
pos(0);
2887 UnicodeString
toParse("1,234","");
2888 df
->parse(toParse
, n
, pos
);
2889 if (n
.getType() != Formattable::kLong
2890 || n
.getLong() != 1234) {
2891 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2898 void NumberFormatRegressionTest::Test9677(void) {
2899 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2900 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2901 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2902 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2903 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2905 UErrorCode status
= U_ZERO_ERROR
;
2906 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2907 if (U_FAILURE(status
)) {
2908 dataerrln("Failure opening unum_open");
2912 if (U_SUCCESS(status
)) {
2913 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2914 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2915 assertSuccess("setting attributes", status
);
2918 if(U_SUCCESS(status
)) {
2919 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2920 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2922 if(U_FAILURE(status
)) {
2923 logln("Got expected parse error %s\n", u_errorName(status
));
2924 status
= U_ZERO_ERROR
;
2926 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2930 if (U_SUCCESS(status
)) {
2931 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2932 assertSuccess("setting attributes", status
);
2933 logln("removed positive prefix");
2936 if(U_SUCCESS(status
)) {
2937 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2938 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2940 if(U_FAILURE(status
)) {
2941 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2942 status
= U_ZERO_ERROR
;
2945 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2947 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
2952 if(U_SUCCESS(status
)) {
2953 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2954 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2956 if(U_FAILURE(status
)) {
2957 logln("text2: Got expected parse error %s\n", u_errorName(status
));
2958 status
= U_ZERO_ERROR
;
2960 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2964 if (U_SUCCESS(status
)) {
2965 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
2966 assertSuccess("setting attributes", status
);
2967 logln("Set a different neg prefix prefix");
2970 if(U_SUCCESS(status
)) {
2971 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2972 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2974 if(U_FAILURE(status
)) {
2975 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
2976 status
= U_ZERO_ERROR
;
2980 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
2982 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
2989 #endif /* #if !UCONFIG_NO_FORMATTING */