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 *lenientMinusTestCases
[] = {
827 static const char *lenientCurrencyTestCases
[] = {
838 static const char *lenientNegativeCurrencyTestCases
[] = {
846 "($ 1\\u00A0000.00)",
850 static const char *lenientPercentTestCases
[] = {
859 static const char *lenientNegativePercentTestCases
[] = {
871 static const char *strictFailureTestCases
[] = {
879 #define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
882 * Test lenient parsing.
885 NumberFormatTest::TestLenientParse(void)
887 UErrorCode status
= U_ZERO_ERROR
;
888 DecimalFormat
*format
= new DecimalFormat("(#,##0)", status
);
891 format
->setParseStrict(FALSE
);
892 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientAffixTestCases
); t
+= 1) {
893 UnicodeString testCase
= ctou(lenientAffixTestCases
[t
]);
895 format
->parse(testCase
, n
, status
);
896 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
898 if (U_FAILURE(status
) || n
.getType() != Formattable::kLong
||
900 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientAffixTestCases
[t
] + (UnicodeString
) "\"");
901 status
= U_ZERO_ERROR
;
907 Locale
en_US("en_US");
908 Locale
sv_SE("sv_SE");
910 NumberFormat
*mFormat
= NumberFormat::createInstance(sv_SE
, status
);
912 mFormat
->setParseStrict(FALSE
);
913 for (int32_t t
= 0; t
< ARRAY_SIZE(lenientMinusTestCases
); t
+= 1) {
914 UnicodeString testCase
= ctou(lenientMinusTestCases
[t
]);
916 mFormat
->parse(testCase
, n
, status
);
917 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
919 if (U_FAILURE(status
) || n
.getType() != Formattable::kLong
|| n
.getLong() != -5) {
920 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientMinusTestCases
[t
] + (UnicodeString
) "\"");
921 status
= U_ZERO_ERROR
;
927 mFormat
= NumberFormat::createInstance(en_US
, status
);
929 mFormat
->setParseStrict(FALSE
);
930 for (int32_t t
= 0; t
< ARRAY_SIZE(lenientMinusTestCases
); t
+= 1) {
931 UnicodeString testCase
= ctou(lenientMinusTestCases
[t
]);
933 mFormat
->parse(testCase
, n
, status
);
934 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
936 if (U_FAILURE(status
) || n
.getType() != Formattable::kLong
|| n
.getLong() != -5) {
937 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientMinusTestCases
[t
] + (UnicodeString
) "\"");
938 status
= U_ZERO_ERROR
;
944 NumberFormat
*cFormat
= NumberFormat::createCurrencyInstance(en_US
, status
);
946 cFormat
->setParseStrict(FALSE
);
947 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientCurrencyTestCases
); t
+= 1) {
948 UnicodeString testCase
= ctou(lenientCurrencyTestCases
[t
]);
950 cFormat
->parse(testCase
, n
, status
);
951 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
953 if (U_FAILURE(status
) ||n
.getType() != Formattable::kLong
||
954 n
.getLong() != 1000) {
955 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientCurrencyTestCases
[t
] + (UnicodeString
) "\"");
956 status
= U_ZERO_ERROR
;
960 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientNegativeCurrencyTestCases
); t
+= 1) {
961 UnicodeString testCase
= ctou(lenientNegativeCurrencyTestCases
[t
]);
962 ParsePosition
pos(0);
964 cFormat
->parse(testCase
, n
, /*status*/pos
);
965 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
967 if (/*U_FAILURE(status)*/pos
.getErrorIndex() >= 0 ||n
.getType() != Formattable::kLong
||
968 n
.getLong() != -1000) {
969 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientNegativeCurrencyTestCases
[t
] + (UnicodeString
) "\" parse position = " +
970 pos
.getIndex() + ", " + pos
.getErrorIndex());
971 status
= U_ZERO_ERROR
;
977 NumberFormat
*pFormat
= NumberFormat::createPercentInstance(en_US
, status
);
979 pFormat
->setParseStrict(FALSE
);
980 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientPercentTestCases
); t
+= 1) {
981 UnicodeString testCase
= ctou(lenientPercentTestCases
[t
]);
983 pFormat
->parse(testCase
, n
, status
);
984 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getDouble());
986 if (U_FAILURE(status
) ||n
.getType() != Formattable::kDouble
||
987 n
.getDouble() != 0.25) {
988 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientPercentTestCases
[t
] + (UnicodeString
) "\"");
989 status
= U_ZERO_ERROR
;
993 for (int32_t t
= 0; t
< ARRAY_SIZE (lenientNegativePercentTestCases
); t
+= 1) {
994 UnicodeString testCase
= ctou(lenientNegativePercentTestCases
[t
]);
996 pFormat
->parse(testCase
, n
, status
);
997 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getDouble());
999 if (U_FAILURE(status
) ||n
.getType() != Formattable::kDouble
||
1000 n
.getDouble() != -0.25) {
1001 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) lenientNegativePercentTestCases
[t
] + (UnicodeString
) "\"");
1002 status
= U_ZERO_ERROR
;
1008 // Test cases that should fail with a strict parse and pass with a
1010 NumberFormat
*nFormat
= NumberFormat::createInstance(en_US
, status
);
1012 // first, make sure that they fail with a strict parse
1013 for (int32_t t
= 0; t
< ARRAY_SIZE(strictFailureTestCases
); t
+= 1) {
1014 UnicodeString testCase
= ctou(strictFailureTestCases
[t
]);
1016 nFormat
->parse(testCase
, n
, status
);
1017 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
1019 if (! U_FAILURE(status
)) {
1020 errln((UnicodeString
)"Strict Parse succeeded for \"" + (UnicodeString
) strictFailureTestCases
[t
] + (UnicodeString
) "\"");
1023 status
= U_ZERO_ERROR
;
1026 // then, make sure that they pass with a lenient parse
1027 nFormat
->setParseStrict(FALSE
);
1028 for (int32_t t
= 0; t
< ARRAY_SIZE(strictFailureTestCases
); t
+= 1) {
1029 UnicodeString testCase
= ctou(strictFailureTestCases
[t
]);
1031 nFormat
->parse(testCase
, n
, status
);
1032 logln((UnicodeString
)"parse(" + testCase
+ ") = " + n
.getLong());
1034 if (U_FAILURE(status
) ||n
.getType() != Formattable::kLong
||
1035 n
.getLong() != 1000) {
1036 errln((UnicodeString
)"Lenient parse failed for \"" + (UnicodeString
) strictFailureTestCases
[t
] + (UnicodeString
) "\"");
1037 status
= U_ZERO_ERROR
;
1044 // -------------------------------------
1047 * Test proper rounding by the format method.
1050 NumberFormatTest::TestRounding487(void)
1052 UErrorCode status
= U_ZERO_ERROR
;
1053 NumberFormat
*nf
= NumberFormat::createInstance(status
);
1054 if (U_FAILURE(status
)) {
1055 dataerrln("Error calling NumberFormat::createInstance()");
1059 roundingTest(*nf
, 0.00159999, 4, "0.0016");
1060 roundingTest(*nf
, 0.00995, 4, "0.01");
1062 roundingTest(*nf
, 12.3995, 3, "12.4");
1064 roundingTest(*nf
, 12.4999, 0, "12");
1065 roundingTest(*nf
, - 19.5, 0, "-20");
1067 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
1071 * Test the functioning of the secondary grouping value.
1073 void NumberFormatTest::TestSecondaryGrouping(void) {
1074 UErrorCode status
= U_ZERO_ERROR
;
1075 DecimalFormatSymbols
US(Locale::getUS(), status
);
1076 CHECK(status
, "DecimalFormatSymbols ct");
1078 DecimalFormat
f("#,##,###", US
, status
);
1079 CHECK(status
, "DecimalFormat ct");
1081 expect2(f
, (int32_t)123456789L, "12,34,56,789");
1082 expectPat(f
, "#,##,###");
1083 f
.applyPattern("#,###", status
);
1084 CHECK(status
, "applyPattern");
1086 f
.setSecondaryGroupingSize(4);
1087 expect2(f
, (int32_t)123456789L, "12,3456,789");
1088 expectPat(f
, "#,####,###");
1089 NumberFormat
*g
= NumberFormat::createInstance(Locale("hi", "IN"), status
);
1090 CHECK(status
, "createInstance(hi_IN)");
1093 int32_t l
= (int32_t)1876543210L;
1096 // expect "1,87,65,43,210", but with Hindi digits
1099 if (out
.length() != 14) {
1102 for (int32_t i
=0; i
<out
.length(); ++i
) {
1103 UBool expectGroup
= FALSE
;
1112 // Later -- fix this to get the actual grouping
1113 // character from the resource bundle.
1114 UBool isGroup
= (out
.charAt(i
) == 0x002C);
1115 if (isGroup
!= expectGroup
) {
1122 errln((UnicodeString
)"FAIL Expected " + l
+
1123 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1124 escape(out
) + "\"");
1126 logln((UnicodeString
)"Ok " + l
+
1128 escape(out
) + "\"");
1132 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1133 UErrorCode ec
= U_ZERO_ERROR
;
1134 DecimalFormatSymbols
US(Locale::getUS(), ec
);
1135 DecimalFormat
fmt("a b#0c ", US
, ec
);
1136 if (U_FAILURE(ec
)) {
1137 errln("FAIL: Constructor");
1141 expect(fmt
, "a b1234c ", n
);
1142 expect(fmt
, "a b1234c ", n
);
1146 * Test currencies whose display name is a ChoiceFormat.
1147 * Less useful now that INR is no longer a choice format! See cldrbug 1961 !
1149 void NumberFormatTest::TestComplexCurrency() {
1150 UErrorCode ec
= U_ZERO_ERROR
;
1151 Locale
loc("kn", "IN", "");
1152 NumberFormat
* fmt
= NumberFormat::createCurrencyInstance(loc
, ec
);
1153 if (U_SUCCESS(ec
)) {
1154 expect2(*fmt
, 1.0, CharsToUnicodeString("Rs.\\u00A01.00"));
1155 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1156 expect(*fmt
, 1.00390625, CharsToUnicodeString("Rs.\\u00A01.00")); // tricky
1157 expect2(*fmt
, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1158 expect2(*fmt
, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1159 expect2(*fmt
, -1.0, CharsToUnicodeString("-Rs.\\u00A01.00"));
1160 expect2(*fmt
, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1162 errln("FAIL: getCurrencyInstance(kn_IN)");
1167 // -------------------------------------
1170 NumberFormatTest::roundingTest(NumberFormat
& nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
1172 nf
.setMaximumFractionDigits(maxFractionDigits
);
1173 UnicodeString out
; nf
.format(x
, out
);
1174 logln((UnicodeString
)"" + x
+ " formats with " + maxFractionDigits
+ " fractional digits to " + out
);
1175 if (!(out
==expected
)) errln((UnicodeString
)"FAIL: Expected " + expected
);
1179 * Upgrade to alphaWorks
1181 void NumberFormatTest::TestExponent(void) {
1182 UErrorCode status
= U_ZERO_ERROR
;
1183 DecimalFormatSymbols
US(Locale::getUS(), status
);
1184 CHECK(status
, "DecimalFormatSymbols constructor");
1185 DecimalFormat
fmt1(UnicodeString("0.###E0"), US
, status
);
1186 CHECK(status
, "DecimalFormat(0.###E0)");
1187 DecimalFormat
fmt2(UnicodeString("0.###E+0"), US
, status
);
1188 CHECK(status
, "DecimalFormat(0.###E+0)");
1190 expect2(fmt1
, n
, "1.234E3");
1191 expect2(fmt2
, n
, "1.234E+3");
1192 expect(fmt1
, "1.234E+3", n
); // Either format should parse "E+3"
1196 * Upgrade to alphaWorks
1198 void NumberFormatTest::TestScientific(void) {
1199 UErrorCode status
= U_ZERO_ERROR
;
1200 DecimalFormatSymbols
US(Locale::getUS(), status
);
1201 CHECK(status
, "DecimalFormatSymbols constructor");
1203 // Test pattern round-trip
1204 const char* PAT
[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1205 "0.###E0;[0.###E0]" };
1206 int32_t PAT_length
= (int32_t)(sizeof(PAT
) / sizeof(PAT
[0]));
1207 int32_t DIGITS
[] = {
1208 // min int, max int, min frac, max frac
1209 0, 1, 0, 0, // "#E0"
1210 1, 1, 0, 4, // "0.####E0"
1211 2, 2, 3, 3, // "00.000E00"
1212 1, 3, 0, 4, // "##0.####E000"
1213 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1215 for (int32_t i
=0; i
<PAT_length
; ++i
) {
1216 UnicodeString
pat(PAT
[i
]);
1217 DecimalFormat
df(pat
, US
, status
);
1218 CHECK(status
, "DecimalFormat constructor");
1222 logln(UnicodeString("Ok Pattern rt \"") +
1226 errln(UnicodeString("FAIL Pattern rt \"") +
1230 // Make sure digit counts match what we expect
1231 if (df
.getMinimumIntegerDigits() != DIGITS
[4*i
] ||
1232 df
.getMaximumIntegerDigits() != DIGITS
[4*i
+1] ||
1233 df
.getMinimumFractionDigits() != DIGITS
[4*i
+2] ||
1234 df
.getMaximumFractionDigits() != DIGITS
[4*i
+3]) {
1235 errln(UnicodeString("FAIL \"" + pat
+
1236 "\" min/max int; min/max frac = ") +
1237 df
.getMinimumIntegerDigits() + "/" +
1238 df
.getMaximumIntegerDigits() + ";" +
1239 df
.getMinimumFractionDigits() + "/" +
1240 df
.getMaximumFractionDigits() + ", expect " +
1242 DIGITS
[4*i
+1] + ";" +
1243 DIGITS
[4*i
+2] + "/" +
1249 // Test the constructor for default locale. We have to
1250 // manually set the default locale, as there is no
1251 // guarantee that the default locale has the same
1252 // scientific format.
1253 Locale def
= Locale::getDefault();
1254 Locale::setDefault(Locale::getUS(), status
);
1255 expect2(NumberFormat::createScientificInstance(status
),
1257 "1.2345678901E4", status
);
1258 Locale::setDefault(def
, status
);
1260 expect2(new DecimalFormat("#E0", US
, status
),
1262 "1.2345E4", status
);
1263 expect(new DecimalFormat("0E0", US
, status
),
1266 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status
),
1268 "1.2345678901E4", status
);
1269 expect(new DecimalFormat("##0.###E0", US
, status
),
1272 expect(new DecimalFormat("##0.###E0", US
, status
),
1275 expect2(new DecimalFormat("##0.####E0", US
, status
),
1277 "12.345E3", status
);
1278 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status
),
1280 "1,2345678901E4", status
);
1281 expect(new DecimalFormat("##0.####E0", US
, status
),
1283 "789.12E-9", status
);
1284 expect2(new DecimalFormat("##0.####E0", US
, status
),
1287 expect(new DecimalFormat(".###E0", US
, status
),
1290 expect2(new DecimalFormat(".###E0", US
, status
),
1294 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1295 new DecimalFormat("##E0", US),
1296 new DecimalFormat("####E0", US),
1297 new DecimalFormat("0E0", US),
1298 new DecimalFormat("00E0", US),
1299 new DecimalFormat("000E0", US),
1302 new String[] { "4.5678E7",
1311 ! Unroll this test into individual tests below...
1314 expect2(new DecimalFormat("#E0", US
, status
),
1315 (int32_t) 45678000, "4.5678E7", status
);
1316 expect2(new DecimalFormat("##E0", US
, status
),
1317 (int32_t) 45678000, "45.678E6", status
);
1318 expect2(new DecimalFormat("####E0", US
, status
),
1319 (int32_t) 45678000, "4567.8E4", status
);
1320 expect(new DecimalFormat("0E0", US
, status
),
1321 (int32_t) 45678000, "5E7", status
);
1322 expect(new DecimalFormat("00E0", US
, status
),
1323 (int32_t) 45678000, "46E6", status
);
1324 expect(new DecimalFormat("000E0", US
, status
),
1325 (int32_t) 45678000, "457E5", status
);
1327 expect(new DecimalFormat("###E0", US, status),
1328 new Object[] { new Double(0.0000123), "12.3E-6",
1329 new Double(0.000123), "123E-6",
1330 new Double(0.00123), "1.23E-3",
1331 new Double(0.0123), "12.3E-3",
1332 new Double(0.123), "123E-3",
1333 new Double(1.23), "1.23E0",
1334 new Double(12.3), "12.3E0",
1335 new Double(123), "123E0",
1336 new Double(1230), "1.23E3",
1339 ! Unroll this test into individual tests below...
1342 expect2(new DecimalFormat("###E0", US
, status
),
1343 0.0000123, "12.3E-6", status
);
1344 expect2(new DecimalFormat("###E0", US
, status
),
1345 0.000123, "123E-6", status
);
1346 expect2(new DecimalFormat("###E0", US
, status
),
1347 0.00123, "1.23E-3", status
);
1348 expect2(new DecimalFormat("###E0", US
, status
),
1349 0.0123, "12.3E-3", status
);
1350 expect2(new DecimalFormat("###E0", US
, status
),
1351 0.123, "123E-3", status
);
1352 expect2(new DecimalFormat("###E0", US
, status
),
1353 1.23, "1.23E0", status
);
1354 expect2(new DecimalFormat("###E0", US
, status
),
1355 12.3, "12.3E0", status
);
1356 expect2(new DecimalFormat("###E0", US
, status
),
1357 123.0, "123E0", status
);
1358 expect2(new DecimalFormat("###E0", US
, status
),
1359 1230.0, "1.23E3", status
);
1361 expect(new DecimalFormat("0.#E+00", US, status),
1362 new Object[] { new Double(0.00012), "1.2E-04",
1363 new Long(12000), "1.2E+04",
1366 ! Unroll this test into individual tests below...
1369 expect2(new DecimalFormat("0.#E+00", US
, status
),
1370 0.00012, "1.2E-04", status
);
1371 expect2(new DecimalFormat("0.#E+00", US
, status
),
1372 (int32_t) 12000, "1.2E+04", status
);
1376 * Upgrade to alphaWorks
1378 void NumberFormatTest::TestPad(void) {
1379 UErrorCode status
= U_ZERO_ERROR
;
1380 DecimalFormatSymbols
US(Locale::getUS(), status
);
1381 CHECK(status
, "DecimalFormatSymbols constructor");
1383 expect2(new DecimalFormat("*^##.##", US
, status
),
1384 int32_t(0), "^^^^0", status
);
1385 expect2(new DecimalFormat("*^##.##", US
, status
),
1386 -1.3, "^-1.3", status
);
1387 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1388 int32_t(0), "0.0E0______ g-m/s^2", status
);
1389 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1390 1.0/3, "333.333E-3_ g-m/s^2", status
);
1391 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1392 int32_t(0), "0.0______ g-m/s^2", status
);
1393 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1394 1.0/3, "0.33333__ g-m/s^2", status
);
1396 // Test padding before a sign
1397 const char *formatStr
= "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1398 expect2(new DecimalFormat(formatStr
, US
, status
),
1399 int32_t(-10), "xxxxxxxxxx(10.0)", status
);
1400 expect2(new DecimalFormat(formatStr
, US
, status
),
1401 int32_t(-1000),"xxxxxxx(1,000.0)", status
);
1402 expect2(new DecimalFormat(formatStr
, US
, status
),
1403 int32_t(-1000000),"xxx(1,000,000.0)", status
);
1404 expect2(new DecimalFormat(formatStr
, US
, status
),
1405 -100.37, "xxxxxxxx(100.37)", status
);
1406 expect2(new DecimalFormat(formatStr
, US
, status
),
1407 -10456.37, "xxxxx(10,456.37)", status
);
1408 expect2(new DecimalFormat(formatStr
, US
, status
),
1409 -1120456.37, "xx(1,120,456.37)", status
);
1410 expect2(new DecimalFormat(formatStr
, US
, status
),
1411 -112045600.37, "(112,045,600.37)", status
);
1412 expect2(new DecimalFormat(formatStr
, US
, status
),
1413 -1252045600.37,"(1,252,045,600.37)", status
);
1415 expect2(new DecimalFormat(formatStr
, US
, status
),
1416 int32_t(10), "xxxxxxxxxxxx10.0", status
);
1417 expect2(new DecimalFormat(formatStr
, US
, status
),
1418 int32_t(1000),"xxxxxxxxx1,000.0", status
);
1419 expect2(new DecimalFormat(formatStr
, US
, status
),
1420 int32_t(1000000),"xxxxx1,000,000.0", status
);
1421 expect2(new DecimalFormat(formatStr
, US
, status
),
1422 100.37, "xxxxxxxxxx100.37", status
);
1423 expect2(new DecimalFormat(formatStr
, US
, status
),
1424 10456.37, "xxxxxxx10,456.37", status
);
1425 expect2(new DecimalFormat(formatStr
, US
, status
),
1426 1120456.37, "xxxx1,120,456.37", status
);
1427 expect2(new DecimalFormat(formatStr
, US
, status
),
1428 112045600.37, "xx112,045,600.37", status
);
1429 expect2(new DecimalFormat(formatStr
, US
, status
),
1430 10252045600.37,"10,252,045,600.37", status
);
1433 // Test padding between a sign and a number
1434 const char *formatStr2
= "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1435 expect2(new DecimalFormat(formatStr2
, US
, status
),
1436 int32_t(-10), "(10.0xxxxxxxxxx)", status
);
1437 expect2(new DecimalFormat(formatStr2
, US
, status
),
1438 int32_t(-1000),"(1,000.0xxxxxxx)", status
);
1439 expect2(new DecimalFormat(formatStr2
, US
, status
),
1440 int32_t(-1000000),"(1,000,000.0xxx)", status
);
1441 expect2(new DecimalFormat(formatStr2
, US
, status
),
1442 -100.37, "(100.37xxxxxxxx)", status
);
1443 expect2(new DecimalFormat(formatStr2
, US
, status
),
1444 -10456.37, "(10,456.37xxxxx)", status
);
1445 expect2(new DecimalFormat(formatStr2
, US
, status
),
1446 -1120456.37, "(1,120,456.37xx)", status
);
1447 expect2(new DecimalFormat(formatStr2
, US
, status
),
1448 -112045600.37, "(112,045,600.37)", status
);
1449 expect2(new DecimalFormat(formatStr2
, US
, status
),
1450 -1252045600.37,"(1,252,045,600.37)", status
);
1452 expect2(new DecimalFormat(formatStr2
, US
, status
),
1453 int32_t(10), "10.0xxxxxxxxxxxx", status
);
1454 expect2(new DecimalFormat(formatStr2
, US
, status
),
1455 int32_t(1000),"1,000.0xxxxxxxxx", status
);
1456 expect2(new DecimalFormat(formatStr2
, US
, status
),
1457 int32_t(1000000),"1,000,000.0xxxxx", status
);
1458 expect2(new DecimalFormat(formatStr2
, US
, status
),
1459 100.37, "100.37xxxxxxxxxx", status
);
1460 expect2(new DecimalFormat(formatStr2
, US
, status
),
1461 10456.37, "10,456.37xxxxxxx", status
);
1462 expect2(new DecimalFormat(formatStr2
, US
, status
),
1463 1120456.37, "1,120,456.37xxxx", status
);
1464 expect2(new DecimalFormat(formatStr2
, US
, status
),
1465 112045600.37, "112,045,600.37xx", status
);
1466 expect2(new DecimalFormat(formatStr2
, US
, status
),
1467 10252045600.37,"10,252,045,600.37", status
);
1469 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1470 DecimalFormat
fmt("#", US
, status
);
1471 CHECK(status
, "DecimalFormat constructor");
1472 UnicodeString
padString("P");
1473 fmt
.setPadCharacter(padString
);
1474 expectPad(fmt
, "*P##.##", DecimalFormat::kPadBeforePrefix
, 5, padString
);
1475 fmt
.setPadCharacter((UnicodeString
)"^");
1476 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, (UnicodeString
)"^");
1477 //commented untill implementation is complete
1478 /* fmt.setPadCharacter((UnicodeString)"^^^");
1479 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1481 padString.append((UChar)0x0061);
1482 padString.append((UChar)0x0302);
1483 fmt.setPadCharacter(padString);
1484 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1485 UnicodeString pattern(patternChars);
1486 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1492 * Upgrade to alphaWorks
1494 void NumberFormatTest::TestPatterns2(void) {
1495 UErrorCode status
= U_ZERO_ERROR
;
1496 DecimalFormatSymbols
US(Locale::getUS(), status
);
1497 CHECK(status
, "DecimalFormatSymbols constructor");
1499 DecimalFormat
fmt("#", US
, status
);
1500 CHECK(status
, "DecimalFormat constructor");
1502 UChar hat
= 0x005E; /*^*/
1504 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, hat
);
1505 expectPad(fmt
, "$*^#", DecimalFormat::kPadAfterPrefix
, 2, hat
);
1506 expectPad(fmt
, "#*^", DecimalFormat::kPadBeforeSuffix
, 1, hat
);
1507 expectPad(fmt
, "#$*^", DecimalFormat::kPadAfterSuffix
, 2, hat
);
1508 expectPad(fmt
, "$*^$#", ILLEGAL
);
1509 expectPad(fmt
, "#$*^$", ILLEGAL
);
1510 expectPad(fmt
, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix
,
1511 12, (UChar
)0x0078 /*x*/);
1512 expectPad(fmt
, "''#0*x", DecimalFormat::kPadBeforeSuffix
,
1513 3, (UChar
)0x0078 /*x*/);
1514 expectPad(fmt
, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix
,
1515 10, (UChar
)0x0061 /*a*/);
1517 fmt
.applyPattern("AA#,##0.00ZZ", status
);
1518 CHECK(status
, "applyPattern");
1519 fmt
.setPadCharacter(hat
);
1521 fmt
.setFormatWidth(10);
1523 fmt
.setPadPosition(DecimalFormat::kPadBeforePrefix
);
1524 expectPat(fmt
, "*^AA#,##0.00ZZ");
1526 fmt
.setPadPosition(DecimalFormat::kPadBeforeSuffix
);
1527 expectPat(fmt
, "AA#,##0.00*^ZZ");
1529 fmt
.setPadPosition(DecimalFormat::kPadAfterSuffix
);
1530 expectPat(fmt
, "AA#,##0.00ZZ*^");
1533 UnicodeString
exp("AA*^#,##0.00ZZ", "");
1534 fmt
.setFormatWidth(12);
1535 fmt
.setPadPosition(DecimalFormat::kPadAfterPrefix
);
1536 expectPat(fmt
, exp
);
1538 fmt
.setFormatWidth(13);
1540 expectPat(fmt
, "AA*^##,##0.00ZZ");
1542 fmt
.setFormatWidth(14);
1544 expectPat(fmt
, "AA*^###,##0.00ZZ");
1546 fmt
.setFormatWidth(15);
1548 expectPat(fmt
, "AA*^####,##0.00ZZ"); // This is the interesting case
1550 fmt
.setFormatWidth(16);
1551 // 12 34567890123456
1552 expectPat(fmt
, "AA*^#,###,##0.00ZZ");
1555 void NumberFormatTest::TestSurrogateSupport(void) {
1556 UErrorCode status
= U_ZERO_ERROR
;
1557 DecimalFormatSymbols
custom(Locale::getUS(), status
);
1558 CHECK(status
, "DecimalFormatSymbols constructor");
1560 custom
.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, "decimal");
1561 custom
.setSymbol(DecimalFormatSymbols::kPlusSignSymbol
, "plus");
1562 custom
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, " minus ");
1563 custom
.setSymbol(DecimalFormatSymbols::kExponentialSymbol
, "exponent");
1565 UnicodeString
patternStr("*\\U00010000##.##", "");
1566 patternStr
= patternStr
.unescape();
1567 UnicodeString
expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1568 expStr
= expStr
.unescape();
1569 expect2(new DecimalFormat(patternStr
, custom
, status
),
1570 int32_t(0), expStr
, status
);
1572 status
= U_ZERO_ERROR
;
1573 expect2(new DecimalFormat("*^##.##", custom
, status
),
1574 int32_t(0), "^^^^0", status
);
1575 status
= U_ZERO_ERROR
;
1576 expect2(new DecimalFormat("##.##", custom
, status
),
1577 -1.3, " minus 1decimal3", status
);
1578 status
= U_ZERO_ERROR
;
1579 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1580 int32_t(0), "0decimal0exponent0 g-m/s^2", status
);
1581 status
= U_ZERO_ERROR
;
1582 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1583 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status
);
1584 status
= U_ZERO_ERROR
;
1585 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1586 int32_t(0), "0decimal0 g-m/s^2", status
);
1587 status
= U_ZERO_ERROR
;
1588 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1589 1.0/3, "0decimal33333 g-m/s^2", status
);
1591 UnicodeString
zero((UChar32
)0x10000);
1592 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, zero
);
1593 expStr
= UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1594 expStr
= expStr
.unescape();
1595 status
= U_ZERO_ERROR
;
1596 expect2(new DecimalFormat("##0.000", custom
, status
),
1597 1.25, expStr
, status
);
1599 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, (UChar
)0x30);
1600 custom
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "units of money");
1601 custom
.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, "money separator");
1602 patternStr
= UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1603 patternStr
= patternStr
.unescape();
1604 expStr
= UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1605 status
= U_ZERO_ERROR
;
1606 expect2(new DecimalFormat(patternStr
, custom
, status
),
1607 int32_t(-20), expStr
, status
);
1609 custom
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, "percent");
1610 patternStr
= "'You''ve lost ' -0.00 %' of your money today'";
1611 patternStr
= patternStr
.unescape();
1612 expStr
= UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1613 status
= U_ZERO_ERROR
;
1614 expect2(new DecimalFormat(patternStr
, custom
, status
),
1615 int32_t(-20), expStr
, status
);
1618 void NumberFormatTest::TestCurrencyPatterns(void) {
1619 int32_t i
, locCount
;
1620 const Locale
* locs
= NumberFormat::getAvailableLocales(locCount
);
1621 for (i
=0; i
<locCount
; ++i
) {
1622 UErrorCode ec
= U_ZERO_ERROR
;
1623 NumberFormat
* nf
= NumberFormat::createCurrencyInstance(locs
[i
], ec
);
1624 if (U_FAILURE(ec
)) {
1625 errln("FAIL: Can't create NumberFormat(%s) - %s", locs
[i
].getName(), u_errorName(ec
));
1627 // Make sure currency formats do not have a variable number
1628 // of fraction digits
1629 int32_t min
= nf
->getMinimumFractionDigits();
1630 int32_t max
= nf
->getMaximumFractionDigits();
1634 nf
->format(1.125, b
);
1635 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1636 " min fraction digits != max fraction digits; "
1637 "x 1.0 => " + escape(a
) +
1638 "; x 1.125 => " + escape(b
));
1641 // Make sure EURO currency formats have exactly 2 fraction digits
1642 if (nf
->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1643 DecimalFormat
* df
= (DecimalFormat
*) nf
;
1644 if (u_strcmp(EUR
, df
->getCurrency()) == 0) {
1645 if (min
!= 2 || max
!= 2) {
1648 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1649 " is a EURO format but it does not have 2 fraction digits; "
1660 void NumberFormatTest::TestRegCurrency(void) {
1661 #if !UCONFIG_NO_SERVICE
1662 UErrorCode status
= U_ZERO_ERROR
;
1664 ucurr_forLocale("en_US", USD
, 4, &status
);
1666 ucurr_forLocale("ja_JP", YEN
, 4, &status
);
1668 static const UChar QQQ
[] = {0x51, 0x51, 0x51, 0};
1669 if(U_FAILURE(status
)) {
1670 errln("Unable to get currency for locale, error %s", u_errorName(status
));
1674 UCurrRegistryKey enkey
= ucurr_register(YEN
, "en_US", &status
);
1675 UCurrRegistryKey enUSEUROkey
= ucurr_register(QQQ
, "en_US_EURO", &status
);
1677 ucurr_forLocale("en_US", TMP
, 4, &status
);
1678 if (u_strcmp(YEN
, TMP
) != 0) {
1679 errln("FAIL: didn't return YEN registered for en_US");
1682 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1683 if (u_strcmp(QQQ
, TMP
) != 0) {
1684 errln("FAIL: didn't return QQQ for en_US_EURO");
1687 int32_t fallbackLen
= ucurr_forLocale("en_XX_BAR", TMP
, 4, &status
);
1689 errln("FAIL: tried to fallback en_XX_BAR");
1691 status
= U_ZERO_ERROR
; // reset
1693 if (!ucurr_unregister(enkey
, &status
)) {
1694 errln("FAIL: couldn't unregister enkey");
1697 ucurr_forLocale("en_US", TMP
, 4, &status
);
1698 if (u_strcmp(USD
, TMP
) != 0) {
1699 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1701 status
= U_ZERO_ERROR
; // reset
1703 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1704 if (u_strcmp(QQQ
, TMP
) != 0) {
1705 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1708 ucurr_forLocale("en_US_BLAH", TMP
, 4, &status
);
1709 if (u_strcmp(USD
, TMP
) != 0) {
1710 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1712 status
= U_ZERO_ERROR
; // reset
1714 if (!ucurr_unregister(enUSEUROkey
, &status
)) {
1715 errln("FAIL: couldn't unregister enUSEUROkey");
1718 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1719 if (u_strcmp(EUR
, TMP
) != 0) {
1720 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1722 status
= U_ZERO_ERROR
; // reset
1726 void NumberFormatTest::TestCurrencyNames(void) {
1727 // Do a basic check of getName()
1728 // USD { "US$", "US Dollar" } // 04/04/1792-
1729 UErrorCode ec
= U_ZERO_ERROR
;
1730 static const UChar USD
[] = {0x55, 0x53, 0x44, 0}; /*USD*/
1731 static const UChar USX
[] = {0x55, 0x53, 0x58, 0}; /*USX*/
1732 static const UChar CAD
[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
1733 static const UChar ITL
[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
1734 UBool isChoiceFormat
;
1736 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1737 // THE LOCALE DATA before diving into the code.
1738 assertEquals("USD.getName(SYMBOL_NAME)",
1740 UnicodeString(ucurr_getName(USD
, "en",
1742 &isChoiceFormat
, &len
, &ec
)));
1743 assertEquals("USD.getName(LONG_NAME)",
1744 UnicodeString("US Dollar"),
1745 UnicodeString(ucurr_getName(USD
, "en",
1747 &isChoiceFormat
, &len
, &ec
)));
1748 assertEquals("CAD.getName(SYMBOL_NAME)",
1749 UnicodeString("CA$"),
1750 UnicodeString(ucurr_getName(CAD
, "en",
1752 &isChoiceFormat
, &len
, &ec
)));
1753 assertEquals("CAD.getName(SYMBOL_NAME)",
1755 UnicodeString(ucurr_getName(CAD
, "en_CA",
1757 &isChoiceFormat
, &len
, &ec
)));
1758 assertEquals("USD.getName(SYMBOL_NAME)",
1759 UnicodeString("US$"),
1760 UnicodeString(ucurr_getName(USD
, "en_AU",
1762 &isChoiceFormat
, &len
, &ec
)));
1763 assertEquals("CAD.getName(SYMBOL_NAME)",
1764 UnicodeString("CA$"),
1765 UnicodeString(ucurr_getName(CAD
, "en_AU",
1767 &isChoiceFormat
, &len
, &ec
)));
1768 assertEquals("USX.getName(LONG_NAME)",
1769 UnicodeString("USX"),
1770 UnicodeString(ucurr_getName(USX
, "en_US",
1772 &isChoiceFormat
, &len
, &ec
)));
1773 assertSuccess("ucurr_getName", ec
);
1777 // Test that a default or fallback warning is being returned. JB 4239.
1778 ucurr_getName(CAD
, "es_ES", UCURR_LONG_NAME
, &isChoiceFormat
,
1780 assertTrue("ucurr_getName (fallback)",
1781 U_USING_FALLBACK_WARNING
== ec
, TRUE
);
1783 ucurr_getName(CAD
, "zh_TW", UCURR_LONG_NAME
, &isChoiceFormat
,
1785 assertTrue("ucurr_getName (fallback)",
1786 U_USING_FALLBACK_WARNING
== ec
, TRUE
);
1788 ucurr_getName(CAD
, "en_US", UCURR_LONG_NAME
, &isChoiceFormat
,
1790 assertTrue("ucurr_getName (default)",
1791 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1793 ucurr_getName(CAD
, "vi", UCURR_LONG_NAME
, &isChoiceFormat
,
1795 assertTrue("ucurr_getName (default)",
1796 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1798 // Test that a default warning is being returned when falling back to root. JB 4536.
1799 ucurr_getName(ITL
, "cy", UCURR_LONG_NAME
, &isChoiceFormat
,
1801 assertTrue("ucurr_getName (default to root)",
1802 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1804 // TODO add more tests later
1807 void NumberFormatTest::TestCurrencyUnit(void){
1808 UErrorCode ec
= U_ZERO_ERROR
;
1809 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1810 CurrencyUnit
cu(USD
, ec
);
1811 assertSuccess("CurrencyUnit", ec
);
1813 const UChar
* r
= cu
.getISOCurrency(); // who is the buffer owner ?
1814 assertEquals("getISOCurrency()", USD
, r
);
1816 CurrencyUnit
cu2(cu
);
1818 errln("CurrencyUnit copy constructed object should be same");
1821 CurrencyUnit
* cu3
= (CurrencyUnit
*)cu
.clone();
1823 errln("CurrencyUnit cloned object should be same");
1828 void NumberFormatTest::TestCurrencyAmount(void){
1829 UErrorCode ec
= U_ZERO_ERROR
;
1830 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1831 CurrencyAmount
ca(9, USD
, ec
);
1832 assertSuccess("CurrencyAmount", ec
);
1834 CurrencyAmount
ca2(ca
);
1836 errln("CurrencyAmount copy constructed object should be same");
1841 errln("CurrencyAmount assigned object should be same");
1844 CurrencyAmount
*ca3
= (CurrencyAmount
*)ca
.clone();
1846 errln("CurrencyAmount cloned object should be same");
1851 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1853 Locale
locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1854 UErrorCode status
= U_ZERO_ERROR
;
1855 UnicodeString
intlCurrencySymbol((UChar
)0xa4);
1857 intlCurrencySymbol
.append((UChar
)0xa4);
1859 logln("Current locale is %s", Locale::getDefault().getName());
1860 Locale::setDefault(locBad
, status
);
1861 logln("Current locale is %s", Locale::getDefault().getName());
1862 DecimalFormatSymbols
mySymbols(status
);
1863 if (status
!= U_USING_FALLBACK_WARNING
) {
1864 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1866 if (strcmp(mySymbols
.getLocale().getName(), locBad
.getName()) != 0) {
1867 errln("DecimalFormatSymbols does not have the right locale.");
1869 int symbolEnum
= (int)DecimalFormatSymbols::kDecimalSeparatorSymbol
;
1870 for (; symbolEnum
< (int)DecimalFormatSymbols::kFormatSymbolCount
; symbolEnum
++) {
1871 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum
+ UnicodeString("] = ")
1872 + prettify(mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
)));
1874 if (mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
).length() == 0
1875 && symbolEnum
!= (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
1876 && symbolEnum
!= (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
)
1878 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum
);
1881 status
= U_ZERO_ERROR
;
1882 Locale::setDefault(locDefault
, status
);
1883 logln("Current locale is %s", Locale::getDefault().getName());
1887 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1888 * behave the same, except for memory ownership semantics. (No
1889 * version of this test on Java, since Java has only one method.)
1891 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1892 UErrorCode ec
= U_ZERO_ERROR
;
1893 DecimalFormatSymbols
*sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1894 if (U_FAILURE(ec
)) {
1895 errln("Fail: DecimalFormatSymbols constructor");
1899 UnicodeString
pat(" #,##0.00");
1900 pat
.insert(0, (UChar
)0x00A4);
1901 DecimalFormat
fmt(pat
, sym
, ec
);
1902 if (U_FAILURE(ec
)) {
1903 errln("Fail: DecimalFormat constructor");
1908 fmt
.format(2350.75, str
);
1909 if (str
== "$ 2,350.75") {
1912 errln("Fail: " + str
+ ", expected $ 2,350.75");
1915 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1916 if (U_FAILURE(ec
)) {
1917 errln("Fail: DecimalFormatSymbols constructor");
1921 sym
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1922 fmt
.adoptDecimalFormatSymbols(sym
);
1925 fmt
.format(2350.75, str
);
1926 if (str
== "Q 2,350.75") {
1929 errln("Fail: adoptDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1932 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1933 if (U_FAILURE(ec
)) {
1934 errln("Fail: DecimalFormatSymbols constructor");
1938 DecimalFormat
fmt2(pat
, sym
, ec
);
1939 if (U_FAILURE(ec
)) {
1940 errln("Fail: DecimalFormat constructor");
1944 DecimalFormatSymbols
sym2(Locale::getUS(), ec
);
1945 if (U_FAILURE(ec
)) {
1946 errln("Fail: DecimalFormatSymbols constructor");
1949 sym2
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1950 fmt2
.setDecimalFormatSymbols(sym2
);
1953 fmt2
.format(2350.75, str
);
1954 if (str
== "Q 2,350.75") {
1957 errln("Fail: setDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1961 void NumberFormatTest::TestPerMill() {
1962 UErrorCode ec
= U_ZERO_ERROR
;
1964 DecimalFormat
fmt(ctou("###.###\\u2030"), ec
);
1965 if (!assertSuccess("DecimalFormat ct", ec
)) return;
1966 assertEquals("0.4857 x ###.###\\u2030",
1967 ctou("485.7\\u2030"), fmt
.format(0.4857, str
));
1969 DecimalFormatSymbols
sym(Locale::getUS(), ec
);
1970 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, ctou("m"));
1971 DecimalFormat
fmt2("", sym
, ec
);
1972 fmt2
.applyLocalizedPattern("###.###m", ec
);
1973 if (!assertSuccess("setup", ec
)) return;
1975 assertEquals("0.4857 x ###.###m",
1976 "485.7m", fmt2
.format(0.4857, str
));
1980 * Generic test for patterns that should be legal/illegal.
1982 void NumberFormatTest::TestIllegalPatterns() {
1984 // Prefix with "-:" for illegal patterns
1985 // Prefix with "+:" for legal patterns
1986 const char* DATA
[] = {
1987 // Unquoted special characters in the suffix are illegal
1992 for (int32_t i
=0; DATA
[i
]; ++i
) {
1993 const char* pat
=DATA
[i
];
1994 UBool valid
= (*pat
) == '+';
1996 UErrorCode ec
= U_ZERO_ERROR
;
1997 DecimalFormat
fmt(pat
, ec
); // locale doesn't matter here
1998 if (U_SUCCESS(ec
) == valid
) {
1999 logln("Ok: pattern \"%s\": %s",
2000 pat
, u_errorName(ec
));
2002 errln("FAIL: pattern \"%s\" should have %s; got %s",
2003 pat
, (valid
?"succeeded":"failed"),
2009 //----------------------------------------------------------------------
2011 static const char* KEYWORDS
[] = {
2012 /*0*/ "ref=", // <reference pattern to parse numbers>
2013 /*1*/ "loc=", // <locale for formats>
2014 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2015 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2016 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2017 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2018 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2019 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2020 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2025 * Return an integer representing the next token from this
2026 * iterator. The integer will be an index into the given list, or
2027 * -1 if there are no more tokens, or -2 if the token is not on
2030 static int32_t keywordIndex(const UnicodeString
& tok
) {
2031 for (int32_t i
=0; KEYWORDS
[i
]!=0; ++i
) {
2032 if (tok
==KEYWORDS
[i
]) {
2040 * Parse a CurrencyAmount using the given NumberFormat, with
2041 * the 'delim' character separating the number and the currency.
2043 static void parseCurrencyAmount(const UnicodeString
& str
,
2044 const NumberFormat
& fmt
,
2046 Formattable
& result
,
2048 UnicodeString num
, cur
;
2049 int32_t i
= str
.indexOf(delim
);
2050 str
.extractBetween(0, i
, num
);
2051 str
.extractBetween(i
+1, INT32_MAX
, cur
);
2053 fmt
.parse(num
, n
, ec
);
2054 result
.adoptObject(new CurrencyAmount(n
, cur
.getTerminatedBuffer(), ec
));
2057 void NumberFormatTest::TestCases() {
2058 UErrorCode ec
= U_ZERO_ERROR
;
2059 TextFile
reader("NumberFormatTestCases.txt", "UTF8", ec
);
2060 if (U_FAILURE(ec
)) {
2061 dataerrln("[DATA] Couldn't open NumberFormatTestCases.txt");
2064 TokenIterator
tokens(&reader
);
2066 Locale
loc("en", "US", "");
2067 DecimalFormat
*ref
= 0, *fmt
= 0;
2068 MeasureFormat
*mfmt
= 0;
2069 UnicodeString pat
, tok
, mloc
, str
, out
, where
, currAmt
;
2074 if (!tokens
.next(tok
, ec
)) {
2077 where
= UnicodeString("(") + tokens
.getLineNumber() + ") ";
2078 int32_t cmd
= keywordIndex(tok
);
2081 // ref= <reference pattern>
2082 if (!tokens
.next(tok
, ec
)) goto error
;
2084 ref
= new DecimalFormat(tok
,
2085 new DecimalFormatSymbols(Locale::getUS(), ec
), ec
);
2086 if (U_FAILURE(ec
)) {
2087 dataerrln("Error constructing DecimalFormat");
2093 if (!tokens
.next(tok
, ec
)) goto error
;
2094 loc
= Locale::createFromName(CharString(tok
));
2100 if (!tokens
.next(tok
, ec
)) goto error
;
2104 fmt
= new DecimalFormat(pat
, new DecimalFormatSymbols(loc
, ec
), ec
);
2105 if (U_FAILURE(ec
)) {
2106 errln("FAIL: " + where
+ "Pattern \"" + pat
+ "\": " + u_errorName(ec
));
2108 if (!tokens
.next(tok
, ec
)) goto error
;
2109 if (!tokens
.next(tok
, ec
)) goto error
;
2111 if (!tokens
.next(tok
, ec
)) goto error
;
2116 if (cmd
== 2 || cmd
== 3 || cmd
== 4) {
2117 // f: <pattern or '-'> <number> <exp. string>
2118 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2119 // rt: <pattern or '-'> <number> <string>
2121 if (!tokens
.next(num
, ec
)) goto error
;
2122 if (!tokens
.next(str
, ec
)) goto error
;
2123 ref
->parse(num
, n
, ec
);
2124 assertSuccess("parse", ec
);
2125 assertEquals(where
+ "\"" + pat
+ "\".format(" + num
+ ")",
2126 str
, fmt
->format(n
, out
.remove(), ec
));
2127 assertSuccess("format", ec
);
2128 if (cmd
== 3) { // fp:
2129 if (!tokens
.next(num
, ec
)) goto error
;
2130 ref
->parse(num
, n
, ec
);
2131 assertSuccess("parse", ec
);
2133 if (cmd
!= 2) { // != f:
2135 fmt
->parse(str
, m
, ec
);
2136 assertSuccess("parse", ec
);
2137 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
2141 // p: <pattern or '-'> <string to parse> <exp. number>
2143 UnicodeString expstr
;
2144 if (!tokens
.next(str
, ec
)) goto error
;
2145 if (!tokens
.next(expstr
, ec
)) goto error
;
2147 ref
->parse(expstr
, exp
, ec
);
2148 assertSuccess("parse", ec
);
2149 fmt
->parse(str
, n
, ec
);
2150 assertSuccess("parse", ec
);
2151 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
2156 if (!tokens
.next(tok
, ec
)) goto error
;
2160 mfmt
= MeasureFormat::createCurrencyFormat(
2161 Locale::createFromName(CharString(mloc
)), ec
);
2162 if (U_FAILURE(ec
)) {
2163 errln("FAIL: " + where
+ "Loc \"" + mloc
+ "\": " + u_errorName(ec
));
2165 if (!tokens
.next(tok
, ec
)) goto error
;
2166 if (!tokens
.next(tok
, ec
)) goto error
;
2167 if (!tokens
.next(tok
, ec
)) goto error
;
2171 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2172 if (!tokens
.next(currAmt
, ec
)) goto error
;
2173 if (!tokens
.next(str
, ec
)) goto error
;
2174 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
2175 if (assertSuccess("parseCurrencyAmount", ec
)) {
2176 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").format(" + currAmt
+ ")",
2177 str
, mfmt
->format(n
, out
.remove(), ec
));
2178 assertSuccess("format", ec
);
2180 if (!tokens
.next(currAmt
, ec
)) goto error
;
2181 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
2182 if (assertSuccess("parseCurrencyAmount", ec
)) {
2184 mfmt
->parseObject(str
, m
, ec
);
2185 if (assertSuccess("parseCurrency", ec
)) {
2186 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").parse(\"" + str
+ "\")",
2192 // perr: <pattern or '-'> <invalid string>
2193 errln("FAIL: Under construction");
2196 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2197 UnicodeString testpat
;
2198 UnicodeString exppat
;
2199 if (!tokens
.next(testpat
, ec
)) goto error
;
2200 if (!tokens
.next(exppat
, ec
)) goto error
;
2201 UBool err
= exppat
== "err";
2202 UBool existingPat
= FALSE
;
2203 if (testpat
== "-") {
2205 errln("FAIL: " + where
+ "Invalid command \"pat: - err\"");
2211 if (exppat
== "-") exppat
= testpat
;
2212 DecimalFormat
* f
= 0;
2213 UErrorCode ec2
= U_ZERO_ERROR
;
2217 f
= new DecimalFormat(testpat
, ec2
);
2219 if (U_SUCCESS(ec2
)) {
2221 errln("FAIL: " + where
+ "Invalid pattern \"" + testpat
+
2225 assertEquals(where
+ "\"" + testpat
+ "\".toPattern()",
2226 exppat
, f
->toPattern(pat2
));
2230 logln("Ok: " + where
+ "Invalid pattern \"" + testpat
+
2231 "\" failed: " + u_errorName(ec2
));
2233 errln("FAIL: " + where
+ "Valid pattern \"" + testpat
+
2234 "\" failed: " + u_errorName(ec2
));
2237 if (!existingPat
) delete f
;
2240 errln("FAIL: " + where
+ "Unknown command \"" + tok
+ "\"");
2247 if (U_SUCCESS(ec
)) {
2248 errln("FAIL: Unexpected EOF");
2250 errln("FAIL: " + where
+ "Unexpected " + u_errorName(ec
));
2260 //----------------------------------------------------------------------
2262 //----------------------------------------------------------------------
2264 UBool
NumberFormatTest::equalValue(const Formattable
& a
, const Formattable
& b
) {
2265 if (a
.getType() == b
.getType()) {
2269 if (a
.getType() == Formattable::kLong
) {
2270 if (b
.getType() == Formattable::kInt64
) {
2271 return a
.getLong() == b
.getLong();
2272 } else if (b
.getType() == Formattable::kDouble
) {
2273 return (double) a
.getLong() == b
.getDouble(); // TODO check use of double instead of long
2275 } else if (a
.getType() == Formattable::kDouble
) {
2276 if (b
.getType() == Formattable::kLong
) {
2277 return a
.getDouble() == (double) b
.getLong();
2278 } else if (b
.getType() == Formattable::kInt64
) {
2279 return a
.getDouble() == (double)b
.getInt64();
2281 } else if (a
.getType() == Formattable::kInt64
) {
2282 if (b
.getType() == Formattable::kLong
) {
2283 return a
.getInt64() == (int64_t)b
.getLong();
2284 } else if (b
.getType() == Formattable::kDouble
) {
2285 return a
.getInt64() == (int64_t)b
.getDouble();
2291 void NumberFormatTest::expect2(NumberFormat
& fmt
, const Formattable
& n
, const UnicodeString
& str
) {
2292 // Don't round-trip format test, since we explicitly do it
2293 expect(fmt
, n
, str
, FALSE
);
2294 expect(fmt
, str
, n
);
2297 void NumberFormatTest::expect2(NumberFormat
* fmt
, const Formattable
& n
,
2298 const UnicodeString
& exp
,
2299 UErrorCode status
) {
2300 if (U_FAILURE(status
)) {
2301 errln("FAIL: NumberFormat constructor");
2303 expect2(*fmt
, n
, exp
);
2308 void NumberFormatTest::expect(NumberFormat
& fmt
, const UnicodeString
& str
, const Formattable
& n
) {
2309 UErrorCode status
= U_ZERO_ERROR
;
2311 fmt
.parse(str
, num
, status
);
2312 if (U_FAILURE(status
)) {
2313 errln(UnicodeString("FAIL: Parse failed for \"") + str
+ "\"");
2317 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2318 if (equalValue(num
, n
)) {
2319 logln(UnicodeString("Ok \"") + str
+ "\" x " +
2323 errln(UnicodeString("FAIL \"") + str
+ "\" x " +
2325 toString(num
) + ", expected " + toString(n
));
2329 void NumberFormatTest::expect(NumberFormat
& fmt
, const Formattable
& n
,
2330 const UnicodeString
& exp
, UBool rt
) {
2333 UErrorCode status
= U_ZERO_ERROR
;
2334 fmt
.format(n
, saw
, pos
, status
);
2335 CHECK(status
, "NumberFormat::format");
2337 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2339 logln(UnicodeString("Ok ") + toString(n
) + " x " +
2340 escape(pat
) + " = \"" +
2341 escape(saw
) + "\"");
2342 // We should be able to round-trip the formatted string =>
2343 // number => string (but not the other way around: number
2344 // => string => number2, might have number2 != number):
2347 fmt
.parse(exp
, n2
, status
);
2348 if (U_FAILURE(status
)) {
2349 errln(UnicodeString("FAIL: Parse failed for \"") + exp
+ "\"");
2353 fmt
.format(n2
, saw2
, pos
, status
);
2354 CHECK(status
, "NumberFormat::format");
2356 errln((UnicodeString
)"FAIL \"" + exp
+ "\" => " + toString(n2
) +
2357 " => \"" + saw2
+ "\"");
2361 errln(UnicodeString("FAIL ") + toString(n
) + " x " +
2362 escape(pat
) + " = \"" +
2363 escape(saw
) + "\", expected \"" + exp
+ "\"");
2367 void NumberFormatTest::expect(NumberFormat
* fmt
, const Formattable
& n
,
2368 const UnicodeString
& exp
,
2369 UErrorCode status
) {
2370 if (U_FAILURE(status
)) {
2371 errln("FAIL: NumberFormat constructor");
2373 expect(*fmt
, n
, exp
);
2378 void NumberFormatTest::expectCurrency(NumberFormat
& nf
, const Locale
& locale
,
2379 double value
, const UnicodeString
& string
) {
2380 UErrorCode ec
= U_ZERO_ERROR
;
2381 DecimalFormat
& fmt
= * (DecimalFormat
*) &nf
;
2382 const UChar DEFAULT_CURR
[] = {45/*-*/,0};
2384 u_strcpy(curr
, DEFAULT_CURR
);
2385 if (*locale
.getLanguage() != 0) {
2386 ucurr_forLocale(locale
.getName(), curr
, 4, &ec
);
2387 assertSuccess("ucurr_forLocale", ec
);
2388 fmt
.setCurrency(curr
, ec
);
2389 assertSuccess("DecimalFormat::setCurrency", ec
);
2390 fmt
.setCurrency(curr
); //Deprecated variant, for coverage only
2393 fmt
.format(value
, s
);
2394 s
.findAndReplace((UChar32
)0x00A0, (UChar32
)0x0020);
2396 // Default display of the number yields "1234.5599999999999"
2397 // instead of "1234.56". Use a formatter to fix this.
2399 NumberFormat::createInstance(Locale::getUS(), ec
);
2401 if (U_FAILURE(ec
)) {
2402 // Oops; bad formatter. Use default op+= display.
2403 v
= (UnicodeString
)"" + value
;
2405 f
->setMaximumFractionDigits(4);
2406 f
->setGroupingUsed(FALSE
);
2407 f
->format(value
, v
);
2412 logln((UnicodeString
)"Ok: " + v
+ " x " + curr
+ " => " + prettify(s
));
2414 errln((UnicodeString
)"FAIL: " + v
+ " x " + curr
+ " => " + prettify(s
) +
2415 ", expected " + prettify(string
));
2419 void NumberFormatTest::expectPat(DecimalFormat
& fmt
, const UnicodeString
& exp
) {
2423 logln(UnicodeString("Ok \"") + pat
+ "\"");
2425 errln(UnicodeString("FAIL \"") + pat
+ "\", expected \"" + exp
+ "\"");
2429 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2431 expectPad(fmt
, pat
, pos
, 0, (UnicodeString
)"");
2433 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2434 int32_t pos
, int32_t width
, UChar pad
) {
2435 expectPad(fmt
, pat
, pos
, width
, UnicodeString(pad
));
2437 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2438 int32_t pos
, int32_t width
, const UnicodeString
& pad
) {
2439 int32_t apos
= 0, awidth
= 0;
2440 UnicodeString apadStr
;
2441 UErrorCode status
= U_ZERO_ERROR
;
2442 fmt
.applyPattern(pat
, status
);
2443 if (U_SUCCESS(status
)) {
2444 apos
= fmt
.getPadPosition();
2445 awidth
= fmt
.getFormatWidth();
2446 apadStr
=fmt
.getPadCharacterString();
2452 if (apos
== pos
&& awidth
== width
&& apadStr
== pad
) {
2453 UnicodeString infoStr
;
2454 if (pos
== ILLEGAL
) {
2455 infoStr
= UnicodeString(" width=", "") + awidth
+ UnicodeString(" pad=", "") + apadStr
;
2457 logln(UnicodeString("Ok \"") + pat
+ "\" pos=" + apos
+ infoStr
);
2459 errln(UnicodeString("FAIL \"") + pat
+ "\" pos=" + apos
+
2460 " width=" + awidth
+ " pad=" + apadStr
+
2461 ", expected " + pos
+ " " + width
+ " " + pad
);
2464 void NumberFormatTest::TestJB3832(){
2465 const char* localeID
= "pt_PT@currency=PTE";
2466 Locale
loc(localeID
);
2467 UErrorCode status
= U_ZERO_ERROR
;
2468 UnicodeString
expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
2470 NumberFormat
* currencyFmt
= NumberFormat::createCurrencyInstance(loc
, status
);
2471 if(U_FAILURE(status
)){
2472 errln("Could not create currency formatter for locale %s", localeID
);
2475 currencyFmt
->format(1150.50, s
);
2477 errln(UnicodeString("FAIL: Expected: ")+expected
2478 + UnicodeString(" Got: ") + s
2479 + UnicodeString( " for locale: ")+ UnicodeString(localeID
) );
2481 if (U_FAILURE(status
)){
2482 errln("FAIL: Status %s", u_errorName(status
));
2487 void NumberFormatTest::TestHost()
2490 Win32NumberTest::testLocales(this);
2494 void NumberFormatTest::TestHostClone()
2497 Verify that a cloned formatter gives the same results
2498 and is useable after the original has been deleted.
2500 // This is mainly important on Windows.
2501 UErrorCode status
= U_ZERO_ERROR
;
2502 Locale
loc("en_US@compat=host");
2503 UDate now
= Calendar::getNow();
2504 NumberFormat
*full
= NumberFormat::createInstance(loc
, status
);
2505 if (full
== NULL
|| U_FAILURE(status
)) {
2506 errln("FAIL: Can't create Relative date instance");
2509 UnicodeString result1
;
2510 full
->format(now
, result1
, status
);
2511 Format
*fullClone
= full
->clone();
2515 UnicodeString result2
;
2516 fullClone
->format(now
, result2
, status
);
2517 if (U_FAILURE(status
)) {
2518 errln("FAIL: format failure.");
2520 if (result1
!= result2
) {
2521 errln("FAIL: Clone returned different result from non-clone.");
2526 void NumberFormatTest::TestCurrencyFormat()
2528 // This test is here to increase code coverage.
2529 UErrorCode status
= U_ZERO_ERROR
;
2530 MeasureFormat
*cloneObj
;
2532 Formattable toFormat
, result
;
2533 static const UChar ISO_CODE
[4] = {0x0047, 0x0042, 0x0050, 0};
2535 Locale saveDefaultLocale
= Locale::getDefault();
2536 Locale::setDefault( Locale::getUK(), status
);
2537 if (U_FAILURE(status
)) {
2538 errln("couldn't set default Locale!");
2542 MeasureFormat
*measureObj
= MeasureFormat::createCurrencyFormat(status
);
2543 Locale::setDefault( saveDefaultLocale
, status
);
2544 if (U_FAILURE(status
)){
2545 errln("FAIL: Status %s", u_errorName(status
));
2548 cloneObj
= (MeasureFormat
*)measureObj
->clone();
2549 if (cloneObj
== NULL
) {
2550 errln("Clone doesn't work");
2553 toFormat
.adoptObject(new CurrencyAmount(1234.56, ISO_CODE
, status
));
2554 measureObj
->format(toFormat
, str
, status
);
2555 measureObj
->parseObject(str
, result
, status
);
2556 if (U_FAILURE(status
)){
2557 errln("FAIL: Status %s", u_errorName(status
));
2559 if (result
!= toFormat
) {
2560 errln("measureObj does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2562 status
= U_ZERO_ERROR
;
2564 cloneObj
->format(toFormat
, str
, status
);
2565 cloneObj
->parseObject(str
, result
, status
);
2566 if (U_FAILURE(status
)){
2567 errln("FAIL: Status %s", u_errorName(status
));
2569 if (result
!= toFormat
) {
2570 errln("Clone does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2572 if (*measureObj
!= *cloneObj
) {
2573 errln("Cloned object is not equal to the original object");
2578 status
= U_USELESS_COLLATOR_ERROR
;
2579 if (MeasureFormat::createCurrencyFormat(status
) != NULL
) {
2580 errln("createCurrencyFormat should have returned NULL.");
2584 /* Port of ICU4J rounding test. */
2585 void NumberFormatTest::TestRounding() {
2586 UErrorCode status
= U_ZERO_ERROR
;
2587 DecimalFormat
*df
= (DecimalFormat
*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status
);
2589 if (U_FAILURE(status
)) {
2590 errln("Unable to create decimal formatter.");
2594 int roundingIncrements
[]={1, 2, 5, 20, 50, 100};
2595 int testValues
[]={0, 300};
2597 for (int j
=0; j
<2; j
++) {
2598 for (int mode
=DecimalFormat::kRoundUp
;mode
<DecimalFormat::kRoundHalfEven
;mode
++) {
2599 df
->setRoundingMode((DecimalFormat::ERoundingMode
)mode
);
2600 for (int increment
=0; increment
<6; increment
++) {
2601 double base
=testValues
[j
];
2602 double rInc
=roundingIncrements
[increment
];
2603 checkRounding(df
, base
, 20, rInc
);
2604 rInc
=1.000000000/rInc
;
2605 checkRounding(df
, base
, 20, rInc
);
2612 void NumberFormatTest::checkRounding(DecimalFormat
* df
, double base
, int iterations
, double increment
) {
2613 df
->setRoundingIncrement(increment
);
2614 double lastParsed
=INT32_MIN
; //Intger.MIN_VALUE
2615 for (int i
=-iterations
; i
<=iterations
;i
++) {
2616 double iValue
=base
+(increment
*(i
*0.1));
2617 double smallIncrement
=0.00000001;
2619 smallIncrement
*=iValue
;
2621 //we not only test the value, but some values in a small range around it
2622 lastParsed
=checkRound(df
, iValue
-smallIncrement
, lastParsed
);
2623 lastParsed
=checkRound(df
, iValue
, lastParsed
);
2624 lastParsed
=checkRound(df
, iValue
+smallIncrement
, lastParsed
);
2628 double NumberFormatTest::checkRound(DecimalFormat
* df
, double iValue
, double lastParsed
) {
2629 UErrorCode status
=U_ZERO_ERROR
;
2630 UnicodeString formattedDecimal
;
2633 df
->format(iValue
, formattedDecimal
, status
);
2635 if (U_FAILURE(status
)) {
2636 errln("Error formatting number.");
2639 df
->parse(formattedDecimal
, result
, status
);
2641 if (U_FAILURE(status
)) {
2642 errln("Error parsing number.");
2645 parsed
=result
.getDouble();
2647 if (lastParsed
>parsed
) {
2648 errln("Rounding wrong direction! %d > %d", lastParsed
, parsed
);
2654 void NumberFormatTest::TestNonpositiveMultiplier() {
2655 UErrorCode status
= U_ZERO_ERROR
;
2656 DecimalFormatSymbols
US(Locale::getUS(), status
);
2657 CHECK(status
, "DecimalFormatSymbols constructor");
2658 DecimalFormat
df(UnicodeString("0"), US
, status
);
2659 CHECK(status
, "DecimalFormat(0)");
2661 // test zero multiplier
2663 int32_t mult
= df
.getMultiplier();
2664 df
.setMultiplier(0);
2665 if (df
.getMultiplier() != mult
) {
2666 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
2669 // test negative multiplier
2671 df
.setMultiplier(-1);
2672 if (df
.getMultiplier() != -1) {
2673 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
2677 expect(df
, "1122.123", -1122.123);
2678 expect(df
, "-1122.123", 1122.123);
2679 expect(df
, "1.2", -1.2);
2680 expect(df
, "-1.2", 1.2);
2682 // TODO: change all the following int64_t tests once BigInteger is ported
2683 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2684 static const char* posOutOfRange
= "9223372036854780000";
2685 static const char* negOutOfRange
= "-9223372036854780000";
2687 expect(df
, U_INT64_MIN
, posOutOfRange
);
2688 expect(df
, U_INT64_MIN
+1, "9223372036854775807");
2689 expect(df
, (int64_t)-123, "123");
2690 expect(df
, (int64_t)123, "-123");
2691 expect(df
, U_INT64_MAX
-1, "-9223372036854775806");
2692 expect(df
, U_INT64_MAX
, "-9223372036854775807");
2694 df
.setMultiplier(-2);
2695 expect(df
, -(U_INT64_MIN
/2)-1, "-9223372036854775806");
2696 expect(df
, -(U_INT64_MIN
/2), "-9223372036854775808");
2697 expect(df
, -(U_INT64_MIN
/2)+1, negOutOfRange
);
2699 df
.setMultiplier(-7);
2700 expect(df
, -(U_INT64_MAX
/7)-1, posOutOfRange
);
2701 expect(df
, -(U_INT64_MAX
/7), "9223372036854775807");
2702 expect(df
, -(U_INT64_MAX
/7)+1, "9223372036854775800");
2704 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
2705 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2706 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
2707 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
2708 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
2709 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
2711 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
2712 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2713 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2714 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2715 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2719 NumberFormatTest::TestSpaceParsing() {
2721 // the string to be parsed, parsed position, parsed error index
2722 const char* DATA
[][3] = {
2723 {"$124", "4", "-1"},
2724 {"$124 $124", "4", "-1"},
2725 {"$124 ", "4", "-1"},
2726 {"$ 124 ", "5", "-1"},
2727 {"$\\u00A0124 ", "5", "-1"},
2728 {" $ 124 ", "6", "-1"},
2729 //{"124$", "4", "-1"}, // TODO: need to handle trailing currency correctly
2730 {"124$", "3", "-1"},
2731 //{"124 $", "5", "-1"}, // TODO: OK or not, need currency spacing rule
2732 {"124 $", "3", "-1"},
2735 UErrorCode status
= U_ZERO_ERROR
;
2736 Locale
locale("en_US");
2737 NumberFormat
* foo
= NumberFormat::createCurrencyInstance(locale
, status
);
2738 if (U_FAILURE(status
)) {
2743 foo
->setParseStrict(FALSE
);
2744 for (uint32_t i
= 0; i
< sizeof(DATA
)/sizeof(DATA
[0]); ++i
) {
2745 ParsePosition
parsePosition(0);
2746 UnicodeString stringToBeParsed
= ctou(DATA
[i
][0]);
2747 int parsedPosition
= atoi(DATA
[i
][1]);
2748 int errorIndex
= atoi(DATA
[i
][2]);
2750 foo
->parse(stringToBeParsed
, result
, parsePosition
);
2751 if (parsePosition
.getIndex() != parsedPosition
||
2752 parsePosition
.getErrorIndex() != errorIndex
) {
2753 errln("FAILED parse " + stringToBeParsed
+ "; wrong position, expected: (" + parsedPosition
+ ", " + errorIndex
+ "); got (" + parsePosition
.getIndex() + ", " + parsePosition
.getErrorIndex() + ")");
2755 if (parsePosition
.getErrorIndex() == -1 &&
2756 result
.getType() == Formattable::kLong
&&
2757 result
.getLong() != 124) {
2758 errln("FAILED parse " + stringToBeParsed
+ "; wrong number, expect: 124, got " + result
.getLong());
2764 #endif /* #if !UCONFIG_NO_FORMATTING */