1 /***********************************************************************
2 * Copyright (c) 1997-2014, 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
);
177 default: name
= ""; break;
182 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
184 if(U_FAILURE(status
)) {
185 if (possibleDataError
) {
186 dataerrln(UnicodeString("FAIL: ", "") + msg
187 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
189 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
190 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
199 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
201 if(U_FAILURE(status
)) {
202 if (possibleDataError
) {
203 dataerrln(UnicodeString("FAIL: ", "") + msg
204 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
206 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
207 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
216 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
218 if(U_FAILURE(status
)) {
219 if (possibleDataError
) {
220 dataerrln(UnicodeString("FAIL: ", "") + msg
221 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
223 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
224 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
233 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
235 inline UnicodeString
str(const char *input
)
237 return CharsToUnicodeString(input
);
241 * NumberFormat.equals comparing with null should always return false.
243 // {sfb} kind of silly in C++, just checking for new success
244 void NumberFormatRegressionTest::Test4075713(void)
247 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
249 logln("NumberFormat.equals passed");
250 /*} catch (NullPointerException e) {
251 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
258 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
261 void NumberFormatRegressionTest::Test4074620(void)
264 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
265 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
267 nf1
->setGroupingUsed(FALSE
);
268 nf2
->setGroupingUsed(TRUE
);
271 errln("Test for bug 4074620 failed");
273 logln("Test for bug 4074620 passed.");
281 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
284 void NumberFormatRegressionTest::Test4088161 (void)
286 UErrorCode status
= U_ZERO_ERROR
;
287 DecimalFormat
*df
= new DecimalFormat(status
);
288 if (!failure(status
, "new DecimalFormat", "")) {
290 df
->setMinimumFractionDigits(0);
291 df
->setMaximumFractionDigits(16);
293 FieldPosition
fp1(0);
294 logln(UnicodeString("d = ") + d
);
295 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
297 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
298 df
->setMaximumFractionDigits(17);
300 FieldPosition
fp2(0);
301 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
302 sBuf2
= df
->format(d
, sBuf2
, fp2
);
304 errln(" format(d) = '" + sBuf2
+ "'");
311 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
312 * DecimalFormat(String, DecimalFormatSymbols).
314 void NumberFormatRegressionTest::Test4087245 (void)
316 UErrorCode status
= U_ZERO_ERROR
;
317 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
318 failure(status
, "new DecimalFormatSymbols", "");
319 // {sfb} One note about this test: if you pass in a pointer
320 // to the symbols, they are adopted and this test will fail,
321 // even though that is the correct behavior. To test the cloning
322 // of the symbols, it is necessary to pass in a reference to the symbols
323 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
324 failure(status
, "new DecimalFormat with symbols", "");
328 FieldPosition
pos(FieldPosition::DONT_CARE
);
329 logln(UnicodeString("format(") + n
+ ") = " +
330 df
->format(n
, buf1
, pos
));
331 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
332 logln(UnicodeString("format(") + n
+ ") = " +
333 df
->format(n
, buf2
, pos
));
335 errln("Test for bug 4087245 failed");
342 * DecimalFormat.format() incorrectly formats 0.0
344 void NumberFormatRegressionTest::Test4087535 (void)
346 UErrorCode status
= U_ZERO_ERROR
;
347 DecimalFormat
*df
= new DecimalFormat(status
);
348 failure(status
, "new DecimalFormat", "");
349 df
->setMinimumIntegerDigits(0);
352 UnicodeString buffer
;
353 FieldPosition
pos(FieldPosition::DONT_CARE
);
354 buffer
= df
->format(n
, buffer
, pos
);
355 if (buffer
.length() == 0)
356 errln(/*n + */": '" + buffer
+ "'");
358 buffer
= df
->format(n
, buffer
, pos
);
359 if (buffer
.length() == 0)
360 errln(/*n + */": '" + buffer
+ "'");
366 * DecimalFormat.format fails when groupingSize is set to 0.
368 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
369 void NumberFormatRegressionTest::Test4088503 (void)
371 UErrorCode status
= U_ZERO_ERROR
;
372 DecimalFormat
*df
= new DecimalFormat(status
);
373 failure(status
, "new DecimalFormat", "");
374 df
->setGroupingSize(0);
376 FieldPosition
fp(FieldPosition::DONT_CARE
);
378 logln(df
->format((int32_t)123, sBuf
, fp
));
379 //if(fp == FieldPosition(0))
380 // errln("Test for bug 4088503 failed.");
381 /*} catch (Exception foo) {
382 errln("Test for bug 4088503 failed.");
388 * NumberFormat.getCurrencyInstance is wrong.
390 void NumberFormatRegressionTest::Test4066646 (void)
392 assignFloatValue(2.04f
);
393 assignFloatValue(2.03f
);
394 assignFloatValue(2.02f
);
395 assignFloatValue(0.0f
);
399 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
401 logln(UnicodeString(" VALUE ") + returnfloat
);
402 UErrorCode status
= U_ZERO_ERROR
;
403 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
404 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
408 nfcommon
->setGroupingUsed(FALSE
);
410 UnicodeString stringValue
;
411 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
412 logln(" DISPLAYVALUE " + stringValue
);
414 nfcommon
->parse(stringValue
, result
, status
);
415 failure(status
, "nfcommon->parse", Locale::getUS());
416 float floatResult
= (float) (result
.getType() == Formattable::kDouble
417 ? result
.getDouble() : result
.getLong());
418 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
419 //String stringValue = nfcommon.format(returnfloat).substring(1);
420 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
421 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
425 } // End Of assignFloatValue()
428 * DecimalFormat throws exception when parsing "0"
430 void NumberFormatRegressionTest::Test4059870(void)
432 UErrorCode status
= U_ZERO_ERROR
;
433 DecimalFormat
*format
= new DecimalFormat("00", status
);
434 failure(status
, "new Decimalformat", Locale::getUS());
438 format
->parse(UnicodeString("0"), result
, status
);
439 failure(status
, "format->parse", Locale::getUS());
442 catch (Exception e) {
443 errln("Test for bug 4059870 failed : " + e);
449 * DecimalFormatSymbol.equals should always return false when
450 * comparing with null.
452 // {sfb} this is silly in C++
453 void NumberFormatRegressionTest::Test4083018 (void)
455 UErrorCode status
= U_ZERO_ERROR
;
456 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
457 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
460 logln("Test Passed!");
462 errln("Test for bug 4083018 failed");
463 /*} catch (Exception foo) {
464 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
471 * DecimalFormat does not round up correctly.
473 void NumberFormatRegressionTest::Test4071492 (void)
475 double x
= 0.00159999;
476 UErrorCode status
= U_ZERO_ERROR
;
477 NumberFormat
*nf
= NumberFormat::createInstance(status
);
478 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
482 nf
->setMaximumFractionDigits(4);
484 FieldPosition
pos(FieldPosition::DONT_CARE
);
485 out
= nf
->format(x
, out
, pos
);
486 logln("0.00159999 formats with 4 fractional digits to " + out
);
487 UnicodeString
expected("0.0016");
489 errln("FAIL: Expected " + expected
);
495 * A space as a group separator for localized pattern causes
496 * wrong format. WorkAround : use non-breaking space.
498 void NumberFormatRegressionTest::Test4086575(void)
500 UErrorCode status
= U_ZERO_ERROR
;
501 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
503 // TODO: There is not a good way to find out that the creation of this number format has
504 // failed. Major rewiring of format construction proposed.
505 if(U_FAILURE(status
)) {
506 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
510 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
512 // C++ workaround to make sure cast works
513 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
515 errln("NumberFormat::createInstance returned incorrect type.");
520 logln("nf toPattern1: " + nf
->toPattern(temp
));
521 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
523 // No group separator
524 logln("...applyLocalizedPattern ###,00;(###,00) ");
525 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
526 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
527 logln("nf toPattern2: " + nf
->toPattern(temp
));
528 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
530 FieldPosition
pos(FieldPosition::DONT_CARE
);
531 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
532 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
534 // Space as group separator
536 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
538 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
540 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
541 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
543 UnicodeString
pat(patChars
, 19, 19);
544 nf
->applyLocalizedPattern(pat
, status
);
545 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
546 logln("nf toPattern2: " + nf
->toPattern(temp
));
547 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
548 UnicodeString buffer
;
549 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
550 //if (buffer != UnicodeString("1\u00a0234,00"))
552 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
554 UnicodeString
cc(c
, 8, 8);
556 errln("nf : " + buffer
); // Expect 1 234,00
559 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
561 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
563 UnicodeString
cc1(c1
, 10, 10);
565 errln("nf : " + buffer
); // Expect (1 234,00)
567 // Erroneously prints:
574 * DecimalFormat.parse returns wrong value
576 // {sfb} slightly converted into a round-trip test, since in C++
577 // there is no Double.toString()
578 void NumberFormatRegressionTest::Test4068693(void)
580 logln("----- Test Application -----");
581 ParsePosition
pos(0);
582 UErrorCode status
= U_ZERO_ERROR
;
583 DecimalFormat
*df
= new DecimalFormat(status
);
584 if(U_FAILURE(status
)) {
585 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
589 failure(status
, "new DecimalFormat");
591 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
592 df
->parse(UnicodeString("123.55456"), d
, pos
);
593 //if (!d.toString().equals("123.55456")) {
595 df
->setMaximumFractionDigits(999);
596 df
->setMaximumIntegerDigits(999);
597 FieldPosition
fp(FieldPosition::DONT_CARE
);
598 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
599 if (dstr
!= UnicodeString("123.55456")) {
600 errln(UnicodeString("Result -> ") + d
.getDouble());
606 /* @bug 4069754, 4067878
607 * null pointer thrown when accessing a deserialized DecimalFormat
610 // {sfb} doesn't apply in C++
611 void NumberFormatRegressionTest::Test4069754(void)
614 myformat it = new myformat();
616 FileOutputStream ostream = new FileOutputStream("t.tmp");
617 ObjectOutputStream p = new ObjectOutputStream(ostream);
622 FileInputStream istream = new FileInputStream("t.tmp");
623 ObjectInputStream p2 = new ObjectInputStream(istream);
624 myformat it2 = (myformat)p2.readObject();
628 } catch (Exception foo) {
629 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
634 * DecimalFormat.applyPattern(String) allows illegal patterns
636 void NumberFormatRegressionTest::Test4087251 (void)
638 UErrorCode status
= U_ZERO_ERROR
;
639 DecimalFormat
*df
= new DecimalFormat(status
);
640 if(U_FAILURE(status
)) {
641 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
645 failure(status
, "new DecimalFormat");
647 df
->applyPattern(UnicodeString("#.#.#"), status
);
648 if( ! U_FAILURE(status
))
649 errln("df->applyPattern with illegal pattern didn't fail");
651 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
652 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
653 /*} catch (IllegalArgumentException e) {
654 logln("Caught Illegal Argument Error !");
656 // Second test; added 5/11/98 when reported to fail on 1.2b3
658 df
->applyPattern("#0.0#0#0", status
);
659 if( ! U_FAILURE(status
))
660 errln("df->applyPattern with illegal pattern didn't fail");
661 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
662 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
663 /*} catch (IllegalArgumentException e) {
664 logln("Ok - IllegalArgumentException for #0.0#0#0");
671 * DecimalFormat.format() loses precision
673 void NumberFormatRegressionTest::Test4090489 (void)
675 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
676 // that NumberFormat can do. For some reason, it does not format the last 1.
678 /* UErrorCode status = U_ZERO_ERROR;
679 DecimalFormat *df = new DecimalFormat(status);
680 failure(status, "new DecimalFormat");
681 df->setMinimumFractionDigits(10);
682 df->setMaximumFractionDigits(999);
683 df->setGroupingUsed(FALSE);
684 double d = 1.000000000000001E7;
685 //BigDecimal bd = new BigDecimal(d);
688 logln(UnicodeString("d = ") + d);
689 //logln("BigDecimal.toString(): " + bd.toString());
690 df->format(d, sb, fp);
691 if (sb != "10000000.0000000100") {
692 errln("DecimalFormat.format(): " + sb);
698 * DecimalFormat.format() loses precision
700 void NumberFormatRegressionTest::Test4090504 (void)
703 logln(UnicodeString("d = ") + d
);
704 UErrorCode status
= U_ZERO_ERROR
;
705 DecimalFormat
*df
= new DecimalFormat(status
);
706 if(U_FAILURE(status
)) {
707 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
711 failure(status
, "new DecimalFormat");
713 FieldPosition
fp(FieldPosition::DONT_CARE
);
715 for (int i
= 17; i
<= 20; i
++) {
716 df
->setMaximumFractionDigits(i
);
717 //sb = new StringBuffer("");
719 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
720 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
722 /*} catch (Exception foo) {
723 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
729 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
731 void NumberFormatRegressionTest::Test4095713 (void)
733 UErrorCode status
= U_ZERO_ERROR
;
734 DecimalFormat
*df
= new DecimalFormat(status
);
735 if(U_FAILURE(status
)) {
736 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
740 failure(status
, "new DecimalFormat");
741 UnicodeString
str("0.1234");
743 //Double d1 = new Double(str);
744 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
747 df
->parse(str
, d2
, pp
);
748 logln(UnicodeString("") + d1
);
749 if (d2
.getDouble() != d1
)
750 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
755 * DecimalFormat.parse() fails when multiplier is not set to 1
757 // {sfb} not sure what to do with this one
758 void NumberFormatRegressionTest::Test4092561 (void)
760 UErrorCode status
= U_ZERO_ERROR
;
761 DecimalFormat
*df
= new DecimalFormat(status
);
762 if(U_FAILURE(status
)) {
763 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
767 failure(status
, "new DecimalFormat");
769 // {sfb} going to cheat here and use sprintf ??
771 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
772 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
773 df.setMultiplier(100);
774 Number num = df.parse(str, new ParsePosition(0));
775 if (num.doubleValue() != -9.223372036854776E16)
776 errln("Bug 4092561 test failed when multiplier is set to not 1.");
782 * DecimalFormat: Negative format ignored.
784 void NumberFormatRegressionTest::Test4092480 (void)
786 UErrorCode status
= U_ZERO_ERROR
;
787 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
788 if(U_FAILURE(status
)) {
789 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
793 failure(status
, "new DecimalFormat");
796 dfFoo
->applyPattern("0000;-000", status
);
797 failure(status
, "dfFoo->applyPattern");
799 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
800 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
801 FieldPosition
pos(FieldPosition::DONT_CARE
);
802 logln(dfFoo
->format((int32_t)42, temp
, pos
));
803 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
804 dfFoo
->applyPattern("000;-000", status
);
805 failure(status
, "dfFoo->applyPattern");
806 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
807 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
808 logln(dfFoo
->format((int32_t)42,temp
, pos
));
809 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
811 dfFoo
->applyPattern("000;-0000", status
);
812 failure(status
, "dfFoo->applyPattern");
813 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
814 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
815 logln(dfFoo
->format((int32_t)42, temp
, pos
));
816 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
818 dfFoo
->applyPattern("0000;-000", status
);
819 failure(status
, "dfFoo->applyPattern");
820 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
821 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
822 logln(dfFoo
->format((int32_t)42, temp
, pos
));
823 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
824 /*} catch (Exception foo) {
825 errln("Message " + foo.getMessage());
831 * NumberFormat.getCurrencyInstance() produces format that uses
832 * decimal separator instead of monetary decimal separator.
834 * Rewrote this test not to depend on the actual pattern. Pattern should
835 * never contain the monetary separator! Decimal separator in pattern is
836 * interpreted as monetary separator if currency symbol is seen!
838 void NumberFormatRegressionTest::Test4087244 (void) {
839 UErrorCode status
= U_ZERO_ERROR
;
841 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
842 Locale
*de
= new Locale(loc
);
843 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
844 if(U_FAILURE(status
)) {
845 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
849 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
851 errln("expected DecimalFormat!");
854 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
855 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
856 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
857 if (decSep
== monSep
) {
858 errln("ERROR in test: want decimal sep != monetary sep");
861 df
->setMinimumIntegerDigits(1);
862 df
->setMinimumFractionDigits(2);
865 df
->format(1.23, str
, pos
);
866 UnicodeString
monStr("1x23");
867 monStr
.replace((int32_t)1, 1, monSep
);
868 UnicodeString
decStr("1x23");
869 decStr
.replace((int32_t)1, 1, decSep
);
870 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
871 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
872 monStr
+ "\" and not \"" + decStr
+ '"');
874 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
876 "\" and not \"" + decStr
+ '"');
882 * Number format data rounding errors for locale FR
884 void NumberFormatRegressionTest::Test4070798 (void)
886 NumberFormat
*formatter
;
887 UnicodeString tempString
;
890 String expectedDefault = "-5\u00a0789,987";
891 String expectedCurrency = "5\u00a0789,98\u00a0F";
892 String expectedPercent = "-578\u00a0998%";
895 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
898 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
901 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
903 UnicodeString
expectedDefault(chars1
, 10, 10);
904 UnicodeString
expectedCurrency(chars2
, 10, 10);
905 UnicodeString
expectedPercent(chars3
, 10, 10);
907 UErrorCode status
= U_ZERO_ERROR
;
909 int len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
910 (void)len
; // Suppress set but not used warning.
911 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
912 if(U_FAILURE(status
)) {
913 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
917 failure(status
, "NumberFormat::createNumberInstance", loc
);
918 tempString
= formatter
->format (-5789.9876, tempString
);
920 if (tempString
== expectedDefault
) {
921 logln ("Bug 4070798 default test passed.");
923 errln(UnicodeString("Failed:") +
924 " Expected " + expectedDefault
+
925 " Received " + tempString
);
928 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
929 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
930 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
932 tempString
= formatter
->format( 5789.9876, tempString
);
934 if (tempString
== expectedCurrency
) {
935 logln ("Bug 4070798 currency test passed.");
937 errln(UnicodeString("Failed:") +
938 " Expected " + expectedCurrency
+
939 " Received " + tempString
);
943 uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
944 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
945 failure(status
, "NumberFormat::createPercentInstance", loc
);
947 tempString
= formatter
->format (-5789.9876, tempString
);
949 if (tempString
== expectedPercent
) {
950 logln ("Bug 4070798 percentage test passed.");
952 errln(UnicodeString("Failed:") +
953 " Expected " + expectedPercent
+
954 " Received " + tempString
);
960 * Data rounding errors for French (Canada) locale
962 void NumberFormatRegressionTest::Test4071005 (void)
964 NumberFormat
*formatter
;
965 UnicodeString tempString
;
967 String expectedDefault = "-5\u00a0789,987";
968 String expectedCurrency = "5\u00a0789,98\u00a0$";
969 String expectedPercent = "-578\u00a0998%";
972 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
975 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
978 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
980 UnicodeString
expectedDefault(chars1
, 10, 10);
981 UnicodeString
expectedCurrency(chars2
, 10, 10);
982 UnicodeString
expectedPercent(chars3
, 10, 10);
984 UErrorCode status
= U_ZERO_ERROR
;
985 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
986 if (failure(status
, "NumberFormat::createNumberInstance", Locale::getCanadaFrench(), TRUE
)){
990 tempString
= formatter
->format (-5789.9876, tempString
);
992 if (tempString
== expectedDefault
) {
993 logln ("Bug 4071005 default test passed.");
995 errln(UnicodeString("Failed:") +
996 " Expected " + expectedDefault
+
997 " Received " + tempString
);
1001 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
1002 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1003 tempString
.remove();
1004 tempString
= formatter
->format( 5789.9876, tempString
);
1006 if (tempString
== expectedCurrency
) {
1007 logln ("Bug 4071005 currency test assed.");
1009 errln(UnicodeString("Failed:") +
1010 " Expected " + expectedCurrency
+
1011 " Received " + tempString
);
1015 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1016 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1017 tempString
.remove();
1018 tempString
= formatter
->format (-5789.9876, tempString
);
1020 if (tempString
== expectedPercent
) {
1021 logln ("Bug 4071005 percentage test passed.");
1023 errln(UnicodeString("Failed:") +
1024 " Expected " + expectedPercent
+
1025 " Received " + tempString
);
1032 * Data rounding errors for German (Germany) locale
1034 void NumberFormatRegressionTest::Test4071014 (void)
1036 NumberFormat
*formatter
;
1037 UnicodeString tempString
;
1039 String expectedDefault = "-5.789,987";
1040 String expectedCurrency = "5.789,98 DM";
1041 String expectedPercent = "-578.998%";
1043 UnicodeString
expectedDefault("-5.789,988");
1044 UnicodeString
expectedCurrency("5.789,99\\u00A0DM");
1045 UnicodeString
expectedPercent("-578.999\\u00A0%");
1047 expectedCurrency
= expectedCurrency
.unescape();
1048 expectedPercent
= expectedPercent
.unescape();
1050 UErrorCode status
= U_ZERO_ERROR
;
1052 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1053 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1054 if (failure(status
, "NumberFormat::createNumberInstance", loc
, TRUE
)){
1058 tempString
.remove();
1059 tempString
= formatter
->format (-5789.9876, tempString
);
1061 if (tempString
== expectedDefault
) {
1062 logln ("Bug 4071014 default test passed.");
1064 errln(UnicodeString("Failed:") +
1065 " Expected " + expectedDefault
+
1066 " Received " + tempString
);
1069 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1070 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1071 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1072 tempString
.remove();
1073 tempString
= formatter
->format( 5789.9876, tempString
);
1075 if (tempString
== expectedCurrency
) {
1076 logln ("Bug 4071014 currency test assed.");
1078 errln(UnicodeString("Failed:") +
1079 " Expected " + expectedCurrency
+
1080 " Received " + tempString
);
1084 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1085 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1086 tempString
.remove();
1087 tempString
= formatter
->format (-5789.9876, tempString
);
1089 if (tempString
== expectedPercent
) {
1090 logln ("Bug 4071014 percentage test passed.");
1092 errln(UnicodeString("Failed:") +
1093 " Expected " + expectedPercent
+
1094 " Received " + tempString
);
1100 * Data rounding errors for Italian locale number formats
1102 void NumberFormatRegressionTest::Test4071859 (void)
1104 NumberFormat
*formatter
;
1105 UnicodeString tempString
;
1107 String expectedDefault = "-5.789,987";
1108 String expectedCurrency = "-L.\\u00A05.789,98";
1109 String expectedPercent = "-578.998%";
1111 UnicodeString
expectedDefault("-5.789,988");
1112 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1113 UnicodeString
expectedPercent("-578.999%");
1114 expectedCurrency
= expectedCurrency
.unescape();
1116 UErrorCode status
= U_ZERO_ERROR
;
1118 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1119 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1120 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1124 tempString
= formatter
->format (-5789.9876, tempString
);
1126 if (tempString
== expectedDefault
) {
1127 logln ("Bug 4071859 default test passed.");
1129 errln(UnicodeString("Failed:") +
1130 " Expected " + expectedDefault
+
1131 " Received " + tempString
);
1134 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1135 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1136 failure(status
, "NumberFormat::createCurrencyInstance");
1137 tempString
.remove();
1138 tempString
= formatter
->format( -5789.9876, tempString
);
1140 if (tempString
== expectedCurrency
) {
1141 logln ("Bug 4071859 currency test assed.");
1143 errln(UnicodeString("Failed:") +
1144 " Expected " + expectedCurrency
+
1145 " Received " + tempString
);
1148 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1149 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1150 failure(status
, "NumberFormat::createPercentInstance");
1151 tempString
.remove();
1152 tempString
= formatter
->format (-5789.9876, tempString
);
1154 if (tempString
== expectedPercent
) {
1155 logln ("Bug 4071859 percentage test passed.");
1157 errln(UnicodeString("Failed:") +
1158 " Expected " + expectedPercent
+
1159 " Received " + tempString
);
1165 * Test rounding for nearest even.
1167 void NumberFormatRegressionTest::Test4093610(void)
1169 UErrorCode status
= U_ZERO_ERROR
;
1170 DecimalFormat
*df
= new DecimalFormat("#0.#", status
);
1171 if (!failure(status
, "new DecimalFormat")) {
1172 UnicodeString
s("12.4");
1173 roundingTest(df
, 12.35, s
);
1174 roundingTest(df
, 12.45, s
);
1176 roundingTest(df
, 12.452,s
);
1178 roundingTest(df
, 12.55, s
);
1179 roundingTest(df
, 12.65, s
);
1181 roundingTest(df
, 12.652,s
);
1183 roundingTest(df
, 12.75, s
);
1184 roundingTest(df
, 12.752,s
);
1185 roundingTest(df
, 12.85, s
);
1187 roundingTest(df
, 12.852,s
);
1189 roundingTest(df
, 12.95, s
);
1190 roundingTest(df
, 12.952,s
);
1196 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1199 FieldPosition
pos(FieldPosition::DONT_CARE
);
1200 out
= df
->format(x
, out
, pos
);
1201 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1202 if (out
!= expected
)
1203 errln("FAIL: Expected " + expected
);
1206 * Tests the setMaximumFractionDigits limit.
1208 void NumberFormatRegressionTest::Test4098741(void)
1211 UErrorCode status
= U_ZERO_ERROR
;
1212 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1213 if (U_FAILURE(status
)) {
1214 dataerrln("Error calling NumberFormat::createPercentInstance");
1219 fmt
->setMaximumFractionDigits(20);
1221 logln(fmt
->format(.001, temp
));
1222 /*} catch (Exception foo) {
1223 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1228 * Tests illegal pattern exception.
1229 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1230 * Part2 has been fixed.
1232 void NumberFormatRegressionTest::Test4074454(void)
1235 UErrorCode status
= U_ZERO_ERROR
;
1236 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1237 if(U_FAILURE(status
)) {
1238 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1242 failure(status
, "new DecimalFormat");
1243 logln("Inconsistent negative pattern is fine.");
1244 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1245 failure(status
, "new DecimalFormat");
1246 UnicodeString tempString
;
1247 FieldPosition
pos(FieldPosition::DONT_CARE
);
1248 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1249 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1250 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1251 /*} catch (Exception foo) {
1252 errln("An exception was thrown for any inconsistent negative pattern.");
1259 * Tests all different comments.
1260 * Response to some comments :
1261 * [1] DecimalFormat.parse API documentation is more than just one line.
1262 * This is not a reproducable doc error in 116 source code.
1263 * [2] See updated javadoc.
1265 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1266 * a null object will be returned. The unchanged parse position also
1267 * reflects an error.
1268 * NumberFormat.parse(String) : If parsing fails, an ParseException
1270 * See updated javadoc for more details.
1271 * [5] See updated javadoc.
1272 * [6] See updated javadoc.
1273 * [7] This is a correct behavior if the DateFormat object is linient.
1274 * Otherwise, an IllegalArgumentException will be thrown when formatting
1275 * "January 35". See GregorianCalendar class javadoc for more details.
1277 void NumberFormatRegressionTest::Test4099404(void)
1280 UErrorCode status
= U_ZERO_ERROR
;
1281 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1282 if(! U_FAILURE(status
))
1283 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1284 /*} catch (Exception foo) {
1285 logln("Bug 4099404 pattern \"000.0#0\" passed");
1290 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1291 if( !U_FAILURE(status
))
1292 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1293 /*} catch (Exception foo) {
1294 logln("Bug 4099404 pattern \"0#0.000\" passed");
1300 * DecimalFormat.applyPattern doesn't set minimum integer digits
1302 void NumberFormatRegressionTest::Test4101481(void)
1304 UErrorCode status
= U_ZERO_ERROR
;
1305 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1306 if(U_FAILURE(status
)) {
1307 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1311 failure(status
, "new DecimalFormat");
1312 if (sdf
->getMinimumIntegerDigits() != 1)
1313 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1316 /* @bug 4052223 (API addition request A27)
1317 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1319 void NumberFormatRegressionTest::Test4052223(void)
1322 UErrorCode status
= U_ZERO_ERROR
;
1323 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1324 if(U_FAILURE(status
)) {
1325 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1329 failure(status
, "new DecimalFormat");
1331 fmt
->parse(UnicodeString("abc3"), num
, status
);
1332 if(! U_FAILURE(status
))
1333 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1334 /*} catch (ParseException foo) {
1335 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1340 * API tests for API addition request A9.
1342 void NumberFormatRegressionTest::Test4061302(void)
1344 UErrorCode status
= U_ZERO_ERROR
;
1345 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1346 failure(status
, "new DecimalFormatSymbols");
1347 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1348 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1349 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1350 if (currency
== UnicodeString("") ||
1351 intlCurrency
== UnicodeString("") ||
1352 monDecSeparator
== UnicodeString(""))
1354 errln("getCurrencySymbols failed, got empty string.");
1356 UnicodeString monDecSeparatorStr
;
1357 monDecSeparatorStr
.append(monDecSeparator
);
1358 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1359 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1360 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1361 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1362 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1363 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1364 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1365 if (currency
!= UnicodeString("XYZ") ||
1366 intlCurrency
!= UnicodeString("ABC") ||
1367 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1368 errln("setCurrencySymbols failed.");
1370 monDecSeparatorStr
.remove();
1371 monDecSeparatorStr
.append(monDecSeparator
);
1372 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1377 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1378 * FieldPosition.getEndIndex.
1380 void NumberFormatRegressionTest::Test4062486(void)
1382 UErrorCode status
= U_ZERO_ERROR
;
1383 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1384 failure(status
, "new DecimalFormat");
1385 UnicodeString formatted
;
1386 FieldPosition
field(0);
1387 double num
= 1234.5;
1388 fmt
->format(num
, formatted
, field
);
1389 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1390 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1391 field
.setBeginIndex(7);
1392 field
.setEndIndex(4);
1393 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1394 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1400 * DecimalFormat.parse incorrectly works with a group separator.
1402 void NumberFormatRegressionTest::Test4108738(void)
1404 UErrorCode status
= U_ZERO_ERROR
;
1405 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1406 failure(status
, "new DecimalFormatSymbols");
1407 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1408 if(U_FAILURE(status
)) {
1409 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1413 failure(status
, "new DecimalFormat");
1414 UnicodeString
text("1.222,111");
1416 ParsePosition
pp(0);
1417 df
->parse(text
, num
, pp
);
1419 // {sfb} how to do this (again) ?
1420 // shouldn't just be another round-trip test, should it?
1422 FieldPosition
pos(FieldPosition::DONT_CARE
);
1423 temp
= df
->format(num
.getDouble(), temp
, pos
);
1424 //if (!num.toString().equals("1.222"))
1425 if (temp
!= UnicodeString("1.222"))
1426 //errln("\"" + text + "\" is parsed as " + num);
1427 errln("\"" + text
+ "\" is parsed as " + temp
);
1428 text
= UnicodeString("1.222x111");
1429 pp
= ParsePosition(0);
1430 df
->parse(text
, num
, pp
);
1432 temp
= df
->format(num
.getDouble(), temp
, pos
);
1433 //if (!num.toString().equals("1.222"))
1434 if (temp
!= UnicodeString("1.222"))
1435 errln("\"" + text
+ "\" is parsed as " + temp
);
1441 * DecimalFormat.format() incorrectly formats negative doubles.
1443 void NumberFormatRegressionTest::Test4106658(void)
1445 UErrorCode status
= U_ZERO_ERROR
;
1446 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1447 if(U_FAILURE(status
)) {
1448 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1452 failure(status
, "new DecimalFormat");
1453 volatile double d1
= 0.0; // volatile to prevent code optimization
1454 double d2
= -0.0001;
1455 UnicodeString buffer
;
1457 FieldPosition
pos(FieldPosition::DONT_CARE
);
1459 #if U_PLATFORM == U_PF_HPUX
1460 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1462 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1464 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1465 df
->format(d1
, buffer
, pos
);
1466 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1467 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1469 df
->format(d2
, buffer
, pos
);
1470 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1471 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1477 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1479 void NumberFormatRegressionTest::Test4106662(void)
1481 UErrorCode status
= U_ZERO_ERROR
;
1482 DecimalFormat
*df
= new DecimalFormat(status
);
1483 if(U_FAILURE(status
)) {
1484 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1488 failure(status
, "new DecimalFormat");
1489 UnicodeString
text("x");
1490 ParsePosition
pos1(0), pos2(0);
1493 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1495 df
->parse(text
, num
, pos1
);
1496 if (pos1
== ParsePosition(0)/*num != null*/) {
1497 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1500 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1501 failure(status
, "new DecimalFormat");
1502 df
->parse(UnicodeString("$"), num
, pos2
);
1503 if (pos2
== ParsePosition(0) /*num != null*/){
1504 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1510 /* @bug 4114639 (duplicate of 4106662)
1511 * NumberFormat.parse doesn't return null
1513 void NumberFormatRegressionTest::Test4114639(void)
1515 UErrorCode status
= U_ZERO_ERROR
;
1516 NumberFormat
*format
= NumberFormat::createInstance(status
);
1517 if(U_FAILURE(status
)) {
1518 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1522 failure(status
, "NumberFormat::createInstance");
1523 UnicodeString
text("time 10:x");
1524 ParsePosition
pos(8);
1526 format
->parse(text
, result
, pos
);
1527 if (/*result != null*/pos
.getErrorIndex() != 8)
1528 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1534 * TODO: this test does not work because we need to use a 64 bit number and a
1535 * a double only MAY only have 52 bits of precision.
1536 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1538 void NumberFormatRegressionTest::Test4106664(void)
1540 UErrorCode status
= U_ZERO_ERROR
;
1541 DecimalFormat
*df
= new DecimalFormat(status
);
1542 if(U_FAILURE(status
)) {
1543 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1547 failure(status
, "new DecimalFormat");
1548 // {sfb} long in java is 64 bits
1549 /*long*/double n
= 1234567890123456.0;
1550 /*int*/int32_t m
= 12345678;
1551 // {sfb} will this work?
1552 //BigInteger bigN = BigInteger.valueOf(n);
1553 //bigN = bigN.multiply(BigInteger.valueOf(m));
1554 double bigN
= n
* m
;
1555 df
->setMultiplier(m
);
1556 df
->setGroupingUsed(FALSE
);
1558 FieldPosition
pos(FieldPosition::DONT_CARE
);
1559 logln("formated: " +
1560 df
->format(n
, temp
, pos
));
1563 sprintf(buf
, "%g", bigN
);
1564 //logln("expected: " + bigN.toString());
1565 logln(UnicodeString("expected: ") + buf
);
1569 /* @bug 4106667 (duplicate of 4106658)
1570 * DecimalFormat.format incorrectly formats -0.0.
1572 void NumberFormatRegressionTest::Test4106667(void)
1574 UErrorCode status
= U_ZERO_ERROR
;
1575 DecimalFormat
*df
= new DecimalFormat(status
);
1576 if(U_FAILURE(status
)) {
1577 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1581 failure(status
, "new DecimalFormat");
1582 UChar foo
[] = { 0x002B };
1583 UnicodeString
bar(foo
, 1, 1);
1584 volatile double d
= 0.0; // volatile to prevent code optimization
1586 UnicodeString buffer
;
1587 FieldPosition
pos(FieldPosition::DONT_CARE
);
1589 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1590 #if U_PLATFORM == U_PF_HPUX
1591 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1593 d
*= -1.0; // Some compilers have a problem with defining -0.0
1595 df
->setPositivePrefix(/*"+"*/bar
);
1596 df
->format(d
, buffer
, pos
);
1597 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1598 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1604 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1606 #if U_PLATFORM == U_PF_OS390
1607 # define MAX_INT_DIGITS 70
1609 # define MAX_INT_DIGITS 128
1612 void NumberFormatRegressionTest::Test4110936(void)
1614 UErrorCode status
= U_ZERO_ERROR
;
1615 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1616 if(U_FAILURE(status
)) {
1617 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1621 failure(status
, "NumberFormat::createInstance");
1622 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1623 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1624 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1625 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1626 nf
->getMaximumIntegerDigits());
1632 * Locale data should use generic currency symbol
1634 * 1) Make sure that all currency formats use the generic currency symbol.
1635 * 2) Make sure we get the same results using the generic symbol or a
1638 void NumberFormatRegressionTest::Test4122840(void)
1641 const Locale
*locales
= Locale::getAvailableLocales(count
);
1643 for (int i
= 0; i
< count
; i
++) {
1644 UErrorCode status
= U_ZERO_ERROR
;
1645 ResourceBundle
*rb
= new ResourceBundle(
1646 NULL
/*"java.text.resources.LocaleElements"*/,
1647 locales
[i
], status
);
1648 failure(status
, "new ResourceBundle");
1649 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1650 failure(status
, "rb.get(NumberElements)");
1651 numPat
= numPat
.getWithFallback("latn",status
);
1652 failure(status
, "rb.get(latn)");
1653 numPat
= numPat
.getWithFallback("patterns",status
);
1654 failure(status
, "rb.get(patterns)");
1655 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1656 failure(status
, "rb.get(currencyFormat)");
1658 // Get the currency pattern for this locale. We have to fish it
1659 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1660 // will return the localized symbol, not \00a4
1662 UnicodeString pattern
= numPat
.getString(status
);
1663 failure(status
, "rb->getString()");
1665 UChar fo
[] = { 0x00A4 };
1666 UnicodeString
foo(fo
, 1, 1);
1668 //if (pattern.indexOf("\u00A4") == -1 ) {
1669 if (pattern
.indexOf(foo
) == -1 ) {
1670 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1671 " does not contain generic currency symbol:" +
1675 // Create a DecimalFormat using the pattern we got and format a number
1676 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1677 failure(status
, "new DecimalFormatSymbols");
1678 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1679 failure(status
, "new DecimalFormat");
1681 UnicodeString result1
;
1682 FieldPosition
pos(FieldPosition::DONT_CARE
);
1683 result1
= fmt1
->format(1.111, result1
, pos
);
1686 // Now substitute in the locale's currency symbol and create another
1687 // pattern. We have to skip locales where the currency symbol
1688 // contains decimal separators, because that confuses things
1690 UChar ba
[] = { 0x002E/*'.'*/ };
1691 UnicodeString
bar(ba
, 1, 1);
1693 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1694 // {sfb} Also, switch the decimal separator to the monetary decimal
1695 // separator to mimic the behavior of a currency format
1696 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1697 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1699 UnicodeString
buf(pattern
);
1700 for (int j
= 0; j
< buf
.length(); j
++) {
1701 if (buf
[j
] == 0x00a4 ) {
1702 if(buf
[j
+ 1] == 0x00a4) {
1703 // {sfb} added to support double currency marker (intl currency sign)
1704 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1705 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1708 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1709 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1714 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1715 failure(status
, "new DecimalFormat");
1717 // Get the currency (if there is one) so we can set the rounding and fraction
1718 const UChar
*currency
= fmt1
->getCurrency();
1719 if (*currency
!= 0) {
1720 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1721 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1722 if (U_SUCCESS(status
)) {
1723 fmt2
->setRoundingIncrement(rounding
);
1724 fmt2
->setMinimumFractionDigits(frac
);
1725 fmt2
->setMaximumFractionDigits(frac
);
1728 failure(status
, "Fetching currency rounding/fractions");
1732 UnicodeString result2
;
1733 fmt2
->format(1.111, result2
, pos
);
1735 if (result1
!= result2
) {
1736 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1737 result1
+ " vs " + result2
);
1750 * DecimalFormat.format() delivers wrong string.
1752 void NumberFormatRegressionTest::Test4125885(void)
1754 UErrorCode status
= U_ZERO_ERROR
;
1755 double rate
= 12.34;
1756 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1757 if(U_FAILURE(status
)) {
1758 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1762 failure(status
, "new DecimalFormat");
1764 logln("toPattern: " + formatDec
->toPattern(temp
));
1765 UnicodeString rateString
;
1766 FieldPosition
pos(FieldPosition::DONT_CARE
);
1767 rateString
= formatDec
->format(rate
, rateString
, pos
);
1768 if (rateString
!= UnicodeString("012.34"))
1769 errln("result : " + rateString
+ " expected : 012.34");
1771 delete formatDec
;// = null;
1772 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1773 failure(status
, "new DecimalFormat");
1774 logln("toPattern: " + formatDec
->toPattern(temp
));
1775 rateString
.remove();
1776 rateString
= formatDec
->format(rate
, rateString
, pos
);
1777 if (rateString
!= UnicodeString("+012.34%"))
1778 errln("result : " + rateString
+ " expected : +012.34%");
1785 * DecimalFormat produces extra zeros when formatting numbers.
1787 void NumberFormatRegressionTest::Test4134034(void)
1789 UErrorCode status
= U_ZERO_ERROR
;
1790 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1791 if (!failure(status
, "new DecimalFormat")) {
1793 FieldPosition
pos(FieldPosition::DONT_CARE
);
1794 f
= nf
->format(9.02, f
, pos
);
1795 if (f
== UnicodeString("9.02"))
1798 errln("9.02 -> " + f
+ "; want 9.02");
1801 f
= nf
->format((int32_t)0, f
, pos
);
1802 if (f
== UnicodeString(".00"))
1805 errln("0 -> " + f
+ "; want .00");
1813 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1814 * a duplicate of 4134034.
1816 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1817 * Possibly related to bug 4125885.
1819 * This class demonstrates a regression in version 1.1.6
1820 * of DecimalFormat class.
1823 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1824 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1825 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1826 * Value 1.2 Format #0.0# Result '1.2'
1827 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1830 * Value 1.2 Format #.00 Result '1.20'
1831 * Value 1.2 Format 0.00 Result '1.20'
1832 * Value 1.2 Format 00.00 Result '01.20'
1833 * Value 1.2 Format #0.0# Result '1.2'
1834 * Value 1.2 Format #0.00 Result '1.20'
1836 void NumberFormatRegressionTest::Test4134300(void) {
1837 UnicodeString DATA
[] = {
1838 // Pattern Expected string
1839 UnicodeString("#.00"), UnicodeString("1.20"),
1840 UnicodeString("0.00"), UnicodeString("1.20"),
1841 UnicodeString("00.00"), UnicodeString("01.20"),
1842 UnicodeString("#0.0#"), UnicodeString("1.2"),
1843 UnicodeString("#0.00"), UnicodeString("1.20")
1846 for (int i
=0; i
< 10; i
+=2) {
1847 UnicodeString result
;
1848 UErrorCode status
= U_ZERO_ERROR
;
1849 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1850 if (!failure(status
, "new DecimalFormat")) {
1851 FieldPosition
pos(FieldPosition::DONT_CARE
);
1852 result
= df
->format(1.2, result
, pos
);
1853 if (result
!= DATA
[i
+1]) {
1854 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1855 "; want " + DATA
[i
+1]);
1858 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1868 * Empty pattern produces double negative prefix.
1870 void NumberFormatRegressionTest::Test4140009(void)
1872 UErrorCode status
= U_ZERO_ERROR
;
1873 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
1874 failure(status
, "new DecimalFormatSymbols");
1875 DecimalFormat
*f
= new DecimalFormat(UnicodeString(""), syms
, status
);
1876 if (!failure(status
, "new DecimalFormat")) {
1878 FieldPosition
pos(FieldPosition::DONT_CARE
);
1879 s
= f
->format(123.456, s
, pos
);
1880 if (s
!= UnicodeString("123.456"))
1881 errln("Fail: Format empty pattern x 123.456 => " + s
);
1883 s
= f
->format(-123.456, s
, pos
);
1884 if (s
!= UnicodeString("-123.456"))
1885 errln("Fail: Format empty pattern x -123.456 => " + s
);
1892 * BigDecimal numbers get their fractions truncated by NumberFormat.
1894 // {sfb} not pertinent in C++ ??
1895 void NumberFormatRegressionTest::Test4141750(void) {
1897 UnicodeString str("12345.67");
1898 BigDecimal bd = new BigDecimal(str);
1899 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1900 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1902 catch (Exception e) {
1903 errln(e.toString());
1904 e.printStackTrace();
1910 * DecimalFormat toPattern() doesn't quote special characters or handle
1913 void NumberFormatRegressionTest::Test4145457() {
1915 UErrorCode status
= U_ZERO_ERROR
;
1916 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1917 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1921 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1923 errln("DecimalFormat needed to continue");
1927 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1928 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1929 nf
->setDecimalFormatSymbols(*sym
);
1930 double pi
= 3.14159;
1932 UnicodeString PATS
[] = {
1933 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1936 for (int32_t i
=0; i
<2; ++i
) {
1937 nf
->applyPattern(PATS
[i
], status
);
1938 failure(status
, "nf->applyPattern");
1940 FieldPosition
pos(FieldPosition::DONT_CARE
);
1941 out
= nf
->format(pi
, out
, pos
);
1943 pat
= nf
->toPattern(pat
);
1945 ParsePosition
pp(0);
1946 nf
->parse(out
, num
, pp
);
1947 double val
= num
.getDouble();
1949 nf
->applyPattern(pat
, status
);
1950 failure(status
, "nf->applyPattern");
1952 out2
= nf
->format(pi
, out2
, pos
);
1954 pat2
= nf
->toPattern(pat2
);
1956 nf
->parse(out2
, num
, pp
);
1957 double val2
= num
.getDouble();
1960 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1961 pat
+ "\" vs. \"" + pat2
+ "\"");
1963 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1965 if (val
== val2
&& out
== out2
) {
1966 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1967 out
+ "\" -> " + val
+ " -> \"" +
1968 out2
+ "\" -> " + val2
);
1971 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1972 out
+ "\" -> " + val
+ " -> \"" +
1973 out2
+ "\" -> " + val2
);
1977 catch (ParseException e) {
1978 errln("Fail: " + e);
1979 e.printStackTrace();
1987 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
1989 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
1991 void NumberFormatRegressionTest::Test4147295(void)
1993 UErrorCode status
= U_ZERO_ERROR
;
1994 DecimalFormat
*sdf
= new DecimalFormat(status
);
1995 UnicodeString
pattern("#,###");
1996 logln("Applying pattern \"" + pattern
+ "\"");
1997 sdf
->applyPattern(pattern
, status
);
1998 if (!failure(status
, "sdf->applyPattern")) {
1999 int minIntDig
= sdf
->getMinimumIntegerDigits();
2000 if (minIntDig
!= 0) {
2001 errln("Test failed");
2002 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2004 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2006 logln("Test passed");
2007 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2015 * DecimalFormat formats -0.0 as +0.0
2016 * See also older related bug 4106658, 4106667
2018 void NumberFormatRegressionTest::Test4147706(void)
2020 UErrorCode status
= U_ZERO_ERROR
;
2021 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2022 failure(status
, "new DecimalFormat");
2023 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2024 if (!failure(status
, "new DecimalFormatSymbols")) {
2026 UnicodeString f2
, temp
;
2027 FieldPosition
pos(FieldPosition::DONT_CARE
);
2028 volatile double d1
= 0.0; // volatile to prevent code optimization
2029 double d2
= -0.0001;
2031 #if U_PLATFORM == U_PF_HPUX
2032 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2034 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2036 df
->adoptDecimalFormatSymbols(syms
);
2037 f1
= df
->format(d1
, f1
, pos
);
2038 f2
= df
->format(d2
, f2
, pos
);
2039 if (f1
!= UnicodeString("-0.0")) {
2040 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2042 if (f2
!= UnicodeString("-0.0")) {
2043 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2051 // Not applicable, since no serialization in C++
2052 /*class myformat implements Serializable
2054 DateFormat _dateFormat = DateFormat.getDateInstance();
2058 GregorianCalendar calendar = new GregorianCalendar();
2059 Date t = calendar.getTime();
2060 String nowStr = _dateFormat.format(t);
2067 * NumberFormat cannot format Double.MAX_VALUE
2069 // TODO: make this test actually test something
2071 NumberFormatRegressionTest::Test4162198(void)
2073 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2074 double dbl
= INT32_MAX
* 1000.0;
2075 UErrorCode status
= U_ZERO_ERROR
;
2076 NumberFormat
*f
= NumberFormat::createInstance(status
);
2077 if(U_FAILURE(status
)) {
2078 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2081 f
->setMaximumFractionDigits(INT32_MAX
);
2082 f
->setMaximumIntegerDigits(INT32_MAX
);
2085 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2088 f
->parse(s
, n
, status
);
2089 if(U_FAILURE(status
))
2090 errln("Couldn't parse!");
2091 //} catch (java.text.ParseException e) {
2092 // errln("Caught a ParseException:");
2093 // e.printStackTrace();
2096 //logln("The string " + s + " parsed as " + n);
2098 // {dlf} The old code assumes n is a double, but it isn't any more...
2099 // Formattable apparently does not and never did interconvert... too bad.
2100 //if(n.getDouble() != dbl) {
2101 // errln("Round trip failure");
2103 if (n
.getInt64() != dbl
) {
2104 errln("Round trip failure");
2112 * NumberFormat does not parse negative zero.
2115 NumberFormatRegressionTest::Test4162852(void)
2117 UErrorCode status
= U_ZERO_ERROR
;
2118 for(int32_t i
=0; i
< 2; ++i
) {
2119 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2120 : NumberFormat::createPercentInstance(status
);
2121 if(U_FAILURE(status
)) {
2122 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2130 f
->parse(s
, n
, status
);
2131 if(U_FAILURE(status
))
2132 errln("Couldn't parse!");
2133 double e
= n
.getDouble();
2134 logln(UnicodeString("") +
2136 '"' + s
+ '"' + " -> " + e
);
2137 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2140 if (e
!= 0.0 || 1.0/e
> 0.0) {
2142 logln("Failed to parse negative zero");
2148 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2151 * May 17 1999 sync up - liu
2153 * NumberFormat truncates data
2155 void NumberFormatRegressionTest::Test4167494(void) {
2156 UErrorCode status
= U_ZERO_ERROR
;
2157 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2158 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2163 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2167 fmt
->parse(s
, num
, status
);
2168 failure(status
, "Parse");
2169 if (num
.getType() == Formattable::kDouble
&&
2170 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2171 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2172 toString(num
) + " ok");
2174 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2175 toString(num
) + " FAIL");
2178 // We don't test Double.MIN_VALUE because the locale data for the US
2179 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2180 // This is correct for now; however, we leave this here as a reminder
2181 // in case we want to address this later.
2187 * May 17 1999 sync up - liu
2189 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2191 void NumberFormatRegressionTest::Test4170798(void) {
2192 UErrorCode status
= U_ZERO_ERROR
;
2193 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2194 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2198 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2200 errln("DecimalFormat needed to continue");
2203 df
->setParseIntegerOnly(TRUE
);
2205 ParsePosition
pos(0);
2206 df
->parse("-0.0", n
, pos
);
2207 if (n
.getType() != Formattable::kLong
2208 || n
.getLong() != 0) {
2209 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n
));
2215 * May 17 1999 sync up - liu
2216 * toPattern only puts the first grouping separator in.
2218 void NumberFormatRegressionTest::Test4176114(void) {
2219 const char* DATA
[] = {
2221 "000", "#000", // No grouping
2222 "#000", "#000", // No grouping
2226 "00,000", "#00,000",
2227 "000,000", "#,000,000",
2228 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2230 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2231 UErrorCode status
= U_ZERO_ERROR
;
2233 for (int i
=0; i
<DATA_length
; i
+=2) {
2234 DecimalFormat
df(DATA
[i
], status
);
2235 if (!failure(status
, "DecimalFormat constructor")) {
2237 UnicodeString
exp(DATA
[i
+1]);
2239 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2240 s
+ ", want " + exp
);
2247 * May 17 1999 sync up - liu
2249 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2251 void NumberFormatRegressionTest::Test4179818(void) {
2252 const char* DATA
[] = {
2253 // Input Pattern Expected output
2254 "1.2511", "#.#", "1.3",
2255 "1.2501", "#.#", "1.3",
2258 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2264 UErrorCode status
= U_ZERO_ERROR
;
2265 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2266 failure(status
, "Construct DecimalFormatSymbols");
2267 DecimalFormat
fmt("#", sym
, status
);
2268 if (!failure(status
, "Construct DecimalFormat")) {
2269 for (int i
=0; i
<DATA_length
; i
+=3) {
2270 double in
= DOUBLE
[i
/3];
2271 UnicodeString
pat(DATA
[i
+1]);
2272 UnicodeString
exp(DATA
[i
+2]);
2273 fmt
.applyPattern(pat
, status
);
2274 failure(status
, "applyPattern");
2277 fmt
.format(in
, out
, pos
);
2279 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2281 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2282 ", expected " + exp
);
2289 * May 17 1999 sync up - liu
2290 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2291 * This includes the minus sign, currency symbol, international currency
2292 * symbol, percent, and permille. This is filed as bugs 4212072 and
2295 void NumberFormatRegressionTest::Test4212072(void) {
2296 UErrorCode status
= U_ZERO_ERROR
;
2297 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2299 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2300 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2301 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2308 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2309 fmt
.setDecimalFormatSymbols(sym
);
2311 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2312 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2316 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2317 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2320 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2322 fmt
.applyPattern(UnicodeString("#%"), status
);
2323 failure(status
, "applyPattern percent");
2324 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2325 fmt
.setDecimalFormatSymbols(sym
);
2327 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2328 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2332 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2333 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2336 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2338 fmt
.applyPattern(str("#\\u2030"), status
);
2339 failure(status
, "applyPattern permill");
2340 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2341 fmt
.setDecimalFormatSymbols(sym
);
2343 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2344 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2348 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2349 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2352 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2354 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2355 failure(status
, "applyPattern currency");
2356 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2357 fmt
.setDecimalFormatSymbols(sym
);
2359 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) {
2360 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2364 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2365 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2368 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2370 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2371 failure(status
, "applyPattern intl currency");
2372 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2373 fmt
.setDecimalFormatSymbols(sym
);
2375 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) {
2376 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2380 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2381 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2384 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2386 // Since the pattern logic has changed, make sure that patterns round
2387 // trip properly. Test stream in/out integrity too.
2389 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2390 static const char* type
[] = {
2395 for (int i
=0; i
<n
; ++i
) {
2396 for (int j
=0; j
<3; ++j
) {
2397 status
= U_ZERO_ERROR
;
2401 nf
= NumberFormat::createInstance(avail
[i
], status
);
2402 failure(status
, "createInstance", avail
[i
]);
2405 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2406 failure(status
, "createCurrencyInstance", avail
[i
]);
2409 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2410 failure(status
, "createPercentInstance", avail
[i
]);
2413 if (U_FAILURE(status
)) {
2416 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2418 // Test toPattern/applyPattern round trip
2421 DecimalFormatSymbols
symb(avail
[i
], status
);
2422 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2423 DecimalFormat
f2(pat
, symb
, status
);
2425 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2430 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2432 "\" -> \"" + f2
.toPattern(p
) + "\"");
2435 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2440 // Test toLocalizedPattern/applyLocalizedPattern round trip
2441 df
->toLocalizedPattern(pat
);
2442 f2
.applyLocalizedPattern(pat
, status
);
2444 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2445 if (U_FAILURE(status
)) {
2449 // Make sure we set the currency attributes appropriately
2450 if (j
== 1) { // Currency format
2451 f2
.setCurrency(f2
.getCurrency(), status
);
2454 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2455 if (U_FAILURE(status
)) {
2461 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2462 " -> localized \"" + pat
+
2463 "\" -> \"" + f2
.toPattern(p
) + "\"");
2468 // Test writeObject/readObject round trip
2469 // NOT ON ICU -- Java only
2475 * May 17 1999 sync up - liu
2476 * DecimalFormat.parse() fails for mulipliers 2^n.
2478 void NumberFormatRegressionTest::Test4216742(void) {
2479 UErrorCode status
= U_ZERO_ERROR
;
2480 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2481 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2485 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2486 int DATA_length
= (int)(sizeof(DATA
) / sizeof(DATA
[0]));
2487 for (int i
=0; i
<DATA_length
; ++i
) {
2488 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2489 for (int m
= 1; m
<= 100; m
++) {
2490 fmt
->setMultiplier(m
);
2492 fmt
->parse(str
, num
, status
);
2493 failure(status
, "parse", Locale::getUS());
2494 if (num
.getType() != Formattable::kLong
&&
2495 num
.getType() != Formattable::kDouble
) {
2496 errln(UnicodeString("FAIL: Wanted number, got ") +
2499 double d
= num
.getType() == Formattable::kDouble
?
2500 num
.getDouble() : (double) num
.getLong();
2501 if ((d
> 0) != (DATA
[i
] > 0)) {
2502 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2503 fmt
->getMultiplier() +
2504 ") => " + toString(num
));
2513 * May 17 1999 sync up - liu
2514 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2517 void NumberFormatRegressionTest::Test4217661(void) {
2518 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2519 const char* S
[] = { "0", "1", "0.01", "1.01" };
2520 int D_length
= (int)(sizeof(D
) / sizeof(D
[0]));
2521 UErrorCode status
= U_ZERO_ERROR
;
2522 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2523 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2527 fmt
->setMaximumFractionDigits(2);
2528 for (int i
=0; i
<D_length
; i
++) {
2530 fmt
->format(D
[i
], s
);
2531 if (s
!= UnicodeString(S
[i
])) {
2532 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2539 * alphaWorks upgrade
2541 void NumberFormatRegressionTest::Test4161100(void) {
2542 UErrorCode status
= U_ZERO_ERROR
;
2543 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2544 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2548 nf
->setMinimumFractionDigits(1);
2549 nf
->setMaximumFractionDigits(1);
2554 logln(UnicodeString() + a
+ " x " +
2555 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2556 if (s
!= UnicodeString("-0.1")) {
2563 * June 16 1999 sync up - liu
2564 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2566 void NumberFormatRegressionTest::Test4243011(void) {
2567 UErrorCode status
= U_ZERO_ERROR
;
2568 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2569 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2570 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2572 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2573 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2574 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2575 int32_t N
= (int32_t)(sizeof(NUM
) / sizeof(NUM
[0]));
2577 for (int32_t i
=0; i
<N
; ++i
) {
2579 UnicodeString
exp(STR
[i
]);
2581 fmt
.format(NUM
[i
], str
, pos
);
2583 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2585 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2593 * June 16 1999 sync up - liu
2594 * format(0.0) gives "0.1" if preceded by parse("99.99").
2595 * (Regression in 1.2.2 RC1)
2597 void NumberFormatRegressionTest::Test4243108(void) {
2598 UErrorCode status
= U_ZERO_ERROR
;
2599 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2600 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2601 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2602 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2609 fmt
.format(0.0, str
, pos
);
2610 UnicodeString
exp("0");
2612 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2614 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2620 fmt
.parse(str
, val
, status
);
2621 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2622 if (val
.getType() == Formattable::kDouble
&&
2623 val
.getDouble() == 99.99) {
2624 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2626 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2631 fmt
.format(0.0, str
, pos
);
2633 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2635 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2642 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2643 * NumberFormat objects.
2645 void NumberFormatRegressionTest::TestJ691(void) {
2646 UErrorCode status
= U_ZERO_ERROR
;
2647 Locale
loc("fr", "CH");
2649 // set up the input date string & expected output
2650 UnicodeString
udt("11.10.2000", "");
2651 UnicodeString
exp("11.10.00", "");
2653 // create a Calendar for this locale
2654 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2655 if (U_FAILURE(status
)) {
2656 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2660 // create a NumberFormat for this locale
2661 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2662 if (U_FAILURE(status
)) {
2663 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2667 // *** Here's the key: We don't want to have to do THIS:
2668 // nf->setParseIntegerOnly(TRUE);
2670 // create the DateFormat
2671 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2672 if (U_FAILURE(status
)) {
2673 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2677 df
->adoptCalendar(cal
);
2678 df
->adoptNumberFormat(nf
);
2680 // set parsing to lenient & parse
2681 df
->setLenient(TRUE
);
2682 UDate ulocdat
= df
->parse(udt
, status
);
2684 // format back to a string
2685 UnicodeString outString
;
2686 df
->format(ulocdat
, outString
);
2688 if (outString
!= exp
) {
2689 errln("FAIL: " + udt
+ " => " + outString
);
2695 //---------------------------------------------------------------------------
2697 // Error Checking / Reporting macros
2699 //---------------------------------------------------------------------------
2700 #define TEST_CHECK_STATUS(status) { \
2701 if (U_FAILURE(status)) { \
2702 if (status == U_MISSING_RESOURCE_ERROR) { \
2703 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2705 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2709 #define TEST_ASSERT(expr) \
2710 if ((expr)==FALSE) {\
2711 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2715 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2717 void NumberFormatRegressionTest::Test8199(void) {
2718 UErrorCode status
= U_ZERO_ERROR
;
2719 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2721 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2724 TEST_CHECK_STATUS(status
);
2726 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2727 // should always truncate, no other rounding scheme.
2729 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2731 nf
->parse(numStr
, val
, status
);
2732 TEST_CHECK_STATUS(status
);
2733 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2734 TEST_ASSERT(1000000000 == val
.getInt64(status
));
2735 TEST_CHECK_STATUS(status
);
2736 TEST_ASSERT(1000000000.6 == val
.getDouble(status
));
2737 TEST_CHECK_STATUS(status
);
2739 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2740 // than int64 because of the fraction
2741 // even though int64 is more precise.
2742 nf
->parse(numStr
, val
, status
);
2743 TEST_CHECK_STATUS(status
);
2744 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2745 TEST_ASSERT(100000000000000001LL == val
.getInt64(status
));
2746 TEST_CHECK_STATUS(status
);
2747 TEST_ASSERT(100000000000000000.0 == val
.getDouble(status
));
2748 TEST_CHECK_STATUS(status
);
2750 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2751 nf
->parse(numStr
, val
, status
);
2752 TEST_CHECK_STATUS(status
);
2753 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2754 TEST_ASSERT(100000000000000000LL == val
.getInt64());
2755 TEST_ASSERT(1.0E17
== val
.getDouble(status
));
2756 TEST_CHECK_STATUS(status
);
2758 numStr
= "9223372036854775807"; // largest int64_t
2759 nf
->parse(numStr
, val
, status
);
2760 TEST_CHECK_STATUS(status
);
2761 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2762 TEST_ASSERT(9223372036854775807LL == val
.getInt64());
2763 // In the following check, note that a substantial range of integers will
2764 // convert to the same double value. There are also platform variations
2765 // in the rounding at compile time of double constants.
2766 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2767 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2768 TEST_CHECK_STATUS(status
);
2770 numStr
= "-9223372036854775808"; // smallest int64_t
2771 nf
->parse(numStr
, val
, status
);
2772 TEST_CHECK_STATUS(status
);
2773 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2774 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2775 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64());
2776 TEST_ASSERT(-9223372036854775808.0 == val
.getDouble(status
));
2777 TEST_CHECK_STATUS(status
);
2779 numStr
= "9223372036854775808"; // largest int64_t + 1
2780 nf
->parse(numStr
, val
, status
);
2781 TEST_CHECK_STATUS(status
);
2782 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2783 TEST_ASSERT(9223372036854775807LL == val
.getInt64(status
));
2784 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2785 status
= U_ZERO_ERROR
;
2786 TEST_ASSERT(9223372036854775810.0 == val
.getDouble(status
));
2787 TEST_CHECK_STATUS(status
);
2789 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2790 nf
->parse(numStr
, val
, status
);
2791 TEST_CHECK_STATUS(status
);
2792 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2793 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings
2794 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64(status
));
2795 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2796 status
= U_ZERO_ERROR
;
2797 TEST_ASSERT(-9223372036854775810.0 == val
.getDouble(status
));
2798 TEST_CHECK_STATUS(status
);
2800 // Test values near the limit of where doubles can represent all integers.
2801 // The implementation strategy of getInt64() changes at this boundary.
2802 // Strings to be parsed include a decimal fraction to force them to be
2803 // parsed as doubles rather than ints. The fraction is discarded
2804 // from the parsed double value because it is beyond what can be represented.
2806 status
= U_ZERO_ERROR
;
2807 numStr
= "9007199254740991.1"; // largest 53 bit int
2808 nf
->parse(numStr
, val
, status
);
2809 TEST_CHECK_STATUS(status
);
2810 // printf("getInt64() returns %lld\n", val.getInt64(status));
2811 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2812 TEST_ASSERT(9007199254740991LL == val
.getInt64(status
));
2813 TEST_ASSERT(9007199254740991.0 == val
.getDouble(status
));
2814 TEST_CHECK_STATUS(status
);
2816 status
= U_ZERO_ERROR
;
2817 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2818 nf
->parse(numStr
, val
, status
);
2819 TEST_CHECK_STATUS(status
);
2820 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2821 TEST_ASSERT(9007199254740992LL == val
.getInt64(status
));
2822 TEST_ASSERT(9007199254740992.0 == val
.getDouble(status
));
2823 TEST_CHECK_STATUS(status
);
2825 status
= U_ZERO_ERROR
;
2826 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2827 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2828 TEST_CHECK_STATUS(status
);
2829 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2830 TEST_ASSERT(9007199254740993LL == val
.getInt64(status
));
2831 TEST_ASSERT(9007199254740994.0 == val
.getDouble(status
));
2832 TEST_CHECK_STATUS(status
);
2837 void NumberFormatRegressionTest::Test9109(void) {
2838 UErrorCode status
= U_ZERO_ERROR
;
2841 DecimalFormat
fmt("+##", status
);
2842 fmt
.setLenient(TRUE
);
2844 if (U_FAILURE(status
)) {
2845 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2848 UnicodeString
text("123");
2849 int32_t expected
= 123;
2852 fmt
.parse(text
, val
, pos
);
2853 if (pos
.getErrorIndex() >= 0) {
2854 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2855 } else if (val
.getLong() != 123) {
2856 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2857 } else if (pos
.getIndex() != 3) {
2858 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2863 void NumberFormatRegressionTest::Test9780(void) {
2864 UErrorCode status
= U_ZERO_ERROR
;
2865 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2866 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2870 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2872 errln("DecimalFormat needed to continue");
2875 df
->setParseIntegerOnly(TRUE
);
2879 ParsePosition
pos(0);
2880 UnicodeString
toParse("1,234","");
2881 df
->parse(toParse
, n
, pos
);
2882 if (n
.getType() != Formattable::kLong
2883 || n
.getLong() != 1234) {
2884 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2887 // should still work in lenient mode, just won't get fastpath
2888 df
->setLenient(TRUE
);
2891 ParsePosition
pos(0);
2892 UnicodeString
toParse("1,234","");
2893 df
->parse(toParse
, n
, pos
);
2894 if (n
.getType() != Formattable::kLong
2895 || n
.getLong() != 1234) {
2896 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2903 void NumberFormatRegressionTest::Test9677(void) {
2904 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2905 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2906 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2907 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2908 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2910 UErrorCode status
= U_ZERO_ERROR
;
2911 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2912 if (U_FAILURE(status
)) {
2913 dataerrln("Failure opening unum_open");
2917 if (U_SUCCESS(status
)) {
2918 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2919 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2920 assertSuccess("setting attributes", status
);
2923 if(U_SUCCESS(status
)) {
2924 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2925 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2927 if(U_FAILURE(status
)) {
2928 logln("Got expected parse error %s\n", u_errorName(status
));
2929 status
= U_ZERO_ERROR
;
2931 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2935 if (U_SUCCESS(status
)) {
2936 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2937 assertSuccess("setting attributes", status
);
2938 logln("removed positive prefix");
2941 if(U_SUCCESS(status
)) {
2942 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2943 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2945 if(U_FAILURE(status
)) {
2946 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2947 status
= U_ZERO_ERROR
;
2950 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2952 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
2957 if(U_SUCCESS(status
)) {
2958 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2959 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2961 if(U_FAILURE(status
)) {
2962 logln("text2: Got expected parse error %s\n", u_errorName(status
));
2963 status
= U_ZERO_ERROR
;
2965 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2969 if (U_SUCCESS(status
)) {
2970 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
2971 assertSuccess("setting attributes", status
);
2972 logln("Set a different neg prefix prefix");
2975 if(U_SUCCESS(status
)) {
2976 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2977 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2979 if(U_FAILURE(status
)) {
2980 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
2981 status
= U_ZERO_ERROR
;
2985 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
2987 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
2993 void NumberFormatRegressionTest::Test10361(void) {
2994 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
2995 // preventing formatting of big decimals.
2996 UErrorCode status
= U_ZERO_ERROR
;
2997 DecimalFormatSymbols
symbols(Locale::getEnglish(), status
);
2998 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###.##", symbols
, status
), status
);
2999 TEST_CHECK_STATUS(status
);
3001 // Create a decimal number with a million digits.
3002 const int32_t NUMSIZE
=1000000;
3003 char *num
= new char[NUMSIZE
];
3004 for (int32_t i
=0; i
<NUMSIZE
; i
++) {
3005 num
[i
] = '0' + (i
+1) % 10;
3007 num
[NUMSIZE
-3] = '.';
3011 Formattable fmtable
;
3012 fmtable
.setDecimalNumber(num
, status
);
3013 TEST_CHECK_STATUS(status
);
3015 FieldPosition
pos(UNUM_DECIMAL_SEPARATOR_FIELD
);
3016 df
->format(fmtable
, s
, pos
, status
);
3017 TEST_CHECK_STATUS(status
);
3018 TEST_ASSERT(999999 == s
.length());
3019 TEST_ASSERT(999997 == pos
.getBeginIndex());
3020 TEST_ASSERT(999998 == pos
.getEndIndex());
3022 UnicodeString
expected(num
, -1, US_INV
);
3023 TEST_ASSERT(expected
== s
);
3027 #endif /* #if !UCONFIG_NO_FORMATTING */