1 /********************************************************************
3 * Copyright (c) 1997-2008, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /* Modification History:
7 * Date Name Description
8 * 07/15/99 helena Ported to HPUX 10/11 CC.
11 #include "unicode/utypes.h"
13 #if !UCONFIG_NO_FORMATTING
16 #include "unicode/dcfmtsym.h"
17 #include "unicode/decimfmt.h"
18 #include "unicode/ucurr.h"
19 #include "unicode/ustring.h"
20 #include "unicode/measfmt.h"
21 #include "unicode/curramt.h"
33 static const UChar EUR
[] = {69,85,82,0}; // "EUR"
35 // *****************************************************************************
36 // class NumberFormatTest
37 // *****************************************************************************
39 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
41 #define CHECK(status,str) if (U_FAILURE(status)) { errln(UnicodeString("FAIL: ") + str); return; }
43 void NumberFormatTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
45 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
47 CASE(0,TestCurrencySign
);
50 CASE(3,TestRounding487
);
52 CASE(5,TestExponential
);
55 // Upgrade to alphaWorks - liu 5/99
57 CASE(8,TestScientific
);
59 CASE(10,TestPatterns2
);
60 CASE(11,TestSecondaryGrouping
);
61 CASE(12,TestSurrogateSupport
);
64 CASE(14,TestCurrencyObject
);
65 CASE(15,TestCurrencyPatterns
);
66 //CASE(16,TestDigitList);
67 CASE(16,TestWhiteSpaceParsing
);
68 CASE(17,TestComplexCurrency
);
69 CASE(18,TestRegCurrency
);
70 CASE(19,TestSymbolsWithBadLocale
);
71 CASE(20,TestAdoptDecimalFormatSymbols
);
73 CASE(21,TestScientific2
);
74 CASE(22,TestScientificGrouping
);
78 CASE(25,TestIllegalPatterns
);
81 CASE(27,TestCurrencyNames
);
82 CASE(28,TestCurrencyAmount
);
83 CASE(29,TestCurrencyUnit
);
84 CASE(30,TestCoverage
);
87 CASE(33,TestHostClone
);
88 CASE(34,TestCurrencyFormat
);
89 CASE(35,TestRounding
);
90 CASE(36,TestNonpositiveMultiplier
);
92 CASE(37,TestLenientParse
);
93 CASE(38,TestSpaceParsing
);
95 default: name
= ""; break;
99 // -------------------------------------
101 // Test API (increase code coverage)
103 NumberFormatTest::TestAPI(void)
106 UErrorCode status
= U_ZERO_ERROR
;
107 NumberFormat
*test
= NumberFormat::createInstance("root", status
);
108 if(U_FAILURE(status
)) {
109 errln("unable to create format object");
112 test
->setMinimumIntegerDigits(10);
113 test
->setMaximumIntegerDigits(2);
115 test
->setMinimumFractionDigits(10);
116 test
->setMaximumFractionDigits(2);
118 UnicodeString result
;
120 Formattable
bla("Paja Patak"); // Donald Duck for non Serbian speakers
121 test
->format(bla
, result
, pos
, status
);
122 if(U_SUCCESS(status
)) {
123 errln("Yuck... Formatted a duck... As a number!");
125 status
= U_ZERO_ERROR
;
130 test
->format(ll
, result
);
131 if (result
!= "12.00"){
132 errln("format int64_t error");
139 class StubNumberForamt
:public NumberFormat
{
141 StubNumberForamt(){};
142 virtual UnicodeString
& format(double ,UnicodeString
& appendTo
,FieldPosition
& ) const {
145 virtual UnicodeString
& format(int32_t ,UnicodeString
& appendTo
,FieldPosition
& ) const {
146 return appendTo
.append((UChar
)0x0033);
148 virtual UnicodeString
& format(int64_t number
,UnicodeString
& appendTo
,FieldPosition
& pos
) const {
149 return NumberFormat::format(number
, appendTo
, pos
);
151 virtual UnicodeString
& format(const Formattable
& , UnicodeString
& appendTo
, FieldPosition
& , UErrorCode
& ) const {
154 virtual void parse(const UnicodeString
& ,
156 ParsePosition
& ) const {}
157 virtual void parse( const UnicodeString
& ,
159 UErrorCode
& ) const {}
160 virtual UClassID
getDynamicClassID(void) const {
161 static char classID
= 0;
162 return (UClassID
)&classID
;
164 virtual Format
* clone() const {return NULL
;}
168 NumberFormatTest::TestCoverage(void){
169 StubNumberForamt stub
;
170 UnicodeString
agent("agent");
173 if (stub
.format(num
, agent
, pos
) != UnicodeString("agent3")){
174 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
178 // Test various patterns
180 NumberFormatTest::TestPatterns(void)
182 UErrorCode status
= U_ZERO_ERROR
;
183 DecimalFormatSymbols
sym(Locale::getUS(), status
);
184 if (U_FAILURE(status
)) { errln("FAIL: Could not construct DecimalFormatSymbols"); return; }
186 const char* pat
[] = { "#.#", "#.", ".#", "#" };
187 int32_t pat_length
= (int32_t)(sizeof(pat
) / sizeof(pat
[0]));
188 const char* newpat
[] = { "#0.#", "#0.", "#.0", "#" };
189 const char* num
[] = { "0", "0.", ".0", "0" };
190 for (int32_t i
=0; i
<pat_length
; ++i
)
192 status
= U_ZERO_ERROR
;
193 DecimalFormat
fmt(pat
[i
], sym
, status
);
194 if (U_FAILURE(status
)) { errln((UnicodeString
)"FAIL: DecimalFormat constructor failed for " + pat
[i
]); continue; }
195 UnicodeString newp
; fmt
.toPattern(newp
);
196 if (!(newp
== newpat
[i
]))
197 errln((UnicodeString
)"FAIL: Pattern " + pat
[i
] + " should transmute to " + newpat
[i
] +
198 "; " + newp
+ " seen instead");
200 UnicodeString s
; (*(NumberFormat
*)&fmt
).format((int32_t)0, s
);
203 errln((UnicodeString
)"FAIL: Pattern " + pat
[i
] + " should format zero as " + num
[i
] +
204 "; " + s
+ " seen instead");
205 logln((UnicodeString
)"Min integer digits = " + fmt
.getMinimumIntegerDigits());
211 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
212 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
213 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
217 NumberFormatTest::TestDigitList(void)
219 // API coverage for DigitList
222 list1.fDecimalAt = 1;
224 list2.set((int32_t)1);
225 if (list1 != list2) {
226 errln("digitlist append, operator!= or set failed ");
228 if (!(list1 == list2)) {
229 errln("digitlist append, operator== or set failed ");
234 // -------------------------------------
236 // Test exponential pattern
238 NumberFormatTest::TestExponential(void)
240 UErrorCode status
= U_ZERO_ERROR
;
241 DecimalFormatSymbols
sym(Locale::getUS(), status
);
242 if (U_FAILURE(status
)) { errln("FAIL: Bad status returned by DecimalFormatSymbols ct"); return; }
243 const char* pat
[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
244 int32_t pat_length
= (int32_t)(sizeof(pat
) / sizeof(pat
[0]));
246 // The following #if statements allow this test to be built and run on
247 // platforms that do not have standard IEEE numerics. For example,
248 // S/390 doubles have an exponent range of -78 to +75. For the
249 // following #if statements to work, float.h must define
250 // DBL_MAX_10_EXP to be a compile-time constant.
252 // This section may be expanded as needed.
254 #if DBL_MAX_10_EXP > 300
255 double val
[] = { 0.01234, 123456789, 1.23e300
, -3.141592653e-271 };
256 int32_t val_length
= (int32_t)(sizeof(val
) / sizeof(val
[0]));
257 const char* valFormat
[] =
260 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
262 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
264 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
266 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
270 0.01234, 123460000, 1.23E300
, -3.1416E-271,
271 0.01234, 123460000, 1.23E300
, -3.1416E-271,
272 0.01234, 123456800, 1.23E300
, -3.141593E-271,
273 0.01234, 123500000, 1.23E300
, -3.142E-271,
275 #elif DBL_MAX_10_EXP > 70
276 double val
[] = { 0.01234, 123456789, 1.23e70
, -3.141592653e-71 };
277 int32_t val_length
= sizeof(val
) / sizeof(val
[0]);
281 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
283 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
285 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
287 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
291 0.01234, 123460000, 1.23E70
, -3.1416E-71,
292 0.01234, 123460000, 1.23E70
, -3.1416E-71,
293 0.01234, 123456800, 1.23E70
, -3.141593E-71,
294 0.01234, 123500000, 1.23E70
, -3.142E-71,
297 // Don't test double conversion
299 int32_t val_length
= 0;
300 char** valFormat
= 0;
301 double* valParse
= 0;
302 logln("Warning: Skipping double conversion tests");
305 int32_t lval
[] = { 0, -1, 1, 123456789 };
306 int32_t lval_length
= (int32_t)(sizeof(lval
) / sizeof(lval
[0]));
307 const char* lvalFormat
[] =
310 "0E0", "-1E0", "1E0", "1.2346E8",
312 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
314 "0E000", "-1E000", "1E000", "123.4568E006",
316 "0E0", "[1E0]", "1E0", "1.235E8"
318 int32_t lvalParse
[] =
325 int32_t ival
= 0, ilval
= 0;
326 for (int32_t p
=0; p
<pat_length
; ++p
)
328 DecimalFormat
fmt(pat
[p
], sym
, status
);
329 if (U_FAILURE(status
)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
330 UnicodeString pattern
;
331 logln((UnicodeString
)"Pattern \"" + pat
[p
] + "\" -toPattern-> \"" +
332 fmt
.toPattern(pattern
) + "\"");
334 for (v
=0; v
<val_length
; ++v
)
336 UnicodeString s
; (*(NumberFormat
*)&fmt
).format(val
[v
], s
);
337 logln((UnicodeString
)" " + val
[v
] + " -format-> " + s
);
338 if (s
!= valFormat
[v
+ival
])
339 errln((UnicodeString
)"FAIL: Expected " + valFormat
[v
+ival
]);
341 ParsePosition
pos(0);
343 fmt
.parse(s
, af
, pos
);
345 UBool useEpsilon
= FALSE
;
346 if (af
.getType() == Formattable::kLong
)
348 else if (af
.getType() == Formattable::kDouble
) {
350 #if defined(OS390) || defined(OS400)
351 // S/390 will show a failure like this:
352 //| -3.141592652999999e-271 -format-> -3.1416E-271
353 //| -parse-> -3.1416e-271
354 //| FAIL: Expected -3.141599999999999e-271
355 // To compensate, we use an epsilon-based equality
356 // test on S/390 only. We don't want to do this in
357 // general because it's less exacting.
362 errln((UnicodeString
)"FAIL: Non-numeric Formattable returned");
365 if (pos
.getIndex() == s
.length())
367 logln((UnicodeString
)" -parse-> " + a
);
368 // Use epsilon comparison as necessary
370 (uprv_fabs(a
- valParse
[v
+ival
]) / a
> (2*DBL_EPSILON
))) ||
371 (!useEpsilon
&& a
!= valParse
[v
+ival
]))
373 errln((UnicodeString
)"FAIL: Expected " + valParse
[v
+ival
]);
377 errln((UnicodeString
)"FAIL: Partial parse (" + pos
.getIndex() + " chars) -> " + a
);
378 errln((UnicodeString
)" should be (" + s
.length() + " chars) -> " + valParse
[v
+ival
]);
381 for (v
=0; v
<lval_length
; ++v
)
384 (*(NumberFormat
*)&fmt
).format(lval
[v
], s
);
385 logln((UnicodeString
)" " + lval
[v
] + "L -format-> " + s
);
386 if (s
!= lvalFormat
[v
+ilval
])
387 errln((UnicodeString
)"ERROR: Expected " + lvalFormat
[v
+ilval
] + " Got: " + s
);
389 ParsePosition
pos(0);
391 fmt
.parse(s
, af
, pos
);
392 if (af
.getType() == Formattable::kLong
||
393 af
.getType() == Formattable::kInt64
) {
394 UErrorCode status
= U_ZERO_ERROR
;
395 int32_t a
= af
.getLong(status
);
396 if (pos
.getIndex() == s
.length())
398 logln((UnicodeString
)" -parse-> " + a
);
399 if (a
!= lvalParse
[v
+ilval
])
400 errln((UnicodeString
)"FAIL: Expected " + lvalParse
[v
+ilval
]);
403 errln((UnicodeString
)"FAIL: Partial parse (" + pos
.getIndex() + " chars) -> " + a
);
406 errln((UnicodeString
)"FAIL: Non-long Formattable returned for " + s
407 + " Double: " + af
.getDouble()
408 + ", Long: " + af
.getLong());
411 ilval
+= lval_length
;
416 NumberFormatTest::TestScientific2() {
418 UErrorCode status
= U_ZERO_ERROR
;
419 DecimalFormat
* fmt
= (DecimalFormat
*)NumberFormat::createCurrencyInstance("en_US", status
);
420 if (U_SUCCESS(status
)) {
422 expect(*fmt
, num
, "$12.34");
423 fmt
->setScientificNotation(TRUE
);
424 expect(*fmt
, num
, "$1.23E1");
425 fmt
->setScientificNotation(FALSE
);
426 expect(*fmt
, num
, "$12.34");
432 NumberFormatTest::TestScientificGrouping() {
434 UErrorCode status
= U_ZERO_ERROR
;
435 DecimalFormat
fmt("##0.00E0",status
);
436 if (U_SUCCESS(status
)) {
437 expect(fmt
, .01234, "12.3E-3");
438 expect(fmt
, .1234, "123E-3");
439 expect(fmt
, 1.234, "1.23E0");
440 expect(fmt
, 12.34, "12.3E0");
441 expect(fmt
, 123.4, "123E0");
442 expect(fmt
, 1234., "1.23E3");
446 /*static void setFromString(DigitList& dl, const char* str) {
448 UBool decimalSet = FALSE;
450 while ((c = *str++)) {
452 dl.fIsPositive = FALSE;
453 } else if (c == '+') {
454 dl.fIsPositive = TRUE;
455 } else if (c == '.') {
456 dl.fDecimalAt = dl.fCount;
463 dl.fDecimalAt = dl.fCount;
468 NumberFormatTest::TestInt64() {
469 UErrorCode status
= U_ZERO_ERROR
;
470 DecimalFormat
fmt("#.#E0",status
);
471 fmt
.setMaximumFractionDigits(20);
472 if (U_SUCCESS(status
)) {
473 expect(fmt
, (Formattable
)(int64_t)0, "0E0");
474 expect(fmt
, (Formattable
)(int64_t)-1, "-1E0");
475 expect(fmt
, (Formattable
)(int64_t)1, "1E0");
476 expect(fmt
, (Formattable
)(int64_t)2147483647, "2.147483647E9");
477 expect(fmt
, (Formattable
)((int64_t)-2147483647-1), "-2.147483648E9");
478 expect(fmt
, (Formattable
)(int64_t)U_INT64_MAX
, "9.223372036854775807E18");
479 expect(fmt
, (Formattable
)(int64_t)U_INT64_MIN
, "-9.223372036854775808E18");
482 // also test digitlist
483 /* int64_t int64max = U_INT64_MAX;
484 int64_t int64min = U_INT64_MIN;
485 const char* int64maxstr = "9223372036854775807";
486 const char* int64minstr = "-9223372036854775808";
487 UnicodeString fail("fail: ");
489 // test max int64 value
491 setFromString(dl, int64maxstr);
493 if (!dl.fitsIntoInt64(FALSE)) {
494 errln(fail + int64maxstr + " didn't fit");
496 int64_t int64Value = dl.getInt64();
497 if (int64Value != int64max) {
498 errln(fail + int64maxstr);
501 int64Value = dl.getInt64();
502 if (int64Value != int64max) {
503 errln(fail + int64maxstr);
506 // test negative of max int64 value (1 shy of min int64 value)
507 dl.fIsPositive = FALSE;
509 if (!dl.fitsIntoInt64(FALSE)) {
510 errln(fail + "-" + int64maxstr + " didn't fit");
512 int64_t int64Value = dl.getInt64();
513 if (int64Value != -int64max) {
514 errln(fail + "-" + int64maxstr);
517 int64Value = dl.getInt64();
518 if (int64Value != -int64max) {
519 errln(fail + "-" + int64maxstr);
522 // test min int64 value
523 setFromString(dl, int64minstr);
525 if (!dl.fitsIntoInt64(FALSE)) {
526 errln(fail + "-" + int64minstr + " didn't fit");
528 int64_t int64Value = dl.getInt64();
529 if (int64Value != int64min) {
530 errln(fail + int64minstr);
533 int64Value = dl.getInt64();
534 if (int64Value != int64min) {
535 errln(fail + int64minstr);
538 // test negative of min int 64 value (1 more than max int64 value)
539 dl.fIsPositive = TRUE; // won't fit
541 if (dl.fitsIntoInt64(FALSE)) {
542 errln(fail + "-(" + int64minstr + ") didn't fit");
547 // -------------------------------------
549 // Test the handling of quotes
551 NumberFormatTest::TestQuotes(void)
553 UErrorCode status
= U_ZERO_ERROR
;
555 DecimalFormatSymbols
*sym
= new DecimalFormatSymbols(Locale::getUS(), status
);
556 pat
= new UnicodeString("a'fo''o'b#");
557 DecimalFormat
*fmt
= new DecimalFormat(*pat
, *sym
, status
);
559 ((NumberFormat
*)fmt
)->format((int32_t)123, s
);
560 logln((UnicodeString
)"Pattern \"" + *pat
+ "\"");
561 logln((UnicodeString
)" Format 123 -> " + escape(s
));
562 if (!(s
=="afo'ob123"))
563 errln((UnicodeString
)"FAIL: Expected afo'ob123");
569 pat
= new UnicodeString("a''b#");
570 fmt
= new DecimalFormat(*pat
, *sym
, status
);
571 ((NumberFormat
*)fmt
)->format((int32_t)123, s
);
572 logln((UnicodeString
)"Pattern \"" + *pat
+ "\"");
573 logln((UnicodeString
)" Format 123 -> " + escape(s
));
575 errln((UnicodeString
)"FAIL: Expected a'b123");
582 * Test the handling of the currency symbol in patterns.
585 NumberFormatTest::TestCurrencySign(void)
587 UErrorCode status
= U_ZERO_ERROR
;
588 DecimalFormatSymbols
* sym
= new DecimalFormatSymbols(Locale::getUS(), status
);
590 UChar currency
= 0x00A4;
591 // "\xA4#,##0.00;-\xA4#,##0.00"
592 pat
.append(currency
).append("#,##0.00;-").
593 append(currency
).append("#,##0.00");
594 DecimalFormat
*fmt
= new DecimalFormat(pat
, *sym
, status
);
595 UnicodeString s
; ((NumberFormat
*)fmt
)->format(1234.56, s
);
597 logln((UnicodeString
)"Pattern \"" + fmt
->toPattern(pat
) + "\"");
598 logln((UnicodeString
)" Format " + 1234.56 + " -> " + escape(s
));
599 if (s
!= "$1,234.56") errln((UnicodeString
)"FAIL: Expected $1,234.56");
601 ((NumberFormat
*)fmt
)->format(- 1234.56, s
);
602 logln((UnicodeString
)" Format " + (-1234.56) + " -> " + escape(s
));
603 if (s
!= "-$1,234.56") errln((UnicodeString
)"FAIL: Expected -$1,234.56");
606 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
607 pat
.append(currency
).append(currency
).
608 append(" #,##0.00;").
609 append(currency
).append(currency
).
610 append(" -#,##0.00");
611 fmt
= new DecimalFormat(pat
, *sym
, status
);
613 ((NumberFormat
*)fmt
)->format(1234.56, s
);
614 logln((UnicodeString
)"Pattern \"" + fmt
->toPattern(pat
) + "\"");
615 logln((UnicodeString
)" Format " + 1234.56 + " -> " + escape(s
));
616 if (s
!= "USD 1,234.56") errln((UnicodeString
)"FAIL: Expected USD 1,234.56");
618 ((NumberFormat
*)fmt
)->format(-1234.56, s
);
619 logln((UnicodeString
)" Format " + (-1234.56) + " -> " + escape(s
));
620 if (s
!= "USD -1,234.56") errln((UnicodeString
)"FAIL: Expected USD -1,234.56");
623 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
626 // -------------------------------------
628 static UChar
toHexString(int32_t i
) { return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10))); }
631 NumberFormatTest::escape(UnicodeString
& s
)
634 for (int32_t i
=0; i
<s
.length(); ++i
)
636 UChar c
= s
[(int32_t)i
];
637 if (c
<= (UChar
)0x7F) buf
+= c
;
639 buf
+= (UChar
)0x5c; buf
+= (UChar
)0x55;
640 buf
+= toHexString((c
& 0xF000) >> 12);
641 buf
+= toHexString((c
& 0x0F00) >> 8);
642 buf
+= toHexString((c
& 0x00F0) >> 4);
643 buf
+= toHexString(c
& 0x000F);
650 // -------------------------------------
651 static const char* testCases
[][2]= {
652 /* locale ID */ /* expected */
653 {"ca_ES_PREEURO", "1.150\\u00A0\\u20A7" },
654 {"de_LU_PREEURO", "1,150\\u00A0F" },
655 {"el_GR_PREEURO", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
656 {"en_BE_PREEURO", "1.150,50\\u00A0BF" },
657 {"es_ES_PREEURO", "\\u20A7\\u00A01.150" },
658 {"eu_ES_PREEURO", "1.150\\u00A0\\u20A7" },
659 {"gl_ES_PREEURO", "1.150\\u00A0\\u20A7" },
660 {"it_IT_PREEURO", "\\u20A4\\u00A01.150" },
661 {"pt_PT_PREEURO", "1,150$50\\u00A0Esc."},
662 {"en_US@currency=JPY", "\\u00A51,150"}
665 * Test localized currency patterns.
668 NumberFormatTest::TestCurrency(void)
670 UErrorCode status
= U_ZERO_ERROR
;
671 NumberFormat
* currencyFmt
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
672 if (U_FAILURE(status
)) {
673 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
677 UnicodeString s
; currencyFmt
->format(1.50, s
);
678 logln((UnicodeString
)"Un pauvre ici a..........." + s
);
679 if (!(s
==CharsToUnicodeString("1,50\\u00A0$")))
680 errln((UnicodeString
)"FAIL: Expected 1,50<nbsp>$");
684 int len
= uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
685 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
),status
);
686 currencyFmt
->format(1.50, s
);
687 logln((UnicodeString
)"Un pauvre en Allemagne a.." + s
);
688 if (!(s
==CharsToUnicodeString("1,50\\u00A0DM")))
689 errln((UnicodeString
)"FAIL: Expected 1,50<nbsp>DM");
692 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
693 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
694 currencyFmt
->format(1.50, s
);
695 logln((UnicodeString
)"Un pauvre en France a....." + s
);
696 if (!(s
==CharsToUnicodeString("1,50\\u00A0F")))
697 errln((UnicodeString
)"FAIL: Expected 1,50<nbsp>F");
699 if (U_FAILURE(status
))
700 errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
702 for(int i
=0; i
< (int)(sizeof(testCases
)/sizeof(testCases
[i
])); i
++){
703 status
= U_ZERO_ERROR
;
704 const char *localeID
= testCases
[i
][0];
705 UnicodeString
expected(testCases
[i
][1], -1, US_INV
);
706 expected
= expected
.unescape();
709 uloc_canonicalize(localeID
, loc
, 256, &status
);
710 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
711 if(U_FAILURE(status
)){
712 errln("Could not create currency formatter for locale %s",localeID
);
715 currencyFmt
->format(1150.50, s
);
717 errln(UnicodeString("FAIL: Expected: ")+expected
718 + UnicodeString(" Got: ") + s
719 + UnicodeString( " for locale: ")+ UnicodeString(localeID
) );
721 if (U_FAILURE(status
)){
722 errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
728 // -------------------------------------
731 * Test the Currency object handling, new as of ICU 2.2.
733 void NumberFormatTest::TestCurrencyObject() {
734 UErrorCode ec
= U_ZERO_ERROR
;
736 NumberFormat::createCurrencyInstance(Locale::getUS(), ec
);
739 errln("FAIL: getCurrencyInstance(US)");
744 Locale
null("", "", "");
746 expectCurrency(*fmt
, null
, 1234.56, "$1,234.56");
748 expectCurrency(*fmt
, Locale::getFrance(),
749 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
751 expectCurrency(*fmt
, Locale::getJapan(),
752 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
754 expectCurrency(*fmt
, Locale("fr", "CH", ""),
755 1234.56, "Fr.1,234.55"); // 0.05 rounding
757 expectCurrency(*fmt
, Locale::getUS(),
758 1234.56, "$1,234.56");
761 fmt
= NumberFormat::createCurrencyInstance(Locale::getFrance(), ec
);
764 errln("FAIL: getCurrencyInstance(FRANCE)");
769 expectCurrency(*fmt
, null
, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
771 expectCurrency(*fmt
, Locale::getJapan(),
772 1234.56, CharsToUnicodeString("1 235 \\u00A5JP")); // Yen
774 expectCurrency(*fmt
, Locale("fr", "CH", ""),
775 1234.56, "1 234,55 sFr."); // 0.05 rounding
777 expectCurrency(*fmt
, Locale::getUS(),
778 1234.56, "1 234,56 $US");
780 expectCurrency(*fmt
, Locale::getFrance(),
781 1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
786 // -------------------------------------
789 * Do rudimentary testing of parsing.
792 NumberFormatTest::TestParse(void)
794 UErrorCode status
= U_ZERO_ERROR
;
795 UnicodeString
arg("0");
796 DecimalFormat
* format
= new DecimalFormat("00", status
);
800 format
->parse(arg
, n
, status
);
801 logln((UnicodeString
)"parse(" + arg
+ ") = " + n
.getLong());
802 if (n
.getType() != Formattable::kLong
||
803 n
.getLong() != 0) errln((UnicodeString
)"FAIL: Expected 0");
805 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
807 //catch(Exception e) {
808 // errln((UnicodeString)"Exception caught: " + e);
812 // -------------------------------------
814 static const char *lenientAffixTestCases
[] = {
821 static const char *lenientCurrencyTestCases
[] = {
832 static const char *lenientNegativeCurrencyTestCases
[] = {
840 "($ 1\\u00A0000.00)",
844 static const char *lenientPercentTestCases
[] = {
853 static const char *lenientNegativePercentTestCases
[] = {
865 static const char *strictFailureTestCases
[] = {
873 #define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
876 * Test lenient parsing.
879 NumberFormatTest::TestLenientParse(void)
881 UErrorCode status
= U_ZERO_ERROR
;
882 DecimalFormat
*format
= new DecimalFormat("(#,##0)", status
);
885 format
->setParseStrict(FALSE
);
886 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientAffixTestCases
); t
+= 1) {
887 UnicodeString testCase
= ctou(lenientAffixTestCases
[t
]);
889 format
->parse(testCase
, n
, status
);
890 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
892 if (U_FAILURE(status
) || n
.getType() != Formattable::kLong
||
894 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientAffixTestCases
[t
] + (UnicodeString
) "\"");
895 status
= U_ZERO_ERROR
;
901 Locale
locale("en_US");
902 NumberFormat
*cFormat
= NumberFormat::createCurrencyInstance(locale
, status
);
904 cFormat
->setParseStrict(FALSE
);
905 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientCurrencyTestCases
); t
+= 1) {
906 UnicodeString testCase
= ctou(lenientCurrencyTestCases
[t
]);
908 cFormat
->parse(testCase
, n
, status
);
909 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
911 if (U_FAILURE(status
) ||n
.getType() != Formattable::kLong
||
912 n
.getLong() != 1000) {
913 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientCurrencyTestCases
[t
] + (UnicodeString
) "\"");
914 status
= U_ZERO_ERROR
;
918 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientNegativeCurrencyTestCases
); t
+= 1) {
919 UnicodeString testCase
= ctou(lenientNegativeCurrencyTestCases
[t
]);
920 ParsePosition
pos(0);
922 cFormat
->parse(testCase
, n
, /*status*/pos
);
923 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
925 if (/*U_FAILURE(status)*/pos
.getErrorIndex() >= 0 ||n
.getType() != Formattable::kLong
||
926 n
.getLong() != -1000) {
927 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientNegativeCurrencyTestCases
[t
] + (UnicodeString
) "\" parse position = " +
928 pos
.getIndex() + ", " + pos
.getErrorIndex());
929 status
= U_ZERO_ERROR
;
935 NumberFormat
*pFormat
= NumberFormat::createPercentInstance(locale
, status
);
937 pFormat
->setParseStrict(FALSE
);
938 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientPercentTestCases
); t
+= 1) {
939 UnicodeString testCase
= ctou(lenientPercentTestCases
[t
]);
941 pFormat
->parse(testCase
, n
, status
);
942 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getDouble());
944 if (U_FAILURE(status
) ||n
.getType() != Formattable::kDouble
||
945 n
.getDouble() != 0.25) {
946 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientPercentTestCases
[t
] + (UnicodeString
) "\"");
947 status
= U_ZERO_ERROR
;
951 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientNegativePercentTestCases
); t
+= 1) {
952 UnicodeString testCase
= ctou(lenientNegativePercentTestCases
[t
]);
954 pFormat
->parse(testCase
, n
, status
);
955 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getDouble());
957 if (U_FAILURE(status
) ||n
.getType() != Formattable::kDouble
||
958 n
.getDouble() != -0.25) {
959 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientNegativePercentTestCases
[t
] + (UnicodeString
) "\"");
960 status
= U_ZERO_ERROR
;
966 // Test cases that should fail with a strict parse and pass with a
968 NumberFormat
*nFormat
= NumberFormat::createInstance(locale
, status
);
970 // first, make sure that they fail with a strict parse
971 for (int32_t t
= 0; t
< ARRAY_SIZE(strictFailureTestCases
); t
+= 1) {
972 UnicodeString testCase
= ctou(strictFailureTestCases
[t
]);
974 nFormat
->parse(testCase
, n
, status
);
975 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
977 if (! U_FAILURE(status
)) {
978 errln((UnicodeString
)"Strict Parse succeeded for \"" + (UnicodeString
) strictFailureTestCases
[t
] + (UnicodeString
) "\"");
981 status
= U_ZERO_ERROR
;
984 // then, make sure that they pass with a lenient parse
985 nFormat
->setParseStrict(FALSE
);
986 for (int32_t t
= 0; t
< ARRAY_SIZE(strictFailureTestCases
); t
+= 1) {
987 UnicodeString testCase
= ctou(strictFailureTestCases
[t
]);
989 nFormat
->parse(testCase
, n
, status
);
990 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
992 if (U_FAILURE(status
) ||n
.getType() != Formattable::kLong
||
993 n
.getLong() != 1000) {
994 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) strictFailureTestCases
[t
] + (UnicodeString
) "\"");
995 status
= U_ZERO_ERROR
;
1002 // -------------------------------------
1005 * Test proper rounding by the format method.
1008 NumberFormatTest::TestRounding487(void)
1010 UErrorCode status
= U_ZERO_ERROR
;
1011 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1012 if (U_FAILURE(status
)) {
1013 dataerrln("Error calling NumberFormat::createInstance()");
1017 roundingTest(*nf
, 0.00159999, 4, "0.0016");
1018 roundingTest(*nf
, 0.00995, 4, "0.01");
1020 roundingTest(*nf
, 12.3995, 3, "12.4");
1022 roundingTest(*nf
, 12.4999, 0, "12");
1023 roundingTest(*nf
, - 19.5, 0, "-20");
1025 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
1029 * Test the functioning of the secondary grouping value.
1031 void NumberFormatTest::TestSecondaryGrouping(void) {
1032 UErrorCode status
= U_ZERO_ERROR
;
1033 DecimalFormatSymbols
US(Locale::getUS(), status
);
1034 CHECK(status
, "DecimalFormatSymbols ct");
1036 DecimalFormat
f("#,##,###", US
, status
);
1037 CHECK(status
, "DecimalFormat ct");
1039 expect2(f
, (int32_t)123456789L, "12,34,56,789");
1040 expectPat(f
, "#,##,###");
1041 f
.applyPattern("#,###", status
);
1042 CHECK(status
, "applyPattern");
1044 f
.setSecondaryGroupingSize(4);
1045 expect2(f
, (int32_t)123456789L, "12,3456,789");
1046 expectPat(f
, "#,####,###");
1047 NumberFormat
*g
= NumberFormat::createInstance(Locale("hi", "IN"), status
);
1048 CHECK(status
, "createInstance(hi_IN)");
1051 int32_t l
= (int32_t)1876543210L;
1054 // expect "1,87,65,43,210", but with Hindi digits
1057 if (out
.length() != 14) {
1060 for (int32_t i
=0; i
<out
.length(); ++i
) {
1061 UBool expectGroup
= FALSE
;
1070 // Later -- fix this to get the actual grouping
1071 // character from the resource bundle.
1072 UBool isGroup
= (out
.charAt(i
) == 0x002C);
1073 if (isGroup
!= expectGroup
) {
1080 errln((UnicodeString
)"FAIL Expected " + l
+
1081 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1082 escape(out
) + "\"");
1084 logln((UnicodeString
)"Ok " + l
+
1086 escape(out
) + "\"");
1090 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1091 UErrorCode ec
= U_ZERO_ERROR
;
1092 DecimalFormatSymbols
US(Locale::getUS(), ec
);
1093 DecimalFormat
fmt("a b#0c ", US
, ec
);
1094 if (U_FAILURE(ec
)) {
1095 errln("FAIL: Constructor");
1099 expect(fmt
, "a b1234c ", n
);
1100 expect(fmt
, "a b1234c ", n
);
1104 * Test currencies whose display name is a ChoiceFormat.
1105 * Less useful now that INR is no longer a choice format! See cldrbug 1961 !
1107 void NumberFormatTest::TestComplexCurrency() {
1108 UErrorCode ec
= U_ZERO_ERROR
;
1109 Locale
loc("kn", "IN", "");
1110 NumberFormat
* fmt
= NumberFormat::createCurrencyInstance(loc
, ec
);
1111 if (U_SUCCESS(ec
)) {
1112 expect2(*fmt
, 1.0, CharsToUnicodeString("Rs.\\u00A01.00"));
1113 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1114 expect(*fmt
, 1.00390625, CharsToUnicodeString("Rs.\\u00A01.00")); // tricky
1115 expect2(*fmt
, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1116 expect2(*fmt
, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1117 expect2(*fmt
, -1.0, CharsToUnicodeString("-Rs.\\u00A01.00"));
1118 expect2(*fmt
, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1120 errln("FAIL: getCurrencyInstance(kn_IN)");
1125 // -------------------------------------
1128 NumberFormatTest::roundingTest(NumberFormat
& nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
1130 nf
.setMaximumFractionDigits(maxFractionDigits
);
1131 UnicodeString out
; nf
.format(x
, out
);
1132 logln((UnicodeString
)"" + x
+ " formats with " + maxFractionDigits
+ " fractional digits to " + out
);
1133 if (!(out
==expected
)) errln((UnicodeString
)"FAIL: Expected " + expected
);
1137 * Upgrade to alphaWorks
1139 void NumberFormatTest::TestExponent(void) {
1140 UErrorCode status
= U_ZERO_ERROR
;
1141 DecimalFormatSymbols
US(Locale::getUS(), status
);
1142 CHECK(status
, "DecimalFormatSymbols constructor");
1143 DecimalFormat
fmt1(UnicodeString("0.###E0"), US
, status
);
1144 CHECK(status
, "DecimalFormat(0.###E0)");
1145 DecimalFormat
fmt2(UnicodeString("0.###E+0"), US
, status
);
1146 CHECK(status
, "DecimalFormat(0.###E+0)");
1148 expect2(fmt1
, n
, "1.234E3");
1149 expect2(fmt2
, n
, "1.234E+3");
1150 expect(fmt1
, "1.234E+3", n
); // Either format should parse "E+3"
1154 * Upgrade to alphaWorks
1156 void NumberFormatTest::TestScientific(void) {
1157 UErrorCode status
= U_ZERO_ERROR
;
1158 DecimalFormatSymbols
US(Locale::getUS(), status
);
1159 CHECK(status
, "DecimalFormatSymbols constructor");
1161 // Test pattern round-trip
1162 const char* PAT
[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1163 "0.###E0;[0.###E0]" };
1164 int32_t PAT_length
= (int32_t)(sizeof(PAT
) / sizeof(PAT
[0]));
1165 int32_t DIGITS
[] = {
1166 // min int, max int, min frac, max frac
1167 0, 1, 0, 0, // "#E0"
1168 1, 1, 0, 4, // "0.####E0"
1169 2, 2, 3, 3, // "00.000E00"
1170 1, 3, 0, 4, // "##0.####E000"
1171 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1173 for (int32_t i
=0; i
<PAT_length
; ++i
) {
1174 UnicodeString
pat(PAT
[i
]);
1175 DecimalFormat
df(pat
, US
, status
);
1176 CHECK(status
, "DecimalFormat constructor");
1180 logln(UnicodeString("Ok Pattern rt \"") +
1184 errln(UnicodeString("FAIL Pattern rt \"") +
1188 // Make sure digit counts match what we expect
1189 if (df
.getMinimumIntegerDigits() != DIGITS
[4*i
] ||
1190 df
.getMaximumIntegerDigits() != DIGITS
[4*i
+1] ||
1191 df
.getMinimumFractionDigits() != DIGITS
[4*i
+2] ||
1192 df
.getMaximumFractionDigits() != DIGITS
[4*i
+3]) {
1193 errln(UnicodeString("FAIL \"" + pat
+
1194 "\" min/max int; min/max frac = ") +
1195 df
.getMinimumIntegerDigits() + "/" +
1196 df
.getMaximumIntegerDigits() + ";" +
1197 df
.getMinimumFractionDigits() + "/" +
1198 df
.getMaximumFractionDigits() + ", expect " +
1200 DIGITS
[4*i
+1] + ";" +
1201 DIGITS
[4*i
+2] + "/" +
1207 // Test the constructor for default locale. We have to
1208 // manually set the default locale, as there is no
1209 // guarantee that the default locale has the same
1210 // scientific format.
1211 Locale def
= Locale::getDefault();
1212 Locale::setDefault(Locale::getUS(), status
);
1213 expect2(NumberFormat::createScientificInstance(status
),
1215 "1.2345678901E4", status
);
1216 Locale::setDefault(def
, status
);
1218 expect2(new DecimalFormat("#E0", US
, status
),
1220 "1.2345E4", status
);
1221 expect(new DecimalFormat("0E0", US
, status
),
1224 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status
),
1226 "1.2345678901E4", status
);
1227 expect(new DecimalFormat("##0.###E0", US
, status
),
1230 expect(new DecimalFormat("##0.###E0", US
, status
),
1233 expect2(new DecimalFormat("##0.####E0", US
, status
),
1235 "12.345E3", status
);
1236 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status
),
1238 "1,2345678901E4", status
);
1239 expect(new DecimalFormat("##0.####E0", US
, status
),
1241 "789.12E-9", status
);
1242 expect2(new DecimalFormat("##0.####E0", US
, status
),
1245 expect(new DecimalFormat(".###E0", US
, status
),
1248 expect2(new DecimalFormat(".###E0", US
, status
),
1252 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1253 new DecimalFormat("##E0", US),
1254 new DecimalFormat("####E0", US),
1255 new DecimalFormat("0E0", US),
1256 new DecimalFormat("00E0", US),
1257 new DecimalFormat("000E0", US),
1260 new String[] { "4.5678E7",
1269 ! Unroll this test into individual tests below...
1272 expect2(new DecimalFormat("#E0", US
, status
),
1273 (int32_t) 45678000, "4.5678E7", status
);
1274 expect2(new DecimalFormat("##E0", US
, status
),
1275 (int32_t) 45678000, "45.678E6", status
);
1276 expect2(new DecimalFormat("####E0", US
, status
),
1277 (int32_t) 45678000, "4567.8E4", status
);
1278 expect(new DecimalFormat("0E0", US
, status
),
1279 (int32_t) 45678000, "5E7", status
);
1280 expect(new DecimalFormat("00E0", US
, status
),
1281 (int32_t) 45678000, "46E6", status
);
1282 expect(new DecimalFormat("000E0", US
, status
),
1283 (int32_t) 45678000, "457E5", status
);
1285 expect(new DecimalFormat("###E0", US, status),
1286 new Object[] { new Double(0.0000123), "12.3E-6",
1287 new Double(0.000123), "123E-6",
1288 new Double(0.00123), "1.23E-3",
1289 new Double(0.0123), "12.3E-3",
1290 new Double(0.123), "123E-3",
1291 new Double(1.23), "1.23E0",
1292 new Double(12.3), "12.3E0",
1293 new Double(123), "123E0",
1294 new Double(1230), "1.23E3",
1297 ! Unroll this test into individual tests below...
1300 expect2(new DecimalFormat("###E0", US
, status
),
1301 0.0000123, "12.3E-6", status
);
1302 expect2(new DecimalFormat("###E0", US
, status
),
1303 0.000123, "123E-6", status
);
1304 expect2(new DecimalFormat("###E0", US
, status
),
1305 0.00123, "1.23E-3", status
);
1306 expect2(new DecimalFormat("###E0", US
, status
),
1307 0.0123, "12.3E-3", status
);
1308 expect2(new DecimalFormat("###E0", US
, status
),
1309 0.123, "123E-3", status
);
1310 expect2(new DecimalFormat("###E0", US
, status
),
1311 1.23, "1.23E0", status
);
1312 expect2(new DecimalFormat("###E0", US
, status
),
1313 12.3, "12.3E0", status
);
1314 expect2(new DecimalFormat("###E0", US
, status
),
1315 123.0, "123E0", status
);
1316 expect2(new DecimalFormat("###E0", US
, status
),
1317 1230.0, "1.23E3", status
);
1319 expect(new DecimalFormat("0.#E+00", US, status),
1320 new Object[] { new Double(0.00012), "1.2E-04",
1321 new Long(12000), "1.2E+04",
1324 ! Unroll this test into individual tests below...
1327 expect2(new DecimalFormat("0.#E+00", US
, status
),
1328 0.00012, "1.2E-04", status
);
1329 expect2(new DecimalFormat("0.#E+00", US
, status
),
1330 (int32_t) 12000, "1.2E+04", status
);
1334 * Upgrade to alphaWorks
1336 void NumberFormatTest::TestPad(void) {
1337 UErrorCode status
= U_ZERO_ERROR
;
1338 DecimalFormatSymbols
US(Locale::getUS(), status
);
1339 CHECK(status
, "DecimalFormatSymbols constructor");
1341 expect2(new DecimalFormat("*^##.##", US
, status
),
1342 int32_t(0), "^^^^0", status
);
1343 expect2(new DecimalFormat("*^##.##", US
, status
),
1344 -1.3, "^-1.3", status
);
1345 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1346 int32_t(0), "0.0E0______ g-m/s^2", status
);
1347 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1348 1.0/3, "333.333E-3_ g-m/s^2", status
);
1349 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1350 int32_t(0), "0.0______ g-m/s^2", status
);
1351 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1352 1.0/3, "0.33333__ g-m/s^2", status
);
1354 // Test padding before a sign
1355 const char *formatStr
= "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1356 expect2(new DecimalFormat(formatStr
, US
, status
),
1357 int32_t(-10), "xxxxxxxxxx(10.0)", status
);
1358 expect2(new DecimalFormat(formatStr
, US
, status
),
1359 int32_t(-1000),"xxxxxxx(1,000.0)", status
);
1360 expect2(new DecimalFormat(formatStr
, US
, status
),
1361 int32_t(-1000000),"xxx(1,000,000.0)", status
);
1362 expect2(new DecimalFormat(formatStr
, US
, status
),
1363 -100.37, "xxxxxxxx(100.37)", status
);
1364 expect2(new DecimalFormat(formatStr
, US
, status
),
1365 -10456.37, "xxxxx(10,456.37)", status
);
1366 expect2(new DecimalFormat(formatStr
, US
, status
),
1367 -1120456.37, "xx(1,120,456.37)", status
);
1368 expect2(new DecimalFormat(formatStr
, US
, status
),
1369 -112045600.37, "(112,045,600.37)", status
);
1370 expect2(new DecimalFormat(formatStr
, US
, status
),
1371 -1252045600.37,"(1,252,045,600.37)", status
);
1373 expect2(new DecimalFormat(formatStr
, US
, status
),
1374 int32_t(10), "xxxxxxxxxxxx10.0", status
);
1375 expect2(new DecimalFormat(formatStr
, US
, status
),
1376 int32_t(1000),"xxxxxxxxx1,000.0", status
);
1377 expect2(new DecimalFormat(formatStr
, US
, status
),
1378 int32_t(1000000),"xxxxx1,000,000.0", status
);
1379 expect2(new DecimalFormat(formatStr
, US
, status
),
1380 100.37, "xxxxxxxxxx100.37", status
);
1381 expect2(new DecimalFormat(formatStr
, US
, status
),
1382 10456.37, "xxxxxxx10,456.37", status
);
1383 expect2(new DecimalFormat(formatStr
, US
, status
),
1384 1120456.37, "xxxx1,120,456.37", status
);
1385 expect2(new DecimalFormat(formatStr
, US
, status
),
1386 112045600.37, "xx112,045,600.37", status
);
1387 expect2(new DecimalFormat(formatStr
, US
, status
),
1388 10252045600.37,"10,252,045,600.37", status
);
1391 // Test padding between a sign and a number
1392 const char *formatStr2
= "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1393 expect2(new DecimalFormat(formatStr2
, US
, status
),
1394 int32_t(-10), "(10.0xxxxxxxxxx)", status
);
1395 expect2(new DecimalFormat(formatStr2
, US
, status
),
1396 int32_t(-1000),"(1,000.0xxxxxxx)", status
);
1397 expect2(new DecimalFormat(formatStr2
, US
, status
),
1398 int32_t(-1000000),"(1,000,000.0xxx)", status
);
1399 expect2(new DecimalFormat(formatStr2
, US
, status
),
1400 -100.37, "(100.37xxxxxxxx)", status
);
1401 expect2(new DecimalFormat(formatStr2
, US
, status
),
1402 -10456.37, "(10,456.37xxxxx)", status
);
1403 expect2(new DecimalFormat(formatStr2
, US
, status
),
1404 -1120456.37, "(1,120,456.37xx)", status
);
1405 expect2(new DecimalFormat(formatStr2
, US
, status
),
1406 -112045600.37, "(112,045,600.37)", status
);
1407 expect2(new DecimalFormat(formatStr2
, US
, status
),
1408 -1252045600.37,"(1,252,045,600.37)", status
);
1410 expect2(new DecimalFormat(formatStr2
, US
, status
),
1411 int32_t(10), "10.0xxxxxxxxxxxx", status
);
1412 expect2(new DecimalFormat(formatStr2
, US
, status
),
1413 int32_t(1000),"1,000.0xxxxxxxxx", status
);
1414 expect2(new DecimalFormat(formatStr2
, US
, status
),
1415 int32_t(1000000),"1,000,000.0xxxxx", status
);
1416 expect2(new DecimalFormat(formatStr2
, US
, status
),
1417 100.37, "100.37xxxxxxxxxx", status
);
1418 expect2(new DecimalFormat(formatStr2
, US
, status
),
1419 10456.37, "10,456.37xxxxxxx", status
);
1420 expect2(new DecimalFormat(formatStr2
, US
, status
),
1421 1120456.37, "1,120,456.37xxxx", status
);
1422 expect2(new DecimalFormat(formatStr2
, US
, status
),
1423 112045600.37, "112,045,600.37xx", status
);
1424 expect2(new DecimalFormat(formatStr2
, US
, status
),
1425 10252045600.37,"10,252,045,600.37", status
);
1427 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1428 DecimalFormat
fmt("#", US
, status
);
1429 CHECK(status
, "DecimalFormat constructor");
1430 UnicodeString
padString("P");
1431 fmt
.setPadCharacter(padString
);
1432 expectPad(fmt
, "*P##.##", DecimalFormat::kPadBeforePrefix
, 5, padString
);
1433 fmt
.setPadCharacter((UnicodeString
)"^");
1434 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, (UnicodeString
)"^");
1435 //commented untill implementation is complete
1436 /* fmt.setPadCharacter((UnicodeString)"^^^");
1437 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1439 padString.append((UChar)0x0061);
1440 padString.append((UChar)0x0302);
1441 fmt.setPadCharacter(padString);
1442 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1443 UnicodeString pattern(patternChars);
1444 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1450 * Upgrade to alphaWorks
1452 void NumberFormatTest::TestPatterns2(void) {
1453 UErrorCode status
= U_ZERO_ERROR
;
1454 DecimalFormatSymbols
US(Locale::getUS(), status
);
1455 CHECK(status
, "DecimalFormatSymbols constructor");
1457 DecimalFormat
fmt("#", US
, status
);
1458 CHECK(status
, "DecimalFormat constructor");
1460 UChar hat
= 0x005E; /*^*/
1462 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, hat
);
1463 expectPad(fmt
, "$*^#", DecimalFormat::kPadAfterPrefix
, 2, hat
);
1464 expectPad(fmt
, "#*^", DecimalFormat::kPadBeforeSuffix
, 1, hat
);
1465 expectPad(fmt
, "#$*^", DecimalFormat::kPadAfterSuffix
, 2, hat
);
1466 expectPad(fmt
, "$*^$#", ILLEGAL
);
1467 expectPad(fmt
, "#$*^$", ILLEGAL
);
1468 expectPad(fmt
, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix
,
1469 12, (UChar
)0x0078 /*x*/);
1470 expectPad(fmt
, "''#0*x", DecimalFormat::kPadBeforeSuffix
,
1471 3, (UChar
)0x0078 /*x*/);
1472 expectPad(fmt
, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix
,
1473 10, (UChar
)0x0061 /*a*/);
1475 fmt
.applyPattern("AA#,##0.00ZZ", status
);
1476 CHECK(status
, "applyPattern");
1477 fmt
.setPadCharacter(hat
);
1479 fmt
.setFormatWidth(10);
1481 fmt
.setPadPosition(DecimalFormat::kPadBeforePrefix
);
1482 expectPat(fmt
, "*^AA#,##0.00ZZ");
1484 fmt
.setPadPosition(DecimalFormat::kPadBeforeSuffix
);
1485 expectPat(fmt
, "AA#,##0.00*^ZZ");
1487 fmt
.setPadPosition(DecimalFormat::kPadAfterSuffix
);
1488 expectPat(fmt
, "AA#,##0.00ZZ*^");
1491 UnicodeString
exp("AA*^#,##0.00ZZ", "");
1492 fmt
.setFormatWidth(12);
1493 fmt
.setPadPosition(DecimalFormat::kPadAfterPrefix
);
1494 expectPat(fmt
, exp
);
1496 fmt
.setFormatWidth(13);
1498 expectPat(fmt
, "AA*^##,##0.00ZZ");
1500 fmt
.setFormatWidth(14);
1502 expectPat(fmt
, "AA*^###,##0.00ZZ");
1504 fmt
.setFormatWidth(15);
1506 expectPat(fmt
, "AA*^####,##0.00ZZ"); // This is the interesting case
1508 fmt
.setFormatWidth(16);
1509 // 12 34567890123456
1510 expectPat(fmt
, "AA*^#,###,##0.00ZZ");
1513 void NumberFormatTest::TestSurrogateSupport(void) {
1514 UErrorCode status
= U_ZERO_ERROR
;
1515 DecimalFormatSymbols
custom(Locale::getUS(), status
);
1516 CHECK(status
, "DecimalFormatSymbols constructor");
1518 custom
.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, "decimal");
1519 custom
.setSymbol(DecimalFormatSymbols::kPlusSignSymbol
, "plus");
1520 custom
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, " minus ");
1521 custom
.setSymbol(DecimalFormatSymbols::kExponentialSymbol
, "exponent");
1523 UnicodeString
patternStr("*\\U00010000##.##", "");
1524 patternStr
= patternStr
.unescape();
1525 UnicodeString
expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1526 expStr
= expStr
.unescape();
1527 expect2(new DecimalFormat(patternStr
, custom
, status
),
1528 int32_t(0), expStr
, status
);
1530 status
= U_ZERO_ERROR
;
1531 expect2(new DecimalFormat("*^##.##", custom
, status
),
1532 int32_t(0), "^^^^0", status
);
1533 status
= U_ZERO_ERROR
;
1534 expect2(new DecimalFormat("##.##", custom
, status
),
1535 -1.3, " minus 1decimal3", status
);
1536 status
= U_ZERO_ERROR
;
1537 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1538 int32_t(0), "0decimal0exponent0 g-m/s^2", status
);
1539 status
= U_ZERO_ERROR
;
1540 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1541 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status
);
1542 status
= U_ZERO_ERROR
;
1543 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1544 int32_t(0), "0decimal0 g-m/s^2", status
);
1545 status
= U_ZERO_ERROR
;
1546 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1547 1.0/3, "0decimal33333 g-m/s^2", status
);
1549 UnicodeString
zero((UChar32
)0x10000);
1550 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, zero
);
1551 expStr
= UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1552 expStr
= expStr
.unescape();
1553 status
= U_ZERO_ERROR
;
1554 expect2(new DecimalFormat("##0.000", custom
, status
),
1555 1.25, expStr
, status
);
1557 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, (UChar
)0x30);
1558 custom
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "units of money");
1559 custom
.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, "money separator");
1560 patternStr
= UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1561 patternStr
= patternStr
.unescape();
1562 expStr
= UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1563 status
= U_ZERO_ERROR
;
1564 expect2(new DecimalFormat(patternStr
, custom
, status
),
1565 int32_t(-20), expStr
, status
);
1567 custom
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, "percent");
1568 patternStr
= "'You''ve lost ' -0.00 %' of your money today'";
1569 patternStr
= patternStr
.unescape();
1570 expStr
= UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1571 status
= U_ZERO_ERROR
;
1572 expect2(new DecimalFormat(patternStr
, custom
, status
),
1573 int32_t(-20), expStr
, status
);
1576 void NumberFormatTest::TestCurrencyPatterns(void) {
1577 int32_t i
, locCount
;
1578 const Locale
* locs
= NumberFormat::getAvailableLocales(locCount
);
1579 for (i
=0; i
<locCount
; ++i
) {
1580 UErrorCode ec
= U_ZERO_ERROR
;
1581 NumberFormat
* nf
= NumberFormat::createCurrencyInstance(locs
[i
], ec
);
1582 if (U_FAILURE(ec
)) {
1583 errln("FAIL: Can't create NumberFormat(%s) - %s", locs
[i
].getName(), u_errorName(ec
));
1585 // Make sure currency formats do not have a variable number
1586 // of fraction digits
1587 int32_t min
= nf
->getMinimumFractionDigits();
1588 int32_t max
= nf
->getMaximumFractionDigits();
1592 nf
->format(1.125, b
);
1593 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1594 " min fraction digits != max fraction digits; "
1595 "x 1.0 => " + escape(a
) +
1596 "; x 1.125 => " + escape(b
));
1599 // Make sure EURO currency formats have exactly 2 fraction digits
1600 if (nf
->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1601 DecimalFormat
* df
= (DecimalFormat
*) nf
;
1602 if (u_strcmp(EUR
, df
->getCurrency()) == 0) {
1603 if (min
!= 2 || max
!= 2) {
1606 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1607 " is a EURO format but it does not have 2 fraction digits; "
1618 void NumberFormatTest::TestRegCurrency(void) {
1619 #if !UCONFIG_NO_SERVICE
1620 UErrorCode status
= U_ZERO_ERROR
;
1622 ucurr_forLocale("en_US", USD
, 4, &status
);
1624 ucurr_forLocale("ja_JP", YEN
, 4, &status
);
1626 static const UChar QQQ
[] = {0x51, 0x51, 0x51, 0};
1627 if(U_FAILURE(status
)) {
1628 errln("Unable to get currency for locale, error %s", u_errorName(status
));
1632 UCurrRegistryKey enkey
= ucurr_register(YEN
, "en_US", &status
);
1633 UCurrRegistryKey enUSEUROkey
= ucurr_register(QQQ
, "en_US_EURO", &status
);
1635 ucurr_forLocale("en_US", TMP
, 4, &status
);
1636 if (u_strcmp(YEN
, TMP
) != 0) {
1637 errln("FAIL: didn't return YEN registered for en_US");
1640 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1641 if (u_strcmp(QQQ
, TMP
) != 0) {
1642 errln("FAIL: didn't return QQQ for en_US_EURO");
1645 int32_t fallbackLen
= ucurr_forLocale("en_XX_BAR", TMP
, 4, &status
);
1647 errln("FAIL: tried to fallback en_XX_BAR");
1649 status
= U_ZERO_ERROR
; // reset
1651 if (!ucurr_unregister(enkey
, &status
)) {
1652 errln("FAIL: couldn't unregister enkey");
1655 ucurr_forLocale("en_US", TMP
, 4, &status
);
1656 if (u_strcmp(USD
, TMP
) != 0) {
1657 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1659 status
= U_ZERO_ERROR
; // reset
1661 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1662 if (u_strcmp(QQQ
, TMP
) != 0) {
1663 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1666 ucurr_forLocale("en_US_BLAH", TMP
, 4, &status
);
1667 if (u_strcmp(USD
, TMP
) != 0) {
1668 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1670 status
= U_ZERO_ERROR
; // reset
1672 if (!ucurr_unregister(enUSEUROkey
, &status
)) {
1673 errln("FAIL: couldn't unregister enUSEUROkey");
1676 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1677 if (u_strcmp(EUR
, TMP
) != 0) {
1678 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1680 status
= U_ZERO_ERROR
; // reset
1684 void NumberFormatTest::TestCurrencyNames(void) {
1685 // Do a basic check of getName()
1686 // USD { "US$", "US Dollar" } // 04/04/1792-
1687 UErrorCode ec
= U_ZERO_ERROR
;
1688 static const UChar USD
[] = {0x55, 0x53, 0x44, 0}; /*USD*/
1689 static const UChar USX
[] = {0x55, 0x53, 0x58, 0}; /*USX*/
1690 static const UChar CAD
[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
1691 static const UChar ITL
[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
1692 UBool isChoiceFormat
;
1694 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1695 // THE LOCALE DATA before diving into the code.
1696 assertEquals("USD.getName(SYMBOL_NAME)",
1698 UnicodeString(ucurr_getName(USD
, "en",
1700 &isChoiceFormat
, &len
, &ec
)));
1701 assertEquals("USD.getName(LONG_NAME)",
1702 UnicodeString("US Dollar"),
1703 UnicodeString(ucurr_getName(USD
, "en",
1705 &isChoiceFormat
, &len
, &ec
)));
1706 assertEquals("CAD.getName(SYMBOL_NAME)",
1707 UnicodeString("CA$"),
1708 UnicodeString(ucurr_getName(CAD
, "en",
1710 &isChoiceFormat
, &len
, &ec
)));
1711 assertEquals("CAD.getName(SYMBOL_NAME)",
1713 UnicodeString(ucurr_getName(CAD
, "en_CA",
1715 &isChoiceFormat
, &len
, &ec
)));
1716 assertEquals("USD.getName(SYMBOL_NAME)",
1717 UnicodeString("US$"),
1718 UnicodeString(ucurr_getName(USD
, "en_AU",
1720 &isChoiceFormat
, &len
, &ec
)));
1721 assertEquals("CAD.getName(SYMBOL_NAME)",
1722 UnicodeString("CA$"),
1723 UnicodeString(ucurr_getName(CAD
, "en_AU",
1725 &isChoiceFormat
, &len
, &ec
)));
1726 assertEquals("USX.getName(LONG_NAME)",
1727 UnicodeString("USX"),
1728 UnicodeString(ucurr_getName(USX
, "en_US",
1730 &isChoiceFormat
, &len
, &ec
)));
1731 assertSuccess("ucurr_getName", ec
);
1735 // Test that a default or fallback warning is being returned. JB 4239.
1736 ucurr_getName(CAD
, "es_ES", UCURR_LONG_NAME
, &isChoiceFormat
,
1738 assertTrue("ucurr_getName (fallback)",
1739 U_USING_FALLBACK_WARNING
== ec
, TRUE
);
1741 ucurr_getName(CAD
, "zh_TW", UCURR_LONG_NAME
, &isChoiceFormat
,
1743 assertTrue("ucurr_getName (fallback)",
1744 U_USING_FALLBACK_WARNING
== ec
, TRUE
);
1746 ucurr_getName(CAD
, "en_US", UCURR_LONG_NAME
, &isChoiceFormat
,
1748 assertTrue("ucurr_getName (default)",
1749 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1751 ucurr_getName(CAD
, "vi", UCURR_LONG_NAME
, &isChoiceFormat
,
1753 assertTrue("ucurr_getName (default)",
1754 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1756 // Test that a default warning is being returned when falling back to root. JB 4536.
1757 ucurr_getName(ITL
, "cy", UCURR_LONG_NAME
, &isChoiceFormat
,
1759 assertTrue("ucurr_getName (default to root)",
1760 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1762 // TODO add more tests later
1765 void NumberFormatTest::TestCurrencyUnit(void){
1766 UErrorCode ec
= U_ZERO_ERROR
;
1767 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1768 CurrencyUnit
cu(USD
, ec
);
1769 assertSuccess("CurrencyUnit", ec
);
1771 const UChar
* r
= cu
.getISOCurrency(); // who is the buffer owner ?
1772 assertEquals("getISOCurrency()", USD
, r
);
1774 CurrencyUnit
cu2(cu
);
1776 errln("CurrencyUnit copy constructed object should be same");
1779 CurrencyUnit
* cu3
= (CurrencyUnit
*)cu
.clone();
1781 errln("CurrencyUnit cloned object should be same");
1786 void NumberFormatTest::TestCurrencyAmount(void){
1787 UErrorCode ec
= U_ZERO_ERROR
;
1788 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1789 CurrencyAmount
ca(9, USD
, ec
);
1790 assertSuccess("CurrencyAmount", ec
);
1792 CurrencyAmount
ca2(ca
);
1794 errln("CurrencyAmount copy constructed object should be same");
1799 errln("CurrencyAmount assigned object should be same");
1802 CurrencyAmount
*ca3
= (CurrencyAmount
*)ca
.clone();
1804 errln("CurrencyAmount cloned object should be same");
1809 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1811 Locale
locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1812 UErrorCode status
= U_ZERO_ERROR
;
1813 UnicodeString
intlCurrencySymbol((UChar
)0xa4);
1815 intlCurrencySymbol
.append((UChar
)0xa4);
1817 logln("Current locale is %s", Locale::getDefault().getName());
1818 Locale::setDefault(locBad
, status
);
1819 logln("Current locale is %s", Locale::getDefault().getName());
1820 DecimalFormatSymbols
mySymbols(status
);
1821 if (status
!= U_USING_FALLBACK_WARNING
) {
1822 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1824 if (strcmp(mySymbols
.getLocale().getName(), locBad
.getName()) != 0) {
1825 errln("DecimalFormatSymbols does not have the right locale.");
1827 int symbolEnum
= (int)DecimalFormatSymbols::kDecimalSeparatorSymbol
;
1828 for (; symbolEnum
< (int)DecimalFormatSymbols::kFormatSymbolCount
; symbolEnum
++) {
1829 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum
+ UnicodeString("] = ")
1830 + prettify(mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
)));
1832 if (mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
).length() == 0
1833 && symbolEnum
!= (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
1834 && symbolEnum
!= (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
)
1836 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum
);
1839 status
= U_ZERO_ERROR
;
1840 Locale::setDefault(locDefault
, status
);
1841 logln("Current locale is %s", Locale::getDefault().getName());
1845 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1846 * behave the same, except for memory ownership semantics. (No
1847 * version of this test on Java, since Java has only one method.)
1849 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1850 UErrorCode ec
= U_ZERO_ERROR
;
1851 DecimalFormatSymbols
*sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1852 if (U_FAILURE(ec
)) {
1853 errln("Fail: DecimalFormatSymbols constructor");
1857 UnicodeString
pat(" #,##0.00");
1858 pat
.insert(0, (UChar
)0x00A4);
1859 DecimalFormat
fmt(pat
, sym
, ec
);
1860 if (U_FAILURE(ec
)) {
1861 errln("Fail: DecimalFormat constructor");
1866 fmt
.format(2350.75, str
);
1867 if (str
== "$ 2,350.75") {
1870 errln("Fail: " + str
+ ", expected $ 2,350.75");
1873 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1874 if (U_FAILURE(ec
)) {
1875 errln("Fail: DecimalFormatSymbols constructor");
1879 sym
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1880 fmt
.adoptDecimalFormatSymbols(sym
);
1883 fmt
.format(2350.75, str
);
1884 if (str
== "Q 2,350.75") {
1887 errln("Fail: adoptDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1890 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1891 if (U_FAILURE(ec
)) {
1892 errln("Fail: DecimalFormatSymbols constructor");
1896 DecimalFormat
fmt2(pat
, sym
, ec
);
1897 if (U_FAILURE(ec
)) {
1898 errln("Fail: DecimalFormat constructor");
1902 DecimalFormatSymbols
sym2(Locale::getUS(), ec
);
1903 if (U_FAILURE(ec
)) {
1904 errln("Fail: DecimalFormatSymbols constructor");
1907 sym2
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1908 fmt2
.setDecimalFormatSymbols(sym2
);
1911 fmt2
.format(2350.75, str
);
1912 if (str
== "Q 2,350.75") {
1915 errln("Fail: setDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1919 void NumberFormatTest::TestPerMill() {
1920 UErrorCode ec
= U_ZERO_ERROR
;
1922 DecimalFormat
fmt(ctou("###.###\\u2030"), ec
);
1923 if (!assertSuccess("DecimalFormat ct", ec
)) return;
1924 assertEquals("0.4857 x ###.###\\u2030",
1925 ctou("485.7\\u2030"), fmt
.format(0.4857, str
));
1927 DecimalFormatSymbols
sym(Locale::getUS(), ec
);
1928 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, ctou("m"));
1929 DecimalFormat
fmt2("", sym
, ec
);
1930 fmt2
.applyLocalizedPattern("###.###m", ec
);
1931 if (!assertSuccess("setup", ec
)) return;
1933 assertEquals("0.4857 x ###.###m",
1934 "485.7m", fmt2
.format(0.4857, str
));
1938 * Generic test for patterns that should be legal/illegal.
1940 void NumberFormatTest::TestIllegalPatterns() {
1942 // Prefix with "-:" for illegal patterns
1943 // Prefix with "+:" for legal patterns
1944 const char* DATA
[] = {
1945 // Unquoted special characters in the suffix are illegal
1950 for (int32_t i
=0; DATA
[i
]; ++i
) {
1951 const char* pat
=DATA
[i
];
1952 UBool valid
= (*pat
) == '+';
1954 UErrorCode ec
= U_ZERO_ERROR
;
1955 DecimalFormat
fmt(pat
, ec
); // locale doesn't matter here
1956 if (U_SUCCESS(ec
) == valid
) {
1957 logln("Ok: pattern \"%s\": %s",
1958 pat
, u_errorName(ec
));
1960 errln("FAIL: pattern \"%s\" should have %s; got %s",
1961 pat
, (valid
?"succeeded":"failed"),
1967 //----------------------------------------------------------------------
1969 static const char* KEYWORDS
[] = {
1970 /*0*/ "ref=", // <reference pattern to parse numbers>
1971 /*1*/ "loc=", // <locale for formats>
1972 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1973 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1974 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1975 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1976 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1977 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1978 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1983 * Return an integer representing the next token from this
1984 * iterator. The integer will be an index into the given list, or
1985 * -1 if there are no more tokens, or -2 if the token is not on
1988 static int32_t keywordIndex(const UnicodeString
& tok
) {
1989 for (int32_t i
=0; KEYWORDS
[i
]!=0; ++i
) {
1990 if (tok
==KEYWORDS
[i
]) {
1998 * Parse a CurrencyAmount using the given NumberFormat, with
1999 * the 'delim' character separating the number and the currency.
2001 static void parseCurrencyAmount(const UnicodeString
& str
,
2002 const NumberFormat
& fmt
,
2004 Formattable
& result
,
2006 UnicodeString num
, cur
;
2007 int32_t i
= str
.indexOf(delim
);
2008 str
.extractBetween(0, i
, num
);
2009 str
.extractBetween(i
+1, INT32_MAX
, cur
);
2011 fmt
.parse(num
, n
, ec
);
2012 result
.adoptObject(new CurrencyAmount(n
, cur
.getTerminatedBuffer(), ec
));
2015 void NumberFormatTest::TestCases() {
2016 UErrorCode ec
= U_ZERO_ERROR
;
2017 TextFile
reader("NumberFormatTestCases.txt", "UTF8", ec
);
2018 if (U_FAILURE(ec
)) {
2019 dataerrln("[DATA] Couldn't open NumberFormatTestCases.txt");
2022 TokenIterator
tokens(&reader
);
2024 Locale
loc("en", "US", "");
2025 DecimalFormat
*ref
= 0, *fmt
= 0;
2026 MeasureFormat
*mfmt
= 0;
2027 UnicodeString pat
, tok
, mloc
, str
, out
, where
, currAmt
;
2032 if (!tokens
.next(tok
, ec
)) {
2035 where
= UnicodeString("(") + tokens
.getLineNumber() + ") ";
2036 int32_t cmd
= keywordIndex(tok
);
2039 // ref= <reference pattern>
2040 if (!tokens
.next(tok
, ec
)) goto error
;
2042 ref
= new DecimalFormat(tok
,
2043 new DecimalFormatSymbols(Locale::getUS(), ec
), ec
);
2044 if (U_FAILURE(ec
)) {
2045 dataerrln("Error constructing DecimalFormat");
2051 if (!tokens
.next(tok
, ec
)) goto error
;
2052 loc
= Locale::createFromName(CharString(tok
));
2058 if (!tokens
.next(tok
, ec
)) goto error
;
2062 fmt
= new DecimalFormat(pat
, new DecimalFormatSymbols(loc
, ec
), ec
);
2063 if (U_FAILURE(ec
)) {
2064 errln("FAIL: " + where
+ "Pattern \"" + pat
+ "\": " + u_errorName(ec
));
2066 if (!tokens
.next(tok
, ec
)) goto error
;
2067 if (!tokens
.next(tok
, ec
)) goto error
;
2069 if (!tokens
.next(tok
, ec
)) goto error
;
2074 if (cmd
== 2 || cmd
== 3 || cmd
== 4) {
2075 // f: <pattern or '-'> <number> <exp. string>
2076 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2077 // rt: <pattern or '-'> <number> <string>
2079 if (!tokens
.next(num
, ec
)) goto error
;
2080 if (!tokens
.next(str
, ec
)) goto error
;
2081 ref
->parse(num
, n
, ec
);
2082 assertSuccess("parse", ec
);
2083 assertEquals(where
+ "\"" + pat
+ "\".format(" + num
+ ")",
2084 str
, fmt
->format(n
, out
.remove(), ec
));
2085 assertSuccess("format", ec
);
2086 if (cmd
== 3) { // fp:
2087 if (!tokens
.next(num
, ec
)) goto error
;
2088 ref
->parse(num
, n
, ec
);
2089 assertSuccess("parse", ec
);
2091 if (cmd
!= 2) { // != f:
2093 fmt
->parse(str
, m
, ec
);
2094 assertSuccess("parse", ec
);
2095 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
2099 // p: <pattern or '-'> <string to parse> <exp. number>
2101 UnicodeString expstr
;
2102 if (!tokens
.next(str
, ec
)) goto error
;
2103 if (!tokens
.next(expstr
, ec
)) goto error
;
2105 ref
->parse(expstr
, exp
, ec
);
2106 assertSuccess("parse", ec
);
2107 fmt
->parse(str
, n
, ec
);
2108 assertSuccess("parse", ec
);
2109 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
2114 if (!tokens
.next(tok
, ec
)) goto error
;
2118 mfmt
= MeasureFormat::createCurrencyFormat(
2119 Locale::createFromName(CharString(mloc
)), ec
);
2120 if (U_FAILURE(ec
)) {
2121 errln("FAIL: " + where
+ "Loc \"" + mloc
+ "\": " + u_errorName(ec
));
2123 if (!tokens
.next(tok
, ec
)) goto error
;
2124 if (!tokens
.next(tok
, ec
)) goto error
;
2125 if (!tokens
.next(tok
, ec
)) goto error
;
2129 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2130 if (!tokens
.next(currAmt
, ec
)) goto error
;
2131 if (!tokens
.next(str
, ec
)) goto error
;
2132 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
2133 if (assertSuccess("parseCurrencyAmount", ec
)) {
2134 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").format(" + currAmt
+ ")",
2135 str
, mfmt
->format(n
, out
.remove(), ec
));
2136 assertSuccess("format", ec
);
2138 if (!tokens
.next(currAmt
, ec
)) goto error
;
2139 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
2140 if (assertSuccess("parseCurrencyAmount", ec
)) {
2142 mfmt
->parseObject(str
, m
, ec
);
2143 if (assertSuccess("parseCurrency", ec
)) {
2144 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").parse(\"" + str
+ "\")",
2150 // perr: <pattern or '-'> <invalid string>
2151 errln("FAIL: Under construction");
2154 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2155 UnicodeString testpat
;
2156 UnicodeString exppat
;
2157 if (!tokens
.next(testpat
, ec
)) goto error
;
2158 if (!tokens
.next(exppat
, ec
)) goto error
;
2159 UBool err
= exppat
== "err";
2160 UBool existingPat
= FALSE
;
2161 if (testpat
== "-") {
2163 errln("FAIL: " + where
+ "Invalid command \"pat: - err\"");
2169 if (exppat
== "-") exppat
= testpat
;
2170 DecimalFormat
* f
= 0;
2171 UErrorCode ec2
= U_ZERO_ERROR
;
2175 f
= new DecimalFormat(testpat
, ec2
);
2177 if (U_SUCCESS(ec2
)) {
2179 errln("FAIL: " + where
+ "Invalid pattern \"" + testpat
+
2183 assertEquals(where
+ "\"" + testpat
+ "\".toPattern()",
2184 exppat
, f
->toPattern(pat2
));
2188 logln("Ok: " + where
+ "Invalid pattern \"" + testpat
+
2189 "\" failed: " + u_errorName(ec2
));
2191 errln("FAIL: " + where
+ "Valid pattern \"" + testpat
+
2192 "\" failed: " + u_errorName(ec2
));
2195 if (!existingPat
) delete f
;
2198 errln("FAIL: " + where
+ "Unknown command \"" + tok
+ "\"");
2205 if (U_SUCCESS(ec
)) {
2206 errln("FAIL: Unexpected EOF");
2208 errln("FAIL: " + where
+ "Unexpected " + u_errorName(ec
));
2218 //----------------------------------------------------------------------
2220 //----------------------------------------------------------------------
2222 UBool
NumberFormatTest::equalValue(const Formattable
& a
, const Formattable
& b
) {
2223 if (a
.getType() == b
.getType()) {
2227 if (a
.getType() == Formattable::kLong
) {
2228 if (b
.getType() == Formattable::kInt64
) {
2229 return a
.getLong() == b
.getLong();
2230 } else if (b
.getType() == Formattable::kDouble
) {
2231 return (double) a
.getLong() == b
.getDouble(); // TODO check use of double instead of long
2233 } else if (a
.getType() == Formattable::kDouble
) {
2234 if (b
.getType() == Formattable::kLong
) {
2235 return a
.getDouble() == (double) b
.getLong();
2236 } else if (b
.getType() == Formattable::kInt64
) {
2237 return a
.getDouble() == (double)b
.getInt64();
2239 } else if (a
.getType() == Formattable::kInt64
) {
2240 if (b
.getType() == Formattable::kLong
) {
2241 return a
.getInt64() == (int64_t)b
.getLong();
2242 } else if (b
.getType() == Formattable::kDouble
) {
2243 return a
.getInt64() == (int64_t)b
.getDouble();
2249 void NumberFormatTest::expect2(NumberFormat
& fmt
, const Formattable
& n
, const UnicodeString
& str
) {
2250 // Don't round-trip format test, since we explicitly do it
2251 expect(fmt
, n
, str
, FALSE
);
2252 expect(fmt
, str
, n
);
2255 void NumberFormatTest::expect2(NumberFormat
* fmt
, const Formattable
& n
,
2256 const UnicodeString
& exp
,
2257 UErrorCode status
) {
2258 if (U_FAILURE(status
)) {
2259 errln("FAIL: NumberFormat constructor");
2261 expect2(*fmt
, n
, exp
);
2266 void NumberFormatTest::expect(NumberFormat
& fmt
, const UnicodeString
& str
, const Formattable
& n
) {
2267 UErrorCode status
= U_ZERO_ERROR
;
2269 fmt
.parse(str
, num
, status
);
2270 if (U_FAILURE(status
)) {
2271 errln(UnicodeString("FAIL: Parse failed for \"") + str
+ "\"");
2275 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2276 if (equalValue(num
, n
)) {
2277 logln(UnicodeString("Ok \"") + str
+ "\" x " +
2281 errln(UnicodeString("FAIL \"") + str
+ "\" x " +
2283 toString(num
) + ", expected " + toString(n
));
2287 void NumberFormatTest::expect(NumberFormat
& fmt
, const Formattable
& n
,
2288 const UnicodeString
& exp
, UBool rt
) {
2291 UErrorCode status
= U_ZERO_ERROR
;
2292 fmt
.format(n
, saw
, pos
, status
);
2293 CHECK(status
, "NumberFormat::format");
2295 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2297 logln(UnicodeString("Ok ") + toString(n
) + " x " +
2298 escape(pat
) + " = \"" +
2299 escape(saw
) + "\"");
2300 // We should be able to round-trip the formatted string =>
2301 // number => string (but not the other way around: number
2302 // => string => number2, might have number2 != number):
2305 fmt
.parse(exp
, n2
, status
);
2306 if (U_FAILURE(status
)) {
2307 errln(UnicodeString("FAIL: Parse failed for \"") + exp
+ "\"");
2311 fmt
.format(n2
, saw2
, pos
, status
);
2312 CHECK(status
, "NumberFormat::format");
2314 errln((UnicodeString
)"FAIL \"" + exp
+ "\" => " + toString(n2
) +
2315 " => \"" + saw2
+ "\"");
2319 errln(UnicodeString("FAIL ") + toString(n
) + " x " +
2320 escape(pat
) + " = \"" +
2321 escape(saw
) + "\", expected \"" + exp
+ "\"");
2325 void NumberFormatTest::expect(NumberFormat
* fmt
, const Formattable
& n
,
2326 const UnicodeString
& exp
,
2327 UErrorCode status
) {
2328 if (U_FAILURE(status
)) {
2329 errln("FAIL: NumberFormat constructor");
2331 expect(*fmt
, n
, exp
);
2336 void NumberFormatTest::expectCurrency(NumberFormat
& nf
, const Locale
& locale
,
2337 double value
, const UnicodeString
& string
) {
2338 UErrorCode ec
= U_ZERO_ERROR
;
2339 DecimalFormat
& fmt
= * (DecimalFormat
*) &nf
;
2340 const UChar DEFAULT_CURR
[] = {45/*-*/,0};
2342 u_strcpy(curr
, DEFAULT_CURR
);
2343 if (*locale
.getLanguage() != 0) {
2344 ucurr_forLocale(locale
.getName(), curr
, 4, &ec
);
2345 assertSuccess("ucurr_forLocale", ec
);
2346 fmt
.setCurrency(curr
, ec
);
2347 assertSuccess("DecimalFormat::setCurrency", ec
);
2348 fmt
.setCurrency(curr
); //Deprecated variant, for coverage only
2351 fmt
.format(value
, s
);
2352 s
.findAndReplace((UChar32
)0x00A0, (UChar32
)0x0020);
2354 // Default display of the number yields "1234.5599999999999"
2355 // instead of "1234.56". Use a formatter to fix this.
2357 NumberFormat::createInstance(Locale::getUS(), ec
);
2359 if (U_FAILURE(ec
)) {
2360 // Oops; bad formatter. Use default op+= display.
2361 v
= (UnicodeString
)"" + value
;
2363 f
->setMaximumFractionDigits(4);
2364 f
->setGroupingUsed(FALSE
);
2365 f
->format(value
, v
);
2370 logln((UnicodeString
)"Ok: " + v
+ " x " + curr
+ " => " + prettify(s
));
2372 errln((UnicodeString
)"FAIL: " + v
+ " x " + curr
+ " => " + prettify(s
) +
2373 ", expected " + prettify(string
));
2377 void NumberFormatTest::expectPat(DecimalFormat
& fmt
, const UnicodeString
& exp
) {
2381 logln(UnicodeString("Ok \"") + pat
+ "\"");
2383 errln(UnicodeString("FAIL \"") + pat
+ "\", expected \"" + exp
+ "\"");
2387 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2389 expectPad(fmt
, pat
, pos
, 0, (UnicodeString
)"");
2391 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2392 int32_t pos
, int32_t width
, UChar pad
) {
2393 expectPad(fmt
, pat
, pos
, width
, UnicodeString(pad
));
2395 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2396 int32_t pos
, int32_t width
, const UnicodeString
& pad
) {
2397 int32_t apos
= 0, awidth
= 0;
2398 UnicodeString apadStr
;
2399 UErrorCode status
= U_ZERO_ERROR
;
2400 fmt
.applyPattern(pat
, status
);
2401 if (U_SUCCESS(status
)) {
2402 apos
= fmt
.getPadPosition();
2403 awidth
= fmt
.getFormatWidth();
2404 apadStr
=fmt
.getPadCharacterString();
2410 if (apos
== pos
&& awidth
== width
&& apadStr
== pad
) {
2411 UnicodeString infoStr
;
2412 if (pos
== ILLEGAL
) {
2413 infoStr
= UnicodeString(" width=", "") + awidth
+ UnicodeString(" pad=", "") + apadStr
;
2415 logln(UnicodeString("Ok \"") + pat
+ "\" pos=" + apos
+ infoStr
);
2417 errln(UnicodeString("FAIL \"") + pat
+ "\" pos=" + apos
+
2418 " width=" + awidth
+ " pad=" + apadStr
+
2419 ", expected " + pos
+ " " + width
+ " " + pad
);
2422 void NumberFormatTest::TestJB3832(){
2423 const char* localeID
= "pt_PT@currency=PTE";
2424 Locale
loc(localeID
);
2425 UErrorCode status
= U_ZERO_ERROR
;
2426 UnicodeString
expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
2428 NumberFormat
* currencyFmt
= NumberFormat::createCurrencyInstance(loc
, status
);
2429 if(U_FAILURE(status
)){
2430 errln("Could not create currency formatter for locale %s", localeID
);
2433 currencyFmt
->format(1150.50, s
);
2435 errln(UnicodeString("FAIL: Expected: ")+expected
2436 + UnicodeString(" Got: ") + s
2437 + UnicodeString( " for locale: ")+ UnicodeString(localeID
) );
2439 if (U_FAILURE(status
)){
2440 errln("FAIL: Status %s", u_errorName(status
));
2445 void NumberFormatTest::TestHost()
2448 Win32NumberTest::testLocales(this);
2452 void NumberFormatTest::TestHostClone()
2455 Verify that a cloned formatter gives the same results
2456 and is useable after the original has been deleted.
2458 // This is mainly important on Windows.
2459 UErrorCode status
= U_ZERO_ERROR
;
2460 Locale
loc("en_US@compat=host");
2461 UDate now
= Calendar::getNow();
2462 NumberFormat
*full
= NumberFormat::createInstance(loc
, status
);
2463 if (full
== NULL
|| U_FAILURE(status
)) {
2464 errln("FAIL: Can't create Relative date instance");
2467 UnicodeString result1
;
2468 full
->format(now
, result1
, status
);
2469 Format
*fullClone
= full
->clone();
2473 UnicodeString result2
;
2474 fullClone
->format(now
, result2
, status
);
2475 if (U_FAILURE(status
)) {
2476 errln("FAIL: format failure.");
2478 if (result1
!= result2
) {
2479 errln("FAIL: Clone returned different result from non-clone.");
2484 void NumberFormatTest::TestCurrencyFormat()
2486 // This test is here to increase code coverage.
2487 UErrorCode status
= U_ZERO_ERROR
;
2488 MeasureFormat
*cloneObj
;
2490 Formattable toFormat
, result
;
2491 static const UChar ISO_CODE
[4] = {0x0047, 0x0042, 0x0050, 0};
2493 Locale saveDefaultLocale
= Locale::getDefault();
2494 Locale::setDefault( Locale::getUK(), status
);
2495 if (U_FAILURE(status
)) {
2496 errln("couldn't set default Locale!");
2500 MeasureFormat
*measureObj
= MeasureFormat::createCurrencyFormat(status
);
2501 Locale::setDefault( saveDefaultLocale
, status
);
2502 if (U_FAILURE(status
)){
2503 errln("FAIL: Status %s", u_errorName(status
));
2506 cloneObj
= (MeasureFormat
*)measureObj
->clone();
2507 if (cloneObj
== NULL
) {
2508 errln("Clone doesn't work");
2511 toFormat
.adoptObject(new CurrencyAmount(1234.56, ISO_CODE
, status
));
2512 measureObj
->format(toFormat
, str
, status
);
2513 measureObj
->parseObject(str
, result
, status
);
2514 if (U_FAILURE(status
)){
2515 errln("FAIL: Status %s", u_errorName(status
));
2517 if (result
!= toFormat
) {
2518 errln("measureObj does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2520 status
= U_ZERO_ERROR
;
2522 cloneObj
->format(toFormat
, str
, status
);
2523 cloneObj
->parseObject(str
, result
, status
);
2524 if (U_FAILURE(status
)){
2525 errln("FAIL: Status %s", u_errorName(status
));
2527 if (result
!= toFormat
) {
2528 errln("Clone does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2530 if (*measureObj
!= *cloneObj
) {
2531 errln("Cloned object is not equal to the original object");
2536 status
= U_USELESS_COLLATOR_ERROR
;
2537 if (MeasureFormat::createCurrencyFormat(status
) != NULL
) {
2538 errln("createCurrencyFormat should have returned NULL.");
2542 /* Port of ICU4J rounding test. */
2543 void NumberFormatTest::TestRounding() {
2544 UErrorCode status
= U_ZERO_ERROR
;
2545 DecimalFormat
*df
= (DecimalFormat
*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status
);
2547 if (U_FAILURE(status
)) {
2548 errln("Unable to create decimal formatter.");
2552 int roundingIncrements
[]={1, 2, 5, 20, 50, 100};
2553 int testValues
[]={0, 300};
2555 for (int j
=0; j
<2; j
++) {
2556 for (int mode
=DecimalFormat::kRoundUp
;mode
<DecimalFormat::kRoundHalfEven
;mode
++) {
2557 df
->setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
2558 for (int increment
=0; increment
<6; increment
++) {
2559 double base
=testValues
[j
];
2560 double rInc
=roundingIncrements
[increment
];
2561 checkRounding(df
, base
, 20, rInc
);
2562 rInc
=1.000000000/rInc
;
2563 checkRounding(df
, base
, 20, rInc
);
2570 void NumberFormatTest::checkRounding(DecimalFormat
* df
, double base
, int iterations
, double increment
) {
2571 df
->setRoundingIncrement(increment
);
2572 double lastParsed
=INT32_MIN
; //Intger.MIN_VALUE
2573 for (int i
=-iterations
; i
<=iterations
;i
++) {
2574 double iValue
=base
+(increment
*(i
*0.1));
2575 double smallIncrement
=0.00000001;
2577 smallIncrement
*=iValue
;
2579 //we not only test the value, but some values in a small range around it
2580 lastParsed
=checkRound(df
, iValue
-smallIncrement
, lastParsed
);
2581 lastParsed
=checkRound(df
, iValue
, lastParsed
);
2582 lastParsed
=checkRound(df
, iValue
+smallIncrement
, lastParsed
);
2586 double NumberFormatTest::checkRound(DecimalFormat
* df
, double iValue
, double lastParsed
) {
2587 UErrorCode status
=U_ZERO_ERROR
;
2588 UnicodeString formattedDecimal
;
2591 df
->format(iValue
, formattedDecimal
, status
);
2593 if (U_FAILURE(status
)) {
2594 errln("Error formatting number.");
2597 df
->parse(formattedDecimal
, result
, status
);
2599 if (U_FAILURE(status
)) {
2600 errln("Error parsing number.");
2603 parsed
=result
.getDouble();
2605 if (lastParsed
>parsed
) {
2606 errln("Rounding wrong direction! %d > %d", lastParsed
, parsed
);
2612 void NumberFormatTest::TestNonpositiveMultiplier() {
2613 UErrorCode status
= U_ZERO_ERROR
;
2614 DecimalFormatSymbols
US(Locale::getUS(), status
);
2615 CHECK(status
, "DecimalFormatSymbols constructor");
2616 DecimalFormat
df(UnicodeString("0"), US
, status
);
2617 CHECK(status
, "DecimalFormat(0)");
2619 // test zero multiplier
2621 int32_t mult
= df
.getMultiplier();
2622 df
.setMultiplier(0);
2623 if (df
.getMultiplier() != mult
) {
2624 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
2627 // test negative multiplier
2629 df
.setMultiplier(-1);
2630 if (df
.getMultiplier() != -1) {
2631 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
2635 expect(df
, "1122.123", -1122.123);
2636 expect(df
, "-1122.123", 1122.123);
2637 expect(df
, "1.2", -1.2);
2638 expect(df
, "-1.2", 1.2);
2640 // TODO: change all the following int64_t tests once BigInteger is ported
2641 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2642 static const char* posOutOfRange
= "9223372036854780000";
2643 static const char* negOutOfRange
= "-9223372036854780000";
2645 expect(df
, U_INT64_MIN
, posOutOfRange
);
2646 expect(df
, U_INT64_MIN
+1, "9223372036854775807");
2647 expect(df
, (int64_t)-123, "123");
2648 expect(df
, (int64_t)123, "-123");
2649 expect(df
, U_INT64_MAX
-1, "-9223372036854775806");
2650 expect(df
, U_INT64_MAX
, "-9223372036854775807");
2652 df
.setMultiplier(-2);
2653 expect(df
, -(U_INT64_MIN
/2)-1, "-9223372036854775806");
2654 expect(df
, -(U_INT64_MIN
/2), "-9223372036854775808");
2655 expect(df
, -(U_INT64_MIN
/2)+1, negOutOfRange
);
2657 df
.setMultiplier(-7);
2658 expect(df
, -(U_INT64_MAX
/7)-1, posOutOfRange
);
2659 expect(df
, -(U_INT64_MAX
/7), "9223372036854775807");
2660 expect(df
, -(U_INT64_MAX
/7)+1, "9223372036854775800");
2662 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
2663 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2664 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
2665 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
2666 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
2667 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
2669 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
2670 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2671 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2672 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2673 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2677 NumberFormatTest::TestSpaceParsing() {
2679 // the string to be parsed, parsed position, parsed error index
2680 const char* DATA
[][3] = {
2681 {"$124", "4", "-1"},
2682 {"$124 $124", "4", "-1"},
2683 {"$124 ", "4", "-1"},
2684 {"$ 124 ", "5", "-1"},
2685 {"$\\u00A0124 ", "5", "-1"},
2686 {" $ 124 ", "6", "-1"},
2687 //{"124$", "4", "-1"}, // TODO: need to handle trailing currency correctly
2688 {"124$", "3", "-1"},
2689 //{"124 $", "5", "-1"}, // TODO: OK or not, need currency spacing rule
2690 {"124 $", "3", "-1"},
2693 UErrorCode status
= U_ZERO_ERROR
;
2694 Locale
locale("en_US");
2695 NumberFormat
* foo
= NumberFormat::createCurrencyInstance(locale
, status
);
2696 if (U_FAILURE(status
)) {
2701 foo
->setParseStrict(FALSE
);
2702 for (uint32_t i
= 0; i
< sizeof(DATA
)/sizeof(DATA
[0]); ++i
) {
2703 ParsePosition
parsePosition(0);
2704 UnicodeString stringToBeParsed
= ctou(DATA
[i
][0]);
2705 int parsedPosition
= atoi(DATA
[i
][1]);
2706 int errorIndex
= atoi(DATA
[i
][2]);
2708 foo
->parse(stringToBeParsed
, result
, parsePosition
);
2709 if (parsePosition
.getIndex() != parsedPosition
||
2710 parsePosition
.getErrorIndex() != errorIndex
) {
2711 errln("FAILED parse " + stringToBeParsed
+ "; wrong position, expected: (" + parsedPosition
+ ", " + errorIndex
+ "); got (" + parsePosition
.getIndex() + ", " + parsePosition
.getErrorIndex() + ")");
2713 if (parsePosition
.getErrorIndex() == -1 &&
2714 result
.getType() == Formattable::kLong
&&
2715 result
.getLong() != 124) {
2716 errln("FAILED parse " + stringToBeParsed
+ "; wrong number, expect: 124, got " + result
.getLong());
2722 #endif /* #if !UCONFIG_NO_FORMATTING */