1 /********************************************************************
3 * Copyright (c) 1997-2006, 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"
31 static const UChar EUR
[] = {69,85,82,0}; // "EUR"
33 // *****************************************************************************
34 // class NumberFormatTest
35 // *****************************************************************************
37 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
39 #define CHECK(status,str) if (U_FAILURE(status)) { errln(UnicodeString("FAIL: ") + str); return; }
41 void NumberFormatTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
43 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
45 CASE(0,TestCurrencySign
);
48 CASE(3,TestRounding487
);
50 CASE(5,TestExponential
);
53 // Upgrade to alphaWorks - liu 5/99
55 CASE(8,TestScientific
);
57 CASE(10,TestPatterns2
);
58 CASE(11,TestSecondaryGrouping
);
59 CASE(12,TestSurrogateSupport
);
62 CASE(14,TestCurrencyObject
);
63 CASE(15,TestCurrencyPatterns
);
64 CASE(16,TestDigitList
);
65 CASE(17,TestWhiteSpaceParsing
);
66 CASE(18,TestComplexCurrency
);
67 CASE(19,TestRegCurrency
);
68 CASE(20,TestSymbolsWithBadLocale
);
69 CASE(21,TestAdoptDecimalFormatSymbols
);
71 CASE(22,TestScientific2
);
72 CASE(23,TestScientificGrouping
);
76 CASE(26,TestIllegalPatterns
);
79 CASE(28,TestCurrencyNames
);
80 CASE(29,TestCurrencyAmount
);
81 CASE(30,TestCurrencyUnit
);
82 CASE(31,TestCoverage
);
85 CASE(34,TestCurrencyFormat
);
86 default: name
= ""; break;
90 // -------------------------------------
92 // Test API (increase code coverage)
94 NumberFormatTest::TestAPI(void)
97 UErrorCode status
= U_ZERO_ERROR
;
98 NumberFormat
*test
= NumberFormat::createInstance("root", status
);
99 if(U_FAILURE(status
)) {
100 errln("unable to create format object");
103 test
->setMinimumIntegerDigits(10);
104 test
->setMaximumIntegerDigits(2);
106 test
->setMinimumFractionDigits(10);
107 test
->setMaximumFractionDigits(2);
109 UnicodeString result
;
111 Formattable
bla("Paja Patak"); // Donald Duck for non Serbian speakers
112 test
->format(bla
, result
, pos
, status
);
113 if(U_SUCCESS(status
)) {
114 errln("Yuck... Formatted a duck... As a number!");
116 status
= U_ZERO_ERROR
;
121 test
->format(ll
, result
);
122 if (result
!= "12.00"){
123 errln("format int64_t error");
130 class StubNumberForamt
:public NumberFormat
{
132 StubNumberForamt(){};
133 virtual UnicodeString
& format(double ,UnicodeString
& appendTo
,FieldPosition
& ) const {
136 virtual UnicodeString
& format(int32_t ,UnicodeString
& appendTo
,FieldPosition
& ) const {
137 return appendTo
.append((UChar
)0x0033);
139 virtual UnicodeString
& format(int64_t number
,UnicodeString
& appendTo
,FieldPosition
& pos
) const {
140 return NumberFormat::format(number
, appendTo
, pos
);
142 virtual UnicodeString
& format(const Formattable
& , UnicodeString
& appendTo
, FieldPosition
& , UErrorCode
& ) const {
145 virtual void parse(const UnicodeString
& ,
147 ParsePosition
& ) const {}
148 virtual void parse( const UnicodeString
& ,
150 UErrorCode
& ) const {}
151 virtual UClassID
getDynamicClassID(void) const {
152 static char classID
= 0;
153 return (UClassID
)&classID
;
155 virtual Format
* clone() const {return NULL
;}
159 NumberFormatTest::TestCoverage(void){
160 StubNumberForamt stub
;
161 UnicodeString
agent("agent");
164 if (stub
.format(num
, agent
, pos
) != UnicodeString("agent3")){
165 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
169 // Test various patterns
171 NumberFormatTest::TestPatterns(void)
173 UErrorCode status
= U_ZERO_ERROR
;
174 DecimalFormatSymbols
sym(Locale::getUS(), status
);
175 if (U_FAILURE(status
)) { errln("FAIL: Could not construct DecimalFormatSymbols"); return; }
177 const char* pat
[] = { "#.#", "#.", ".#", "#" };
178 int32_t pat_length
= (int32_t)(sizeof(pat
) / sizeof(pat
[0]));
179 const char* newpat
[] = { "#0.#", "#0.", "#.0", "#" };
180 const char* num
[] = { "0", "0.", ".0", "0" };
181 for (int32_t i
=0; i
<pat_length
; ++i
)
183 status
= U_ZERO_ERROR
;
184 DecimalFormat
fmt(pat
[i
], sym
, status
);
185 if (U_FAILURE(status
)) { errln((UnicodeString
)"FAIL: DecimalFormat constructor failed for " + pat
[i
]); continue; }
186 UnicodeString newp
; fmt
.toPattern(newp
);
187 if (!(newp
== newpat
[i
]))
188 errln((UnicodeString
)"FAIL: Pattern " + pat
[i
] + " should transmute to " + newpat
[i
] +
189 "; " + newp
+ " seen instead");
191 UnicodeString s
; (*(NumberFormat
*)&fmt
).format((int32_t)0, s
);
194 errln((UnicodeString
)"FAIL: Pattern " + pat
[i
] + " should format zero as " + num
[i
] +
195 "; " + s
+ " seen instead");
196 logln((UnicodeString
)"Min integer digits = " + fmt
.getMinimumIntegerDigits());
202 NumberFormatTest::TestDigitList(void)
204 // API coverage for DigitList
206 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
207 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
208 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
212 list1
.fDecimalAt
= 1;
214 list2
.set((int32_t)1);
215 if (list1
!= list2
) {
216 errln("digitlist append, operator!= or set failed ");
218 if (!(list1
== list2
)) {
219 errln("digitlist append, operator== or set failed ");
223 // -------------------------------------
225 // Test exponential pattern
227 NumberFormatTest::TestExponential(void)
229 UErrorCode status
= U_ZERO_ERROR
;
230 DecimalFormatSymbols
sym(Locale::getUS(), status
);
231 if (U_FAILURE(status
)) { errln("FAIL: Bad status returned by DecimalFormatSymbols ct"); return; }
232 const char* pat
[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
233 int32_t pat_length
= (int32_t)(sizeof(pat
) / sizeof(pat
[0]));
235 // The following #if statements allow this test to be built and run on
236 // platforms that do not have standard IEEE numerics. For example,
237 // S/390 doubles have an exponent range of -78 to +75. For the
238 // following #if statements to work, float.h must define
239 // DBL_MAX_10_EXP to be a compile-time constant.
241 // This section may be expanded as needed.
243 #if DBL_MAX_10_EXP > 300
244 double val
[] = { 0.01234, 123456789, 1.23e300
, -3.141592653e-271 };
245 int32_t val_length
= (int32_t)(sizeof(val
) / sizeof(val
[0]));
246 const char* valFormat
[] =
249 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
251 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
253 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
255 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
259 0.01234, 123460000, 1.23E300
, -3.1416E-271,
260 0.01234, 123460000, 1.23E300
, -3.1416E-271,
261 0.01234, 123456800, 1.23E300
, -3.141593E-271,
262 0.01234, 123500000, 1.23E300
, -3.142E-271,
264 #elif DBL_MAX_10_EXP > 70
265 double val
[] = { 0.01234, 123456789, 1.23e70
, -3.141592653e-71 };
266 int32_t val_length
= sizeof(val
) / sizeof(val
[0]);
270 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
272 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
274 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
276 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
280 0.01234, 123460000, 1.23E70
, -3.1416E-71,
281 0.01234, 123460000, 1.23E70
, -3.1416E-71,
282 0.01234, 123456800, 1.23E70
, -3.141593E-71,
283 0.01234, 123500000, 1.23E70
, -3.142E-71,
286 // Don't test double conversion
288 int32_t val_length
= 0;
289 char** valFormat
= 0;
290 double* valParse
= 0;
291 logln("Warning: Skipping double conversion tests");
294 int32_t lval
[] = { 0, -1, 1, 123456789 };
295 int32_t lval_length
= (int32_t)(sizeof(lval
) / sizeof(lval
[0]));
296 const char* lvalFormat
[] =
299 "0E0", "-1E0", "1E0", "1.2346E8",
301 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
303 "0E000", "-1E000", "1E000", "123.4568E006",
305 "0E0", "[1E0]", "1E0", "1.235E8"
307 int32_t lvalParse
[] =
314 int32_t ival
= 0, ilval
= 0;
315 for (int32_t p
=0; p
<pat_length
; ++p
)
317 DecimalFormat
fmt(pat
[p
], sym
, status
);
318 if (U_FAILURE(status
)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
319 UnicodeString pattern
;
320 logln((UnicodeString
)"Pattern \"" + pat
[p
] + "\" -toPattern-> \"" +
321 fmt
.toPattern(pattern
) + "\"");
323 for (v
=0; v
<val_length
; ++v
)
325 UnicodeString s
; (*(NumberFormat
*)&fmt
).format(val
[v
], s
);
326 logln((UnicodeString
)" " + val
[v
] + " -format-> " + s
);
327 if (s
!= valFormat
[v
+ival
])
328 errln((UnicodeString
)"FAIL: Expected " + valFormat
[v
+ival
]);
330 ParsePosition
pos(0);
332 fmt
.parse(s
, af
, pos
);
334 UBool useEpsilon
= FALSE
;
335 if (af
.getType() == Formattable::kLong
)
337 else if (af
.getType() == Formattable::kDouble
) {
339 #if defined(OS390) || defined(OS400)
340 // S/390 will show a failure like this:
341 //| -3.141592652999999e-271 -format-> -3.1416E-271
342 //| -parse-> -3.1416e-271
343 //| FAIL: Expected -3.141599999999999e-271
344 // To compensate, we use an epsilon-based equality
345 // test on S/390 only. We don't want to do this in
346 // general because it's less exacting.
351 errln((UnicodeString
)"FAIL: Non-numeric Formattable returned");
354 if (pos
.getIndex() == s
.length())
356 logln((UnicodeString
)" -parse-> " + a
);
357 // Use epsilon comparison as necessary
359 (uprv_fabs(a
- valParse
[v
+ival
]) / a
> (2*DBL_EPSILON
))) ||
360 (!useEpsilon
&& a
!= valParse
[v
+ival
]))
362 errln((UnicodeString
)"FAIL: Expected " + valParse
[v
+ival
]);
366 errln((UnicodeString
)"FAIL: Partial parse (" + pos
.getIndex() + " chars) -> " + a
);
367 errln((UnicodeString
)" should be (" + s
.length() + " chars) -> " + valParse
[v
+ival
]);
370 for (v
=0; v
<lval_length
; ++v
)
373 (*(NumberFormat
*)&fmt
).format(lval
[v
], s
);
374 logln((UnicodeString
)" " + lval
[v
] + "L -format-> " + s
);
375 if (s
!= lvalFormat
[v
+ilval
])
376 errln((UnicodeString
)"ERROR: Expected " + lvalFormat
[v
+ilval
] + " Got: " + s
);
378 ParsePosition
pos(0);
380 fmt
.parse(s
, af
, pos
);
381 if (af
.getType() == Formattable::kLong
||
382 af
.getType() == Formattable::kInt64
) {
383 UErrorCode status
= U_ZERO_ERROR
;
384 int32_t a
= af
.getLong(status
);
385 if (pos
.getIndex() == s
.length())
387 logln((UnicodeString
)" -parse-> " + a
);
388 if (a
!= lvalParse
[v
+ilval
])
389 errln((UnicodeString
)"FAIL: Expected " + lvalParse
[v
+ilval
]);
392 errln((UnicodeString
)"FAIL: Partial parse (" + pos
.getIndex() + " chars) -> " + a
);
395 errln((UnicodeString
)"FAIL: Non-long Formattable returned for " + s
396 + " Double: " + af
.getDouble()
397 + ", Long: " + af
.getLong());
400 ilval
+= lval_length
;
405 NumberFormatTest::TestScientific2() {
407 UErrorCode status
= U_ZERO_ERROR
;
408 DecimalFormat
* fmt
= (DecimalFormat
*)NumberFormat::createCurrencyInstance("en_US", status
);
409 if (U_SUCCESS(status
)) {
411 expect(*fmt
, num
, "$12.34");
412 fmt
->setScientificNotation(TRUE
);
413 expect(*fmt
, num
, "$1.23E1");
414 fmt
->setScientificNotation(FALSE
);
415 expect(*fmt
, num
, "$12.34");
421 NumberFormatTest::TestScientificGrouping() {
423 UErrorCode status
= U_ZERO_ERROR
;
424 DecimalFormat
fmt("##0.00E0",status
);
425 if (U_SUCCESS(status
)) {
426 expect(fmt
, .01234, "12.3E-3");
427 expect(fmt
, .1234, "123E-3");
428 expect(fmt
, 1.234, "1.23E0");
429 expect(fmt
, 12.34, "12.3E0");
430 expect(fmt
, 123.4, "123E0");
431 expect(fmt
, 1234., "1.23E3");
435 static void setFromString(DigitList
& dl
, const char* str
) {
437 UBool decimalSet
= FALSE
;
439 while ((c
= *str
++)) {
441 dl
.fIsPositive
= FALSE
;
442 } else if (c
== '+') {
443 dl
.fIsPositive
= TRUE
;
444 } else if (c
== '.') {
445 dl
.fDecimalAt
= dl
.fCount
;
452 dl
.fDecimalAt
= dl
.fCount
;
457 NumberFormatTest::TestInt64() {
458 UErrorCode status
= U_ZERO_ERROR
;
459 DecimalFormat
fmt("#.#E0",status
);
460 fmt
.setMaximumFractionDigits(20);
461 if (U_SUCCESS(status
)) {
462 expect(fmt
, (Formattable
)(int64_t)0, "0E0");
463 expect(fmt
, (Formattable
)(int64_t)-1, "-1E0");
464 expect(fmt
, (Formattable
)(int64_t)1, "1E0");
465 expect(fmt
, (Formattable
)(int64_t)2147483647, "2.147483647E9");
466 expect(fmt
, (Formattable
)((int64_t)-2147483647-1), "-2.147483648E9");
467 expect(fmt
, (Formattable
)(int64_t)U_INT64_MAX
, "9.223372036854775807E18");
468 expect(fmt
, (Formattable
)(int64_t)U_INT64_MIN
, "-9.223372036854775808E18");
471 // also test digitlist
472 int64_t int64max
= U_INT64_MAX
;
473 int64_t int64min
= U_INT64_MIN
;
474 const char* int64maxstr
= "9223372036854775807";
475 const char* int64minstr
= "-9223372036854775808";
476 UnicodeString
fail("fail: ");
478 // test max int64 value
480 setFromString(dl
, int64maxstr
);
482 if (!dl
.fitsIntoInt64(FALSE
)) {
483 errln(fail
+ int64maxstr
+ " didn't fit");
485 int64_t int64Value
= dl
.getInt64();
486 if (int64Value
!= int64max
) {
487 errln(fail
+ int64maxstr
);
490 int64Value
= dl
.getInt64();
491 if (int64Value
!= int64max
) {
492 errln(fail
+ int64maxstr
);
495 // test negative of max int64 value (1 shy of min int64 value)
496 dl
.fIsPositive
= FALSE
;
498 if (!dl
.fitsIntoInt64(FALSE
)) {
499 errln(fail
+ "-" + int64maxstr
+ " didn't fit");
501 int64_t int64Value
= dl
.getInt64();
502 if (int64Value
!= -int64max
) {
503 errln(fail
+ "-" + int64maxstr
);
506 int64Value
= dl
.getInt64();
507 if (int64Value
!= -int64max
) {
508 errln(fail
+ "-" + int64maxstr
);
511 // test min int64 value
512 setFromString(dl
, int64minstr
);
514 if (!dl
.fitsIntoInt64(FALSE
)) {
515 errln(fail
+ "-" + int64minstr
+ " didn't fit");
517 int64_t int64Value
= dl
.getInt64();
518 if (int64Value
!= int64min
) {
519 errln(fail
+ int64minstr
);
522 int64Value
= dl
.getInt64();
523 if (int64Value
!= int64min
) {
524 errln(fail
+ int64minstr
);
527 // test negative of min int 64 value (1 more than max int64 value)
528 dl
.fIsPositive
= TRUE
; // won't fit
530 if (dl
.fitsIntoInt64(FALSE
)) {
531 errln(fail
+ "-(" + int64minstr
+ ") didn't fit");
536 // -------------------------------------
538 // Test the handling of quotes
540 NumberFormatTest::TestQuotes(void)
542 UErrorCode status
= U_ZERO_ERROR
;
544 DecimalFormatSymbols
*sym
= new DecimalFormatSymbols(Locale::getUS(), status
);
545 pat
= new UnicodeString("a'fo''o'b#");
546 DecimalFormat
*fmt
= new DecimalFormat(*pat
, *sym
, status
);
548 ((NumberFormat
*)fmt
)->format((int32_t)123, s
);
549 logln((UnicodeString
)"Pattern \"" + *pat
+ "\"");
550 logln((UnicodeString
)" Format 123 -> " + escape(s
));
551 if (!(s
=="afo'ob123"))
552 errln((UnicodeString
)"FAIL: Expected afo'ob123");
558 pat
= new UnicodeString("a''b#");
559 fmt
= new DecimalFormat(*pat
, *sym
, status
);
560 ((NumberFormat
*)fmt
)->format((int32_t)123, s
);
561 logln((UnicodeString
)"Pattern \"" + *pat
+ "\"");
562 logln((UnicodeString
)" Format 123 -> " + escape(s
));
564 errln((UnicodeString
)"FAIL: Expected a'b123");
571 * Test the handling of the currency symbol in patterns.
574 NumberFormatTest::TestCurrencySign(void)
576 UErrorCode status
= U_ZERO_ERROR
;
577 DecimalFormatSymbols
* sym
= new DecimalFormatSymbols(Locale::getUS(), status
);
579 UChar currency
= 0x00A4;
580 // "\xA4#,##0.00;-\xA4#,##0.00"
581 pat
.append(currency
).append("#,##0.00;-").
582 append(currency
).append("#,##0.00");
583 DecimalFormat
*fmt
= new DecimalFormat(pat
, *sym
, status
);
584 UnicodeString s
; ((NumberFormat
*)fmt
)->format(1234.56, s
);
586 logln((UnicodeString
)"Pattern \"" + fmt
->toPattern(pat
) + "\"");
587 logln((UnicodeString
)" Format " + 1234.56 + " -> " + escape(s
));
588 if (s
!= "$1,234.56") errln((UnicodeString
)"FAIL: Expected $1,234.56");
590 ((NumberFormat
*)fmt
)->format(- 1234.56, s
);
591 logln((UnicodeString
)" Format " + (-1234.56) + " -> " + escape(s
));
592 if (s
!= "-$1,234.56") errln((UnicodeString
)"FAIL: Expected -$1,234.56");
595 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
596 pat
.append(currency
).append(currency
).
597 append(" #,##0.00;").
598 append(currency
).append(currency
).
599 append(" -#,##0.00");
600 fmt
= new DecimalFormat(pat
, *sym
, status
);
602 ((NumberFormat
*)fmt
)->format(1234.56, s
);
603 logln((UnicodeString
)"Pattern \"" + fmt
->toPattern(pat
) + "\"");
604 logln((UnicodeString
)" Format " + 1234.56 + " -> " + escape(s
));
605 if (s
!= "USD 1,234.56") errln((UnicodeString
)"FAIL: Expected USD 1,234.56");
607 ((NumberFormat
*)fmt
)->format(-1234.56, s
);
608 logln((UnicodeString
)" Format " + (-1234.56) + " -> " + escape(s
));
609 if (s
!= "USD -1,234.56") errln((UnicodeString
)"FAIL: Expected USD -1,234.56");
612 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
615 // -------------------------------------
617 static UChar
toHexString(int32_t i
) { return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10))); }
620 NumberFormatTest::escape(UnicodeString
& s
)
623 for (int32_t i
=0; i
<s
.length(); ++i
)
625 UChar c
= s
[(int32_t)i
];
626 if (c
<= (UChar
)0x7F) buf
+= c
;
628 buf
+= (UChar
)0x5c; buf
+= (UChar
)0x55;
629 buf
+= toHexString((c
& 0xF000) >> 12);
630 buf
+= toHexString((c
& 0x0F00) >> 8);
631 buf
+= toHexString((c
& 0x00F0) >> 4);
632 buf
+= toHexString(c
& 0x000F);
639 // -------------------------------------
640 static const char* testCases
[][2]= {
641 /* locale ID */ /* expected */
642 {"ca_ES_PREEURO", "\\u20A7 1.150" },
643 {"de_LU_PREEURO", "1,150 F" },
644 {"el_GR_PREEURO", "1.150,50 \\u0394\\u03C1\\u03C7" },
645 {"en_BE_PREEURO", "1.150,50 BF" },
646 {"es_ES_PREEURO", "1.150 \\u20A7" },
647 {"eu_ES_PREEURO", "\\u20A7 1.150" },
648 {"gl_ES_PREEURO", "\\u20A7 1.150" },
649 {"it_IT_PREEURO", "\\u20A4 1.150" },
650 {"pt_PT_PREEURO", "1,150$50 Esc."},
651 {"en_US@currency=JPY", "\\u00A51,150"}
654 * Test localized currency patterns.
657 NumberFormatTest::TestCurrency(void)
659 UErrorCode status
= U_ZERO_ERROR
;
660 NumberFormat
* currencyFmt
= NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status
);
661 if (U_FAILURE(status
)) {
662 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
666 UnicodeString s
; currencyFmt
->format(1.50, s
);
667 logln((UnicodeString
)"Un pauvre ici a..........." + s
);
669 errln((UnicodeString
)"FAIL: Expected 1,50 $");
673 int len
= uloc_canonicalize("de_DE_PREEURO", loc
, 256, &status
);
674 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
),status
);
675 currencyFmt
->format(1.50, s
);
676 logln((UnicodeString
)"Un pauvre en Allemagne a.." + s
);
678 errln((UnicodeString
)"FAIL: Expected 1,50 DM");
681 len
= uloc_canonicalize("fr_FR_PREEURO", loc
, 256, &status
);
682 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
683 currencyFmt
->format(1.50, s
);
684 logln((UnicodeString
)"Un pauvre en France a....." + s
);
686 errln((UnicodeString
)"FAIL: Expected 1,50 F");
688 if (U_FAILURE(status
))
689 errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
691 for(int i
=0; i
< (int)(sizeof(testCases
)/sizeof(testCases
[i
])); i
++){
692 status
= U_ZERO_ERROR
;
693 const char *localeID
= testCases
[i
][0];
694 UnicodeString
expected(testCases
[i
][1]);
695 expected
= expected
.unescape();
698 uloc_canonicalize(localeID
, loc
, 256, &status
);
699 currencyFmt
= NumberFormat::createCurrencyInstance(Locale(loc
), status
);
700 if(U_FAILURE(status
)){
701 errln("Could not create currency formatter for locale %s",localeID
);
704 currencyFmt
->format(1150.50, s
);
706 errln(UnicodeString("FAIL: Expected: ")+expected
707 + UnicodeString(" Got: ") + s
708 + UnicodeString( " for locale: ")+ UnicodeString(localeID
) );
710 if (U_FAILURE(status
)){
711 errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
717 // -------------------------------------
720 * Test the Currency object handling, new as of ICU 2.2.
722 void NumberFormatTest::TestCurrencyObject() {
723 UErrorCode ec
= U_ZERO_ERROR
;
725 NumberFormat::createCurrencyInstance(Locale::getUS(), ec
);
728 errln("FAIL: getCurrencyInstance(US)");
733 Locale
null("", "", "");
735 expectCurrency(*fmt
, null
, 1234.56, "$1,234.56");
737 expectCurrency(*fmt
, Locale::getFrance(),
738 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
740 expectCurrency(*fmt
, Locale::getJapan(),
741 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
743 expectCurrency(*fmt
, Locale("fr", "CH", ""),
744 1234.56, "SwF1,234.55"); // 0.05 rounding
746 expectCurrency(*fmt
, Locale::getUS(),
747 1234.56, "$1,234.56");
750 fmt
= NumberFormat::createCurrencyInstance(Locale::getFrance(), ec
);
753 errln("FAIL: getCurrencyInstance(FRANCE)");
758 expectCurrency(*fmt
, null
, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
760 expectCurrency(*fmt
, Locale::getJapan(),
761 1234.56, CharsToUnicodeString("1 235 \\u00A5")); // Yen
763 expectCurrency(*fmt
, Locale("fr", "CH", ""),
764 1234.56, "1 234,55 sFr."); // 0.05 rounding
766 expectCurrency(*fmt
, Locale::getUS(),
767 1234.56, "1 234,56 $");
769 expectCurrency(*fmt
, Locale::getFrance(),
770 1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
775 // -------------------------------------
778 * Do rudimentary testing of parsing.
781 NumberFormatTest::TestParse(void)
783 UErrorCode status
= U_ZERO_ERROR
;
784 UnicodeString
arg("0");
785 DecimalFormat
* format
= new DecimalFormat("00", status
);
787 Formattable n
; format
->parse(arg
, n
, status
);
788 logln((UnicodeString
)"parse(" + arg
+ ") = " + n
.getLong());
789 if (n
.getType() != Formattable::kLong
||
790 n
.getLong() != 0) errln((UnicodeString
)"FAIL: Expected 0");
792 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
794 //catch(Exception e) {
795 // errln((UnicodeString)"Exception caught: " + e);
799 // -------------------------------------
802 * Test proper rounding by the format method.
805 NumberFormatTest::TestRounding487(void)
807 UErrorCode status
= U_ZERO_ERROR
;
808 NumberFormat
*nf
= NumberFormat::createInstance(status
);
809 if (U_FAILURE(status
)) {
810 dataerrln("Error calling NumberFormat::createInstance()");
814 roundingTest(*nf
, 0.00159999, 4, "0.0016");
815 roundingTest(*nf
, 0.00995, 4, "0.01");
817 roundingTest(*nf
, 12.3995, 3, "12.4");
819 roundingTest(*nf
, 12.4999, 0, "12");
820 roundingTest(*nf
, - 19.5, 0, "-20");
822 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: Status " + (int32_t)status
);
826 * Test the functioning of the secondary grouping value.
828 void NumberFormatTest::TestSecondaryGrouping(void) {
829 UErrorCode status
= U_ZERO_ERROR
;
830 DecimalFormatSymbols
US(Locale::getUS(), status
);
831 CHECK(status
, "DecimalFormatSymbols ct");
833 DecimalFormat
f("#,##,###", US
, status
);
834 CHECK(status
, "DecimalFormat ct");
836 expect2(f
, (int32_t)123456789L, "12,34,56,789");
837 expectPat(f
, "#,##,###");
838 f
.applyPattern("#,###", status
);
839 CHECK(status
, "applyPattern");
841 f
.setSecondaryGroupingSize(4);
842 expect2(f
, (int32_t)123456789L, "12,3456,789");
843 expectPat(f
, "#,####,###");
844 NumberFormat
*g
= NumberFormat::createInstance(Locale("hi", "IN"), status
);
845 CHECK(status
, "createInstance(hi_IN)");
848 int32_t l
= (int32_t)1876543210L;
851 // expect "1,87,65,43,210", but with Hindi digits
854 if (out
.length() != 14) {
857 for (int32_t i
=0; i
<out
.length(); ++i
) {
858 UBool expectGroup
= FALSE
;
867 // Later -- fix this to get the actual grouping
868 // character from the resource bundle.
869 UBool isGroup
= (out
.charAt(i
) == 0x002C);
870 if (isGroup
!= expectGroup
) {
877 errln((UnicodeString
)"FAIL Expected " + l
+
878 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
881 logln((UnicodeString
)"Ok " + l
+
887 void NumberFormatTest::TestWhiteSpaceParsing(void) {
888 UErrorCode ec
= U_ZERO_ERROR
;
889 DecimalFormatSymbols
US(Locale::getUS(), ec
);
890 DecimalFormat
fmt("a b#0c ", US
, ec
);
892 errln("FAIL: Constructor");
896 expect(fmt
, "a b1234c ", n
);
897 expect(fmt
, "a b1234c ", n
);
901 * Test currencies whose display name is a ChoiceFormat.
903 void NumberFormatTest::TestComplexCurrency() {
904 UErrorCode ec
= U_ZERO_ERROR
;
905 Locale
loc("en", "IN", "");
906 NumberFormat
* fmt
= NumberFormat::createCurrencyInstance(loc
, ec
);
908 expect2(*fmt
, 1.0, "Re. 1.00");
909 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
910 expect(*fmt
, 1.00390625, "Re. 1.00"); // tricky
911 expect2(*fmt
, 12345678.0, "Rs. 1,23,45,678.00");
912 expect2(*fmt
, 0.5, "Rs. 0.50");
913 expect2(*fmt
, -1.0, "-Re. 1.00");
914 expect2(*fmt
, -10.0, "-Rs. 10.00");
916 errln("FAIL: getCurrencyInstance(en_IN)");
921 // -------------------------------------
924 NumberFormatTest::roundingTest(NumberFormat
& nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
926 nf
.setMaximumFractionDigits(maxFractionDigits
);
927 UnicodeString out
; nf
.format(x
, out
);
928 logln((UnicodeString
)"" + x
+ " formats with " + maxFractionDigits
+ " fractional digits to " + out
);
929 if (!(out
==expected
)) errln((UnicodeString
)"FAIL: Expected " + expected
);
933 * Upgrade to alphaWorks
935 void NumberFormatTest::TestExponent(void) {
936 UErrorCode status
= U_ZERO_ERROR
;
937 DecimalFormatSymbols
US(Locale::getUS(), status
);
938 CHECK(status
, "DecimalFormatSymbols constructor");
939 DecimalFormat
fmt1(UnicodeString("0.###E0"), US
, status
);
940 CHECK(status
, "DecimalFormat(0.###E0)");
941 DecimalFormat
fmt2(UnicodeString("0.###E+0"), US
, status
);
942 CHECK(status
, "DecimalFormat(0.###E+0)");
944 expect2(fmt1
, n
, "1.234E3");
945 expect2(fmt2
, n
, "1.234E+3");
946 expect(fmt1
, "1.234E+3", n
); // Either format should parse "E+3"
950 * Upgrade to alphaWorks
952 void NumberFormatTest::TestScientific(void) {
953 UErrorCode status
= U_ZERO_ERROR
;
954 DecimalFormatSymbols
US(Locale::getUS(), status
);
955 CHECK(status
, "DecimalFormatSymbols constructor");
957 // Test pattern round-trip
958 const char* PAT
[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
959 "0.###E0;[0.###E0]" };
960 int32_t PAT_length
= (int32_t)(sizeof(PAT
) / sizeof(PAT
[0]));
962 // min int, max int, min frac, max frac
964 1, 1, 0, 4, // "0.####E0"
965 2, 2, 3, 3, // "00.000E00"
966 1, 3, 0, 4, // "##0.####E000"
967 1, 1, 0, 3, // "0.###E0;[0.###E0]"
969 for (int32_t i
=0; i
<PAT_length
; ++i
) {
970 UnicodeString
pat(PAT
[i
]);
971 DecimalFormat
df(pat
, US
, status
);
972 CHECK(status
, "DecimalFormat constructor");
976 logln(UnicodeString("Ok Pattern rt \"") +
980 errln(UnicodeString("FAIL Pattern rt \"") +
984 // Make sure digit counts match what we expect
985 if (df
.getMinimumIntegerDigits() != DIGITS
[4*i
] ||
986 df
.getMaximumIntegerDigits() != DIGITS
[4*i
+1] ||
987 df
.getMinimumFractionDigits() != DIGITS
[4*i
+2] ||
988 df
.getMaximumFractionDigits() != DIGITS
[4*i
+3]) {
989 errln(UnicodeString("FAIL \"" + pat
+
990 "\" min/max int; min/max frac = ") +
991 df
.getMinimumIntegerDigits() + "/" +
992 df
.getMaximumIntegerDigits() + ";" +
993 df
.getMinimumFractionDigits() + "/" +
994 df
.getMaximumFractionDigits() + ", expect " +
996 DIGITS
[4*i
+1] + ";" +
997 DIGITS
[4*i
+2] + "/" +
1003 // Test the constructor for default locale. We have to
1004 // manually set the default locale, as there is no
1005 // guarantee that the default locale has the same
1006 // scientific format.
1007 Locale def
= Locale::getDefault();
1008 Locale::setDefault(Locale::getUS(), status
);
1009 expect2(NumberFormat::createScientificInstance(status
),
1011 "1.2345678901E4", status
);
1012 Locale::setDefault(def
, status
);
1014 expect2(new DecimalFormat("#E0", US
, status
),
1016 "1.2345E4", status
);
1017 expect(new DecimalFormat("0E0", US
, status
),
1020 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status
),
1022 "1.2345678901E4", status
);
1023 expect(new DecimalFormat("##0.###E0", US
, status
),
1026 expect(new DecimalFormat("##0.###E0", US
, status
),
1029 expect2(new DecimalFormat("##0.####E0", US
, status
),
1031 "12.345E3", status
);
1032 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status
),
1034 "1,2345678901E4", status
);
1035 expect(new DecimalFormat("##0.####E0", US
, status
),
1037 "789.12E-9", status
);
1038 expect2(new DecimalFormat("##0.####E0", US
, status
),
1041 expect(new DecimalFormat(".###E0", US
, status
),
1044 expect2(new DecimalFormat(".###E0", US
, status
),
1048 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1049 new DecimalFormat("##E0", US),
1050 new DecimalFormat("####E0", US),
1051 new DecimalFormat("0E0", US),
1052 new DecimalFormat("00E0", US),
1053 new DecimalFormat("000E0", US),
1056 new String[] { "4.5678E7",
1065 ! Unroll this test into individual tests below...
1068 expect2(new DecimalFormat("#E0", US
, status
),
1069 (int32_t) 45678000, "4.5678E7", status
);
1070 expect2(new DecimalFormat("##E0", US
, status
),
1071 (int32_t) 45678000, "45.678E6", status
);
1072 expect2(new DecimalFormat("####E0", US
, status
),
1073 (int32_t) 45678000, "4567.8E4", status
);
1074 expect(new DecimalFormat("0E0", US
, status
),
1075 (int32_t) 45678000, "5E7", status
);
1076 expect(new DecimalFormat("00E0", US
, status
),
1077 (int32_t) 45678000, "46E6", status
);
1078 expect(new DecimalFormat("000E0", US
, status
),
1079 (int32_t) 45678000, "457E5", status
);
1081 expect(new DecimalFormat("###E0", US, status),
1082 new Object[] { new Double(0.0000123), "12.3E-6",
1083 new Double(0.000123), "123E-6",
1084 new Double(0.00123), "1.23E-3",
1085 new Double(0.0123), "12.3E-3",
1086 new Double(0.123), "123E-3",
1087 new Double(1.23), "1.23E0",
1088 new Double(12.3), "12.3E0",
1089 new Double(123), "123E0",
1090 new Double(1230), "1.23E3",
1093 ! Unroll this test into individual tests below...
1096 expect2(new DecimalFormat("###E0", US
, status
),
1097 0.0000123, "12.3E-6", status
);
1098 expect2(new DecimalFormat("###E0", US
, status
),
1099 0.000123, "123E-6", status
);
1100 expect2(new DecimalFormat("###E0", US
, status
),
1101 0.00123, "1.23E-3", status
);
1102 expect2(new DecimalFormat("###E0", US
, status
),
1103 0.0123, "12.3E-3", status
);
1104 expect2(new DecimalFormat("###E0", US
, status
),
1105 0.123, "123E-3", status
);
1106 expect2(new DecimalFormat("###E0", US
, status
),
1107 1.23, "1.23E0", status
);
1108 expect2(new DecimalFormat("###E0", US
, status
),
1109 12.3, "12.3E0", status
);
1110 expect2(new DecimalFormat("###E0", US
, status
),
1111 123.0, "123E0", status
);
1112 expect2(new DecimalFormat("###E0", US
, status
),
1113 1230.0, "1.23E3", status
);
1115 expect(new DecimalFormat("0.#E+00", US, status),
1116 new Object[] { new Double(0.00012), "1.2E-04",
1117 new Long(12000), "1.2E+04",
1120 ! Unroll this test into individual tests below...
1123 expect2(new DecimalFormat("0.#E+00", US
, status
),
1124 0.00012, "1.2E-04", status
);
1125 expect2(new DecimalFormat("0.#E+00", US
, status
),
1126 (int32_t) 12000, "1.2E+04", status
);
1130 * Upgrade to alphaWorks
1132 void NumberFormatTest::TestPad(void) {
1133 UErrorCode status
= U_ZERO_ERROR
;
1134 DecimalFormatSymbols
US(Locale::getUS(), status
);
1135 CHECK(status
, "DecimalFormatSymbols constructor");
1137 expect2(new DecimalFormat("*^##.##", US
, status
),
1138 int32_t(0), "^^^^0", status
);
1139 expect2(new DecimalFormat("*^##.##", US
, status
),
1140 -1.3, "^-1.3", status
);
1141 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1142 int32_t(0), "0.0E0______ g-m/s^2", status
);
1143 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US
, status
),
1144 1.0/3, "333.333E-3_ g-m/s^2", status
);
1145 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1146 int32_t(0), "0.0______ g-m/s^2", status
);
1147 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US
, status
),
1148 1.0/3, "0.33333__ g-m/s^2", status
);
1150 // Test padding before a sign
1151 const char *formatStr
= "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1152 expect2(new DecimalFormat(formatStr
, US
, status
),
1153 int32_t(-10), "xxxxxxxxxx(10.0)", status
);
1154 expect2(new DecimalFormat(formatStr
, US
, status
),
1155 int32_t(-1000),"xxxxxxx(1,000.0)", status
);
1156 expect2(new DecimalFormat(formatStr
, US
, status
),
1157 int32_t(-1000000),"xxx(1,000,000.0)", status
);
1158 expect2(new DecimalFormat(formatStr
, US
, status
),
1159 -100.37, "xxxxxxxx(100.37)", status
);
1160 expect2(new DecimalFormat(formatStr
, US
, status
),
1161 -10456.37, "xxxxx(10,456.37)", status
);
1162 expect2(new DecimalFormat(formatStr
, US
, status
),
1163 -1120456.37, "xx(1,120,456.37)", status
);
1164 expect2(new DecimalFormat(formatStr
, US
, status
),
1165 -112045600.37, "(112,045,600.37)", status
);
1166 expect2(new DecimalFormat(formatStr
, US
, status
),
1167 -1252045600.37,"(1,252,045,600.37)", status
);
1169 expect2(new DecimalFormat(formatStr
, US
, status
),
1170 int32_t(10), "xxxxxxxxxxxx10.0", status
);
1171 expect2(new DecimalFormat(formatStr
, US
, status
),
1172 int32_t(1000),"xxxxxxxxx1,000.0", status
);
1173 expect2(new DecimalFormat(formatStr
, US
, status
),
1174 int32_t(1000000),"xxxxx1,000,000.0", status
);
1175 expect2(new DecimalFormat(formatStr
, US
, status
),
1176 100.37, "xxxxxxxxxx100.37", status
);
1177 expect2(new DecimalFormat(formatStr
, US
, status
),
1178 10456.37, "xxxxxxx10,456.37", status
);
1179 expect2(new DecimalFormat(formatStr
, US
, status
),
1180 1120456.37, "xxxx1,120,456.37", status
);
1181 expect2(new DecimalFormat(formatStr
, US
, status
),
1182 112045600.37, "xx112,045,600.37", status
);
1183 expect2(new DecimalFormat(formatStr
, US
, status
),
1184 10252045600.37,"10,252,045,600.37", status
);
1187 // Test padding between a sign and a number
1188 const char *formatStr2
= "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1189 expect2(new DecimalFormat(formatStr2
, US
, status
),
1190 int32_t(-10), "(10.0xxxxxxxxxx)", status
);
1191 expect2(new DecimalFormat(formatStr2
, US
, status
),
1192 int32_t(-1000),"(1,000.0xxxxxxx)", status
);
1193 expect2(new DecimalFormat(formatStr2
, US
, status
),
1194 int32_t(-1000000),"(1,000,000.0xxx)", status
);
1195 expect2(new DecimalFormat(formatStr2
, US
, status
),
1196 -100.37, "(100.37xxxxxxxx)", status
);
1197 expect2(new DecimalFormat(formatStr2
, US
, status
),
1198 -10456.37, "(10,456.37xxxxx)", status
);
1199 expect2(new DecimalFormat(formatStr2
, US
, status
),
1200 -1120456.37, "(1,120,456.37xx)", status
);
1201 expect2(new DecimalFormat(formatStr2
, US
, status
),
1202 -112045600.37, "(112,045,600.37)", status
);
1203 expect2(new DecimalFormat(formatStr2
, US
, status
),
1204 -1252045600.37,"(1,252,045,600.37)", status
);
1206 expect2(new DecimalFormat(formatStr2
, US
, status
),
1207 int32_t(10), "10.0xxxxxxxxxxxx", status
);
1208 expect2(new DecimalFormat(formatStr2
, US
, status
),
1209 int32_t(1000),"1,000.0xxxxxxxxx", status
);
1210 expect2(new DecimalFormat(formatStr2
, US
, status
),
1211 int32_t(1000000),"1,000,000.0xxxxx", status
);
1212 expect2(new DecimalFormat(formatStr2
, US
, status
),
1213 100.37, "100.37xxxxxxxxxx", status
);
1214 expect2(new DecimalFormat(formatStr2
, US
, status
),
1215 10456.37, "10,456.37xxxxxxx", status
);
1216 expect2(new DecimalFormat(formatStr2
, US
, status
),
1217 1120456.37, "1,120,456.37xxxx", status
);
1218 expect2(new DecimalFormat(formatStr2
, US
, status
),
1219 112045600.37, "112,045,600.37xx", status
);
1220 expect2(new DecimalFormat(formatStr2
, US
, status
),
1221 10252045600.37,"10,252,045,600.37", status
);
1223 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1224 DecimalFormat
fmt("#", US
, status
);
1225 CHECK(status
, "DecimalFormat constructor");
1226 UnicodeString
padString("P");
1227 fmt
.setPadCharacter(padString
);
1228 expectPad(fmt
, "*P##.##", DecimalFormat::kPadBeforePrefix
, 5, padString
);
1229 fmt
.setPadCharacter((UnicodeString
)"^");
1230 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, (UnicodeString
)"^");
1231 //commented untill implementation is complete
1232 /* fmt.setPadCharacter((UnicodeString)"^^^");
1233 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1235 padString.append((UChar)0x0061);
1236 padString.append((UChar)0x0302);
1237 fmt.setPadCharacter(padString);
1238 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1239 UnicodeString pattern(patternChars);
1240 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1246 * Upgrade to alphaWorks
1248 void NumberFormatTest::TestPatterns2(void) {
1249 UErrorCode status
= U_ZERO_ERROR
;
1250 DecimalFormatSymbols
US(Locale::getUS(), status
);
1251 CHECK(status
, "DecimalFormatSymbols constructor");
1253 DecimalFormat
fmt("#", US
, status
);
1254 CHECK(status
, "DecimalFormat constructor");
1256 UChar hat
= 0x005E; /*^*/
1258 expectPad(fmt
, "*^#", DecimalFormat::kPadBeforePrefix
, 1, hat
);
1259 expectPad(fmt
, "$*^#", DecimalFormat::kPadAfterPrefix
, 2, hat
);
1260 expectPad(fmt
, "#*^", DecimalFormat::kPadBeforeSuffix
, 1, hat
);
1261 expectPad(fmt
, "#$*^", DecimalFormat::kPadAfterSuffix
, 2, hat
);
1262 expectPad(fmt
, "$*^$#", ILLEGAL
);
1263 expectPad(fmt
, "#$*^$", ILLEGAL
);
1264 expectPad(fmt
, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix
,
1265 12, (UChar
)0x0078 /*x*/);
1266 expectPad(fmt
, "''#0*x", DecimalFormat::kPadBeforeSuffix
,
1267 3, (UChar
)0x0078 /*x*/);
1268 expectPad(fmt
, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix
,
1269 10, (UChar
)0x0061 /*a*/);
1271 fmt
.applyPattern("AA#,##0.00ZZ", status
);
1272 CHECK(status
, "applyPattern");
1273 fmt
.setPadCharacter(hat
);
1275 fmt
.setFormatWidth(10);
1277 fmt
.setPadPosition(DecimalFormat::kPadBeforePrefix
);
1278 expectPat(fmt
, "*^AA#,##0.00ZZ");
1280 fmt
.setPadPosition(DecimalFormat::kPadBeforeSuffix
);
1281 expectPat(fmt
, "AA#,##0.00*^ZZ");
1283 fmt
.setPadPosition(DecimalFormat::kPadAfterSuffix
);
1284 expectPat(fmt
, "AA#,##0.00ZZ*^");
1287 UnicodeString
exp("AA*^#,##0.00ZZ", "");
1288 fmt
.setFormatWidth(12);
1289 fmt
.setPadPosition(DecimalFormat::kPadAfterPrefix
);
1290 expectPat(fmt
, exp
);
1292 fmt
.setFormatWidth(13);
1294 expectPat(fmt
, "AA*^##,##0.00ZZ");
1296 fmt
.setFormatWidth(14);
1298 expectPat(fmt
, "AA*^###,##0.00ZZ");
1300 fmt
.setFormatWidth(15);
1302 expectPat(fmt
, "AA*^####,##0.00ZZ"); // This is the interesting case
1304 fmt
.setFormatWidth(16);
1305 // 12 34567890123456
1306 expectPat(fmt
, "AA*^#,###,##0.00ZZ");
1309 void NumberFormatTest::TestSurrogateSupport(void) {
1310 UErrorCode status
= U_ZERO_ERROR
;
1311 DecimalFormatSymbols
custom(Locale::getUS(), status
);
1312 CHECK(status
, "DecimalFormatSymbols constructor");
1314 custom
.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol
, "decimal");
1315 custom
.setSymbol(DecimalFormatSymbols::kPlusSignSymbol
, "plus");
1316 custom
.setSymbol(DecimalFormatSymbols::kMinusSignSymbol
, " minus ");
1317 custom
.setSymbol(DecimalFormatSymbols::kExponentialSymbol
, "exponent");
1319 UnicodeString
patternStr("*\\U00010000##.##", "");
1320 patternStr
= patternStr
.unescape();
1321 UnicodeString
expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1322 expStr
= expStr
.unescape();
1323 expect2(new DecimalFormat(patternStr
, custom
, status
),
1324 int32_t(0), expStr
, status
);
1326 status
= U_ZERO_ERROR
;
1327 expect2(new DecimalFormat("*^##.##", custom
, status
),
1328 int32_t(0), "^^^^0", status
);
1329 status
= U_ZERO_ERROR
;
1330 expect2(new DecimalFormat("##.##", custom
, status
),
1331 -1.3, " minus 1decimal3", status
);
1332 status
= U_ZERO_ERROR
;
1333 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1334 int32_t(0), "0decimal0exponent0 g-m/s^2", status
);
1335 status
= U_ZERO_ERROR
;
1336 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom
, status
),
1337 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status
);
1338 status
= U_ZERO_ERROR
;
1339 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1340 int32_t(0), "0decimal0 g-m/s^2", status
);
1341 status
= U_ZERO_ERROR
;
1342 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom
, status
),
1343 1.0/3, "0decimal33333 g-m/s^2", status
);
1345 UnicodeString
zero((UChar32
)0x10000);
1346 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, zero
);
1347 expStr
= UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1348 expStr
= expStr
.unescape();
1349 status
= U_ZERO_ERROR
;
1350 expect2(new DecimalFormat("##0.000", custom
, status
),
1351 1.25, expStr
, status
);
1353 custom
.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol
, (UChar
)0x30);
1354 custom
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "units of money");
1355 custom
.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol
, "money separator");
1356 patternStr
= "0.00 \\u00A4' in your bank account'";
1357 patternStr
= patternStr
.unescape();
1358 expStr
= UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1359 status
= U_ZERO_ERROR
;
1360 expect2(new DecimalFormat(patternStr
, custom
, status
),
1361 int32_t(-20), expStr
, status
);
1363 custom
.setSymbol(DecimalFormatSymbols::kPercentSymbol
, "percent");
1364 patternStr
= "'You''ve lost ' -0.00 %' of your money today'";
1365 patternStr
= patternStr
.unescape();
1366 expStr
= UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1367 status
= U_ZERO_ERROR
;
1368 expect2(new DecimalFormat(patternStr
, custom
, status
),
1369 int32_t(-20), expStr
, status
);
1372 void NumberFormatTest::TestCurrencyPatterns(void) {
1373 int32_t i
, locCount
;
1374 const Locale
* locs
= NumberFormat::getAvailableLocales(locCount
);
1375 for (i
=0; i
<locCount
; ++i
) {
1376 UErrorCode ec
= U_ZERO_ERROR
;
1377 NumberFormat
* nf
= NumberFormat::createCurrencyInstance(locs
[i
], ec
);
1378 if (U_FAILURE(ec
)) {
1379 errln("FAIL: Can't create NumberFormat(%s) - %s", locs
[i
].getName(), u_errorName(ec
));
1381 // Make sure currency formats do not have a variable number
1382 // of fraction digits
1383 int32_t min
= nf
->getMinimumFractionDigits();
1384 int32_t max
= nf
->getMaximumFractionDigits();
1388 nf
->format(1.125, b
);
1389 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1390 " min fraction digits != max fraction digits; "
1391 "x 1.0 => " + escape(a
) +
1392 "; x 1.125 => " + escape(b
));
1395 // Make sure EURO currency formats have exactly 2 fraction digits
1396 if (nf
->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1397 DecimalFormat
* df
= (DecimalFormat
*) nf
;
1398 if (u_strcmp(EUR
, df
->getCurrency()) == 0) {
1399 if (min
!= 2 || max
!= 2) {
1402 errln((UnicodeString
)"FAIL: " + locs
[i
].getName() +
1403 " is a EURO format but it does not have 2 fraction digits; "
1414 void NumberFormatTest::TestRegCurrency(void) {
1415 #if !UCONFIG_NO_SERVICE
1416 UErrorCode status
= U_ZERO_ERROR
;
1418 ucurr_forLocale("en_US", USD
, 4, &status
);
1420 ucurr_forLocale("ja_JP", YEN
, 4, &status
);
1422 static const UChar QQQ
[] = {0x51, 0x51, 0x51, 0};
1423 if(U_FAILURE(status
)) {
1424 errln("Unable to get currency for locale, error %s", u_errorName(status
));
1428 UCurrRegistryKey enkey
= ucurr_register(YEN
, "en_US", &status
);
1429 UCurrRegistryKey enUSEUROkey
= ucurr_register(QQQ
, "en_US_EURO", &status
);
1431 ucurr_forLocale("en_US", TMP
, 4, &status
);
1432 if (u_strcmp(YEN
, TMP
) != 0) {
1433 errln("FAIL: didn't return YEN registered for en_US");
1436 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1437 if (u_strcmp(QQQ
, TMP
) != 0) {
1438 errln("FAIL: didn't return QQQ for en_US_EURO");
1441 int32_t fallbackLen
= ucurr_forLocale("en_XX_BAR", TMP
, 4, &status
);
1443 errln("FAIL: tried to fallback en_XX_BAR");
1445 status
= U_ZERO_ERROR
; // reset
1447 if (!ucurr_unregister(enkey
, &status
)) {
1448 errln("FAIL: couldn't unregister enkey");
1451 ucurr_forLocale("en_US", TMP
, 4, &status
);
1452 if (u_strcmp(USD
, TMP
) != 0) {
1453 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1455 status
= U_ZERO_ERROR
; // reset
1457 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1458 if (u_strcmp(QQQ
, TMP
) != 0) {
1459 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1462 ucurr_forLocale("en_US_BLAH", TMP
, 4, &status
);
1463 if (u_strcmp(USD
, TMP
) != 0) {
1464 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1466 status
= U_ZERO_ERROR
; // reset
1468 if (!ucurr_unregister(enUSEUROkey
, &status
)) {
1469 errln("FAIL: couldn't unregister enUSEUROkey");
1472 ucurr_forLocale("en_US_EURO", TMP
, 4, &status
);
1473 if (u_strcmp(EUR
, TMP
) != 0) {
1474 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1476 status
= U_ZERO_ERROR
; // reset
1480 void NumberFormatTest::TestCurrencyNames(void) {
1481 // Do a basic check of getName()
1482 // USD { "US$", "US Dollar" } // 04/04/1792-
1483 UErrorCode ec
= U_ZERO_ERROR
;
1484 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1485 static const UChar CAD
[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
1486 static const UChar ITL
[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
1487 UBool isChoiceFormat
;
1489 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1490 // THE LOCALE DATA before diving into the code.
1491 assertEquals("USD.getName(SYMBOL_NAME)",
1492 UnicodeString("US$"),
1493 UnicodeString(ucurr_getName(USD
, "en",
1495 &isChoiceFormat
, &len
, &ec
)));
1496 assertEquals("USD.getName(LONG_NAME)",
1497 UnicodeString("US Dollar"),
1498 UnicodeString(ucurr_getName(USD
, "en",
1500 &isChoiceFormat
, &len
, &ec
)));
1501 assertSuccess("ucurr_getName", ec
);
1503 // Test that a default or fallback warning is being returned. JB 4239.
1504 (void) ucurr_getName(CAD
, "en_US", UCURR_LONG_NAME
, &isChoiceFormat
,
1506 assertTrue("ucurr_getName (fallback)",
1507 U_USING_FALLBACK_WARNING
== ec
, TRUE
);
1508 (void) ucurr_getName(CAD
, "vi", UCURR_LONG_NAME
, &isChoiceFormat
,
1510 assertTrue("ucurr_getName (default)",
1511 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1513 // Test that a default warning is being returned when falling back to root. JB 4536.
1514 (void) ucurr_getName(ITL
, "cy", UCURR_LONG_NAME
, &isChoiceFormat
,
1516 assertTrue("ucurr_getName (default to root)",
1517 U_USING_DEFAULT_WARNING
== ec
, TRUE
);
1519 // TODO add more tests later
1522 void NumberFormatTest::TestCurrencyUnit(void){
1523 UErrorCode ec
= U_ZERO_ERROR
;
1524 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1525 CurrencyUnit
cu(USD
, ec
);
1526 assertSuccess("CurrencyUnit", ec
);
1528 const UChar
* r
= cu
.getISOCurrency(); // who is the buffer owner ?
1529 assertEquals("getISOCurrency()", USD
, r
);
1531 CurrencyUnit
cu2(cu
);
1533 errln("CurrencyUnit copy constructed object should be same");
1536 CurrencyUnit
* cu3
= (CurrencyUnit
*)cu
.clone();
1538 errln("CurrencyUnit cloned object should be same");
1543 void NumberFormatTest::TestCurrencyAmount(void){
1544 UErrorCode ec
= U_ZERO_ERROR
;
1545 static const UChar USD
[] = {85, 83, 68, 0}; /*USD*/
1546 CurrencyAmount
ca(9, USD
, ec
);
1547 assertSuccess("CurrencyAmount", ec
);
1549 CurrencyAmount
ca2(ca
);
1551 errln("CurrencyAmount copy constructed object should be same");
1556 errln("CurrencyAmount assigned object should be same");
1559 CurrencyAmount
*ca3
= (CurrencyAmount
*)ca
.clone();
1561 errln("CurrencyAmount cloned object should be same");
1566 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1568 Locale
locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1569 UErrorCode status
= U_ZERO_ERROR
;
1570 UnicodeString
intlCurrencySymbol((UChar
)0xa4);
1572 intlCurrencySymbol
.append((UChar
)0xa4);
1574 logln("Current locale is %s", Locale::getDefault().getName());
1575 Locale::setDefault(locBad
, status
);
1576 logln("Current locale is %s", Locale::getDefault().getName());
1577 DecimalFormatSymbols
mySymbols(status
);
1578 if (status
!= U_USING_FALLBACK_WARNING
) {
1579 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1581 if (strcmp(mySymbols
.getLocale().getName(), locBad
.getName()) != 0) {
1582 errln("DecimalFormatSymbols does not have the right locale.");
1584 int symbolEnum
= (int)DecimalFormatSymbols::kDecimalSeparatorSymbol
;
1585 for (; symbolEnum
< (int)DecimalFormatSymbols::kFormatSymbolCount
; symbolEnum
++) {
1586 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum
+ UnicodeString("] = ")
1587 + prettify(mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
)));
1589 if (mySymbols
.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol
)symbolEnum
).length() == 0
1590 && symbolEnum
!= (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
1591 && symbolEnum
!= (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol
)
1593 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum
);
1596 status
= U_ZERO_ERROR
;
1597 Locale::setDefault(locDefault
, status
);
1598 logln("Current locale is %s", Locale::getDefault().getName());
1602 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1603 * behave the same, except for memory ownership semantics. (No
1604 * version of this test on Java, since Java has only one method.)
1606 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1607 UErrorCode ec
= U_ZERO_ERROR
;
1608 DecimalFormatSymbols
*sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1609 if (U_FAILURE(ec
)) {
1610 errln("Fail: DecimalFormatSymbols constructor");
1614 UnicodeString
pat(" #,##0.00");
1615 pat
.insert(0, (UChar
)0x00A4);
1616 DecimalFormat
fmt(pat
, sym
, ec
);
1617 if (U_FAILURE(ec
)) {
1618 errln("Fail: DecimalFormat constructor");
1623 fmt
.format(2350.75, str
);
1624 if (str
== "$ 2,350.75") {
1627 errln("Fail: " + str
+ ", expected $ 2,350.75");
1630 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1631 if (U_FAILURE(ec
)) {
1632 errln("Fail: DecimalFormatSymbols constructor");
1636 sym
->setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1637 fmt
.adoptDecimalFormatSymbols(sym
);
1640 fmt
.format(2350.75, str
);
1641 if (str
== "Q 2,350.75") {
1644 errln("Fail: adoptDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1647 sym
= new DecimalFormatSymbols(Locale::getUS(), ec
);
1648 if (U_FAILURE(ec
)) {
1649 errln("Fail: DecimalFormatSymbols constructor");
1653 DecimalFormat
fmt2(pat
, sym
, ec
);
1654 if (U_FAILURE(ec
)) {
1655 errln("Fail: DecimalFormat constructor");
1659 DecimalFormatSymbols
sym2(Locale::getUS(), ec
);
1660 if (U_FAILURE(ec
)) {
1661 errln("Fail: DecimalFormatSymbols constructor");
1664 sym2
.setSymbol(DecimalFormatSymbols::kCurrencySymbol
, "Q");
1665 fmt2
.setDecimalFormatSymbols(sym2
);
1668 fmt2
.format(2350.75, str
);
1669 if (str
== "Q 2,350.75") {
1672 errln("Fail: setDecimalFormatSymbols -> " + str
+ ", expected Q 2,350.75");
1676 void NumberFormatTest::TestPerMill() {
1677 UErrorCode ec
= U_ZERO_ERROR
;
1679 DecimalFormat
fmt(ctou("###.###\\u2030"), ec
);
1680 if (!assertSuccess("DecimalFormat ct", ec
)) return;
1681 assertEquals("0.4857 x ###.###\\u2030",
1682 ctou("485.7\\u2030"), fmt
.format(0.4857, str
));
1684 DecimalFormatSymbols
sym(Locale::getUS(), ec
);
1685 sym
.setSymbol(DecimalFormatSymbols::kPerMillSymbol
, ctou("m"));
1686 DecimalFormat
fmt2("", sym
, ec
);
1687 fmt2
.applyLocalizedPattern("###.###m", ec
);
1688 if (!assertSuccess("setup", ec
)) return;
1690 assertEquals("0.4857 x ###.###m",
1691 "485.7m", fmt2
.format(0.4857, str
));
1695 * Generic test for patterns that should be legal/illegal.
1697 void NumberFormatTest::TestIllegalPatterns() {
1699 // Prefix with "-:" for illegal patterns
1700 // Prefix with "+:" for legal patterns
1701 const char* DATA
[] = {
1702 // Unquoted special characters in the suffix are illegal
1707 for (int32_t i
=0; DATA
[i
]; ++i
) {
1708 const char* pat
=DATA
[i
];
1709 UBool valid
= (*pat
) == '+';
1711 UErrorCode ec
= U_ZERO_ERROR
;
1712 DecimalFormat
fmt(pat
, ec
); // locale doesn't matter here
1713 if (U_SUCCESS(ec
) == valid
) {
1714 logln("Ok: pattern \"%s\": %s",
1715 pat
, u_errorName(ec
));
1717 errln("FAIL: pattern \"%s\" should have %s; got %s",
1718 pat
, (valid
?"succeeded":"failed"),
1724 //----------------------------------------------------------------------
1726 static const char* KEYWORDS
[] = {
1727 /*0*/ "ref=", // <reference pattern to parse numbers>
1728 /*1*/ "loc=", // <locale for formats>
1729 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1730 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1731 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1732 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1733 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1734 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1735 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1740 * Return an integer representing the next token from this
1741 * iterator. The integer will be an index into the given list, or
1742 * -1 if there are no more tokens, or -2 if the token is not on
1745 static int32_t keywordIndex(const UnicodeString
& tok
) {
1746 for (int32_t i
=0; KEYWORDS
[i
]!=0; ++i
) {
1747 if (tok
==KEYWORDS
[i
]) {
1755 * Parse a CurrencyAmount using the given NumberFormat, with
1756 * the 'delim' character separating the number and the currency.
1758 static void parseCurrencyAmount(const UnicodeString
& str
,
1759 const NumberFormat
& fmt
,
1761 Formattable
& result
,
1763 UnicodeString num
, cur
;
1764 int32_t i
= str
.indexOf(delim
);
1765 str
.extractBetween(0, i
, num
);
1766 str
.extractBetween(i
+1, INT32_MAX
, cur
);
1768 fmt
.parse(num
, n
, ec
);
1769 result
.adoptObject(new CurrencyAmount(n
, cur
.getTerminatedBuffer(), ec
));
1772 void NumberFormatTest::TestCases() {
1773 UErrorCode ec
= U_ZERO_ERROR
;
1774 TextFile
reader("NumberFormatTestCases.txt", "UTF8", ec
);
1775 if (U_FAILURE(ec
)) {
1776 errln("FAIL: Couldn't open NumberFormatTestCases.txt");
1779 TokenIterator
tokens(&reader
);
1781 Locale
loc("en", "US", "");
1782 DecimalFormat
*ref
= 0, *fmt
= 0;
1783 MeasureFormat
*mfmt
= 0;
1784 UnicodeString pat
, tok
, mloc
, str
, out
, where
, currAmt
;
1789 if (!tokens
.next(tok
, ec
)) {
1792 where
= UnicodeString("(") + tokens
.getLineNumber() + ") ";
1793 int32_t cmd
= keywordIndex(tok
);
1796 // ref= <reference pattern>
1797 if (!tokens
.next(tok
, ec
)) goto error
;
1799 ref
= new DecimalFormat(tok
,
1800 new DecimalFormatSymbols(Locale::getUS(), ec
), ec
);
1801 if (U_FAILURE(ec
)) {
1802 dataerrln("Error constructing DecimalFormat");
1808 if (!tokens
.next(tok
, ec
)) goto error
;
1809 loc
= Locale::createFromName(CharString(tok
));
1815 if (!tokens
.next(tok
, ec
)) goto error
;
1819 fmt
= new DecimalFormat(pat
, new DecimalFormatSymbols(loc
, ec
), ec
);
1820 if (U_FAILURE(ec
)) {
1821 errln("FAIL: " + where
+ "Pattern \"" + pat
+ "\": " + u_errorName(ec
));
1823 if (!tokens
.next(tok
, ec
)) goto error
;
1824 if (!tokens
.next(tok
, ec
)) goto error
;
1826 if (!tokens
.next(tok
, ec
)) goto error
;
1831 if (cmd
== 2 || cmd
== 3 || cmd
== 4) {
1832 // f: <pattern or '-'> <number> <exp. string>
1833 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1834 // rt: <pattern or '-'> <number> <string>
1836 if (!tokens
.next(num
, ec
)) goto error
;
1837 if (!tokens
.next(str
, ec
)) goto error
;
1838 ref
->parse(num
, n
, ec
);
1839 assertSuccess("parse", ec
);
1840 assertEquals(where
+ "\"" + pat
+ "\".format(" + num
+ ")",
1841 str
, fmt
->format(n
, out
.remove(), ec
));
1842 assertSuccess("format", ec
);
1843 if (cmd
== 3) { // fp:
1844 if (!tokens
.next(num
, ec
)) goto error
;
1845 ref
->parse(num
, n
, ec
);
1846 assertSuccess("parse", ec
);
1848 if (cmd
!= 2) { // != f:
1850 fmt
->parse(str
, m
, ec
);
1851 assertSuccess("parse", ec
);
1852 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
1856 // p: <pattern or '-'> <string to parse> <exp. number>
1858 UnicodeString expstr
;
1859 if (!tokens
.next(str
, ec
)) goto error
;
1860 if (!tokens
.next(expstr
, ec
)) goto error
;
1862 ref
->parse(expstr
, exp
, ec
);
1863 assertSuccess("parse", ec
);
1864 fmt
->parse(str
, n
, ec
);
1865 assertSuccess("parse", ec
);
1866 assertEquals(where
+ "\"" + pat
+ "\".parse(\"" + str
+ "\")",
1871 if (!tokens
.next(tok
, ec
)) goto error
;
1875 mfmt
= MeasureFormat::createCurrencyFormat(
1876 Locale::createFromName(CharString(mloc
)), ec
);
1877 if (U_FAILURE(ec
)) {
1878 errln("FAIL: " + where
+ "Loc \"" + mloc
+ "\": " + u_errorName(ec
));
1880 if (!tokens
.next(tok
, ec
)) goto error
;
1881 if (!tokens
.next(tok
, ec
)) goto error
;
1882 if (!tokens
.next(tok
, ec
)) goto error
;
1886 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1887 if (!tokens
.next(currAmt
, ec
)) goto error
;
1888 if (!tokens
.next(str
, ec
)) goto error
;
1889 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
1890 if (assertSuccess("parseCurrencyAmount", ec
)) {
1891 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").format(" + currAmt
+ ")",
1892 str
, mfmt
->format(n
, out
.remove(), ec
));
1893 assertSuccess("format", ec
);
1895 if (!tokens
.next(currAmt
, ec
)) goto error
;
1896 parseCurrencyAmount(currAmt
, *ref
, (UChar
)0x2F/*'/'*/, n
, ec
);
1897 if (assertSuccess("parseCurrencyAmount", ec
)) {
1899 mfmt
->parseObject(str
, m
, ec
);
1900 if (assertSuccess("parseCurrency", ec
)) {
1901 assertEquals(where
+ "getCurrencyFormat(" + mloc
+ ").parse(\"" + str
+ "\")",
1907 // perr: <pattern or '-'> <invalid string>
1908 errln("FAIL: Under construction");
1911 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1912 UnicodeString testpat
;
1913 UnicodeString exppat
;
1914 if (!tokens
.next(testpat
, ec
)) goto error
;
1915 if (!tokens
.next(exppat
, ec
)) goto error
;
1916 UBool err
= exppat
== "err";
1917 UBool existingPat
= FALSE
;
1918 if (testpat
== "-") {
1920 errln("FAIL: " + where
+ "Invalid command \"pat: - err\"");
1926 if (exppat
== "-") exppat
= testpat
;
1927 DecimalFormat
* f
= 0;
1928 UErrorCode ec2
= U_ZERO_ERROR
;
1932 f
= new DecimalFormat(testpat
, ec2
);
1934 if (U_SUCCESS(ec2
)) {
1936 errln("FAIL: " + where
+ "Invalid pattern \"" + testpat
+
1940 assertEquals(where
+ "\"" + testpat
+ "\".toPattern()",
1941 exppat
, f
->toPattern(pat2
));
1945 logln("Ok: " + where
+ "Invalid pattern \"" + testpat
+
1946 "\" failed: " + u_errorName(ec2
));
1948 errln("FAIL: " + where
+ "Valid pattern \"" + testpat
+
1949 "\" failed: " + u_errorName(ec2
));
1952 if (!existingPat
) delete f
;
1955 errln("FAIL: " + where
+ "Unknown command \"" + tok
+ "\"");
1962 if (U_SUCCESS(ec
)) {
1963 errln("FAIL: Unexpected EOF");
1965 errln("FAIL: " + where
+ "Unexpected " + u_errorName(ec
));
1975 //----------------------------------------------------------------------
1977 //----------------------------------------------------------------------
1979 UBool
NumberFormatTest::equalValue(const Formattable
& a
, const Formattable
& b
) {
1980 if (a
.getType() == b
.getType()) {
1984 if (a
.getType() == Formattable::kLong
) {
1985 if (b
.getType() == Formattable::kInt64
) {
1986 return a
.getLong() == b
.getLong();
1987 } else if (b
.getType() == Formattable::kDouble
) {
1988 return (double) a
.getLong() == b
.getDouble(); // TODO check use of double instead of long
1990 } else if (a
.getType() == Formattable::kDouble
) {
1991 if (b
.getType() == Formattable::kLong
) {
1992 return a
.getDouble() == (double) b
.getLong();
1993 } else if (b
.getType() == Formattable::kInt64
) {
1994 return a
.getDouble() == (double)b
.getInt64();
1996 } else if (a
.getType() == Formattable::kInt64
) {
1997 if (b
.getType() == Formattable::kLong
) {
1998 return a
.getInt64() == (int64_t)b
.getLong();
1999 } else if (b
.getType() == Formattable::kDouble
) {
2000 return a
.getInt64() == (int64_t)b
.getDouble();
2006 void NumberFormatTest::expect2(NumberFormat
& fmt
, const Formattable
& n
, const UnicodeString
& str
) {
2007 // Don't round-trip format test, since we explicitly do it
2008 expect(fmt
, n
, str
, FALSE
);
2009 expect(fmt
, str
, n
);
2012 void NumberFormatTest::expect2(NumberFormat
* fmt
, const Formattable
& n
,
2013 const UnicodeString
& exp
,
2014 UErrorCode status
) {
2015 if (U_FAILURE(status
)) {
2016 errln("FAIL: NumberFormat constructor");
2018 expect2(*fmt
, n
, exp
);
2023 void NumberFormatTest::expect(NumberFormat
& fmt
, const UnicodeString
& str
, const Formattable
& n
) {
2024 UErrorCode status
= U_ZERO_ERROR
;
2026 fmt
.parse(str
, num
, status
);
2027 if (U_FAILURE(status
)) {
2028 errln(UnicodeString("FAIL: Parse failed for \"") + str
+ "\"");
2032 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2033 if (equalValue(num
, n
)) {
2034 logln(UnicodeString("Ok \"") + str
+ "\" x " +
2038 errln(UnicodeString("FAIL \"") + str
+ "\" x " +
2040 toString(num
) + ", expected " + toString(n
));
2044 void NumberFormatTest::expect(NumberFormat
& fmt
, const Formattable
& n
,
2045 const UnicodeString
& exp
, UBool rt
) {
2048 UErrorCode status
= U_ZERO_ERROR
;
2049 fmt
.format(n
, saw
, pos
, status
);
2050 CHECK(status
, "NumberFormat::format");
2052 ((DecimalFormat
*) &fmt
)->toPattern(pat
);
2054 logln(UnicodeString("Ok ") + toString(n
) + " x " +
2055 escape(pat
) + " = \"" +
2056 escape(saw
) + "\"");
2057 // We should be able to round-trip the formatted string =>
2058 // number => string (but not the other way around: number
2059 // => string => number2, might have number2 != number):
2062 fmt
.parse(exp
, n2
, status
);
2063 if (U_FAILURE(status
)) {
2064 errln(UnicodeString("FAIL: Parse failed for \"") + exp
+ "\"");
2068 fmt
.format(n2
, saw2
, pos
, status
);
2069 CHECK(status
, "NumberFormat::format");
2071 errln((UnicodeString
)"FAIL \"" + exp
+ "\" => " + toString(n2
) +
2072 " => \"" + saw2
+ "\"");
2076 errln(UnicodeString("FAIL ") + toString(n
) + " x " +
2077 escape(pat
) + " = \"" +
2078 escape(saw
) + "\", expected \"" + exp
+ "\"");
2082 void NumberFormatTest::expect(NumberFormat
* fmt
, const Formattable
& n
,
2083 const UnicodeString
& exp
,
2084 UErrorCode status
) {
2085 if (U_FAILURE(status
)) {
2086 errln("FAIL: NumberFormat constructor");
2088 expect(*fmt
, n
, exp
);
2093 void NumberFormatTest::expectCurrency(NumberFormat
& nf
, const Locale
& locale
,
2094 double value
, const UnicodeString
& string
) {
2095 UErrorCode ec
= U_ZERO_ERROR
;
2096 DecimalFormat
& fmt
= * (DecimalFormat
*) &nf
;
2097 const UChar DEFAULT_CURR
[] = {45/*-*/,0};
2099 u_strcpy(curr
, DEFAULT_CURR
);
2100 if (*locale
.getLanguage() != 0) {
2101 ucurr_forLocale(locale
.getName(), curr
, 4, &ec
);
2102 assertSuccess("ucurr_forLocale", ec
);
2103 fmt
.setCurrency(curr
, ec
);
2104 assertSuccess("DecimalFormat::setCurrency", ec
);
2105 fmt
.setCurrency(curr
); //Deprecated variant, for coverage only
2108 fmt
.format(value
, s
);
2109 s
.findAndReplace((UChar32
)0x00A0, (UChar32
)0x0020);
2111 // Default display of the number yields "1234.5599999999999"
2112 // instead of "1234.56". Use a formatter to fix this.
2114 NumberFormat::createInstance(Locale::getUS(), ec
);
2116 if (U_FAILURE(ec
)) {
2117 // Oops; bad formatter. Use default op+= display.
2118 v
= (UnicodeString
)"" + value
;
2120 f
->setMaximumFractionDigits(4);
2121 f
->setGroupingUsed(FALSE
);
2122 f
->format(value
, v
);
2127 logln((UnicodeString
)"Ok: " + v
+ " x " + curr
+ " => " + prettify(s
));
2129 errln((UnicodeString
)"FAIL: " + v
+ " x " + curr
+ " => " + prettify(s
) +
2130 ", expected " + prettify(string
));
2134 void NumberFormatTest::expectPat(DecimalFormat
& fmt
, const UnicodeString
& exp
) {
2138 logln(UnicodeString("Ok \"") + pat
+ "\"");
2140 errln(UnicodeString("FAIL \"") + pat
+ "\", expected \"" + exp
+ "\"");
2144 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2146 expectPad(fmt
, pat
, pos
, 0, (UnicodeString
)"");
2148 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2149 int32_t pos
, int32_t width
, UChar pad
) {
2150 expectPad(fmt
, pat
, pos
, width
, UnicodeString(pad
));
2152 void NumberFormatTest::expectPad(DecimalFormat
& fmt
, const UnicodeString
& pat
,
2153 int32_t pos
, int32_t width
, const UnicodeString
& pad
) {
2154 int32_t apos
= 0, awidth
= 0;
2155 UnicodeString apadStr
;
2156 UErrorCode status
= U_ZERO_ERROR
;
2157 fmt
.applyPattern(pat
, status
);
2158 if (U_SUCCESS(status
)) {
2159 apos
= fmt
.getPadPosition();
2160 awidth
= fmt
.getFormatWidth();
2161 apadStr
=fmt
.getPadCharacterString();
2167 if (apos
== pos
&& awidth
== width
&& apadStr
== pad
) {
2168 UnicodeString infoStr
;
2169 if (pos
== ILLEGAL
) {
2170 infoStr
= UnicodeString(" width=", "") + awidth
+ UnicodeString(" pad=", "") + apadStr
;
2172 logln(UnicodeString("Ok \"") + pat
+ "\" pos=" + apos
+ infoStr
);
2174 errln(UnicodeString("FAIL \"") + pat
+ "\" pos=" + apos
+
2175 " width=" + awidth
+ " pad=" + apadStr
+
2176 ", expected " + pos
+ " " + width
+ " " + pad
);
2179 void NumberFormatTest::TestJB3832(){
2180 const char* localeID
= "pt_PT@currency=PTE";
2181 Locale
loc(localeID
);
2182 UErrorCode status
= U_ZERO_ERROR
;
2183 UnicodeString
expected("1,150$50 Esc.");
2185 NumberFormat
* currencyFmt
= NumberFormat::createCurrencyInstance(loc
, status
);
2186 if(U_FAILURE(status
)){
2187 errln("Could not create currency formatter for locale %s", localeID
);
2190 currencyFmt
->format(1150.50, s
);
2192 errln(UnicodeString("FAIL: Expected: ")+expected
2193 + UnicodeString(" Got: ") + s
2194 + UnicodeString( " for locale: ")+ UnicodeString(localeID
) );
2196 if (U_FAILURE(status
)){
2197 errln("FAIL: Status %s", u_errorName(status
));
2202 void NumberFormatTest::TestHost()
2205 Win32NumberTest::testLocales(this);
2209 void NumberFormatTest::TestCurrencyFormat()
2211 // This test is here to increase code coverage.
2212 UErrorCode status
= U_ZERO_ERROR
;
2213 MeasureFormat
*cloneObj
;
2215 Formattable toFormat
, result
;
2216 static const UChar ISO_CODE
[4] = {0x0047, 0x0042, 0x0050, 0};
2218 Locale saveDefaultLocale
= Locale::getDefault();
2219 Locale::setDefault( Locale::getUK(), status
);
2220 if (U_FAILURE(status
)) {
2221 errln("couldn't set default Locale!");
2225 MeasureFormat
*measureObj
= MeasureFormat::createCurrencyFormat(status
);
2226 Locale::setDefault( saveDefaultLocale
, status
);
2227 if (U_FAILURE(status
)){
2228 errln("FAIL: Status %s", u_errorName(status
));
2231 cloneObj
= (MeasureFormat
*)measureObj
->clone();
2232 if (cloneObj
== NULL
) {
2233 errln("Clone doesn't work");
2236 toFormat
.adoptObject(new CurrencyAmount(1234.56, ISO_CODE
, status
));
2237 measureObj
->format(toFormat
, str
, status
);
2238 measureObj
->parseObject(str
, result
, status
);
2239 if (U_FAILURE(status
)){
2240 errln("FAIL: Status %s", u_errorName(status
));
2242 if (result
!= toFormat
) {
2243 errln("measureObj does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2245 status
= U_ZERO_ERROR
;
2247 cloneObj
->format(toFormat
, str
, status
);
2248 cloneObj
->parseObject(str
, result
, status
);
2249 if (U_FAILURE(status
)){
2250 errln("FAIL: Status %s", u_errorName(status
));
2252 if (result
!= toFormat
) {
2253 errln("Clone does not round trip. Formatted string was \"" + str
+ "\" Got: " + toString(result
) + " Expected: " + toString(toFormat
));
2260 #endif /* #if !UCONFIG_NO_FORMATTING */