1 /***********************************************************************
2 * Copyright (c) 1997-2016, 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"
26 class MyNumberFormatTest
: public NumberFormat
30 virtual UClassID
getDynamicClassID(void) const;
32 virtual UnicodeString
& format( double number
,
33 UnicodeString
& toAppendTo
,
34 FieldPositionIterator
* posIter
,
35 UErrorCode
& status
) const
37 return NumberFormat::format(number
, toAppendTo
, posIter
, status
);
40 /* Just keep this here to make some of the compilers happy */
41 virtual UnicodeString
& format(const Formattable
& obj
,
42 UnicodeString
& toAppendTo
,
44 UErrorCode
& status
) const
46 return NumberFormat::format(obj
, toAppendTo
, pos
, status
);
49 /* Just use one of the format functions */
50 virtual UnicodeString
& format( double /* number */,
51 UnicodeString
& toAppendTo
,
52 FieldPosition
& /* pos */) const
59 public Number parse(String text, ParsePosition parsePosition)
60 { return new Integer(0); }
63 /* Just use one of the parse functions */
64 virtual void parse( const UnicodeString
& /* text */,
66 ParsePosition
& /* parsePosition */) const
68 result
.setLong((int32_t)0);
71 virtual void parse( const UnicodeString
& text
,
73 UErrorCode
& status
) const
75 NumberFormat::parse(text
, result
, status
);
77 virtual Format
* clone() const
80 virtual UnicodeString
& format(int32_t,
83 { return foo
.remove(); }
85 virtual UnicodeString
& format(int64_t,
88 { return foo
.remove(); }
90 virtual void applyPattern(const UnicodeString
&, UParseError
&, UErrorCode
&){
94 int32_t gMyNumberFormatTestClassID
;
95 UClassID
MyNumberFormatTest::getDynamicClassID() const
97 return (UClassID
)&gMyNumberFormatTestClassID
;
101 // *****************************************************************************
102 // class NumberFormatRegressionTest
103 // *****************************************************************************
105 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
108 NumberFormatRegressionTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
110 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
122 CASE(10,Test4086575
);
123 CASE(11,Test4068693
);
124 CASE(12,Test4069754
);
125 CASE(13,Test4087251
);
126 CASE(14,Test4090489
);
127 CASE(15,Test4090504
);
128 CASE(16,Test4095713
);
129 CASE(17,Test4092561
);
130 CASE(18,Test4092480
);
131 CASE(19,Test4087244
);
132 CASE(20,Test4070798
);
133 CASE(21,Test4071005
);
134 CASE(22,Test4071014
);
135 CASE(23,Test4071859
);
136 CASE(24,Test4093610
);
137 CASE(25,Test4098741
);
138 CASE(26,Test4074454
);
139 CASE(27,Test4099404
);
140 CASE(28,Test4101481
);
141 CASE(29,Test4052223
);
142 CASE(30,Test4061302
);
143 CASE(31,Test4062486
);
144 CASE(32,Test4108738
);
145 CASE(33,Test4106658
);
146 CASE(34,Test4106662
);
147 CASE(35,Test4114639
);
148 CASE(36,Test4106664
);
149 CASE(37,Test4106667
);
150 CASE(38,Test4110936
);
151 CASE(39,Test4122840
);
152 CASE(40,Test4125885
);
153 CASE(41,Test4134034
);
154 CASE(42,Test4134300
);
155 CASE(43,Test4140009
);
156 CASE(44,Test4141750
);
157 CASE(45,Test4145457
);
158 CASE(46,Test4147295
);
159 CASE(47,Test4147706
);
160 CASE(48,Test4162198
);
161 CASE(49,Test4162852
);
162 CASE(50,Test4167494
);
163 CASE(51,Test4170798
);
164 CASE(52,Test4176114
);
165 CASE(53,Test4179818
);
166 CASE(54,Test4212072
);
167 CASE(55,Test4216742
);
168 CASE(56,Test4217661
);
169 CASE(57,Test4161100
);
170 CASE(58,Test4243011
);
171 CASE(59,Test4243108
);
179 default: name
= ""; break;
184 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const Locale
& l
, UBool possibleDataError
)
186 if(U_FAILURE(status
)) {
187 if (possibleDataError
) {
188 dataerrln(UnicodeString("FAIL: ", "") + msg
189 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
191 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
192 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
.getName(),""));
201 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, const char *l
, UBool possibleDataError
)
203 if(U_FAILURE(status
)) {
204 if (possibleDataError
) {
205 dataerrln(UnicodeString("FAIL: ", "") + msg
206 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
208 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
209 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), "") + UnicodeString(l
, ""));
218 NumberFormatRegressionTest::failure(UErrorCode status
, const UnicodeString
& msg
, UBool possibleDataError
)
220 if(U_FAILURE(status
)) {
221 if (possibleDataError
) {
222 dataerrln(UnicodeString("FAIL: ", "") + msg
223 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
225 errcheckln(status
, UnicodeString("FAIL: ", "") + msg
226 + UnicodeString(" failed, error ", "") + UnicodeString(u_errorName(status
), ""));
235 * Convert Java-style strings with \u Unicode escapes into UnicodeString objects
237 inline UnicodeString
str(const char *input
)
239 return CharsToUnicodeString(input
);
243 * NumberFormat.equals comparing with null should always return false.
245 // {sfb} kind of silly in C++, just checking for new success
246 void NumberFormatRegressionTest::Test4075713(void)
249 MyNumberFormatTest
*tmp
= new MyNumberFormatTest();
251 logln("NumberFormat.equals passed");
252 /*} catch (NullPointerException e) {
253 errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
260 * NumberFormat.equals comparing two obj equal even the setGroupingUsed
263 void NumberFormatRegressionTest::Test4074620(void)
266 MyNumberFormatTest
*nf1
= new MyNumberFormatTest();
267 MyNumberFormatTest
*nf2
= new MyNumberFormatTest();
269 nf1
->setGroupingUsed(FALSE
);
270 nf2
->setGroupingUsed(TRUE
);
273 errln("Test for bug 4074620 failed");
275 logln("Test for bug 4074620 passed.");
283 * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
286 void NumberFormatRegressionTest::Test4088161 (void)
288 UErrorCode status
= U_ZERO_ERROR
;
289 DecimalFormat
*df
= new DecimalFormat(status
);
290 if (!failure(status
, "new DecimalFormat", "")) {
292 df
->setMinimumFractionDigits(0);
293 df
->setMaximumFractionDigits(16);
295 FieldPosition
fp1(0);
296 logln(UnicodeString("d = ") + d
);
297 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
299 logln(" format(d) = '" + df
->format(d
, sBuf1
, fp1
) + "'");
300 df
->setMaximumFractionDigits(17);
302 FieldPosition
fp2(0);
303 logln(UnicodeString("maxFractionDigits = ") + df
->getMaximumFractionDigits());
304 sBuf2
= df
->format(d
, sBuf2
, fp2
);
306 errln(" format(d) = '" + sBuf2
+ "'");
313 * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
314 * DecimalFormat(String, DecimalFormatSymbols).
316 void NumberFormatRegressionTest::Test4087245 (void)
318 UErrorCode status
= U_ZERO_ERROR
;
319 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(status
);
320 failure(status
, "new DecimalFormatSymbols", "");
321 // {sfb} One note about this test: if you pass in a pointer
322 // to the symbols, they are adopted and this test will fail,
323 // even though that is the correct behavior. To test the cloning
324 // of the symbols, it is necessary to pass in a reference to the symbols
325 DecimalFormat
*df
= new DecimalFormat("#,##0.0", *symbols
, status
);
326 failure(status
, "new DecimalFormat with symbols", "");
330 FieldPosition
pos(FieldPosition::DONT_CARE
);
331 logln(UnicodeString("format(") + n
+ ") = " +
332 df
->format(n
, buf1
, pos
));
333 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, UnicodeString((UChar
)0x70)); // change value of field
334 logln(UnicodeString("format(") + n
+ ") = " +
335 df
->format(n
, buf2
, pos
));
337 errln("Test for bug 4087245 failed");
344 * DecimalFormat.format() incorrectly formats 0.0
346 void NumberFormatRegressionTest::Test4087535 (void)
348 UErrorCode status
= U_ZERO_ERROR
;
349 DecimalFormat
*df
= new DecimalFormat(status
);
350 if (U_FAILURE(status
)) {
351 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
354 df
->setMinimumIntegerDigits(0);
357 UnicodeString buffer
;
358 FieldPosition
pos(FieldPosition::DONT_CARE
);
359 buffer
= df
->format(n
, buffer
, pos
);
360 if (buffer
.length() == 0)
361 errln(/*n + */": '" + buffer
+ "'");
363 buffer
= df
->format(n
, buffer
, pos
);
364 if (buffer
.length() == 0)
365 errln(/*n + */": '" + buffer
+ "'");
371 * DecimalFormat.format fails when groupingSize is set to 0.
373 // {sfb} how do I tell if this worked? --> FieldPosition doesn't change ??
374 void NumberFormatRegressionTest::Test4088503 (void)
376 UErrorCode status
= U_ZERO_ERROR
;
377 DecimalFormat
*df
= new DecimalFormat(status
);
378 if (U_FAILURE(status
)) {
379 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
382 df
->setGroupingSize(0);
384 FieldPosition
fp(FieldPosition::DONT_CARE
);
386 logln(df
->format((int32_t)123, sBuf
, fp
));
387 //if(fp == FieldPosition(0))
388 // errln("Test for bug 4088503 failed.");
389 /*} catch (Exception foo) {
390 errln("Test for bug 4088503 failed.");
396 * NumberFormat.getCurrencyInstance is wrong.
398 void NumberFormatRegressionTest::Test4066646 (void)
400 assignFloatValue(2.04f
);
401 assignFloatValue(2.03f
);
402 assignFloatValue(2.02f
);
403 assignFloatValue(0.0f
);
407 NumberFormatRegressionTest::assignFloatValue(float returnfloat
)
409 logln(UnicodeString(" VALUE ") + returnfloat
);
410 UErrorCode status
= U_ZERO_ERROR
;
411 NumberFormat
*nfcommon
= NumberFormat::createCurrencyInstance(Locale::getUS(), status
);
412 if (failure(status
, "NumberFormat::createCurrencyInstance", Locale::getUS(), TRUE
)){
416 nfcommon
->setGroupingUsed(FALSE
);
418 UnicodeString stringValue
;
419 stringValue
= nfcommon
->format(returnfloat
, stringValue
);
420 logln(" DISPLAYVALUE " + stringValue
);
422 nfcommon
->parse(stringValue
, result
, status
);
423 failure(status
, "nfcommon->parse", Locale::getUS());
424 float floatResult
= (float) (result
.getType() == Formattable::kDouble
425 ? result
.getDouble() : result
.getLong());
426 if( uprv_fabs(floatResult
- returnfloat
) > 0.0001)
427 //String stringValue = nfcommon.format(returnfloat).substring(1);
428 //if (Float.valueOf(stringValue).floatValue() != returnfloat)
429 errln(UnicodeString("FAIL: expected ") + returnfloat
+ ", got " + floatResult
+ " (" + stringValue
+")");
433 } // End Of assignFloatValue()
436 * DecimalFormat throws exception when parsing "0"
438 void NumberFormatRegressionTest::Test4059870(void)
440 UErrorCode status
= U_ZERO_ERROR
;
441 DecimalFormat
*format
= new DecimalFormat("00", status
);
442 failure(status
, "new Decimalformat", Locale::getUS());
446 format
->parse(UnicodeString("0"), result
, status
);
447 failure(status
, "format->parse", Locale::getUS());
450 catch (Exception e) {
451 errln("Test for bug 4059870 failed : " + e);
457 * DecimalFormatSymbol.equals should always return false when
458 * comparing with null.
460 // {sfb} this is silly in C++
461 void NumberFormatRegressionTest::Test4083018 (void)
463 UErrorCode status
= U_ZERO_ERROR
;
464 DecimalFormatSymbols
*dfs
= new DecimalFormatSymbols(status
);
465 failure(status
, "new DecimalFormatSymbols", Locale::getUS());
468 logln("Test Passed!");
470 errln("Test for bug 4083018 failed");
471 /*} catch (Exception foo) {
472 errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
479 * DecimalFormat does not round up correctly.
481 void NumberFormatRegressionTest::Test4071492 (void)
483 double x
= 0.00159999;
484 UErrorCode status
= U_ZERO_ERROR
;
485 NumberFormat
*nf
= NumberFormat::createInstance(status
);
486 if (failure(status
, "NumberFormat::createInstance", Locale::getUS(), TRUE
)) {
490 nf
->setMaximumFractionDigits(4);
492 FieldPosition
pos(FieldPosition::DONT_CARE
);
493 out
= nf
->format(x
, out
, pos
);
494 logln("0.00159999 formats with 4 fractional digits to " + out
);
495 UnicodeString
expected("0.0016");
497 errln("FAIL: Expected " + expected
);
503 * A space as a group separator for localized pattern causes
504 * wrong format. WorkAround : use non-breaking space.
506 void NumberFormatRegressionTest::Test4086575(void)
508 UErrorCode status
= U_ZERO_ERROR
;
509 NumberFormat
*nf1
= NumberFormat::createInstance(Locale::getFrance(), status
);
511 // TODO: There is not a good way to find out that the creation of this number format has
512 // failed. Major rewiring of format construction proposed.
513 if(U_FAILURE(status
)) {
514 dataerrln("Something is wrong with French number format - it should not fallback. Exitting - %s", u_errorName(status
));
518 failure(status
, "NumberFormat::createInstance", Locale::getFrance());
520 // C++ workaround to make sure cast works
521 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nf1
);
523 errln("NumberFormat::createInstance returned incorrect type.");
528 logln("nf toPattern1: " + nf
->toPattern(temp
));
529 logln("nf toLocPattern1: " + nf
->toLocalizedPattern(temp
));
531 // No group separator
532 logln("...applyLocalizedPattern ###,00;(###,00) ");
533 nf
->applyLocalizedPattern(UnicodeString("###,00;(###,00)"), status
);
534 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
535 logln("nf toPattern2: " + nf
->toPattern(temp
));
536 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
538 FieldPosition
pos(FieldPosition::DONT_CARE
);
539 logln("nf: " + nf
->format((int32_t)1234, temp
, pos
)); // 1234,00
540 logln("nf: " + nf
->format((int32_t)-1234, temp
, pos
)); // (1234,00)
542 // Space as group separator
544 logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
546 //nf->applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
548 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x3b,
549 0x28, 0x23, 0x00a0, 0x23, 0x23, 0x23, 0x2c, 0x30, 0x30, 0x29
551 UnicodeString
pat(patChars
, 19, 19);
552 nf
->applyLocalizedPattern(pat
, status
);
553 failure(status
, "nf->applyLocalizedPattern", Locale::getFrance());
554 logln("nf toPattern2: " + nf
->toPattern(temp
));
555 logln("nf toLocPattern2: " + nf
->toLocalizedPattern(temp
));
556 UnicodeString buffer
;
557 buffer
= nf
->format((int32_t)1234, buffer
, pos
);
558 //if (buffer != UnicodeString("1\u00a0234,00"))
560 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30
562 UnicodeString
cc(c
, 8, 8);
564 errln("nf : " + buffer
); // Expect 1 234,00
567 buffer
= nf
->format((int32_t)-1234, buffer
, pos
);
569 0x28, 0x31, 0x00a0, 0x32, 0x33, 0x34, 0x2c, 0x30, 0x30, 0x29
571 UnicodeString
cc1(c1
, 10, 10);
573 errln("nf : " + buffer
); // Expect (1 234,00)
575 // Erroneously prints:
582 * DecimalFormat.parse returns wrong value
584 // {sfb} slightly converted into a round-trip test, since in C++
585 // there is no Double.toString()
586 void NumberFormatRegressionTest::Test4068693(void)
588 logln("----- Test Application -----");
589 ParsePosition
pos(0);
590 UErrorCode status
= U_ZERO_ERROR
;
591 DecimalFormat
*df
= new DecimalFormat(status
);
592 if(U_FAILURE(status
)) {
593 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
597 failure(status
, "new DecimalFormat");
599 //Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
600 df
->parse(UnicodeString("123.55456"), d
, pos
);
601 //if (!d.toString().equals("123.55456")) {
603 df
->setMaximumFractionDigits(999);
604 df
->setMaximumIntegerDigits(999);
605 FieldPosition
fp(FieldPosition::DONT_CARE
);
606 dstr
= df
->format(d
.getDouble(), dstr
, fp
);
607 if (dstr
!= UnicodeString("123.55456")) {
608 errln(UnicodeString("Result -> ") + d
.getDouble());
614 /* @bug 4069754, 4067878
615 * null pointer thrown when accessing a deserialized DecimalFormat
618 // {sfb} doesn't apply in C++
619 void NumberFormatRegressionTest::Test4069754(void)
622 myformat it = new myformat();
624 FileOutputStream ostream = new FileOutputStream("t.tmp");
625 ObjectOutputStream p = new ObjectOutputStream(ostream);
630 FileInputStream istream = new FileInputStream("t.tmp");
631 ObjectInputStream p2 = new ObjectInputStream(istream);
632 myformat it2 = (myformat)p2.readObject();
636 } catch (Exception foo) {
637 errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
642 * DecimalFormat.applyPattern(String) allows illegal patterns
644 void NumberFormatRegressionTest::Test4087251 (void)
646 UErrorCode status
= U_ZERO_ERROR
;
647 DecimalFormat
*df
= new DecimalFormat(status
);
648 if(U_FAILURE(status
)) {
649 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
653 failure(status
, "new DecimalFormat");
655 df
->applyPattern(UnicodeString("#.#.#"), status
);
656 if( ! U_FAILURE(status
))
657 errln("df->applyPattern with illegal pattern didn't fail");
659 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
660 //errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
661 /*} catch (IllegalArgumentException e) {
662 logln("Caught Illegal Argument Error !");
664 // Second test; added 5/11/98 when reported to fail on 1.2b3
666 df
->applyPattern("#0.0#0#0", status
);
667 if( ! U_FAILURE(status
))
668 errln("df->applyPattern with illegal pattern didn't fail");
669 logln("toPattern() returns \"" + df
->toPattern(temp
) + "\"");
670 //errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
671 /*} catch (IllegalArgumentException e) {
672 logln("Ok - IllegalArgumentException for #0.0#0#0");
679 * DecimalFormat.format() loses precision
681 void NumberFormatRegressionTest::Test4090489 (void)
683 // {sfb} sprintf doesn't correctly handle the double, so there is nothing
684 // that NumberFormat can do. For some reason, it does not format the last 1.
686 /* UErrorCode status = U_ZERO_ERROR;
687 DecimalFormat *df = new DecimalFormat(status);
688 failure(status, "new DecimalFormat");
689 df->setMinimumFractionDigits(10);
690 df->setMaximumFractionDigits(999);
691 df->setGroupingUsed(FALSE);
692 double d = 1.000000000000001E7;
693 //BigDecimal bd = new BigDecimal(d);
696 logln(UnicodeString("d = ") + d);
697 //logln("BigDecimal.toString(): " + bd.toString());
698 df->format(d, sb, fp);
699 if (sb != "10000000.0000000100") {
700 errln("DecimalFormat.format(): " + sb);
706 * DecimalFormat.format() loses precision
708 void NumberFormatRegressionTest::Test4090504 (void)
711 logln(UnicodeString("d = ") + d
);
712 UErrorCode status
= U_ZERO_ERROR
;
713 DecimalFormat
*df
= new DecimalFormat(status
);
714 if(U_FAILURE(status
)) {
715 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
719 failure(status
, "new DecimalFormat");
721 FieldPosition
fp(FieldPosition::DONT_CARE
);
723 for (int i
= 17; i
<= 20; i
++) {
724 df
->setMaximumFractionDigits(i
);
725 //sb = new StringBuffer("");
727 logln(UnicodeString(" getMaximumFractionDigits() = ") + i
);
728 logln(UnicodeString(" formated: ") + df
->format(d
, sb
, fp
));
730 /*} catch (Exception foo) {
731 errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
737 * DecimalFormat.parse(String str, ParsePosition pp) loses precision
739 void NumberFormatRegressionTest::Test4095713 (void)
741 UErrorCode status
= U_ZERO_ERROR
;
742 DecimalFormat
*df
= new DecimalFormat(status
);
743 if(U_FAILURE(status
)) {
744 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
748 failure(status
, "new DecimalFormat");
749 UnicodeString
str("0.1234");
751 //Double d1 = new Double(str);
752 //Double d2 = (Double) df.parse(str, new ParsePosition(0));
755 df
->parse(str
, d2
, pp
);
756 logln(UnicodeString("") + d1
);
757 if (d2
.getDouble() != d1
)
758 errln(UnicodeString("Bug 4095713 test failed, new double value : ") + d2
.getDouble());
763 * DecimalFormat.parse() fails when multiplier is not set to 1
765 // {sfb} not sure what to do with this one
766 void NumberFormatRegressionTest::Test4092561 (void)
768 UErrorCode status
= U_ZERO_ERROR
;
769 DecimalFormat
*df
= new DecimalFormat(status
);
770 if(U_FAILURE(status
)) {
771 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
775 failure(status
, "new DecimalFormat");
777 // {sfb} going to cheat here and use sprintf ??
779 /*UnicodeString str = Long.toString(Long.MIN_VALUE);
780 logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
781 df.setMultiplier(100);
782 Number num = df.parse(str, new ParsePosition(0));
783 if (num.doubleValue() != -9.223372036854776E16)
784 errln("Bug 4092561 test failed when multiplier is set to not 1.");
790 * DecimalFormat: Negative format ignored.
792 void NumberFormatRegressionTest::Test4092480 (void)
794 UErrorCode status
= U_ZERO_ERROR
;
795 DecimalFormat
*dfFoo
= new DecimalFormat(UnicodeString("000"), status
);
796 if(U_FAILURE(status
)) {
797 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
801 failure(status
, "new DecimalFormat");
804 dfFoo
->applyPattern("0000;-000", status
);
805 failure(status
, "dfFoo->applyPattern");
807 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
808 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
809 FieldPosition
pos(FieldPosition::DONT_CARE
);
810 logln(dfFoo
->format((int32_t)42, temp
, pos
));
811 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
812 dfFoo
->applyPattern("000;-000", status
);
813 failure(status
, "dfFoo->applyPattern");
814 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
815 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
816 logln(dfFoo
->format((int32_t)42,temp
, pos
));
817 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
819 dfFoo
->applyPattern("000;-0000", status
);
820 failure(status
, "dfFoo->applyPattern");
821 if (dfFoo
->toPattern(temp
) != UnicodeString("#000"))
822 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
823 logln(dfFoo
->format((int32_t)42, temp
, pos
));
824 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
826 dfFoo
->applyPattern("0000;-000", status
);
827 failure(status
, "dfFoo->applyPattern");
828 if (dfFoo
->toPattern(temp
) != UnicodeString("#0000"))
829 errln("dfFoo.toPattern : " + dfFoo
->toPattern(temp
));
830 logln(dfFoo
->format((int32_t)42, temp
, pos
));
831 logln(dfFoo
->format((int32_t)-42, temp
, pos
));
832 /*} catch (Exception foo) {
833 errln("Message " + foo.getMessage());
839 * NumberFormat.getCurrencyInstance() produces format that uses
840 * decimal separator instead of monetary decimal separator.
842 * Rewrote this test not to depend on the actual pattern. Pattern should
843 * never contain the monetary separator! Decimal separator in pattern is
844 * interpreted as monetary separator if currency symbol is seen!
846 void NumberFormatRegressionTest::Test4087244 (void) {
847 UErrorCode status
= U_ZERO_ERROR
;
849 uloc_canonicalize("pt_PT_PREEURO", loc
, 256, &status
);
850 Locale
*de
= new Locale(loc
);
851 NumberFormat
*nf
= NumberFormat::createCurrencyInstance(*de
, status
);
852 if(U_FAILURE(status
)) {
853 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
857 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
859 errln("expected DecimalFormat!");
862 const DecimalFormatSymbols
*sym
= df
->getDecimalFormatSymbols();
863 UnicodeString decSep
= sym
->getSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
);
864 UnicodeString monSep
= sym
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
865 if (decSep
== monSep
) {
866 errln("ERROR in test: want decimal sep != monetary sep");
869 df
->setMinimumIntegerDigits(1);
870 df
->setMinimumFractionDigits(2);
873 df
->format(1.23, str
, pos
);
874 UnicodeString
monStr("1x23");
875 monStr
.replace((int32_t)1, 1, monSep
);
876 UnicodeString
decStr("1x23");
877 decStr
.replace((int32_t)1, 1, decSep
);
878 if (str
.indexOf(monStr
) >= 0 && str
.indexOf(decStr
) < 0) {
879 logln(UnicodeString("OK: 1.23 -> \"") + str
+ "\" contains \"" +
880 monStr
+ "\" and not \"" + decStr
+ '"');
882 errln(UnicodeString("FAIL: 1.23 -> \"") + str
+ "\", should contain \"" +
884 "\" and not \"" + decStr
+ '"');
890 * Number format data rounding errors for locale FR
892 void NumberFormatRegressionTest::Test4070798 (void)
894 NumberFormat
*formatter
;
895 UnicodeString tempString
;
898 String expectedDefault = "-5\u00a0789,987";
899 String expectedCurrency = "5\u00a0789,98\u00a0F";
900 String expectedPercent = "-578\u00a0998%";
903 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
906 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x46
909 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
911 UnicodeString
expectedDefault(chars1
, 10, 10);
912 UnicodeString
expectedCurrency(chars2
, 10, 10);
913 UnicodeString
expectedPercent(chars3
, 10, 10);
915 UErrorCode status
= U_ZERO_ERROR
;
917 int len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
918 (void)len
; // Suppress set but not used warning.
919 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
920 if(U_FAILURE(status
)) {
921 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
925 failure(status
, "NumberFormat::createInstance", loc
);
926 tempString
= formatter
->format (-5789.9876, tempString
);
928 if (tempString
== expectedDefault
) {
929 logln ("Bug 4070798 default test passed.");
931 errln(UnicodeString("Failed:") +
932 " Expected " + expectedDefault
+
933 " Received " + tempString
);
936 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
937 formatter
= NumberFormat::createCurrencyInstance(loc
, status
);
938 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
940 tempString
= formatter
->format( 5789.9876, tempString
);
942 if (tempString
== expectedCurrency
) {
943 logln ("Bug 4070798 currency test passed.");
945 errln(UnicodeString("Failed:") +
946 " Expected " + expectedCurrency
+
947 " Received " + tempString
);
951 uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
952 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
953 failure(status
, "NumberFormat::createPercentInstance", loc
);
955 tempString
= formatter
->format (-5789.9876, tempString
);
957 if (tempString
== expectedPercent
) {
958 logln ("Bug 4070798 percentage test passed.");
960 errln(UnicodeString("Failed:") +
961 " Expected " + expectedPercent
+
962 " Received " + tempString
);
968 * Data rounding errors for French (Canada) locale
970 void NumberFormatRegressionTest::Test4071005 (void)
972 NumberFormat
*formatter
;
973 UnicodeString tempString
;
975 String expectedDefault = "-5\u00a0789,987";
976 String expectedCurrency = "5\u00a0789,98\u00a0$";
977 String expectedPercent = "-578\u00a0998%";
980 0x2d, 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x38, 0x38
983 0x35, 0x00a0, 0x37, 0x38, 0x39, 0x2c, 0x39, 0x39, 0x00a0, 0x24
986 0x2d, 0x35, 0x37, 0x38, 0x00a0, 0x39, 0x39, 0x39, 0x00a0, 0x25
988 UnicodeString
expectedDefault(chars1
, 10, 10);
989 UnicodeString
expectedCurrency(chars2
, 10, 10);
990 UnicodeString
expectedPercent(chars3
, 10, 10);
992 UErrorCode status
= U_ZERO_ERROR
;
993 formatter
= NumberFormat::createInstance(Locale::getCanadaFrench(), status
);
994 if (failure(status
, "NumberFormat::createInstance", Locale::getCanadaFrench(), TRUE
)){
998 tempString
= formatter
->format (-5789.9876, tempString
);
1000 if (tempString
== expectedDefault
) {
1001 logln ("Bug 4071005 default test passed.");
1003 errln(UnicodeString("Failed:") +
1004 " Expected " + expectedDefault
+
1005 " Received " + tempString
);
1009 formatter
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
1010 failure(status
, "NumberFormat::createCurrencyInstance", Locale::getCanadaFrench());
1011 tempString
.remove();
1012 tempString
= formatter
->format( 5789.9876, tempString
);
1014 if (tempString
== expectedCurrency
) {
1015 logln ("Bug 4071005 currency test assed.");
1017 errln(UnicodeString("Failed:") +
1018 " Expected " + expectedCurrency
+
1019 " Received " + tempString
);
1023 formatter
= NumberFormat::createPercentInstance(Locale::getCanadaFrench(), status
);
1024 failure(status
, "NumberFormat::createPercentInstance", Locale::getCanadaFrench());
1025 tempString
.remove();
1026 tempString
= formatter
->format (-5789.9876, tempString
);
1028 if (tempString
== expectedPercent
) {
1029 logln ("Bug 4071005 percentage test passed.");
1031 errln(UnicodeString("Failed:") +
1032 " Expected " + expectedPercent
+
1033 " Received " + tempString
);
1040 * Data rounding errors for German (Germany) locale
1042 void NumberFormatRegressionTest::Test4071014 (void)
1044 NumberFormat
*formatter
;
1045 UnicodeString tempString
;
1047 String expectedDefault = "-5.789,987";
1048 String expectedCurrency = "5.789,98 DM";
1049 String expectedPercent = "-578.998%";
1051 UnicodeString
expectedDefault("-5.789,988");
1052 UnicodeString
expectedCurrency("5.789,99\\u00A0DM");
1053 UnicodeString
expectedPercent("-578.999\\u00A0%");
1055 expectedCurrency
= expectedCurrency
.unescape();
1056 expectedPercent
= expectedPercent
.unescape();
1058 UErrorCode status
= U_ZERO_ERROR
;
1060 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1061 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1062 if (failure(status
, "NumberFormat::createInstance", loc
, TRUE
)){
1066 tempString
.remove();
1067 tempString
= formatter
->format (-5789.9876, tempString
);
1069 if (tempString
== expectedDefault
) {
1070 logln ("Bug 4071014 default test passed.");
1072 errln(UnicodeString("Failed:") +
1073 " Expected " + expectedDefault
+
1074 " Received " + tempString
);
1077 uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
1078 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1079 failure(status
, "NumberFormat::createCurrencyInstance", loc
);
1080 tempString
.remove();
1081 tempString
= formatter
->format( 5789.9876, tempString
);
1083 if (tempString
== expectedCurrency
) {
1084 logln ("Bug 4071014 currency test assed.");
1086 errln(UnicodeString("Failed:") +
1087 " Expected " + expectedCurrency
+
1088 " Received " + tempString
);
1092 formatter
= NumberFormat::createPercentInstance(Locale::getGermany(), status
);
1093 failure(status
, "NumberFormat::createPercentInstance", Locale::getGermany());
1094 tempString
.remove();
1095 tempString
= formatter
->format (-5789.9876, tempString
);
1097 if (tempString
== expectedPercent
) {
1098 logln ("Bug 4071014 percentage test passed.");
1100 errln(UnicodeString("Failed:") +
1101 " Expected " + expectedPercent
+
1102 " Received " + tempString
);
1108 * Data rounding errors for Italian locale number formats
1110 void NumberFormatRegressionTest::Test4071859 (void)
1112 NumberFormat
*formatter
;
1113 UnicodeString tempString
;
1115 String expectedDefault = "-5.789,987";
1116 String expectedCurrency = "-L.\\u00A05.789,98";
1117 String expectedPercent = "-578.998%";
1119 UnicodeString
expectedDefault("-5.789,988");
1120 UnicodeString
expectedCurrency("-ITL\\u00A05.790", -1, US_INV
);
1121 UnicodeString
expectedPercent("-578.999%");
1122 expectedCurrency
= expectedCurrency
.unescape();
1124 UErrorCode status
= U_ZERO_ERROR
;
1126 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1127 formatter
= NumberFormat::createInstance(Locale(loc
), status
);
1128 if (failure(status
, "NumberFormat::createNumberInstance", TRUE
)){
1132 tempString
= formatter
->format (-5789.9876, tempString
);
1134 if (tempString
== expectedDefault
) {
1135 logln ("Bug 4071859 default test passed.");
1137 errln(UnicodeString("Failed:") +
1138 " Expected " + expectedDefault
+
1139 " Received " + tempString
);
1142 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1143 formatter
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
1144 failure(status
, "NumberFormat::createCurrencyInstance");
1145 tempString
.remove();
1146 tempString
= formatter
->format( -5789.9876, tempString
);
1148 if (tempString
== expectedCurrency
) {
1149 logln ("Bug 4071859 currency test assed.");
1151 errln(UnicodeString("Failed:") +
1152 " Expected " + expectedCurrency
+
1153 " Received " + tempString
);
1156 uloc_canonicalize("it_IT_PREEURO", loc
, 256, &status
);
1157 formatter
= NumberFormat::createPercentInstance(Locale(loc
), status
);
1158 failure(status
, "NumberFormat::createPercentInstance");
1159 tempString
.remove();
1160 tempString
= formatter
->format (-5789.9876, tempString
);
1162 if (tempString
== expectedPercent
) {
1163 logln ("Bug 4071859 percentage test passed.");
1165 errln(UnicodeString("Failed:") +
1166 " Expected " + expectedPercent
+
1167 " Received " + tempString
);
1173 * Test rounding for nearest even.
1175 void NumberFormatRegressionTest::Test4093610(void)
1177 UErrorCode status
= U_ZERO_ERROR
;
1178 DecimalFormat
*df
= new DecimalFormat("#0.#", status
);
1179 if (!failure(status
, "new DecimalFormat")) {
1180 UnicodeString
s("12.4");
1181 roundingTest(df
, 12.35, s
);
1182 roundingTest(df
, 12.45, s
);
1184 roundingTest(df
, 12.452,s
);
1186 roundingTest(df
, 12.55, s
);
1187 roundingTest(df
, 12.65, s
);
1189 roundingTest(df
, 12.652,s
);
1191 roundingTest(df
, 12.75, s
);
1192 roundingTest(df
, 12.752,s
);
1193 roundingTest(df
, 12.85, s
);
1195 roundingTest(df
, 12.852,s
);
1197 roundingTest(df
, 12.95, s
);
1198 roundingTest(df
, 12.952,s
);
1204 void NumberFormatRegressionTest::roundingTest(DecimalFormat
*df
, double x
, UnicodeString
& expected
)
1207 FieldPosition
pos(FieldPosition::DONT_CARE
);
1208 out
= df
->format(x
, out
, pos
);
1209 logln(UnicodeString("") + x
+ " formats with 1 fractional digits to " + out
);
1210 if (out
!= expected
)
1211 errln("FAIL: Expected " + expected
);
1214 * Tests the setMaximumFractionDigits limit.
1216 void NumberFormatRegressionTest::Test4098741(void)
1219 UErrorCode status
= U_ZERO_ERROR
;
1220 NumberFormat
*fmt
= NumberFormat::createPercentInstance(status
);
1221 if (U_FAILURE(status
)) {
1222 dataerrln("Error calling NumberFormat::createPercentInstance");
1227 fmt
->setMaximumFractionDigits(20);
1229 logln(fmt
->format(.001, temp
));
1230 /*} catch (Exception foo) {
1231 errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
1236 * Tests illegal pattern exception.
1237 * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
1238 * Part2 has been fixed.
1240 void NumberFormatRegressionTest::Test4074454(void)
1243 UErrorCode status
= U_ZERO_ERROR
;
1244 DecimalFormat
*fmt
= new DecimalFormat("#,#00.00;-#.#", status
);
1245 if(U_FAILURE(status
)) {
1246 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1250 failure(status
, "new DecimalFormat");
1251 logln("Inconsistent negative pattern is fine.");
1252 DecimalFormat
*newFmt
= new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces", status
);
1253 failure(status
, "new DecimalFormat");
1254 UnicodeString tempString
;
1255 FieldPosition
pos(FieldPosition::DONT_CARE
);
1256 tempString
= newFmt
->format(3456.78, tempString
, pos
);
1257 if (tempString
!= UnicodeString("3,456.78 p'ieces"))
1258 dataerrln("Failed! 3456.78 p'ieces expected, but got : " + tempString
);
1259 /*} catch (Exception foo) {
1260 errln("An exception was thrown for any inconsistent negative pattern.");
1267 * Tests all different comments.
1268 * Response to some comments :
1269 * [1] DecimalFormat.parse API documentation is more than just one line.
1270 * This is not a reproducable doc error in 116 source code.
1271 * [2] See updated javadoc.
1273 * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
1274 * a null object will be returned. The unchanged parse position also
1275 * reflects an error.
1276 * NumberFormat.parse(String) : If parsing fails, an ParseException
1278 * See updated javadoc for more details.
1279 * [5] See updated javadoc.
1280 * [6] See updated javadoc.
1281 * [7] This is a correct behavior if the DateFormat object is linient.
1282 * Otherwise, an IllegalArgumentException will be thrown when formatting
1283 * "January 35". See GregorianCalendar class javadoc for more details.
1285 void NumberFormatRegressionTest::Test4099404(void)
1288 UErrorCode status
= U_ZERO_ERROR
;
1289 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("000.0#0"), status
);
1290 if(! U_FAILURE(status
))
1291 errln(UnicodeString("Bug 4099404 failed applying illegal pattern \"000.0#0\""));
1292 /*} catch (Exception foo) {
1293 logln("Bug 4099404 pattern \"000.0#0\" passed");
1298 fmt
= new DecimalFormat(UnicodeString("0#0.000"), status
);
1299 if( !U_FAILURE(status
))
1300 errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
1301 /*} catch (Exception foo) {
1302 logln("Bug 4099404 pattern \"0#0.000\" passed");
1308 * DecimalFormat.applyPattern doesn't set minimum integer digits
1310 void NumberFormatRegressionTest::Test4101481(void)
1312 UErrorCode status
= U_ZERO_ERROR
;
1313 DecimalFormat
*sdf
= new DecimalFormat(UnicodeString("#,##0"), status
);
1314 if(U_FAILURE(status
)) {
1315 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1319 failure(status
, "new DecimalFormat");
1320 if (sdf
->getMinimumIntegerDigits() != 1)
1321 errln(UnicodeString("Minimum integer digits : ") + sdf
->getMinimumIntegerDigits());
1324 /* @bug 4052223 (API addition request A27)
1325 * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
1327 void NumberFormatRegressionTest::Test4052223(void)
1330 UErrorCode status
= U_ZERO_ERROR
;
1331 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,#00.00"), status
);
1332 if(U_FAILURE(status
)) {
1333 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1337 failure(status
, "new DecimalFormat");
1339 fmt
->parse(UnicodeString("abc3"), num
, status
);
1340 if(! U_FAILURE(status
))
1341 errln(UnicodeString("Bug 4052223 failed : can't parse string \"a\". Got ") /*+ num*/);
1342 /*} catch (ParseException foo) {
1343 logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
1348 * API tests for API addition request A9.
1350 void NumberFormatRegressionTest::Test4061302(void)
1352 UErrorCode status
= U_ZERO_ERROR
;
1353 DecimalFormatSymbols
*fmt
= new DecimalFormatSymbols(status
);
1354 if (U_FAILURE(status
)) {
1355 dataerrln("Error creating DecimalFormatSymbols - %s", u_errorName(status
));
1358 UnicodeString
currency(fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1359 UnicodeString
intlCurrency(fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1360 UnicodeString
monDecSeparator(fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1361 if (currency
== UnicodeString("") ||
1362 intlCurrency
== UnicodeString("") ||
1363 monDecSeparator
== UnicodeString(""))
1365 errln("getCurrencySymbols failed, got empty string.");
1367 UnicodeString monDecSeparatorStr
;
1368 monDecSeparatorStr
.append(monDecSeparator
);
1369 logln((UnicodeString
)"Before set ==> Currency : " + currency
+(UnicodeString
)" Intl Currency : " + intlCurrency
+ (UnicodeString
)" Monetary Decimal Separator : " + monDecSeparatorStr
);
1370 fmt
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, UnicodeString("XYZ"));
1371 fmt
->setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, UnicodeString("ABC"));
1372 fmt
->setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, UnicodeString((UChar
)0x002A/*'*'*/));
1373 currency
= fmt
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
);
1374 intlCurrency
= fmt
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
);
1375 monDecSeparator
= fmt
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
);
1376 if (currency
!= UnicodeString("XYZ") ||
1377 intlCurrency
!= UnicodeString("ABC") ||
1378 monDecSeparator
!= UnicodeString((UChar
)0x002A/*'*'*/)) {
1379 errln("setCurrencySymbols failed.");
1381 monDecSeparatorStr
.remove();
1382 monDecSeparatorStr
.append(monDecSeparator
);
1383 logln("After set ==> Currency : " + currency
+ " Intl Currency : " + intlCurrency
+ " Monetary Decimal Separator : " + monDecSeparatorStr
);
1388 * API tests for API addition request A23. FieldPosition.getBeginIndex and
1389 * FieldPosition.getEndIndex.
1391 void NumberFormatRegressionTest::Test4062486(void)
1393 UErrorCode status
= U_ZERO_ERROR
;
1394 DecimalFormat
*fmt
= new DecimalFormat(UnicodeString("#,##0.00"), status
);
1395 if (U_FAILURE(status
)) {
1396 dataerrln("Error creating DecimalFormat - %s", u_errorName(status
));
1399 UnicodeString formatted
;
1400 FieldPosition
field(0);
1401 double num
= 1234.5;
1402 fmt
->format(num
, formatted
, field
);
1403 if (field
.getBeginIndex() != 0 && field
.getEndIndex() != 5)
1404 errln(UnicodeString("Format 1234.5 failed. Begin index: ") /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1405 field
.setBeginIndex(7);
1406 field
.setEndIndex(4);
1407 if (field
.getBeginIndex() != 7 && field
.getEndIndex() != 4)
1408 errln("Set begin/end field indexes failed. Begin index: " /*+ field.getBeginIndex() + " End index: " + field.getEndIndex()*/);
1414 * DecimalFormat.parse incorrectly works with a group separator.
1416 void NumberFormatRegressionTest::Test4108738(void)
1418 UErrorCode status
= U_ZERO_ERROR
;
1419 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getUS(), status
);
1420 failure(status
, "new DecimalFormatSymbols");
1421 DecimalFormat
*df
= new DecimalFormat("#,##0.###", syms
, status
);
1422 if(U_FAILURE(status
)) {
1423 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1427 failure(status
, "new DecimalFormat");
1428 UnicodeString
text("1.222,111");
1430 ParsePosition
pp(0);
1431 df
->parse(text
, num
, pp
);
1433 // {sfb} how to do this (again) ?
1434 // shouldn't just be another round-trip test, should it?
1436 FieldPosition
pos(FieldPosition::DONT_CARE
);
1437 temp
= df
->format(num
.getDouble(), temp
, pos
);
1438 //if (!num.toString().equals("1.222"))
1439 if (temp
!= UnicodeString("1.222"))
1440 //errln("\"" + text + "\" is parsed as " + num);
1441 errln("\"" + text
+ "\" is parsed as " + temp
);
1442 text
= UnicodeString("1.222x111");
1443 pp
= ParsePosition(0);
1444 df
->parse(text
, num
, pp
);
1446 temp
= df
->format(num
.getDouble(), temp
, pos
);
1447 //if (!num.toString().equals("1.222"))
1448 if (temp
!= UnicodeString("1.222"))
1449 errln("\"" + text
+ "\" is parsed as " + temp
);
1455 * DecimalFormat.format() incorrectly formats negative doubles.
1457 void NumberFormatRegressionTest::Test4106658(void)
1459 UErrorCode status
= U_ZERO_ERROR
;
1460 DecimalFormat
*df
= new DecimalFormat(status
); // Corrected; see 4147706
1461 if(U_FAILURE(status
)) {
1462 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1466 failure(status
, "new DecimalFormat");
1467 volatile double d1
= 0.0; // volatile to prevent code optimization
1468 double d2
= -0.0001;
1469 UnicodeString buffer
;
1471 FieldPosition
pos(FieldPosition::DONT_CARE
);
1473 #if U_PLATFORM == U_PF_HPUX
1474 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1476 d1
*= -1.0; // Some compilers have a problem with defining -0.0
1478 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1479 df
->format(d1
, buffer
, pos
);
1480 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1481 errln(UnicodeString("") + d1
+ " is formatted as " + buffer
);
1483 df
->format(d2
, buffer
, pos
);
1484 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1485 errln(UnicodeString("") + d2
+ " is formatted as " + buffer
);
1491 * DecimalFormat.parse returns 0 if string parameter is incorrect.
1493 void NumberFormatRegressionTest::Test4106662(void)
1495 UErrorCode status
= U_ZERO_ERROR
;
1496 DecimalFormat
*df
= new DecimalFormat(status
);
1497 if(U_FAILURE(status
)) {
1498 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1502 failure(status
, "new DecimalFormat");
1503 UnicodeString
text("x");
1504 ParsePosition
pos1(0), pos2(0);
1507 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1509 df
->parse(text
, num
, pos1
);
1510 if (pos1
== ParsePosition(0)/*num != null*/) {
1511 errln(UnicodeString("Test Failed: \"") + text
+ "\" is parsed as " /*+ num*/);
1514 df
= new DecimalFormat(UnicodeString("$###.00"), status
);
1515 failure(status
, "new DecimalFormat");
1516 df
->parse(UnicodeString("$"), num
, pos2
);
1517 if (pos2
== ParsePosition(0) /*num != null*/){
1518 errln(UnicodeString("Test Failed: \"$\" is parsed as ") /*+ num*/);
1524 /* @bug 4114639 (duplicate of 4106662)
1525 * NumberFormat.parse doesn't return null
1527 void NumberFormatRegressionTest::Test4114639(void)
1529 UErrorCode status
= U_ZERO_ERROR
;
1530 NumberFormat
*format
= NumberFormat::createInstance(status
);
1531 if(U_FAILURE(status
)) {
1532 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1536 failure(status
, "NumberFormat::createInstance");
1537 UnicodeString
text("time 10:x");
1538 ParsePosition
pos(8);
1540 format
->parse(text
, result
, pos
);
1541 if (/*result != null*/pos
.getErrorIndex() != 8)
1542 errln(UnicodeString("Should return null but got : ") /*+ result*/); // Should be null; it isn't
1548 * TODO: this test does not work because we need to use a 64 bit number and a
1549 * a double only MAY only have 52 bits of precision.
1550 * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
1552 void NumberFormatRegressionTest::Test4106664(void)
1554 UErrorCode status
= U_ZERO_ERROR
;
1555 DecimalFormat
*df
= new DecimalFormat(status
);
1556 if(U_FAILURE(status
)) {
1557 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1561 failure(status
, "new DecimalFormat");
1562 // {sfb} long in java is 64 bits
1563 /*long*/double n
= 1234567890123456.0;
1564 /*int*/int32_t m
= 12345678;
1565 // {sfb} will this work?
1566 //BigInteger bigN = BigInteger.valueOf(n);
1567 //bigN = bigN.multiply(BigInteger.valueOf(m));
1568 double bigN
= n
* m
;
1569 df
->setMultiplier(m
);
1570 df
->setGroupingUsed(FALSE
);
1572 FieldPosition
pos(FieldPosition::DONT_CARE
);
1573 logln("formated: " +
1574 df
->format(n
, temp
, pos
));
1577 sprintf(buf
, "%g", bigN
);
1578 //logln("expected: " + bigN.toString());
1579 logln(UnicodeString("expected: ") + buf
);
1583 /* @bug 4106667 (duplicate of 4106658)
1584 * DecimalFormat.format incorrectly formats -0.0.
1586 void NumberFormatRegressionTest::Test4106667(void)
1588 UErrorCode status
= U_ZERO_ERROR
;
1589 DecimalFormat
*df
= new DecimalFormat(status
);
1590 if(U_FAILURE(status
)) {
1591 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1595 failure(status
, "new DecimalFormat");
1596 UChar foo
[] = { 0x002B };
1597 UnicodeString
bar(foo
, 1, 1);
1598 volatile double d
= 0.0; // volatile to prevent code optimization
1600 UnicodeString buffer
;
1601 FieldPosition
pos(FieldPosition::DONT_CARE
);
1603 logln("pattern: \"" + df
->toPattern(temp
) + "\"");
1604 #if U_PLATFORM == U_PF_HPUX
1605 d
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
1607 d
*= -1.0; // Some compilers have a problem with defining -0.0
1609 df
->setPositivePrefix(/*"+"*/bar
);
1610 df
->format(d
, buffer
, pos
);
1611 if (buffer
!= UnicodeString("-0")) // Corrected; see 4147706
1612 errln(/*d + */UnicodeString(" is formatted as ") + buffer
);
1618 * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
1620 #if U_PLATFORM == U_PF_OS390
1621 # define MAX_INT_DIGITS 70
1623 # define MAX_INT_DIGITS 128
1626 void NumberFormatRegressionTest::Test4110936(void)
1628 UErrorCode status
= U_ZERO_ERROR
;
1629 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1630 if(U_FAILURE(status
)) {
1631 dataerrln("Error creating DecimalFormat: %s", u_errorName(status
));
1635 failure(status
, "NumberFormat::createInstance");
1636 nf
->setMaximumIntegerDigits(MAX_INT_DIGITS
);
1637 logln("setMaximumIntegerDigits(MAX_INT_DIGITS)");
1638 if (nf
->getMaximumIntegerDigits() != MAX_INT_DIGITS
)
1639 errln(UnicodeString("getMaximumIntegerDigits() returns ") +
1640 nf
->getMaximumIntegerDigits());
1646 * Locale data should use generic currency symbol
1648 * 1) Make sure that all currency formats use the generic currency symbol.
1649 * 2) Make sure we get the same results using the generic symbol or a
1652 void NumberFormatRegressionTest::Test4122840(void)
1655 const Locale
*locales
= Locale::getAvailableLocales(count
);
1657 for (int i
= 0; i
< count
; i
++) {
1658 UErrorCode status
= U_ZERO_ERROR
;
1659 ResourceBundle
*rb
= new ResourceBundle(
1660 NULL
/*"java.text.resources.LocaleElements"*/,
1661 locales
[i
], status
);
1662 failure(status
, "new ResourceBundle");
1663 ResourceBundle numPat
= rb
->getWithFallback("NumberElements", status
);
1664 failure(status
, "rb.get(NumberElements)");
1665 numPat
= numPat
.getWithFallback("latn",status
);
1666 failure(status
, "rb.get(latn)");
1667 numPat
= numPat
.getWithFallback("patterns",status
);
1668 failure(status
, "rb.get(patterns)");
1669 numPat
= numPat
.getWithFallback("currencyFormat",status
);
1670 failure(status
, "rb.get(currencyFormat)");
1672 // Get the currency pattern for this locale. We have to fish it
1673 // out of the ResourceBundle directly, since DecimalFormat.toPattern
1674 // will return the localized symbol, not \00a4
1676 UnicodeString pattern
= numPat
.getString(status
);
1677 failure(status
, "rb->getString()");
1679 UChar fo
[] = { 0x00A4 };
1680 UnicodeString
foo(fo
, 1, 1);
1682 //if (pattern.indexOf("\u00A4") == -1 ) {
1683 if (pattern
.indexOf(foo
) == -1 ) {
1684 errln(UnicodeString("Currency format for ") + UnicodeString(locales
[i
].getName()) +
1685 " does not contain generic currency symbol:" +
1689 // Create a DecimalFormat using the pattern we got and format a number
1690 DecimalFormatSymbols
*symbols
= new DecimalFormatSymbols(locales
[i
], status
);
1691 failure(status
, "new DecimalFormatSymbols");
1692 DecimalFormat
*fmt1
= new DecimalFormat(pattern
, *symbols
, status
);
1693 failure(status
, "new DecimalFormat");
1695 UnicodeString result1
;
1696 FieldPosition
pos(FieldPosition::DONT_CARE
);
1697 result1
= fmt1
->format(1.111, result1
, pos
);
1700 // Now substitute in the locale's currency symbol and create another
1701 // pattern. We have to skip locales where the currency symbol
1702 // contains decimal separators, because that confuses things
1704 UChar ba
[] = { 0x002E/*'.'*/ };
1705 UnicodeString
bar(ba
, 1, 1);
1707 if (symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).indexOf(bar
) == -1) {
1708 // {sfb} Also, switch the decimal separator to the monetary decimal
1709 // separator to mimic the behavior of a currency format
1710 symbols
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
,
1711 symbols
->getSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
));
1713 UnicodeString
buf(pattern
);
1714 for (int j
= 0; j
< buf
.length(); j
++) {
1715 if (buf
[j
] == 0x00a4 ) {
1716 if(buf
[j
+ 1] == 0x00a4) {
1717 // {sfb} added to support double currency marker (intl currency sign)
1718 buf
.replace(j
, /*j+*/2, symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
));
1719 j
+= symbols
->getSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
).length();
1722 buf
.replace(j
, /*j+*/1, symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
));
1723 j
+= symbols
->getSymbol(DecimalFormatSymbols::kCurrencySymbol
).length() - 1;
1728 DecimalFormat
*fmt2
= new DecimalFormat(buf
, *symbols
, status
);
1729 failure(status
, "new DecimalFormat");
1731 // Get the currency (if there is one) so we can set the rounding and fraction
1732 const UChar
*currency
= fmt1
->getCurrency();
1733 if (*currency
!= 0) {
1734 double rounding
= ucurr_getRoundingIncrement(currency
, &status
);
1735 int32_t frac
= ucurr_getDefaultFractionDigits(currency
, &status
);
1736 if (U_SUCCESS(status
)) {
1737 fmt2
->setRoundingIncrement(rounding
);
1738 fmt2
->setMinimumFractionDigits(frac
);
1739 fmt2
->setMaximumFractionDigits(frac
);
1742 failure(status
, "Fetching currency rounding/fractions");
1746 UnicodeString result2
;
1747 fmt2
->format(1.111, result2
, pos
);
1749 if (result1
!= result2
) {
1750 errln("Results for " + (UnicodeString
)(locales
[i
].getName()) + " differ: " +
1751 result1
+ " vs " + result2
);
1764 * DecimalFormat.format() delivers wrong string.
1766 void NumberFormatRegressionTest::Test4125885(void)
1768 UErrorCode status
= U_ZERO_ERROR
;
1769 double rate
= 12.34;
1770 DecimalFormat
*formatDec
= new DecimalFormat ("000.00", status
);
1771 if(U_FAILURE(status
)) {
1772 errcheckln(status
, "Error creating DecimalFormat: %s", u_errorName(status
));
1776 failure(status
, "new DecimalFormat");
1778 logln("toPattern: " + formatDec
->toPattern(temp
));
1779 UnicodeString rateString
;
1780 FieldPosition
pos(FieldPosition::DONT_CARE
);
1781 rateString
= formatDec
->format(rate
, rateString
, pos
);
1782 if (rateString
!= UnicodeString("012.34"))
1783 errln("result : " + rateString
+ " expected : 012.34");
1785 delete formatDec
;// = null;
1786 formatDec
= new DecimalFormat ("+000.00%;-000.00%", status
);
1787 failure(status
, "new DecimalFormat");
1788 logln("toPattern: " + formatDec
->toPattern(temp
));
1789 rateString
.remove();
1790 rateString
= formatDec
->format(rate
, rateString
, pos
);
1791 if (rateString
!= UnicodeString("+012.34%"))
1792 errln("result : " + rateString
+ " expected : +012.34%");
1799 * DecimalFormat produces extra zeros when formatting numbers.
1801 void NumberFormatRegressionTest::Test4134034(void)
1803 UErrorCode status
= U_ZERO_ERROR
;
1804 DecimalFormat
*nf
= new DecimalFormat("##,###,###.00", status
);
1805 if (!failure(status
, "new DecimalFormat")) {
1807 FieldPosition
pos(FieldPosition::DONT_CARE
);
1808 f
= nf
->format(9.02, f
, pos
);
1809 if (f
== UnicodeString("9.02"))
1812 errln("9.02 -> " + f
+ "; want 9.02");
1815 f
= nf
->format((int32_t)0, f
, pos
);
1816 if (f
== UnicodeString(".00"))
1819 errln("0 -> " + f
+ "; want .00");
1827 * CANNOT REPRODUCE - This bug could not be reproduced. It may be
1828 * a duplicate of 4134034.
1830 * JDK 1.1.6 Bug, did NOT occur in 1.1.5
1831 * Possibly related to bug 4125885.
1833 * This class demonstrates a regression in version 1.1.6
1834 * of DecimalFormat class.
1837 * Value 1.2 Format #.00 Result '01.20' !!!wrong
1838 * Value 1.2 Format 0.00 Result '001.20' !!!wrong
1839 * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
1840 * Value 1.2 Format #0.0# Result '1.2'
1841 * Value 1.2 Format #0.00 Result '001.20' !!!wrong
1844 * Value 1.2 Format #.00 Result '1.20'
1845 * Value 1.2 Format 0.00 Result '1.20'
1846 * Value 1.2 Format 00.00 Result '01.20'
1847 * Value 1.2 Format #0.0# Result '1.2'
1848 * Value 1.2 Format #0.00 Result '1.20'
1850 void NumberFormatRegressionTest::Test4134300(void) {
1851 UnicodeString DATA
[] = {
1852 // Pattern Expected string
1853 UnicodeString("#.00"), UnicodeString("1.20"),
1854 UnicodeString("0.00"), UnicodeString("1.20"),
1855 UnicodeString("00.00"), UnicodeString("01.20"),
1856 UnicodeString("#0.0#"), UnicodeString("1.2"),
1857 UnicodeString("#0.00"), UnicodeString("1.20")
1860 for (int i
=0; i
< 10; i
+=2) {
1861 UnicodeString result
;
1862 UErrorCode status
= U_ZERO_ERROR
;
1863 DecimalFormat
*df
= new DecimalFormat(DATA
[i
], status
);
1864 if (!failure(status
, "new DecimalFormat")) {
1865 FieldPosition
pos(FieldPosition::DONT_CARE
);
1866 result
= df
->format(1.2, result
, pos
);
1867 if (result
!= DATA
[i
+1]) {
1868 errln("Fail: 1.2 x " + DATA
[i
] + " = " + result
+
1869 "; want " + DATA
[i
+1]);
1872 logln("Ok: 1.2 x " + DATA
[i
] + " = " + result
);
1882 * Empty pattern produces double negative prefix.
1884 void NumberFormatRegressionTest::Test4140009(void)
1886 UErrorCode status
= U_ZERO_ERROR
;
1887 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
1888 failure(status
, "new DecimalFormatSymbols");
1889 DecimalFormat
*f
= new DecimalFormat(UnicodeString(""), syms
, status
);
1890 if (!failure(status
, "new DecimalFormat")) {
1892 FieldPosition
pos(FieldPosition::DONT_CARE
);
1893 s
= f
->format(123.456, s
, pos
);
1894 if (s
!= UnicodeString("123.456"))
1895 errln("Fail: Format empty pattern x 123.456 => " + s
);
1897 s
= f
->format(-123.456, s
, pos
);
1898 if (s
!= UnicodeString("-123.456"))
1899 errln("Fail: Format empty pattern x -123.456 => " + s
);
1906 * BigDecimal numbers get their fractions truncated by NumberFormat.
1908 // {sfb} not pertinent in C++ ??
1909 void NumberFormatRegressionTest::Test4141750(void) {
1911 UnicodeString str("12345.67");
1912 BigDecimal bd = new BigDecimal(str);
1913 String sd = NumberFormat.getInstance(Locale.US).format(bd);
1914 if (!sd.endsWith("67")) errln("Fail: " + str + " x format -> " + sd);
1916 catch (Exception e) {
1917 errln(e.toString());
1918 e.printStackTrace();
1924 * DecimalFormat toPattern() doesn't quote special characters or handle
1927 void NumberFormatRegressionTest::Test4145457() {
1929 UErrorCode status
= U_ZERO_ERROR
;
1930 NumberFormat
*nff
= NumberFormat::createInstance(status
);
1931 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
1935 DecimalFormat
*nf
= dynamic_cast<DecimalFormat
*>(nff
);
1937 errln("DecimalFormat needed to continue");
1941 DecimalFormatSymbols
*sym
= (DecimalFormatSymbols
*) nf
->getDecimalFormatSymbols();
1942 sym
->setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, (UChar
)/*'\''*/0x0027);
1943 nf
->setDecimalFormatSymbols(*sym
);
1944 double pi
= 3.14159;
1946 UnicodeString PATS
[] = {
1947 UnicodeString("#.00 'num''ber'"), UnicodeString("''#.00''")
1950 for (int32_t i
=0; i
<2; ++i
) {
1951 nf
->applyPattern(PATS
[i
], status
);
1952 failure(status
, "nf->applyPattern");
1954 FieldPosition
pos(FieldPosition::DONT_CARE
);
1955 out
= nf
->format(pi
, out
, pos
);
1957 pat
= nf
->toPattern(pat
);
1959 ParsePosition
pp(0);
1960 nf
->parse(out
, num
, pp
);
1961 double val
= num
.getDouble();
1963 nf
->applyPattern(pat
, status
);
1964 failure(status
, "nf->applyPattern");
1966 out2
= nf
->format(pi
, out2
, pos
);
1968 pat2
= nf
->toPattern(pat2
);
1970 nf
->parse(out2
, num
, pp
);
1971 double val2
= num
.getDouble();
1974 errln("Fail with \"" + PATS
[i
] + "\": Patterns should concur, \"" +
1975 pat
+ "\" vs. \"" + pat2
+ "\"");
1977 logln("Ok \"" + PATS
[i
] + "\" toPattern() -> \"" + pat
+ '"');
1979 if (val
== val2
&& out
== out2
) {
1980 logln(UnicodeString("Ok ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1981 out
+ "\" -> " + val
+ " -> \"" +
1982 out2
+ "\" -> " + val2
);
1985 errln(UnicodeString("Fail ") + pi
+ " x \"" + PATS
[i
] + "\" -> \"" +
1986 out
+ "\" -> " + val
+ " -> \"" +
1987 out2
+ "\" -> " + val2
);
1991 catch (ParseException e) {
1992 errln("Fail: " + e);
1993 e.printStackTrace();
2001 * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
2003 * This bug is a duplicate of 4139344, which is a duplicate of 4134300
2005 void NumberFormatRegressionTest::Test4147295(void)
2007 UErrorCode status
= U_ZERO_ERROR
;
2008 DecimalFormat
*sdf
= new DecimalFormat(status
);
2009 UnicodeString
pattern("#,###");
2010 logln("Applying pattern \"" + pattern
+ "\"");
2011 sdf
->applyPattern(pattern
, status
);
2012 if (!failure(status
, "sdf->applyPattern")) {
2013 int minIntDig
= sdf
->getMinimumIntegerDigits();
2014 if (minIntDig
!= 0) {
2015 errln("Test failed");
2016 errln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2018 errln(UnicodeString(" new pattern: ") + sdf
->toPattern(temp
));
2020 logln("Test passed");
2021 logln(UnicodeString(" Minimum integer digits : ") + minIntDig
);
2029 * DecimalFormat formats -0.0 as +0.0
2030 * See also older related bug 4106658, 4106667
2032 void NumberFormatRegressionTest::Test4147706(void)
2034 UErrorCode status
= U_ZERO_ERROR
;
2035 DecimalFormat
*df
= new DecimalFormat("#,##0.0##", status
);
2036 failure(status
, "new DecimalFormat");
2037 DecimalFormatSymbols
*syms
= new DecimalFormatSymbols(Locale::getEnglish(), status
);
2038 if (!failure(status
, "new DecimalFormatSymbols")) {
2040 UnicodeString f2
, temp
;
2041 FieldPosition
pos(FieldPosition::DONT_CARE
);
2042 volatile double d1
= 0.0; // volatile to prevent code optimization
2043 double d2
= -0.0001;
2045 #if U_PLATFORM == U_PF_HPUX
2046 d1
= 0.0 * -1.0; // old HPUX compiler ignores volatile keyword
2048 d1
*= -1.0; // Some compilers have a problem with defining -0.0
2050 df
->adoptDecimalFormatSymbols(syms
);
2051 f1
= df
->format(d1
, f1
, pos
);
2052 f2
= df
->format(d2
, f2
, pos
);
2053 if (f1
!= UnicodeString("-0.0")) {
2054 errln(UnicodeString("") + d1
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f1
+ '"');
2056 if (f2
!= UnicodeString("-0.0")) {
2057 errln(UnicodeString("") + d2
+ UnicodeString(" x \"") + df
->toPattern(temp
) + "\" is formatted as \"" + f2
+ '"');
2065 // Not applicable, since no serialization in C++
2066 /*class myformat implements Serializable
2068 DateFormat _dateFormat = DateFormat.getDateInstance();
2072 GregorianCalendar calendar = new GregorianCalendar();
2073 Date t = calendar.getTime();
2074 String nowStr = _dateFormat.format(t);
2081 * NumberFormat cannot format Double.MAX_VALUE
2083 // TODO: make this test actually test something
2085 NumberFormatRegressionTest::Test4162198(void)
2087 // for some reason, DBL_MAX will not round trip. (bug in sprintf/atof)
2088 double dbl
= INT32_MAX
* 1000.0;
2089 UErrorCode status
= U_ZERO_ERROR
;
2090 NumberFormat
*f
= NumberFormat::createInstance(status
);
2091 if(U_FAILURE(status
)) {
2092 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2095 f
->setMaximumFractionDigits(INT32_MAX
);
2096 f
->setMaximumIntegerDigits(INT32_MAX
);
2099 logln(UnicodeString("The number ") + dbl
+ " formatted to " + s
);
2102 f
->parse(s
, n
, status
);
2103 if(U_FAILURE(status
))
2104 errln("Couldn't parse!");
2105 //} catch (java.text.ParseException e) {
2106 // errln("Caught a ParseException:");
2107 // e.printStackTrace();
2110 //logln("The string " + s + " parsed as " + n);
2112 // {dlf} The old code assumes n is a double, but it isn't any more...
2113 // Formattable apparently does not and never did interconvert... too bad.
2114 //if(n.getDouble() != dbl) {
2115 // errln("Round trip failure");
2117 if (n
.getInt64() != dbl
) {
2118 errln("Round trip failure");
2126 * NumberFormat does not parse negative zero.
2129 NumberFormatRegressionTest::Test4162852(void)
2131 UErrorCode status
= U_ZERO_ERROR
;
2132 for(int32_t i
=0; i
< 2; ++i
) {
2133 NumberFormat
*f
= (i
== 0) ? NumberFormat::createInstance(status
)
2134 : NumberFormat::createPercentInstance(status
);
2135 if(U_FAILURE(status
)) {
2136 dataerrln("Couldn't create number format - %s", u_errorName(status
));
2144 f
->parse(s
, n
, status
);
2145 if(U_FAILURE(status
))
2146 errln("Couldn't parse!");
2147 double e
= n
.getDouble();
2148 logln(UnicodeString("") +
2150 '"' + s
+ '"' + " -> " + e
);
2151 #if (U_PLATFORM == U_PF_OS390 && !defined(IEEE_754)) || U_PLATFORM == U_PF_OS400
2154 if (e
!= 0.0 || 1.0/e
> 0.0) {
2156 logln("Failed to parse negative zero");
2162 static double _u_abs(double a
) { return a
<0?-a
:a
; }
2165 * May 17 1999 sync up - liu
2167 * NumberFormat truncates data
2169 void NumberFormatRegressionTest::Test4167494(void) {
2170 UErrorCode status
= U_ZERO_ERROR
;
2171 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2172 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2177 double a
= DBL_MAX
* 0.99; // DBL_MAX itself overflows to +Inf
2181 fmt
->parse(s
, num
, status
);
2182 failure(status
, "Parse");
2183 if (num
.getType() == Formattable::kDouble
&&
2184 _u_abs(num
.getDouble() - a
) / a
< 0.01) { // RT within 1%
2185 logln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2186 toString(num
) + " ok");
2188 errln(UnicodeString("") + a
+ " -> \"" + s
+ "\" -> " +
2189 toString(num
) + " FAIL");
2192 // We don't test Double.MIN_VALUE because the locale data for the US
2193 // currently doesn't specify enough digits to display Double.MIN_VALUE.
2194 // This is correct for now; however, we leave this here as a reminder
2195 // in case we want to address this later.
2201 * May 17 1999 sync up - liu
2203 * DecimalFormat.parse() fails when ParseIntegerOnly set to true
2205 void NumberFormatRegressionTest::Test4170798(void) {
2206 UErrorCode status
= U_ZERO_ERROR
;
2207 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2208 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2212 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2214 errln("DecimalFormat needed to continue");
2217 df
->setParseIntegerOnly(TRUE
);
2219 ParsePosition
pos(0);
2220 df
->parse("-0.0", n
, pos
);
2221 if (n
.getType() != Formattable::kLong
2222 || n
.getLong() != 0) {
2223 errln(UnicodeString("FAIL: parse(\"-0.0\") returns ") + toString(n
));
2229 * May 17 1999 sync up - liu
2230 * toPattern only puts the first grouping separator in.
2232 void NumberFormatRegressionTest::Test4176114(void) {
2233 const char* DATA
[] = {
2235 "000", "#000", // No grouping
2236 "#000", "#000", // No grouping
2240 "00,000", "#00,000",
2241 "000,000", "#,000,000",
2242 "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
2244 int DATA_length
= UPRV_LENGTHOF(DATA
);
2245 UErrorCode status
= U_ZERO_ERROR
;
2247 for (int i
=0; i
<DATA_length
; i
+=2) {
2248 DecimalFormat
df(DATA
[i
], status
);
2249 if (!failure(status
, "DecimalFormat constructor")) {
2251 UnicodeString
exp(DATA
[i
+1]);
2253 errln(UnicodeString("FAIL: ") + DATA
[i
] + " -> " +
2254 s
+ ", want " + exp
);
2261 * May 17 1999 sync up - liu
2263 * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
2265 void NumberFormatRegressionTest::Test4179818(void) {
2266 const char* DATA
[] = {
2267 // Input Pattern Expected output
2268 "1.2511", "#.#", "1.3",
2269 "1.2501", "#.#", "1.3",
2272 int DATA_length
= UPRV_LENGTHOF(DATA
);
2278 UErrorCode status
= U_ZERO_ERROR
;
2279 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2280 failure(status
, "Construct DecimalFormatSymbols");
2281 DecimalFormat
fmt("#", sym
, status
);
2282 if (!failure(status
, "Construct DecimalFormat")) {
2283 for (int i
=0; i
<DATA_length
; i
+=3) {
2284 double in
= DOUBLE
[i
/3];
2285 UnicodeString
pat(DATA
[i
+1]);
2286 UnicodeString
exp(DATA
[i
+2]);
2287 fmt
.applyPattern(pat
, status
);
2288 failure(status
, "applyPattern");
2291 fmt
.format(in
, out
, pos
);
2293 logln(UnicodeString("Ok: ") + in
+ " x " + pat
+ " = " + out
);
2295 errln(UnicodeString("FAIL: ") + in
+ " x " + pat
+ " = " + out
+
2296 ", expected " + exp
);
2303 * May 17 1999 sync up - liu
2304 * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
2305 * This includes the minus sign, currency symbol, international currency
2306 * symbol, percent, and permille. This is filed as bugs 4212072 and
2309 void NumberFormatRegressionTest::Test4212072(void) {
2310 UErrorCode status
= U_ZERO_ERROR
;
2311 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2313 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2314 DecimalFormat
fmt(UnicodeString("#"), sym
, status
);
2315 if(failure(status
, "DecimalFormat ct", Locale::getUS())) {
2322 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x5e);
2323 fmt
.setDecimalFormatSymbols(sym
);
2325 if (fmt
.format((int32_t)-1, s
, pos
) != UNICODE_STRING("^1", 2)) {
2326 errln(UnicodeString("FAIL: -1 x (minus=^) -> ") + s
+
2330 if (fmt
.getNegativePrefix(s
) != UnicodeString((UChar
)0x5e)) {
2331 errln(UnicodeString("FAIL: (minus=^).getNegativePrefix -> ") +
2334 sym
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, (UChar
)0x2d);
2336 fmt
.applyPattern(UnicodeString("#%"), status
);
2337 failure(status
, "applyPattern percent");
2338 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x5e);
2339 fmt
.setDecimalFormatSymbols(sym
);
2341 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("25^", 3)) {
2342 errln(UnicodeString("FAIL: 0.25 x (percent=^) -> ") + s
+
2346 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2347 errln(UnicodeString("FAIL: (percent=^).getPositiveSuffix -> ") +
2350 sym
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, (UChar
)0x25);
2352 fmt
.applyPattern(str("#\\u2030"), status
);
2353 failure(status
, "applyPattern permill");
2354 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x5e);
2355 fmt
.setDecimalFormatSymbols(sym
);
2357 if (fmt
.format(0.25, s
, pos
) != UNICODE_STRING("250^", 4)) {
2358 errln(UnicodeString("FAIL: 0.25 x (permill=^) -> ") + s
+
2362 if (fmt
.getPositiveSuffix(s
) != UnicodeString((UChar
)0x5e)) {
2363 errln(UnicodeString("FAIL: (permill=^).getPositiveSuffix -> ") +
2366 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, (UChar
)0x2030);
2368 fmt
.applyPattern(str("\\u00A4#.00"), status
);
2369 failure(status
, "applyPattern currency");
2370 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "usd");
2371 fmt
.setDecimalFormatSymbols(sym
);
2373 if (fmt
.format(12.5, s
, pos
) != UnicodeString("usd12.50")) {
2374 errln(UnicodeString("FAIL: 12.5 x (currency=usd) -> ") + s
+
2378 if (fmt
.getPositivePrefix(s
) != UnicodeString("usd")) {
2379 errln(UnicodeString("FAIL: (currency=usd).getPositivePrefix -> ") +
2382 sym
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "$");
2384 fmt
.applyPattern(str("\\u00A4\\u00A4#.00"), status
);
2385 failure(status
, "applyPattern intl currency");
2386 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "DOL");
2387 fmt
.setDecimalFormatSymbols(sym
);
2389 if (fmt
.format(12.5, s
, pos
) != UnicodeString("DOL12.50")) {
2390 errln(UnicodeString("FAIL: 12.5 x (intlcurrency=DOL) -> ") + s
+
2394 if (fmt
.getPositivePrefix(s
) != UnicodeString("DOL")) {
2395 errln(UnicodeString("FAIL: (intlcurrency=DOL).getPositivePrefix -> ") +
2398 sym
.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol
, "USD");
2400 // Since the pattern logic has changed, make sure that patterns round
2401 // trip properly. Test stream in/out integrity too.
2403 const Locale
* avail
= NumberFormat::getAvailableLocales(n
);
2404 static const char* type
[] = {
2409 for (int i
=0; i
<n
; ++i
) {
2410 for (int j
=0; j
<3; ++j
) {
2411 status
= U_ZERO_ERROR
;
2415 nf
= NumberFormat::createInstance(avail
[i
], status
);
2416 failure(status
, "createInstance", avail
[i
]);
2419 nf
= NumberFormat::createCurrencyInstance(avail
[i
], status
);
2420 failure(status
, "createCurrencyInstance", avail
[i
]);
2423 nf
= NumberFormat::createPercentInstance(avail
[i
], status
);
2424 failure(status
, "createPercentInstance", avail
[i
]);
2427 if (U_FAILURE(status
)) {
2430 DecimalFormat
*df
= (DecimalFormat
*) nf
;
2432 // Test toPattern/applyPattern round trip
2435 DecimalFormatSymbols
symb(avail
[i
], status
);
2436 failure(status
, "Construct DecimalFormatSymbols", avail
[i
]);
2437 DecimalFormat
f2(pat
, symb
, status
);
2439 UnicodeString("Construct DecimalFormat(") + pat
+ ")")) {
2444 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2446 "\" -> \"" + f2
.toPattern(p
) + "\"");
2449 logln(UnicodeString("PASS: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2454 // Test toLocalizedPattern/applyLocalizedPattern round trip
2455 // TODO(refactor): don't worry about localized patterns for now.
2456 // df->toLocalizedPattern(pat);
2457 // f2.applyLocalizedPattern(pat, status);
2459 UnicodeString("applyLocalizedPattern(") + pat
+ ")", avail
[i
]);
2460 if (U_FAILURE(status
)) {
2464 // TODO(refactor): don't worry about localized patterns for now.
2465 // Make sure we set the currency attributes appropriately
2466 // if (j == 1) { // Currency format
2467 // f2.setCurrency(f2.getCurrency(), status);
2470 UnicodeString("setCurrency() for (") + pat
+ ")", avail
[i
]);
2471 if (U_FAILURE(status
)) {
2477 errln(UnicodeString("FAIL: ") + type
[j
] + avail
[i
].getDisplayName(l
) +
2478 " -> localized \"" + pat
+
2479 "\" -> \"" + f2
.toPattern(p
) + "\"");
2484 // Test writeObject/readObject round trip
2485 // NOT ON ICU -- Java only
2491 * May 17 1999 sync up - liu
2492 * DecimalFormat.parse() fails for mulipliers 2^n.
2494 void NumberFormatRegressionTest::Test4216742(void) {
2495 UErrorCode status
= U_ZERO_ERROR
;
2496 DecimalFormat
*fmt
= (DecimalFormat
*) NumberFormat::createInstance(Locale::getUS(), status
);
2497 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2501 int32_t DATA
[] = { INT32_MIN
, INT32_MAX
, -100000000, 100000000 };
2502 int DATA_length
= UPRV_LENGTHOF(DATA
);
2503 for (int i
=0; i
<DATA_length
; ++i
) {
2504 UnicodeString
str((UnicodeString
)"" + DATA
[i
]);
2505 for (int m
= 1; m
<= 100; m
++) {
2506 fmt
->setMultiplier(m
);
2508 fmt
->parse(str
, num
, status
);
2509 failure(status
, "parse", Locale::getUS());
2510 if (num
.getType() != Formattable::kLong
&&
2511 num
.getType() != Formattable::kDouble
) {
2512 errln(UnicodeString("FAIL: Wanted number, got ") +
2515 double d
= num
.getType() == Formattable::kDouble
?
2516 num
.getDouble() : (double) num
.getLong();
2517 if ((d
> 0) != (DATA
[i
] > 0)) {
2518 errln(UnicodeString("\"") + str
+ "\" parse(x " +
2519 fmt
->getMultiplier() +
2520 ") => " + toString(num
));
2529 * May 17 1999 sync up - liu
2530 * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
2533 void NumberFormatRegressionTest::Test4217661(void) {
2534 const double D
[] = { 0.001, 1.001, 0.006, 1.006 };
2535 const char* S
[] = { "0", "1", "0.01", "1.01" };
2536 int D_length
= UPRV_LENGTHOF(D
);
2537 UErrorCode status
= U_ZERO_ERROR
;
2538 NumberFormat
*fmt
= NumberFormat::createInstance(Locale::getUS(), status
);
2539 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2543 fmt
->setMaximumFractionDigits(2);
2544 for (int i
=0; i
<D_length
; i
++) {
2546 fmt
->format(D
[i
], s
);
2547 if (s
!= UnicodeString(S
[i
])) {
2548 errln(UnicodeString("FAIL: Got ") + s
+ ", exp " + S
[i
]);
2555 * alphaWorks upgrade
2557 void NumberFormatRegressionTest::Test4161100(void) {
2558 UErrorCode status
= U_ZERO_ERROR
;
2559 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2560 if (failure(status
, "createInstance", Locale::getUS(), TRUE
)){
2564 nf
->setMinimumFractionDigits(1);
2565 nf
->setMaximumFractionDigits(1);
2570 logln(UnicodeString() + a
+ " x " +
2571 ((DecimalFormat
*) nf
)->toPattern(pat
) + " = " + s
);
2572 if (s
!= UnicodeString("-0.1")) {
2579 * June 16 1999 sync up - liu
2580 * Formatting .5 rounds to "1" instead of "0". (Regression in 1.2.2 RC1)
2582 void NumberFormatRegressionTest::Test4243011(void) {
2583 UErrorCode status
= U_ZERO_ERROR
;
2584 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2585 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2586 DecimalFormat
fmt(UnicodeString("0."), sym
, status
);
2588 if (!failure(status
, "DecimalFormat ct", Locale::getUS())) {
2589 const double NUM
[] = { -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5 };
2590 const char* STR
[] = { "-2.", "-2.", "-0.", "0.", "2.", "2.", "4.", "4." };
2591 int32_t N
= UPRV_LENGTHOF(NUM
);
2593 for (int32_t i
=0; i
<N
; ++i
) {
2595 UnicodeString
exp(STR
[i
]);
2597 fmt
.format(NUM
[i
], str
, pos
);
2599 logln(UnicodeString("Ok ") + NUM
[i
] + " x 0. = " + str
);
2601 errln(UnicodeString("FAIL ") + NUM
[i
] + " x 0. = " + str
+
2609 * June 16 1999 sync up - liu
2610 * format(0.0) gives "0.1" if preceded by parse("99.99").
2611 * (Regression in 1.2.2 RC1)
2613 void NumberFormatRegressionTest::Test4243108(void) {
2614 UErrorCode status
= U_ZERO_ERROR
;
2615 DecimalFormatSymbols
sym(Locale::getUS(), status
);
2616 failure(status
, "DecimalFormatSymbols ct", Locale::getUS());
2617 DecimalFormat
fmt(UnicodeString("#.#"), sym
, status
);
2618 if (failure(status
, "DecimalFormat ct", Locale::getUS())) {
2625 fmt
.format(0.0, str
, pos
);
2626 UnicodeString
exp("0");
2628 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2630 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2636 fmt
.parse(str
, val
, status
);
2637 failure(status
, "DecimalFormat.parse(99.99)", Locale::getUS());
2638 if (val
.getType() == Formattable::kDouble
&&
2639 val
.getDouble() == 99.99) {
2640 logln(UnicodeString("Ok 99.99 / #.# = ") + toString(val
));
2642 errln(UnicodeString("FAIL 99.99 / #.# = ") + toString(val
) +
2647 fmt
.format(0.0, str
, pos
);
2649 logln(UnicodeString("Ok 0.0 x #.# = ") + str
);
2651 errln(UnicodeString("FAIL 0.0 x #.# = ") + str
+
2658 * DateFormat should call setIntegerParseOnly(TRUE) on adopted
2659 * NumberFormat objects.
2661 void NumberFormatRegressionTest::TestJ691(void) {
2662 UErrorCode status
= U_ZERO_ERROR
;
2663 Locale
loc("fr", "CH");
2665 // set up the input date string & expected output
2666 UnicodeString
udt("11.10.2000", "");
2667 UnicodeString
exp("11.10.00", "");
2669 // create a Calendar for this locale
2670 Calendar
*cal
= Calendar::createInstance(loc
, status
);
2671 if (U_FAILURE(status
)) {
2672 dataerrln("FAIL: Calendar::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2676 // create a NumberFormat for this locale
2677 NumberFormat
*nf
= NumberFormat::createInstance(loc
, status
);
2678 if (U_FAILURE(status
)) {
2679 dataerrln("FAIL: NumberFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2683 // *** Here's the key: We don't want to have to do THIS:
2684 // nf->setParseIntegerOnly(TRUE);
2686 // create the DateFormat
2687 DateFormat
*df
= DateFormat::createDateInstance(DateFormat::kShort
, loc
);
2688 if (U_FAILURE(status
)) {
2689 errln("FAIL: DateFormat::createInstance() returned " + (UnicodeString
)u_errorName(status
));
2693 df
->adoptCalendar(cal
);
2694 df
->adoptNumberFormat(nf
);
2696 // set parsing to lenient & parse
2697 df
->setLenient(TRUE
);
2698 UDate ulocdat
= df
->parse(udt
, status
);
2700 // format back to a string
2701 UnicodeString outString
;
2702 df
->format(ulocdat
, outString
);
2704 if (outString
!= exp
) {
2705 errln("FAIL: " + udt
+ " => " + outString
);
2711 //---------------------------------------------------------------------------
2713 // Error Checking / Reporting macros
2715 //---------------------------------------------------------------------------
2716 #define TEST_CHECK_STATUS(status) { \
2717 if (U_FAILURE(status)) { \
2718 if (status == U_MISSING_RESOURCE_ERROR) { \
2719 dataerrln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2721 errln("File %s, Line %d: status=%s", __FILE__, __LINE__, u_errorName(status)); \
2725 #define TEST_ASSERT(expr) \
2726 if ((expr)==FALSE) {\
2727 errln("File %s, line %d: Assertion Failed: " #expr "\n", __FILE__, __LINE__);\
2729 #define TEST_ASSERT_EQUALS(x,y) \
2732 int32_t len = sprintf (_msg,"File %s, line %d: Assertion Failed: " #x "==" #y "\n", __FILE__, __LINE__); \
2734 U_ASSERT(len < (int32_t) sizeof(_msg)); \
2735 assertEquals((const char*) _msg, x,y); \
2739 // Ticket 8199: Parse failure for numbers in the range of 1E10 - 1E18
2741 void NumberFormatRegressionTest::Test8199(void) {
2742 UErrorCode status
= U_ZERO_ERROR
;
2743 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getEnglish(), status
);
2745 dataerrln("Fail: NumberFormat::createInstance(Locale::getEnglish(), status)");
2748 TEST_CHECK_STATUS(status
);
2750 // Note: Retrieving parsed values from a Formattable as a reduced-precision type
2751 // should always truncate, no other rounding scheme.
2753 UnicodeString numStr
= "1000000000.6"; // 9 zeroes
2755 nf
->parse(numStr
, val
, status
);
2756 TEST_CHECK_STATUS(status
);
2757 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2758 TEST_ASSERT(1000000000 == val
.getInt64(status
));
2759 TEST_CHECK_STATUS(status
);
2760 TEST_ASSERT(1000000000.6 == val
.getDouble(status
));
2761 TEST_CHECK_STATUS(status
);
2763 numStr
= "100000000000000001.1"; // approx 1E17, parses as a double rather
2764 // than int64 because of the fraction
2765 // even though int64 is more precise.
2766 nf
->parse(numStr
, val
, status
);
2767 TEST_CHECK_STATUS(status
);
2768 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2769 TEST_ASSERT(100000000000000001LL == val
.getInt64(status
));
2770 TEST_CHECK_STATUS(status
);
2771 TEST_ASSERT(100000000000000000.0 == val
.getDouble(status
));
2772 TEST_CHECK_STATUS(status
);
2774 numStr
= "1E17"; // Parses with the internal decimal number having non-zero exponent
2775 nf
->parse(numStr
, val
, status
);
2776 TEST_CHECK_STATUS(status
);
2777 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2778 TEST_ASSERT(100000000000000000LL == val
.getInt64());
2779 TEST_ASSERT(1.0E17
== val
.getDouble(status
));
2780 TEST_CHECK_STATUS(status
);
2782 numStr
= "9223372036854775807"; // largest int64_t
2783 nf
->parse(numStr
, val
, status
);
2784 TEST_CHECK_STATUS(status
);
2785 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2786 TEST_ASSERT(9223372036854775807LL == val
.getInt64());
2787 // In the following check, note that a substantial range of integers will
2788 // convert to the same double value. There are also platform variations
2789 // in the rounding at compile time of double constants.
2790 TEST_ASSERT(9223372036854775808.0 >= val
.getDouble(status
));
2791 TEST_ASSERT(9223372036854774700.0 <= val
.getDouble(status
));
2792 TEST_CHECK_STATUS(status
);
2794 numStr
= "-9223372036854775808"; // smallest int64_t
2795 nf
->parse(numStr
, val
, status
);
2796 TEST_CHECK_STATUS(status
);
2797 TEST_ASSERT(Formattable::kInt64
== val
.getType());
2798 // TEST_ASSERT(-9223372036854775808LL == val.getInt64()); // Compiler chokes on constant.
2799 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64());
2800 TEST_ASSERT(-9223372036854775808.0 == val
.getDouble(status
));
2801 TEST_CHECK_STATUS(status
);
2803 numStr
= "9223372036854775808"; // largest int64_t + 1
2804 nf
->parse(numStr
, val
, status
);
2805 TEST_CHECK_STATUS(status
);
2806 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2807 TEST_ASSERT(9223372036854775807LL == val
.getInt64(status
));
2808 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2809 status
= U_ZERO_ERROR
;
2810 TEST_ASSERT(9223372036854775810.0 == val
.getDouble(status
));
2811 TEST_CHECK_STATUS(status
);
2813 numStr
= "-9223372036854775809"; // smallest int64_t - 1
2814 nf
->parse(numStr
, val
, status
);
2815 TEST_CHECK_STATUS(status
);
2816 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2817 // TEST_ASSERT(-9223372036854775808LL == val.getInt64(status)); // spurious compiler warnings
2818 TEST_ASSERT((int64_t)0x8000000000000000LL
== val
.getInt64(status
));
2819 TEST_ASSERT(status
== U_INVALID_FORMAT_ERROR
);
2820 status
= U_ZERO_ERROR
;
2821 TEST_ASSERT(-9223372036854775810.0 == val
.getDouble(status
));
2822 TEST_CHECK_STATUS(status
);
2824 // Test values near the limit of where doubles can represent all integers.
2825 // The implementation strategy of getInt64() changes at this boundary.
2826 // Strings to be parsed include a decimal fraction to force them to be
2827 // parsed as doubles rather than ints. The fraction is discarded
2828 // from the parsed double value because it is beyond what can be represented.
2830 status
= U_ZERO_ERROR
;
2831 numStr
= "9007199254740991.1"; // largest 53 bit int
2832 nf
->parse(numStr
, val
, status
);
2833 TEST_CHECK_STATUS(status
);
2834 // printf("getInt64() returns %lld\n", val.getInt64(status));
2835 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2836 TEST_ASSERT(9007199254740991LL == val
.getInt64(status
));
2837 TEST_ASSERT(9007199254740991.0 == val
.getDouble(status
));
2838 TEST_CHECK_STATUS(status
);
2840 status
= U_ZERO_ERROR
;
2841 numStr
= "9007199254740992.1"; // 54 bits for the int part.
2842 nf
->parse(numStr
, val
, status
);
2843 TEST_CHECK_STATUS(status
);
2844 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2845 TEST_ASSERT(9007199254740992LL == val
.getInt64(status
));
2846 TEST_ASSERT(9007199254740992.0 == val
.getDouble(status
));
2847 TEST_CHECK_STATUS(status
);
2849 status
= U_ZERO_ERROR
;
2850 numStr
= "9007199254740993.1"; // 54 bits for the int part. Double will round
2851 nf
->parse(numStr
, val
, status
); // the ones digit, putting it up to ...994
2852 TEST_CHECK_STATUS(status
);
2853 TEST_ASSERT(Formattable::kDouble
== val
.getType());
2854 TEST_ASSERT_EQUALS((int64_t)9007199254740993LL,val
.getInt64(status
));
2855 TEST_ASSERT_EQUALS((double)9007199254740994.0,(double)val
.getDouble(status
));
2856 TEST_CHECK_STATUS(status
);
2861 void NumberFormatRegressionTest::Test9109(void) {
2862 UErrorCode status
= U_ZERO_ERROR
;
2865 DecimalFormat
fmt("+##", status
);
2866 if (U_FAILURE(status
)) {
2867 dataerrln("Failed to create DecimalFormat with pattern '+##' - %s", u_errorName(status
));
2871 fmt
.setLenient(TRUE
);
2872 UnicodeString
text("123");
2873 int32_t expected
= 123;
2876 fmt
.parse(text
, val
, pos
);
2877 if (pos
.getErrorIndex() >= 0) {
2878 errln(UnicodeString("Parse failure at ") + pos
.getErrorIndex());
2879 } else if (val
.getLong() != 123) {
2880 errln(UnicodeString("Incorrect parse result: ") + val
.getLong() + " expected: " + expected
);
2881 } else if (pos
.getIndex() != 3) {
2882 errln(UnicodeString("Incorrect parse position: ") + pos
.getIndex() + " expected: " + expos
);
2887 void NumberFormatRegressionTest::Test9780(void) {
2888 UErrorCode status
= U_ZERO_ERROR
;
2889 NumberFormat
*nf
= NumberFormat::createInstance(Locale::getUS(), status
);
2890 if (failure(status
, "NumberFormat::createInstance", TRUE
)){
2894 DecimalFormat
*df
= dynamic_cast<DecimalFormat
*>(nf
);
2896 errln("DecimalFormat needed to continue");
2899 df
->setParseIntegerOnly(TRUE
);
2903 ParsePosition
pos(0);
2904 UnicodeString
toParse("1,234","");
2905 df
->parse(toParse
, n
, pos
);
2906 if (n
.getType() != Formattable::kLong
2907 || n
.getLong() != 1234) {
2908 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2911 // should still work in lenient mode, just won't get fastpath
2912 df
->setLenient(TRUE
);
2915 ParsePosition
pos(0);
2916 UnicodeString
toParse("1,234","");
2917 df
->parse(toParse
, n
, pos
);
2918 if (n
.getType() != Formattable::kLong
2919 || n
.getLong() != 1234) {
2920 errln(UnicodeString("FAIL: parse(\"") + toParse
+ UnicodeString("\") returns ") + toString(n
));
2927 void NumberFormatRegressionTest::Test9677(void) {
2928 static const UChar pattern
[] = { 0x23,0x23,0x23,0x23,0x2E,0x23,0x23,0x23,0x23,0 }; // "####.####"
2929 static const UChar positivePrefix
[] = { 0x40,0 }; // "@"
2930 static const UChar negativePrefix
[] = { 0x6E,0 }; // "n"
2931 static const UChar text
[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // 123456789
2932 static const UChar text2
[] = { 0x6E, 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0 }; // n123456789
2934 UErrorCode status
= U_ZERO_ERROR
;
2935 LocalUNumberFormatPointer
f(unum_open(UNUM_DEFAULT
, NULL
, 0, "en_US", NULL
, &status
));
2936 if (U_FAILURE(status
)) {
2937 dataerrln("Failure opening unum_open");
2941 if (U_SUCCESS(status
)) {
2942 unum_applyPattern(f
.getAlias(), FALSE
, pattern
, -1, NULL
, &status
);
2943 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, positivePrefix
, -1, &status
);
2944 assertSuccess("setting attributes", status
);
2947 if(U_SUCCESS(status
)) {
2948 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2949 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2951 if(U_FAILURE(status
)) {
2952 logln("Got expected parse error %s\n", u_errorName(status
));
2953 status
= U_ZERO_ERROR
;
2955 errln("FAIL: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2959 if (U_SUCCESS(status
)) {
2960 unum_setTextAttribute(f
.getAlias(), UNUM_POSITIVE_PREFIX
, NULL
, 0, &status
);
2961 assertSuccess("setting attributes", status
);
2962 logln("removed positive prefix");
2965 if(U_SUCCESS(status
)) {
2966 int32_t n
= unum_parse(f
.getAlias(), text
, -1, NULL
, &status
);
2967 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2969 if(U_FAILURE(status
)) {
2970 errln("FAIL: with pos prefix removed, parse error %s\n", u_errorName(status
));
2971 status
= U_ZERO_ERROR
;
2974 errln("FAIL: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
), n
);
2976 logln("PASS: with pos prefix removed , unum_parse status %s, result %d expected 123456789\n", u_errorName(status
),n
);
2981 if(U_SUCCESS(status
)) {
2982 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
2983 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
2985 if(U_FAILURE(status
)) {
2986 logln("text2: Got expected parse error %s\n", u_errorName(status
));
2987 status
= U_ZERO_ERROR
;
2989 errln("FAIL: text2: unum_parse status %s, result %d - expected failure\n", u_errorName(status
), n
);
2993 if (U_SUCCESS(status
)) {
2994 unum_setTextAttribute(f
.getAlias(), UNUM_NEGATIVE_PREFIX
, negativePrefix
, -1, &status
);
2995 assertSuccess("setting attributes", status
);
2996 logln("Set a different neg prefix prefix");
2999 if(U_SUCCESS(status
)) {
3000 int32_t n
= unum_parse(f
.getAlias(), text2
, -1, NULL
, &status
);
3001 logln("unum_parse status %s, result %d\n", u_errorName(status
), n
);
3003 if(U_FAILURE(status
)) {
3004 errln("FAIL: with different neg prefix , parse error %s\n", u_errorName(status
));
3005 status
= U_ZERO_ERROR
;
3009 errln("FAIL: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3011 logln("PASS: with different neg prefix , unum_parse status %s, result %d expected -123456789\n", u_errorName(status
), n
);
3017 void NumberFormatRegressionTest::Test10361(void) {
3018 // DecimalFormat/NumberFormat were artificially limiting the number of digits,
3019 // preventing formatting of big decimals.
3020 UErrorCode status
= U_ZERO_ERROR
;
3021 DecimalFormatSymbols
symbols(Locale::getEnglish(), status
);
3022 LocalPointer
<DecimalFormat
> df(new DecimalFormat("###.##", symbols
, status
), status
);
3023 TEST_CHECK_STATUS(status
);
3025 // Create a decimal number with a million digits.
3026 const int32_t NUMSIZE
=1000000;
3027 char *num
= new char[NUMSIZE
];
3028 for (int32_t i
=0; i
<NUMSIZE
; i
++) {
3029 num
[i
] = '0' + (i
+1) % 10;
3031 num
[NUMSIZE
-3] = '.';
3035 Formattable fmtable
;
3036 fmtable
.setDecimalNumber(num
, status
);
3037 TEST_CHECK_STATUS(status
);
3039 FieldPosition
pos(UNUM_DECIMAL_SEPARATOR_FIELD
);
3040 df
->format(fmtable
, s
, pos
, status
);
3041 TEST_CHECK_STATUS(status
);
3042 TEST_ASSERT(999999 == s
.length());
3043 TEST_ASSERT(999997 == pos
.getBeginIndex());
3044 TEST_ASSERT(999998 == pos
.getEndIndex());
3046 UnicodeString
expected(num
, -1, US_INV
);
3047 TEST_ASSERT(expected
== s
);
3051 #endif /* #if !UCONFIG_NO_FORMATTING */