]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/numfmtst.cpp
ICU-6.2.4.tar.gz
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
CommitLineData
b75a7d8f
A
1/********************************************************************
2 * COPYRIGHT:
374ca955 3 * Copyright (c) 1997-2004, International Business Machines Corporation and
b75a7d8f
A
4 * others. All Rights Reserved.
5 ********************************************************************/
6/* Modification History:
7* Date Name Description
8* 07/15/99 helena Ported to HPUX 10/11 CC.
9*/
10
11#include "unicode/utypes.h"
12
13#if !UCONFIG_NO_FORMATTING
14
15#include "numfmtst.h"
16#include "unicode/dcfmtsym.h"
17#include "unicode/decimfmt.h"
18#include "unicode/ucurr.h"
19#include "unicode/ustring.h"
374ca955
A
20#include "unicode/measfmt.h"
21#include "unicode/curramt.h"
22#include "digitlst.h"
23#include "textfile.h"
24#include "tokiter.h"
25#include "charstr.h"
26#include "putilimp.h"
b75a7d8f
A
27#include <float.h>
28#include <string.h>
b75a7d8f
A
29
30static const UChar EUR[] = {69,85,82,0}; // "EUR"
31
32// *****************************************************************************
33// class NumberFormatTest
34// *****************************************************************************
35
36#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
37
38#define CHECK(status,str) if (U_FAILURE(status)) { errln(UnicodeString("FAIL: ") + str); return; }
39
40void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
41{
42 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
43 switch (index) {
44 CASE(0,TestCurrencySign);
45 CASE(1,TestCurrency);
46 CASE(2,TestParse);
47 CASE(3,TestRounding487);
48 CASE(4,TestQuotes);
49 CASE(5,TestExponential);
50 CASE(6,TestPatterns);
51
52 // Upgrade to alphaWorks - liu 5/99
53 CASE(7,TestExponent);
54 CASE(8,TestScientific);
55 CASE(9,TestPad);
56 CASE(10,TestPatterns2);
57 CASE(11,TestSecondaryGrouping);
58 CASE(12,TestSurrogateSupport);
59 CASE(13,TestAPI);
60
61 CASE(14,TestCurrencyObject);
62 CASE(15,TestCurrencyPatterns);
63 CASE(16,TestDigitList);
64 CASE(17,TestWhiteSpaceParsing);
65 CASE(18,TestComplexCurrency);
66 CASE(19,TestRegCurrency);
67 CASE(20,TestSymbolsWithBadLocale);
68 CASE(21,TestAdoptDecimalFormatSymbols);
69
374ca955
A
70 CASE(22,TestScientific2);
71 CASE(23,TestScientificGrouping);
72 CASE(24,TestInt64);
73
74 CASE(25,TestPerMill);
75 CASE(26,TestIllegalPatterns);
76 CASE(27,TestCases);
77
78 CASE(28,TestCurrencyNames);
79
b75a7d8f
A
80 default: name = ""; break;
81 }
82}
83
84// -------------------------------------
85
86// Test API (increase code coverage)
87void
88NumberFormatTest::TestAPI(void)
89{
90 logln("Test API");
91 UErrorCode status = U_ZERO_ERROR;
92 NumberFormat *test = NumberFormat::createInstance("root", status);
93 if(U_FAILURE(status)) {
94 errln("unable to create format object");
95 }
96 if(test != NULL) {
97 test->setMinimumIntegerDigits(10);
98 test->setMaximumIntegerDigits(2);
99
100 test->setMinimumFractionDigits(10);
101 test->setMaximumFractionDigits(2);
102
103 UnicodeString result;
104 FieldPosition pos;
105 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
106 test->format(bla, result, pos, status);
107 if(U_SUCCESS(status)) {
108 errln("Yuck... Formatted a duck... As a number!");
109 } else {
110 status = U_ZERO_ERROR;
111 }
112
113 delete test;
114 }
b75a7d8f
A
115}
116
117// Test various patterns
118void
119NumberFormatTest::TestPatterns(void)
120{
121 UErrorCode status = U_ZERO_ERROR;
122 DecimalFormatSymbols sym(Locale::getUS(), status);
123 if (U_FAILURE(status)) { errln("FAIL: Could not construct DecimalFormatSymbols"); return; }
124
125 const char* pat[] = { "#.#", "#.", ".#", "#" };
126 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
127 const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
128 const char* num[] = { "0", "0.", ".0", "0" };
129 for (int32_t i=0; i<pat_length; ++i)
130 {
131 status = U_ZERO_ERROR;
132 DecimalFormat fmt(pat[i], sym, status);
133 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
134 UnicodeString newp; fmt.toPattern(newp);
135 if (!(newp == newpat[i]))
136 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
137 "; " + newp + " seen instead");
138
139 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
140 if (!(s == num[i]))
141 {
142 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
143 "; " + s + " seen instead");
144 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
145 }
146 }
147}
148
149void
150NumberFormatTest::TestDigitList(void)
151{
152 // API coverage for DigitList
153 /*
154 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
155 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
156 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
157 */
158 DigitList list1;
159 list1.append('1');
160 list1.fDecimalAt = 1;
161 DigitList list2;
374ca955 162 list2.set((int32_t)1);
b75a7d8f
A
163 if (list1 != list2) {
164 errln("digitlist append, operator!= or set failed ");
165 }
166 if (!(list1 == list2)) {
167 errln("digitlist append, operator== or set failed ");
168 }
169}
170
171// -------------------------------------
172
173// Test exponential pattern
174void
175NumberFormatTest::TestExponential(void)
176{
177 UErrorCode status = U_ZERO_ERROR;
178 DecimalFormatSymbols sym(Locale::getUS(), status);
179 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormatSymbols ct"); return; }
180 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
181 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
182
183// The following #if statements allow this test to be built and run on
184// platforms that do not have standard IEEE numerics. For example,
185// S/390 doubles have an exponent range of -78 to +75. For the
186// following #if statements to work, float.h must define
187// DBL_MAX_10_EXP to be a compile-time constant.
188
189// This section may be expanded as needed.
190
191#if DBL_MAX_10_EXP > 300
192 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
193 int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
194 const char* valFormat[] =
195 {
196 // 0.####E0
197 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
198 // 00.000E00
199 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
200 // ##0.######E000
201 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
202 // 0.###E0;[0.###E0]
203 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
204 };
205 double valParse[] =
206 {
207 0.01234, 123460000, 1.23E300, -3.1416E-271,
208 0.01234, 123460000, 1.23E300, -3.1416E-271,
209 0.01234, 123456800, 1.23E300, -3.141593E-271,
210 0.01234, 123500000, 1.23E300, -3.142E-271,
211 };
212#elif DBL_MAX_10_EXP > 70
213 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
214 int32_t val_length = sizeof(val) / sizeof(val[0]);
215 char* valFormat[] =
216 {
217 // 0.####E0
218 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
219 // 00.000E00
220 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
221 // ##0.######E000
222 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
223 // 0.###E0;[0.###E0]
224 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
225 };
226 double valParse[] =
227 {
228 0.01234, 123460000, 1.23E70, -3.1416E-71,
229 0.01234, 123460000, 1.23E70, -3.1416E-71,
230 0.01234, 123456800, 1.23E70, -3.141593E-71,
231 0.01234, 123500000, 1.23E70, -3.142E-71,
232 };
233#else
234 // Don't test double conversion
235 double* val = 0;
236 int32_t val_length = 0;
237 char** valFormat = 0;
238 double* valParse = 0;
239 logln("Warning: Skipping double conversion tests");
240#endif
241
242 int32_t lval[] = { 0, -1, 1, 123456789 };
243 int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
244 const char* lvalFormat[] =
245 {
246 // 0.####E0
247 "0E0", "-1E0", "1E0", "1.2346E8",
248 // 00.000E00
249 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
250 // ##0.######E000
251 "0E000", "-1E000", "1E000", "123.4568E006",
252 // 0.###E0;[0.###E0]
253 "0E0", "[1E0]", "1E0", "1.235E8"
254 };
255 int32_t lvalParse[] =
256 {
257 0, -1, 1, 123460000,
258 0, -1, 1, 123460000,
259 0, -1, 1, 123456800,
260 0, -1, 1, 123500000,
261 };
262 int32_t ival = 0, ilval = 0;
263 for (int32_t p=0; p<pat_length; ++p)
264 {
265 DecimalFormat fmt(pat[p], sym, status);
266 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
267 UnicodeString pattern;
268 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
269 fmt.toPattern(pattern) + "\"");
270 int32_t v;
271 for (v=0; v<val_length; ++v)
272 {
273 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
274 logln((UnicodeString)" " + val[v] + " -format-> " + s);
275 if (s != valFormat[v+ival])
276 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
277
278 ParsePosition pos(0);
279 Formattable af;
280 fmt.parse(s, af, pos);
281 double a;
282 UBool useEpsilon = FALSE;
283 if (af.getType() == Formattable::kLong)
284 a = af.getLong();
285 else if (af.getType() == Formattable::kDouble) {
286 a = af.getDouble();
287#if defined(OS390) || defined(OS400)
288 // S/390 will show a failure like this:
289 //| -3.141592652999999e-271 -format-> -3.1416E-271
290 //| -parse-> -3.1416e-271
291 //| FAIL: Expected -3.141599999999999e-271
292 // To compensate, we use an epsilon-based equality
293 // test on S/390 only. We don't want to do this in
294 // general because it's less exacting.
295 useEpsilon = TRUE;
296#endif
297 }
298 else {
299 errln((UnicodeString)"FAIL: Non-numeric Formattable returned");
300 continue;
301 }
302 if (pos.getIndex() == s.length())
303 {
304 logln((UnicodeString)" -parse-> " + a);
305 // Use epsilon comparison as necessary
306 if ((useEpsilon &&
307 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
308 (!useEpsilon && a != valParse[v+ival]))
309 {
310 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival]);
311 }
312 }
313 else {
314 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
315 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
316 }
317 }
318 for (v=0; v<lval_length; ++v)
319 {
320 UnicodeString s;
321 (*(NumberFormat*)&fmt).format(lval[v], s);
322 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
323 if (s != lvalFormat[v+ilval])
324 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
325
326 ParsePosition pos(0);
327 Formattable af;
328 fmt.parse(s, af, pos);
374ca955
A
329 if (af.getType() == Formattable::kLong ||
330 af.getType() == Formattable::kInt64) {
331 UErrorCode status = U_ZERO_ERROR;
332 int32_t a = af.getLong(status);
b75a7d8f
A
333 if (pos.getIndex() == s.length())
334 {
335 logln((UnicodeString)" -parse-> " + a);
336 if (a != lvalParse[v+ilval])
337 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval]);
338 }
339 else
340 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
341 }
342 else
343 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
344 + " Double: " + af.getDouble()
345 + ", Long: " + af.getLong());
346 }
347 ival += val_length;
348 ilval += lval_length;
349 }
350}
351
374ca955
A
352void
353NumberFormatTest::TestScientific2() {
354 // jb 2552
355 UErrorCode status = U_ZERO_ERROR;
356 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
357 if (U_SUCCESS(status)) {
358 double num = 12.34;
359 expect(*fmt, num, "$12.34");
360 fmt->setScientificNotation(TRUE);
361 expect(*fmt, num, "$1.23E1");
362 fmt->setScientificNotation(FALSE);
363 expect(*fmt, num, "$12.34");
364 }
365 delete fmt;
366}
367
368void
369NumberFormatTest::TestScientificGrouping() {
370 // jb 2552
371 UErrorCode status = U_ZERO_ERROR;
372 DecimalFormat fmt("##0.00E0",status);
373 if (U_SUCCESS(status)) {
374 expect(fmt, .01234, "12.3E-3");
375 expect(fmt, .1234, "123E-3");
376 expect(fmt, 1.234, "1.23E0");
377 expect(fmt, 12.34, "12.3E0");
378 expect(fmt, 123.4, "123E0");
379 expect(fmt, 1234., "1.23E3");
380 }
381}
382
383static void setFromString(DigitList& dl, const char* str) {
384 char c;
385 UBool decimalSet = FALSE;
386 dl.clear();
387 while ((c = *str++)) {
388 if (c == '-') {
389 dl.fIsPositive = FALSE;
390 } else if (c == '+') {
391 dl.fIsPositive = TRUE;
392 } else if (c == '.') {
393 dl.fDecimalAt = dl.fCount;
394 decimalSet = TRUE;
395 } else {
396 dl.append(c);
397 }
398 }
399 if (!decimalSet) {
400 dl.fDecimalAt = dl.fCount;
401 }
402}
403
404void
405NumberFormatTest::TestInt64() {
406 UErrorCode status = U_ZERO_ERROR;
407 DecimalFormat fmt("#.#E0",status);
408 fmt.setMaximumFractionDigits(20);
409 if (U_SUCCESS(status)) {
410 expect(fmt, (Formattable)(int64_t)0, "0E0");
411 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
412 expect(fmt, (Formattable)(int64_t)1, "1E0");
413 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
414 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
415 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
416 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
417 }
418
419 // also test digitlist
420 int64_t int64max = U_INT64_MAX;
421 int64_t int64min = U_INT64_MIN;
422 const char* int64maxstr = "9223372036854775807";
423 const char* int64minstr = "-9223372036854775808";
424 UnicodeString fail("fail: ");
425
426 // test max int64 value
427 DigitList dl;
428 setFromString(dl, int64maxstr);
429 {
430 if (!dl.fitsIntoInt64(FALSE)) {
431 errln(fail + int64maxstr + " didn't fit");
432 }
433 int64_t int64Value = dl.getInt64();
434 if (int64Value != int64max) {
435 errln(fail + int64maxstr);
436 }
437 dl.set(int64Value);
438 int64Value = dl.getInt64();
439 if (int64Value != int64max) {
440 errln(fail + int64maxstr);
441 }
442 }
443 // test negative of max int64 value (1 shy of min int64 value)
444 dl.fIsPositive = FALSE;
445 {
446 if (!dl.fitsIntoInt64(FALSE)) {
447 errln(fail + "-" + int64maxstr + " didn't fit");
448 }
449 int64_t int64Value = dl.getInt64();
450 if (int64Value != -int64max) {
451 errln(fail + "-" + int64maxstr);
452 }
453 dl.set(int64Value);
454 int64Value = dl.getInt64();
455 if (int64Value != -int64max) {
456 errln(fail + "-" + int64maxstr);
457 }
458 }
459 // test min int64 value
460 setFromString(dl, int64minstr);
461 {
462 if (!dl.fitsIntoInt64(FALSE)) {
463 errln(fail + "-" + int64minstr + " didn't fit");
464 }
465 int64_t int64Value = dl.getInt64();
466 if (int64Value != int64min) {
467 errln(fail + int64minstr);
468 }
469 dl.set(int64Value);
470 int64Value = dl.getInt64();
471 if (int64Value != int64min) {
472 errln(fail + int64minstr);
473 }
474 }
475 // test negative of min int 64 value (1 more than max int64 value)
476 dl.fIsPositive = TRUE; // won't fit
477 {
478 if (dl.fitsIntoInt64(FALSE)) {
479 errln(fail + "-(" + int64minstr + ") didn't fit");
480 }
481 }
482}
483
b75a7d8f
A
484// -------------------------------------
485
486// Test the handling of quotes
487void
488NumberFormatTest::TestQuotes(void)
489{
490 UErrorCode status = U_ZERO_ERROR;
491 UnicodeString *pat;
492 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
493 pat = new UnicodeString("a'fo''o'b#");
494 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
495 UnicodeString s;
496 ((NumberFormat*)fmt)->format((int32_t)123, s);
497 logln((UnicodeString)"Pattern \"" + *pat + "\"");
498 logln((UnicodeString)" Format 123 -> " + escape(s));
499 if (!(s=="afo'ob123"))
500 errln((UnicodeString)"FAIL: Expected afo'ob123");
501
502 s.truncate(0);
503 delete fmt;
504 delete pat;
505
506 pat = new UnicodeString("a''b#");
507 fmt = new DecimalFormat(*pat, *sym, status);
508 ((NumberFormat*)fmt)->format((int32_t)123, s);
509 logln((UnicodeString)"Pattern \"" + *pat + "\"");
510 logln((UnicodeString)" Format 123 -> " + escape(s));
511 if (!(s=="a'b123"))
512 errln((UnicodeString)"FAIL: Expected a'b123");
513 delete fmt;
514 delete pat;
515 delete sym;
516}
517
518/**
519 * Test the handling of the currency symbol in patterns.
520 */
521void
522NumberFormatTest::TestCurrencySign(void)
523{
524 UErrorCode status = U_ZERO_ERROR;
525 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
526 UnicodeString pat;
527 UChar currency = 0x00A4;
528 // "\xA4#,##0.00;-\xA4#,##0.00"
529 pat.append(currency).append("#,##0.00;-").
530 append(currency).append("#,##0.00");
531 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
532 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
533 pat.truncate(0);
534 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
535 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
536 if (s != "$1,234.56") errln((UnicodeString)"FAIL: Expected $1,234.56");
537 s.truncate(0);
538 ((NumberFormat*)fmt)->format(- 1234.56, s);
539 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
540 if (s != "-$1,234.56") errln((UnicodeString)"FAIL: Expected -$1,234.56");
541 delete fmt;
542 pat.truncate(0);
543 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
544 pat.append(currency).append(currency).
545 append(" #,##0.00;").
546 append(currency).append(currency).
547 append(" -#,##0.00");
548 fmt = new DecimalFormat(pat, *sym, status);
549 s.truncate(0);
550 ((NumberFormat*)fmt)->format(1234.56, s);
551 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
552 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
553 if (s != "USD 1,234.56") errln((UnicodeString)"FAIL: Expected USD 1,234.56");
554 s.truncate(0);
555 ((NumberFormat*)fmt)->format(-1234.56, s);
556 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
557 if (s != "USD -1,234.56") errln((UnicodeString)"FAIL: Expected USD -1,234.56");
558 delete fmt;
559 delete sym;
560 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
561}
562
563// -------------------------------------
564
565static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
566
567UnicodeString&
568NumberFormatTest::escape(UnicodeString& s)
569{
570 UnicodeString buf;
571 for (int32_t i=0; i<s.length(); ++i)
572 {
573 UChar c = s[(int32_t)i];
574 if (c <= (UChar)0x7F) buf += c;
575 else {
576 buf += (UChar)0x5c; buf += (UChar)0x55;
577 buf += toHexString((c & 0xF000) >> 12);
578 buf += toHexString((c & 0x0F00) >> 8);
579 buf += toHexString((c & 0x00F0) >> 4);
580 buf += toHexString(c & 0x000F);
581 }
582 }
583 return (s = buf);
584}
585
586
587// -------------------------------------
374ca955
A
588static const char* testCases[][2]= {
589 /* locale ID */ /* expected */
590 {"ca_ES_PREEURO", "\\u20A7 1.150" },
591 {"de_LU_PREEURO", "1,150 F" },
592 {"el_GR_PREEURO", "1.150,50 \\u0394\\u03C1\\u03C7" },
593 {"en_BE_PREEURO", "1.150,50 BF" },
594 {"es_ES_PREEURO", "1.150 \\u20A7" },
595 {"eu_ES_PREEURO", "\\u20A7 1.150" },
596 {"gl_ES_PREEURO", "\\u20A7 1.150" },
597 {"it_IT_PREEURO", "\\u20A4 1.150" },
598 {"pt_PT_PREEURO", "1,150$50 Esc."}
599};
b75a7d8f
A
600/**
601 * Test localized currency patterns.
602 */
603void
604NumberFormatTest::TestCurrency(void)
605{
606 UErrorCode status = U_ZERO_ERROR;
607 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
608 UnicodeString s; currencyFmt->format(1.50, s);
609 logln((UnicodeString)"Un pauvre ici a..........." + s);
610 if (!(s=="1,50 $"))
611 errln((UnicodeString)"FAIL: Expected 1,50 $");
612 delete currencyFmt;
613 s.truncate(0);
374ca955
A
614 char loc[256]={0};
615 int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
616 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
b75a7d8f
A
617 currencyFmt->format(1.50, s);
618 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
619 if (!(s=="1,50 DM"))
620 errln((UnicodeString)"FAIL: Expected 1,50 DM");
621 delete currencyFmt;
622 s.truncate(0);
374ca955
A
623 len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
624 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
b75a7d8f
A
625 currencyFmt->format(1.50, s);
626 logln((UnicodeString)"Un pauvre en France a....." + s);
627 if (!(s=="1,50 F"))
628 errln((UnicodeString)"FAIL: Expected 1,50 F");
629 delete currencyFmt;
630 if (U_FAILURE(status))
631 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
374ca955
A
632
633 for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
634 status = U_ZERO_ERROR;
635 const char *localeID = testCases[i][0];
636 UnicodeString expected(testCases[i][1]);
637 expected = expected.unescape();
638 s.truncate(0);
639 char loc[256]={0};
640 uloc_canonicalize(localeID, loc, 256, &status);
641 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
642 if(U_FAILURE(status)){
643 errln("Could not create currency formatter for locale %s",localeID);
644 continue;
645 }
646 currencyFmt->format(1150.50, s);
647 if(s!=expected){
648 errln(UnicodeString("FAIL: Expected: ")+expected
649 + UnicodeString(" Got: ") + s
650 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
651 }
652 if (U_FAILURE(status)){
653 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
654 }
655 delete currencyFmt;
656 }
b75a7d8f
A
657}
658
659// -------------------------------------
660
661/**
662 * Test the Currency object handling, new as of ICU 2.2.
663 */
664void NumberFormatTest::TestCurrencyObject() {
665 UErrorCode ec = U_ZERO_ERROR;
666 NumberFormat* fmt =
667 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
668
669 if (U_FAILURE(ec)) {
670 errln("FAIL: getCurrencyInstance(US)");
671 delete fmt;
672 return;
673 }
674
675 Locale null("", "", "");
676
677 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
678
679 expectCurrency(*fmt, Locale::getFrance(),
680 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
681
682 expectCurrency(*fmt, Locale::getJapan(),
683 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
684
685 expectCurrency(*fmt, Locale("fr", "CH", ""),
686 1234.56, "SwF1,234.55"); // 0.05 rounding
687
688 expectCurrency(*fmt, Locale::getUS(),
689 1234.56, "$1,234.56");
690
691 delete fmt;
692 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
693
694 if (U_FAILURE(ec)) {
695 errln("FAIL: getCurrencyInstance(FRANCE)");
696 delete fmt;
697 return;
698 }
699
700 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
701
702 expectCurrency(*fmt, Locale::getJapan(),
703 1234.56, CharsToUnicodeString("1 235 \\u00A5")); // Yen
704
705 expectCurrency(*fmt, Locale("fr", "CH", ""),
706 1234.56, "1 234,55 sFr."); // 0.05 rounding
707
708 expectCurrency(*fmt, Locale::getUS(),
709 1234.56, "1 234,56 $");
710
711 expectCurrency(*fmt, Locale::getFrance(),
712 1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
713
714 delete fmt;
715}
716
717// -------------------------------------
718
719/**
720 * Do rudimentary testing of parsing.
721 */
722void
723NumberFormatTest::TestParse(void)
724{
725 UErrorCode status = U_ZERO_ERROR;
726 UnicodeString arg("0");
727 DecimalFormat* format = new DecimalFormat("00", status);
728 //try {
729 Formattable n; format->parse(arg, n, status);
730 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
731 if (n.getType() != Formattable::kLong ||
732 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
733 delete format;
734 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
735 //}
736 //catch(Exception e) {
737 // errln((UnicodeString)"Exception caught: " + e);
738 //}
739}
740
741// -------------------------------------
742
743/**
744 * Test proper rounding by the format method.
745 */
746void
747NumberFormatTest::TestRounding487(void)
748{
749 UErrorCode status = U_ZERO_ERROR;
750 NumberFormat *nf = NumberFormat::createInstance(status);
751 roundingTest(*nf, 0.00159999, 4, "0.0016");
752 roundingTest(*nf, 0.00995, 4, "0.01");
753
754 roundingTest(*nf, 12.3995, 3, "12.4");
755
756 roundingTest(*nf, 12.4999, 0, "12");
757 roundingTest(*nf, - 19.5, 0, "-20");
758 delete nf;
759 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
760}
761
762/**
763 * Test the functioning of the secondary grouping value.
764 */
765void NumberFormatTest::TestSecondaryGrouping(void) {
766 UErrorCode status = U_ZERO_ERROR;
767 DecimalFormatSymbols US(Locale::getUS(), status);
768 CHECK(status, "DecimalFormatSymbols ct");
769
770 DecimalFormat f("#,##,###", US, status);
771 CHECK(status, "DecimalFormat ct");
772
773 expect2(f, (int32_t)123456789L, "12,34,56,789");
774 expectPat(f, "#,##,###");
775 f.applyPattern("#,###", status);
776 CHECK(status, "applyPattern");
777
778 f.setSecondaryGroupingSize(4);
779 expect2(f, (int32_t)123456789L, "12,3456,789");
780 expectPat(f, "#,####,###");
781 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
782 CHECK(status, "createInstance(hi_IN)");
783
784 UnicodeString out;
785 int32_t l = (int32_t)1876543210L;
786 g->format(l, out);
787 delete g;
788 // expect "1,87,65,43,210", but with Hindi digits
789 // 01234567890123
790 UBool ok = TRUE;
791 if (out.length() != 14) {
792 ok = FALSE;
793 } else {
794 for (int32_t i=0; i<out.length(); ++i) {
795 UBool expectGroup = FALSE;
796 switch (i) {
797 case 1:
798 case 4:
799 case 7:
800 case 10:
801 expectGroup = TRUE;
802 break;
803 }
804 // Later -- fix this to get the actual grouping
805 // character from the resource bundle.
806 UBool isGroup = (out.charAt(i) == 0x002C);
807 if (isGroup != expectGroup) {
808 ok = FALSE;
809 break;
810 }
811 }
812 }
813 if (!ok) {
814 errln((UnicodeString)"FAIL Expected " + l +
815 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
816 escape(out) + "\"");
817 } else {
818 logln((UnicodeString)"Ok " + l +
819 " x hi_IN -> \"" +
820 escape(out) + "\"");
821 }
822}
823
824void NumberFormatTest::TestWhiteSpaceParsing(void) {
825 UErrorCode ec = U_ZERO_ERROR;
826 DecimalFormatSymbols US(Locale::getUS(), ec);
827 DecimalFormat fmt("a b#0c ", US, ec);
828 if (U_FAILURE(ec)) {
829 errln("FAIL: Constructor");
830 return;
831 }
832 int32_t n = 1234;
833 expect(fmt, "a b1234c ", n);
834 expect(fmt, "a b1234c ", n);
835}
836
837/**
838 * Test currencies whose display name is a ChoiceFormat.
839 */
840void NumberFormatTest::TestComplexCurrency() {
841 UErrorCode ec = U_ZERO_ERROR;
842 Locale loc("en", "IN", "");
843 NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
844 if (U_SUCCESS(ec)) {
845 expect2(*fmt, 1.0, "Re. 1.00");
846 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
847 expect(*fmt, 1.00390625, "Re. 1.00"); // tricky
848 expect2(*fmt, 12345678.0, "Rs. 1,23,45,678.00");
849 expect2(*fmt, 0.5, "Rs. 0.50");
850 expect2(*fmt, -1.0, "-Re. 1.00");
851 expect2(*fmt, -10.0, "-Rs. 10.00");
852 } else {
853 errln("FAIL: getCurrencyInstance(en_IN)");
854 }
855 delete fmt;
856}
857
858// -------------------------------------
859
860void
861NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
862{
863 nf.setMaximumFractionDigits(maxFractionDigits);
864 UnicodeString out; nf.format(x, out);
865 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
866 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
867}
868
869/**
870 * Upgrade to alphaWorks
871 */
872void NumberFormatTest::TestExponent(void) {
873 UErrorCode status = U_ZERO_ERROR;
874 DecimalFormatSymbols US(Locale::getUS(), status);
875 CHECK(status, "DecimalFormatSymbols constructor");
876 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
877 CHECK(status, "DecimalFormat(0.###E0)");
878 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
879 CHECK(status, "DecimalFormat(0.###E+0)");
880 int32_t n = 1234;
881 expect2(fmt1, n, "1.234E3");
882 expect2(fmt2, n, "1.234E+3");
883 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
884}
885
886/**
887 * Upgrade to alphaWorks
888 */
889void NumberFormatTest::TestScientific(void) {
890 UErrorCode status = U_ZERO_ERROR;
891 DecimalFormatSymbols US(Locale::getUS(), status);
892 CHECK(status, "DecimalFormatSymbols constructor");
893
894 // Test pattern round-trip
895 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
896 "0.###E0;[0.###E0]" };
897 int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
898 int32_t DIGITS[] = {
899 // min int, max int, min frac, max frac
900 0, 1, 0, 0, // "#E0"
901 1, 1, 0, 4, // "0.####E0"
902 2, 2, 3, 3, // "00.000E00"
903 1, 3, 0, 4, // "##0.####E000"
904 1, 1, 0, 3, // "0.###E0;[0.###E0]"
905 };
906 for (int32_t i=0; i<PAT_length; ++i) {
907 UnicodeString pat(PAT[i]);
908 DecimalFormat df(pat, US, status);
909 CHECK(status, "DecimalFormat constructor");
910 UnicodeString pat2;
911 df.toPattern(pat2);
912 if (pat == pat2) {
913 logln(UnicodeString("Ok Pattern rt \"") +
914 pat + "\" -> \"" +
915 pat2 + "\"");
916 } else {
917 errln(UnicodeString("FAIL Pattern rt \"") +
918 pat + "\" -> \"" +
919 pat2 + "\"");
920 }
921 // Make sure digit counts match what we expect
922 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
923 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
924 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
925 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
926 errln(UnicodeString("FAIL \"" + pat +
927 "\" min/max int; min/max frac = ") +
928 df.getMinimumIntegerDigits() + "/" +
929 df.getMaximumIntegerDigits() + ";" +
930 df.getMinimumFractionDigits() + "/" +
931 df.getMaximumFractionDigits() + ", expect " +
932 DIGITS[4*i] + "/" +
933 DIGITS[4*i+1] + ";" +
934 DIGITS[4*i+2] + "/" +
935 DIGITS[4*i+3]);
936 }
937 }
938
939
940 // Test the constructor for default locale. We have to
941 // manually set the default locale, as there is no
942 // guarantee that the default locale has the same
943 // scientific format.
944 Locale def = Locale::getDefault();
945 Locale::setDefault(Locale::getUS(), status);
946 expect2(NumberFormat::createScientificInstance(status),
947 12345.678901,
948 "1.2345678901E4", status);
949 Locale::setDefault(def, status);
950
951 expect2(new DecimalFormat("#E0", US, status),
952 12345.0,
953 "1.2345E4", status);
954 expect(new DecimalFormat("0E0", US, status),
955 12345.0,
956 "1E4", status);
957 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
958 12345.678901,
959 "1.2345678901E4", status);
960 expect(new DecimalFormat("##0.###E0", US, status),
961 12345.0,
962 "12.34E3", status);
963 expect(new DecimalFormat("##0.###E0", US, status),
964 12345.00001,
965 "12.35E3", status);
966 expect2(new DecimalFormat("##0.####E0", US, status),
967 (int32_t) 12345,
968 "12.345E3", status);
969 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
970 12345.678901,
971 "1,2345678901E4", status);
972 expect(new DecimalFormat("##0.####E0", US, status),
973 789.12345e-9,
974 "789.12E-9", status);
975 expect2(new DecimalFormat("##0.####E0", US, status),
976 780.e-9,
977 "780E-9", status);
978 expect(new DecimalFormat(".###E0", US, status),
979 45678.0,
980 ".457E5", status);
981 expect2(new DecimalFormat(".###E0", US, status),
982 (int32_t) 0,
983 ".0E0", status);
984 /*
985 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
986 new DecimalFormat("##E0", US),
987 new DecimalFormat("####E0", US),
988 new DecimalFormat("0E0", US),
989 new DecimalFormat("00E0", US),
990 new DecimalFormat("000E0", US),
991 },
992 new Long(45678000),
993 new String[] { "4.5678E7",
994 "45.678E6",
995 "4567.8E4",
996 "5E7",
997 "46E6",
998 "457E5",
999 }
1000 );
1001 !
1002 ! Unroll this test into individual tests below...
1003 !
1004 */
1005 expect2(new DecimalFormat("#E0", US, status),
1006 (int32_t) 45678000, "4.5678E7", status);
1007 expect2(new DecimalFormat("##E0", US, status),
1008 (int32_t) 45678000, "45.678E6", status);
1009 expect2(new DecimalFormat("####E0", US, status),
1010 (int32_t) 45678000, "4567.8E4", status);
1011 expect(new DecimalFormat("0E0", US, status),
1012 (int32_t) 45678000, "5E7", status);
1013 expect(new DecimalFormat("00E0", US, status),
1014 (int32_t) 45678000, "46E6", status);
1015 expect(new DecimalFormat("000E0", US, status),
1016 (int32_t) 45678000, "457E5", status);
1017 /*
1018 expect(new DecimalFormat("###E0", US, status),
1019 new Object[] { new Double(0.0000123), "12.3E-6",
1020 new Double(0.000123), "123E-6",
1021 new Double(0.00123), "1.23E-3",
1022 new Double(0.0123), "12.3E-3",
1023 new Double(0.123), "123E-3",
1024 new Double(1.23), "1.23E0",
1025 new Double(12.3), "12.3E0",
1026 new Double(123), "123E0",
1027 new Double(1230), "1.23E3",
1028 });
1029 !
1030 ! Unroll this test into individual tests below...
1031 !
1032 */
1033 expect2(new DecimalFormat("###E0", US, status),
1034 0.0000123, "12.3E-6", status);
1035 expect2(new DecimalFormat("###E0", US, status),
1036 0.000123, "123E-6", status);
1037 expect2(new DecimalFormat("###E0", US, status),
1038 0.00123, "1.23E-3", status);
1039 expect2(new DecimalFormat("###E0", US, status),
1040 0.0123, "12.3E-3", status);
1041 expect2(new DecimalFormat("###E0", US, status),
1042 0.123, "123E-3", status);
1043 expect2(new DecimalFormat("###E0", US, status),
1044 1.23, "1.23E0", status);
1045 expect2(new DecimalFormat("###E0", US, status),
1046 12.3, "12.3E0", status);
1047 expect2(new DecimalFormat("###E0", US, status),
1048 123.0, "123E0", status);
1049 expect2(new DecimalFormat("###E0", US, status),
1050 1230.0, "1.23E3", status);
1051 /*
1052 expect(new DecimalFormat("0.#E+00", US, status),
1053 new Object[] { new Double(0.00012), "1.2E-04",
1054 new Long(12000), "1.2E+04",
1055 });
1056 !
1057 ! Unroll this test into individual tests below...
1058 !
1059 */
1060 expect2(new DecimalFormat("0.#E+00", US, status),
1061 0.00012, "1.2E-04", status);
1062 expect2(new DecimalFormat("0.#E+00", US, status),
1063 (int32_t) 12000, "1.2E+04", status);
1064}
1065
1066/**
1067 * Upgrade to alphaWorks
1068 */
1069void NumberFormatTest::TestPad(void) {
1070 UErrorCode status = U_ZERO_ERROR;
1071 DecimalFormatSymbols US(Locale::getUS(), status);
1072 CHECK(status, "DecimalFormatSymbols constructor");
1073
1074 expect2(new DecimalFormat("*^##.##", US, status),
1075 int32_t(0), "^^^^0", status);
1076 expect2(new DecimalFormat("*^##.##", US, status),
1077 -1.3, "^-1.3", status);
374ca955 1078 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
b75a7d8f 1079 int32_t(0), "0.0E0______ g-m/s^2", status);
374ca955 1080 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
b75a7d8f 1081 1.0/3, "333.333E-3_ g-m/s^2", status);
374ca955 1082 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
b75a7d8f 1083 int32_t(0), "0.0______ g-m/s^2", status);
374ca955 1084 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
b75a7d8f
A
1085 1.0/3, "0.33333__ g-m/s^2", status);
1086
1087 // Test padding before a sign
1088 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1089 expect2(new DecimalFormat(formatStr, US, status),
1090 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1091 expect2(new DecimalFormat(formatStr, US, status),
1092 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1093 expect2(new DecimalFormat(formatStr, US, status),
1094 int32_t(-1000000),"xxx(1,000,000.0)", status);
1095 expect2(new DecimalFormat(formatStr, US, status),
1096 -100.37, "xxxxxxxx(100.37)", status);
1097 expect2(new DecimalFormat(formatStr, US, status),
1098 -10456.37, "xxxxx(10,456.37)", status);
1099 expect2(new DecimalFormat(formatStr, US, status),
1100 -1120456.37, "xx(1,120,456.37)", status);
1101 expect2(new DecimalFormat(formatStr, US, status),
1102 -112045600.37, "(112,045,600.37)", status);
1103 expect2(new DecimalFormat(formatStr, US, status),
1104 -1252045600.37,"(1,252,045,600.37)", status);
1105
1106 expect2(new DecimalFormat(formatStr, US, status),
1107 int32_t(10), "xxxxxxxxxxxx10.0", status);
1108 expect2(new DecimalFormat(formatStr, US, status),
1109 int32_t(1000),"xxxxxxxxx1,000.0", status);
1110 expect2(new DecimalFormat(formatStr, US, status),
1111 int32_t(1000000),"xxxxx1,000,000.0", status);
1112 expect2(new DecimalFormat(formatStr, US, status),
1113 100.37, "xxxxxxxxxx100.37", status);
1114 expect2(new DecimalFormat(formatStr, US, status),
1115 10456.37, "xxxxxxx10,456.37", status);
1116 expect2(new DecimalFormat(formatStr, US, status),
1117 1120456.37, "xxxx1,120,456.37", status);
1118 expect2(new DecimalFormat(formatStr, US, status),
1119 112045600.37, "xx112,045,600.37", status);
1120 expect2(new DecimalFormat(formatStr, US, status),
1121 10252045600.37,"10,252,045,600.37", status);
1122
1123
1124 // Test padding between a sign and a number
1125 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1126 expect2(new DecimalFormat(formatStr2, US, status),
1127 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1128 expect2(new DecimalFormat(formatStr2, US, status),
1129 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1130 expect2(new DecimalFormat(formatStr2, US, status),
1131 int32_t(-1000000),"(1,000,000.0xxx)", status);
1132 expect2(new DecimalFormat(formatStr2, US, status),
1133 -100.37, "(100.37xxxxxxxx)", status);
1134 expect2(new DecimalFormat(formatStr2, US, status),
1135 -10456.37, "(10,456.37xxxxx)", status);
1136 expect2(new DecimalFormat(formatStr2, US, status),
1137 -1120456.37, "(1,120,456.37xx)", status);
1138 expect2(new DecimalFormat(formatStr2, US, status),
1139 -112045600.37, "(112,045,600.37)", status);
1140 expect2(new DecimalFormat(formatStr2, US, status),
1141 -1252045600.37,"(1,252,045,600.37)", status);
1142
1143 expect2(new DecimalFormat(formatStr2, US, status),
1144 int32_t(10), "10.0xxxxxxxxxxxx", status);
1145 expect2(new DecimalFormat(formatStr2, US, status),
1146 int32_t(1000),"1,000.0xxxxxxxxx", status);
1147 expect2(new DecimalFormat(formatStr2, US, status),
1148 int32_t(1000000),"1,000,000.0xxxxx", status);
1149 expect2(new DecimalFormat(formatStr2, US, status),
1150 100.37, "100.37xxxxxxxxxx", status);
1151 expect2(new DecimalFormat(formatStr2, US, status),
1152 10456.37, "10,456.37xxxxxxx", status);
1153 expect2(new DecimalFormat(formatStr2, US, status),
1154 1120456.37, "1,120,456.37xxxx", status);
1155 expect2(new DecimalFormat(formatStr2, US, status),
1156 112045600.37, "112,045,600.37xx", status);
1157 expect2(new DecimalFormat(formatStr2, US, status),
1158 10252045600.37,"10,252,045,600.37", status);
1159
1160 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1161 DecimalFormat fmt("#", US, status);
1162 CHECK(status, "DecimalFormat constructor");
1163 UnicodeString padString("P");
1164 fmt.setPadCharacter(padString);
1165 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1166 fmt.setPadCharacter((UnicodeString)"^");
1167 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1168 //commented untill implementation is complete
1169 /* fmt.setPadCharacter((UnicodeString)"^^^");
1170 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1171 padString.remove();
1172 padString.append((UChar)0x0061);
1173 padString.append((UChar)0x0302);
1174 fmt.setPadCharacter(padString);
1175 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1176 UnicodeString pattern(patternChars);
1177 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1178 */
1179
1180}
1181
1182/**
1183 * Upgrade to alphaWorks
1184 */
1185void NumberFormatTest::TestPatterns2(void) {
1186 UErrorCode status = U_ZERO_ERROR;
1187 DecimalFormatSymbols US(Locale::getUS(), status);
1188 CHECK(status, "DecimalFormatSymbols constructor");
1189
1190 DecimalFormat fmt("#", US, status);
1191 CHECK(status, "DecimalFormat constructor");
1192
1193 UChar hat = 0x005E; /*^*/
1194
1195 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1196 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1197 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1198 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1199 expectPad(fmt, "$*^$#", ILLEGAL);
1200 expectPad(fmt, "#$*^$", ILLEGAL);
1201 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1202 12, (UChar)0x0078 /*x*/);
1203 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1204 3, (UChar)0x0078 /*x*/);
1205 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1206 10, (UChar)0x0061 /*a*/);
1207
1208 fmt.applyPattern("AA#,##0.00ZZ", status);
1209 CHECK(status, "applyPattern");
1210 fmt.setPadCharacter(hat);
1211
1212 fmt.setFormatWidth(10);
1213
1214 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1215 expectPat(fmt, "*^AA#,##0.00ZZ");
1216
1217 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1218 expectPat(fmt, "AA#,##0.00*^ZZ");
1219
1220 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1221 expectPat(fmt, "AA#,##0.00ZZ*^");
1222
1223 // 12 3456789012
1224 UnicodeString exp("AA*^#,##0.00ZZ", "");
1225 fmt.setFormatWidth(12);
1226 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1227 expectPat(fmt, exp);
1228
1229 fmt.setFormatWidth(13);
1230 // 12 34567890123
1231 expectPat(fmt, "AA*^##,##0.00ZZ");
1232
1233 fmt.setFormatWidth(14);
1234 // 12 345678901234
1235 expectPat(fmt, "AA*^###,##0.00ZZ");
1236
1237 fmt.setFormatWidth(15);
1238 // 12 3456789012345
1239 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1240
1241 fmt.setFormatWidth(16);
1242 // 12 34567890123456
1243 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1244}
1245
1246void NumberFormatTest::TestSurrogateSupport(void) {
1247 UErrorCode status = U_ZERO_ERROR;
1248 DecimalFormatSymbols custom(Locale::getUS(), status);
1249 CHECK(status, "DecimalFormatSymbols constructor");
1250
1251 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1252 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1253 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1254 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1255
1256 UnicodeString patternStr("*\\U00010000##.##", "");
1257 patternStr = patternStr.unescape();
1258 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1259 expStr = expStr.unescape();
1260 expect2(new DecimalFormat(patternStr, custom, status),
1261 int32_t(0), expStr, status);
1262
1263 status = U_ZERO_ERROR;
1264 expect2(new DecimalFormat("*^##.##", custom, status),
1265 int32_t(0), "^^^^0", status);
1266 status = U_ZERO_ERROR;
1267 expect2(new DecimalFormat("##.##", custom, status),
1268 -1.3, " minus 1decimal3", status);
1269 status = U_ZERO_ERROR;
374ca955 1270 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
b75a7d8f
A
1271 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1272 status = U_ZERO_ERROR;
374ca955 1273 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
b75a7d8f
A
1274 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1275 status = U_ZERO_ERROR;
374ca955 1276 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
b75a7d8f
A
1277 int32_t(0), "0decimal0 g-m/s^2", status);
1278 status = U_ZERO_ERROR;
374ca955 1279 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
b75a7d8f
A
1280 1.0/3, "0decimal33333 g-m/s^2", status);
1281
1282 UnicodeString zero((UChar32)0x10000);
1283 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1284 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1285 expStr = expStr.unescape();
1286 status = U_ZERO_ERROR;
1287 expect2(new DecimalFormat("##0.000", custom, status),
1288 1.25, expStr, status);
1289
1290 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1291 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1292 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1293 patternStr = "0.00 \\u00A4' in your bank account'";
1294 patternStr = patternStr.unescape();
1295 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1296 status = U_ZERO_ERROR;
1297 expect2(new DecimalFormat(patternStr, custom, status),
1298 int32_t(-20), expStr, status);
1299
1300 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1301 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1302 patternStr = patternStr.unescape();
1303 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1304 status = U_ZERO_ERROR;
1305 expect2(new DecimalFormat(patternStr, custom, status),
1306 int32_t(-20), expStr, status);
1307}
1308
1309void NumberFormatTest::TestCurrencyPatterns(void) {
1310 int32_t i, locCount;
1311 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1312 for (i=0; i<locCount; ++i) {
1313 UErrorCode ec = U_ZERO_ERROR;
1314 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1315 if (U_FAILURE(ec)) {
374ca955 1316 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
b75a7d8f
A
1317 } else {
1318 // Make sure currency formats do not have a variable number
1319 // of fraction digits
1320 int32_t min = nf->getMinimumFractionDigits();
1321 int32_t max = nf->getMaximumFractionDigits();
1322 if (min != max) {
1323 UnicodeString a, b;
1324 nf->format(1.0, a);
1325 nf->format(1.125, b);
1326 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1327 " min fraction digits != max fraction digits; "
1328 "x 1.0 => " + escape(a) +
1329 "; x 1.125 => " + escape(b));
1330 }
1331
1332 // Make sure EURO currency formats have exactly 2 fraction digits
1333 if (nf->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1334 DecimalFormat* df = (DecimalFormat*) nf;
1335 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1336 if (min != 2 || max != 2) {
1337 UnicodeString a;
1338 nf->format(1.0, a);
1339 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1340 " is a EURO format but it does not have 2 fraction digits; "
1341 "x 1.0 => " +
1342 escape(a));
1343 }
1344 }
1345 }
1346 }
1347 delete nf;
1348 }
1349}
1350
1351void NumberFormatTest::TestRegCurrency(void) {
374ca955
A
1352#if !UCONFIG_NO_SERVICE
1353 UErrorCode status = U_ZERO_ERROR;
1354 UChar USD[4];
1355 ucurr_forLocale("en_US", USD, 4, &status);
1356 UChar YEN[4];
1357 ucurr_forLocale("ja_JP", YEN, 4, &status);
1358 UChar TMP[4];
1359 static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
1360 if(U_FAILURE(status)) {
1361 errln("Unable to get currency for locale, error %s", u_errorName(status));
1362 return;
1363 }
1364
1365 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1366 UCurrRegistryKey enUSEUROkey = ucurr_register(QQQ, "en_US_EURO", &status);
1367
1368 ucurr_forLocale("en_US", TMP, 4, &status);
1369 if (u_strcmp(YEN, TMP) != 0) {
1370 errln("FAIL: didn't return YEN registered for en_US");
1371 }
b75a7d8f 1372
374ca955
A
1373 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1374 if (u_strcmp(QQQ, TMP) != 0) {
1375 errln("FAIL: didn't return QQQ for en_US_EURO");
1376 }
1377
1378 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1379 if (fallbackLen) {
1380 errln("FAIL: tried to fallback en_XX_BAR");
1381 }
1382 status = U_ZERO_ERROR; // reset
1383
1384 if (!ucurr_unregister(enkey, &status)) {
1385 errln("FAIL: couldn't unregister enkey");
1386 }
b75a7d8f 1387
374ca955
A
1388 ucurr_forLocale("en_US", TMP, 4, &status);
1389 if (u_strcmp(USD, TMP) != 0) {
1390 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1391 }
1392 status = U_ZERO_ERROR; // reset
1393
1394 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1395 if (u_strcmp(QQQ, TMP) != 0) {
1396 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1397 }
1398
1399 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1400 if (u_strcmp(USD, TMP) != 0) {
1401 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1402 }
1403 status = U_ZERO_ERROR; // reset
1404
1405 if (!ucurr_unregister(enUSEUROkey, &status)) {
1406 errln("FAIL: couldn't unregister enUSEUROkey");
1407 }
1408
1409 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1410 if (u_strcmp(EUR, TMP) != 0) {
1411 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1412 }
1413 status = U_ZERO_ERROR; // reset
1414#endif
1415}
b75a7d8f 1416
374ca955
A
1417void NumberFormatTest::TestCurrencyNames(void) {
1418 // Do a basic check of getName()
1419 // USD { "US$", "US Dollar" } // 04/04/1792-
1420 UErrorCode ec = U_ZERO_ERROR;
1421 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
1422 UBool isChoiceFormat;
1423 int32_t len;
1424 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1425 // THE LOCALE DATA before diving into the code.
1426 assertEquals("USD.getName(SYMBOL_NAME)",
1427 UnicodeString("US$"),
1428 UnicodeString(ucurr_getName(USD, "en",
1429 UCURR_SYMBOL_NAME,
1430 &isChoiceFormat, &len, &ec)));
1431 assertEquals("USD.getName(LONG_NAME)",
1432 UnicodeString("US Dollar"),
1433 UnicodeString(ucurr_getName(USD, "en",
1434 UCURR_LONG_NAME,
1435 &isChoiceFormat, &len, &ec)));
1436 assertSuccess("ucurr_getName", ec);
1437
1438 // TODO add more tests later
b75a7d8f
A
1439}
1440
1441void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1442 Locale locDefault;
1443 Locale locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1444 UErrorCode status = U_ZERO_ERROR;
1445 UnicodeString intlCurrencySymbol((UChar)0xa4);
1446
1447 intlCurrencySymbol.append((UChar)0xa4);
1448
1449 logln("Current locale is %s", Locale::getDefault().getName());
1450 Locale::setDefault(locBad, status);
1451 logln("Current locale is %s", Locale::getDefault().getName());
1452 DecimalFormatSymbols mySymbols(status);
1453 if (status != U_USING_FALLBACK_WARNING) {
1454 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1455 }
1456 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
1457 errln("DecimalFormatSymbols does not have the right locale.");
1458 }
374ca955
A
1459 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
1460 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
1461 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ")
1462 + prettify(mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum)));
1463
1464 if (mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum).length() == 0
1465 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol)
1466 {
b75a7d8f
A
1467 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
1468 }
1469 }
1470 status = U_ZERO_ERROR;
1471 Locale::setDefault(locDefault, status);
1472 logln("Current locale is %s", Locale::getDefault().getName());
1473}
1474
1475/**
1476 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1477 * behave the same, except for memory ownership semantics. (No
1478 * version of this test on Java, since Java has only one method.)
1479 */
1480void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1481 UErrorCode ec = U_ZERO_ERROR;
1482 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1483 if (U_FAILURE(ec)) {
1484 errln("Fail: DecimalFormatSymbols constructor");
1485 delete sym;
1486 return;
1487 }
1488 UnicodeString pat(" #,##0.00");
1489 pat.insert(0, (UChar)0x00A4);
1490 DecimalFormat fmt(pat, sym, ec);
1491 if (U_FAILURE(ec)) {
1492 errln("Fail: DecimalFormat constructor");
1493 return;
1494 }
1495
1496 UnicodeString str;
1497 fmt.format(2350.75, str);
1498 if (str == "$ 2,350.75") {
1499 logln(str);
1500 } else {
1501 errln("Fail: " + str + ", expected $ 2,350.75");
1502 }
1503
1504 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1505 if (U_FAILURE(ec)) {
1506 errln("Fail: DecimalFormatSymbols constructor");
1507 delete sym;
1508 return;
1509 }
1510 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1511 fmt.adoptDecimalFormatSymbols(sym);
1512
1513 str.truncate(0);
1514 fmt.format(2350.75, str);
1515 if (str == "Q 2,350.75") {
1516 logln(str);
1517 } else {
1518 errln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1519 }
1520
1521 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1522 if (U_FAILURE(ec)) {
1523 errln("Fail: DecimalFormatSymbols constructor");
1524 delete sym;
1525 return;
1526 }
1527 DecimalFormat fmt2(pat, sym, ec);
1528 if (U_FAILURE(ec)) {
1529 errln("Fail: DecimalFormat constructor");
1530 return;
1531 }
1532
1533 DecimalFormatSymbols sym2(Locale::getUS(), ec);
1534 if (U_FAILURE(ec)) {
1535 errln("Fail: DecimalFormatSymbols constructor");
1536 return;
1537 }
1538 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1539 fmt2.setDecimalFormatSymbols(sym2);
1540
1541 str.truncate(0);
1542 fmt2.format(2350.75, str);
1543 if (str == "Q 2,350.75") {
1544 logln(str);
1545 } else {
1546 errln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1547 }
1548}
1549
374ca955
A
1550void NumberFormatTest::TestPerMill() {
1551 UErrorCode ec = U_ZERO_ERROR;
1552 UnicodeString str;
1553 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
1554 if (!assertSuccess("DecimalFormat ct", ec)) return;
1555 assertEquals("0.4857 x ###.###\\u2030",
1556 ctou("485.7\\u2030"), fmt.format(0.4857, str));
1557
1558 DecimalFormatSymbols sym(Locale::getUS(), ec);
1559 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
1560 DecimalFormat fmt2("", sym, ec);
1561 fmt2.applyLocalizedPattern("###.###m", ec);
1562 if (!assertSuccess("setup", ec)) return;
1563 str.truncate(0);
1564 assertEquals("0.4857 x ###.###m",
1565 "485.7m", fmt2.format(0.4857, str));
1566}
1567
1568/**
1569 * Generic test for patterns that should be legal/illegal.
1570 */
1571void NumberFormatTest::TestIllegalPatterns() {
1572 // Test cases:
1573 // Prefix with "-:" for illegal patterns
1574 // Prefix with "+:" for legal patterns
1575 const char* DATA[] = {
1576 // Unquoted special characters in the suffix are illegal
1577 "-:000.000|###",
1578 "+:000.000'|###'",
1579 0
1580 };
1581 for (int32_t i=0; DATA[i]; ++i) {
1582 const char* pat=DATA[i];
1583 UBool valid = (*pat) == '+';
1584 pat += 2;
1585 UErrorCode ec = U_ZERO_ERROR;
1586 DecimalFormat fmt(pat, ec); // locale doesn't matter here
1587 if (U_SUCCESS(ec) == valid) {
1588 logln("Ok: pattern \"%s\": %s",
1589 pat, u_errorName(ec));
1590 } else {
1591 errln("FAIL: pattern \"%s\" should have %s; got %s",
1592 pat, (valid?"succeeded":"failed"),
1593 u_errorName(ec));
1594 }
1595 }
1596}
1597
1598//----------------------------------------------------------------------
1599
1600static const char* KEYWORDS[] = {
1601 /*0*/ "ref=", // <reference pattern to parse numbers>
1602 /*1*/ "loc=", // <locale for formats>
1603 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1604 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1605 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1606 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1607 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1608 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1609 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1610 0
1611};
1612
1613/**
1614 * Return an integer representing the next token from this
1615 * iterator. The integer will be an index into the given list, or
1616 * -1 if there are no more tokens, or -2 if the token is not on
1617 * the list.
1618 */
1619static int32_t keywordIndex(const UnicodeString& tok) {
1620 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
1621 if (tok==KEYWORDS[i]) {
1622 return i;
1623 }
1624 }
1625 return -1;
1626}
1627
1628/**
1629 * Parse a CurrencyAmount using the given NumberFormat, with
1630 * the 'delim' character separating the number and the currency.
1631 */
1632static void parseCurrencyAmount(const UnicodeString& str,
1633 const NumberFormat& fmt,
1634 UChar delim,
1635 Formattable& result,
1636 UErrorCode& ec) {
1637 UnicodeString num, cur;
1638 int32_t i = str.indexOf(delim);
1639 str.extractBetween(0, i, num);
1640 str.extractBetween(i+1, INT32_MAX, cur);
1641 Formattable n;
1642 fmt.parse(num, n, ec);
1643 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
1644}
1645
1646void NumberFormatTest::TestCases() {
1647 UErrorCode ec = U_ZERO_ERROR;
1648 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
1649 if (U_FAILURE(ec)) {
1650 errln("FAIL: Couldn't open NumberFormatTestCases.txt");
1651 return;
1652 }
1653 TokenIterator tokens(&reader);
1654
1655 Locale loc("en", "US", "");
1656 DecimalFormat *ref = 0, *fmt = 0;
1657 MeasureFormat *mfmt = 0;
1658 UnicodeString pat, tok, mloc, str, out, where, currAmt;
1659 Formattable n;
1660
1661 for (;;) {
1662 ec = U_ZERO_ERROR;
1663 if (!tokens.next(tok, ec)) {
1664 break;
1665 }
1666 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
1667 int32_t cmd = keywordIndex(tok);
1668 switch (cmd) {
1669 case 0:
1670 // ref= <reference pattern>
1671 if (!tokens.next(tok, ec)) goto error;
1672 delete ref;
1673 ref = new DecimalFormat(tok,
1674 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
1675 break;
1676 case 1:
1677 // loc= <locale>
1678 if (!tokens.next(tok, ec)) goto error;
1679 loc = Locale::createFromName(CharString(tok));
1680 break;
1681 case 2: // f:
1682 case 3: // fp:
1683 case 4: // rt:
1684 case 5: // p:
1685 if (!tokens.next(tok, ec)) goto error;
1686 if (tok != "-") {
1687 pat = tok;
1688 delete fmt;
1689 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
1690 if (U_FAILURE(ec)) {
1691 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
1692 ec = U_ZERO_ERROR;
1693 if (!tokens.next(tok, ec)) goto error;
1694 if (!tokens.next(tok, ec)) goto error;
1695 if (cmd == 3) {
1696 if (!tokens.next(tok, ec)) goto error;
1697 }
1698 continue;
1699 }
1700 }
1701 if (cmd == 2 || cmd == 3 || cmd == 4) {
1702 // f: <pattern or '-'> <number> <exp. string>
1703 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
1704 // rt: <pattern or '-'> <number> <string>
1705 UnicodeString num;
1706 if (!tokens.next(num, ec)) goto error;
1707 if (!tokens.next(str, ec)) goto error;
1708 ref->parse(num, n, ec);
1709 assertSuccess("parse", ec);
1710 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
1711 str, fmt->format(n, out.remove(), ec));
1712 assertSuccess("format", ec);
1713 if (cmd == 3) { // fp:
1714 if (!tokens.next(num, ec)) goto error;
1715 ref->parse(num, n, ec);
1716 assertSuccess("parse", ec);
1717 }
1718 if (cmd != 2) { // != f:
1719 Formattable m;
1720 fmt->parse(str, m, ec);
1721 assertSuccess("parse", ec);
1722 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
1723 n, m);
1724 }
1725 }
1726 // p: <pattern or '-'> <string to parse> <exp. number>
1727 else {
1728 UnicodeString expstr;
1729 if (!tokens.next(str, ec)) goto error;
1730 if (!tokens.next(expstr, ec)) goto error;
1731 Formattable exp, n;
1732 ref->parse(expstr, exp, ec);
1733 assertSuccess("parse", ec);
1734 fmt->parse(str, n, ec);
1735 assertSuccess("parse", ec);
1736 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
1737 exp, n);
1738 }
1739 break;
1740 case 8: // fpc:
1741 if (!tokens.next(tok, ec)) goto error;
1742 if (tok != "-") {
1743 mloc = tok;
1744 delete mfmt;
1745 mfmt = MeasureFormat::createCurrencyFormat(
1746 Locale::createFromName(CharString(mloc)), ec);
1747 if (U_FAILURE(ec)) {
1748 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
1749 ec = U_ZERO_ERROR;
1750 if (!tokens.next(tok, ec)) goto error;
1751 if (!tokens.next(tok, ec)) goto error;
1752 if (!tokens.next(tok, ec)) goto error;
1753 continue;
1754 }
1755 }
1756 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1757 if (!tokens.next(currAmt, ec)) goto error;
1758 if (!tokens.next(str, ec)) goto error;
1759 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
1760 if (assertSuccess("parseCurrencyAmount", ec)) {
1761 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
1762 str, mfmt->format(n, out.remove(), ec));
1763 assertSuccess("format", ec);
1764 }
1765 if (!tokens.next(currAmt, ec)) goto error;
1766 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
1767 if (assertSuccess("parseCurrencyAmount", ec)) {
1768 Formattable m;
1769 mfmt->parseObject(str, m, ec);
1770 if (assertSuccess("parseCurrency", ec)) {
1771 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
1772 n, m);
1773 }
1774 }
1775 break;
1776 case 6:
1777 // perr: <pattern or '-'> <invalid string>
1778 errln("FAIL: Under construction");
1779 goto done;
1780 case 7: {
1781 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
1782 UnicodeString testpat;
1783 UnicodeString exppat;
1784 if (!tokens.next(testpat, ec)) goto error;
1785 if (!tokens.next(exppat, ec)) goto error;
1786 UBool err = exppat == "err";
1787 UBool existingPat = FALSE;
1788 if (testpat == "-") {
1789 if (err) {
1790 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
1791 continue;
1792 }
1793 existingPat = TRUE;
1794 testpat = pat;
1795 }
1796 if (exppat == "-") exppat = testpat;
1797 DecimalFormat* f = 0;
1798 UErrorCode ec2 = U_ZERO_ERROR;
1799 if (existingPat) {
1800 f = fmt;
1801 } else {
1802 f = new DecimalFormat(testpat, ec2);
1803 }
1804 if (U_SUCCESS(ec2)) {
1805 if (err) {
1806 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
1807 "\" was accepted");
1808 } else {
1809 UnicodeString pat2;
1810 assertEquals(where + "\"" + testpat + "\".toPattern()",
1811 exppat, f->toPattern(pat2));
1812 }
1813 } else {
1814 if (err) {
1815 logln("Ok: " + where + "Invalid pattern \"" + testpat +
1816 "\" failed: " + u_errorName(ec2));
1817 } else {
1818 errln("FAIL: " + where + "Valid pattern \"" + testpat +
1819 "\" failed: " + u_errorName(ec2));
1820 }
1821 }
1822 if (!existingPat) delete f;
1823 } break;
1824 case -1:
1825 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
1826 goto done;
1827 }
1828 }
1829 goto done;
1830
1831 error:
1832 if (U_SUCCESS(ec)) {
1833 errln("FAIL: Unexpected EOF");
1834 } else {
1835 errln("FAIL: " + where + "Unexpected " + u_errorName(ec));
1836 }
1837
1838 done:
1839 delete mfmt;
1840 delete fmt;
1841 delete ref;
1842}
1843
1844
b75a7d8f
A
1845//----------------------------------------------------------------------
1846// Support methods
1847//----------------------------------------------------------------------
1848
1849UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
374ca955
A
1850 if (a.getType() == b.getType()) {
1851 return a == b;
1852 }
1853
b75a7d8f 1854 if (a.getType() == Formattable::kLong) {
374ca955 1855 if (b.getType() == Formattable::kInt64) {
b75a7d8f
A
1856 return a.getLong() == b.getLong();
1857 } else if (b.getType() == Formattable::kDouble) {
374ca955 1858 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
b75a7d8f
A
1859 }
1860 } else if (a.getType() == Formattable::kDouble) {
1861 if (b.getType() == Formattable::kLong) {
1862 return a.getDouble() == (double) b.getLong();
374ca955
A
1863 } else if (b.getType() == Formattable::kInt64) {
1864 return a.getDouble() == (double)b.getInt64();
1865 }
1866 } else if (a.getType() == Formattable::kInt64) {
1867 if (b.getType() == Formattable::kLong) {
1868 return a.getInt64() == (int64_t)b.getLong();
b75a7d8f 1869 } else if (b.getType() == Formattable::kDouble) {
374ca955 1870 return a.getInt64() == (int64_t)b.getDouble();
b75a7d8f
A
1871 }
1872 }
1873 return FALSE;
1874}
1875
1876void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
1877 // Don't round-trip format test, since we explicitly do it
1878 expect(fmt, n, str, FALSE);
1879 expect(fmt, str, n);
1880}
1881
1882void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
1883 const UnicodeString& exp,
1884 UErrorCode status) {
1885 if (U_FAILURE(status)) {
1886 errln("FAIL: NumberFormat constructor");
1887 } else {
1888 expect2(*fmt, n, exp);
1889 }
1890 delete fmt;
1891}
1892
1893void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
1894 UErrorCode status = U_ZERO_ERROR;
1895 Formattable num;
1896 fmt.parse(str, num, status);
1897 if (U_FAILURE(status)) {
1898 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
1899 return;
1900 }
1901 UnicodeString pat;
1902 ((DecimalFormat*) &fmt)->toPattern(pat);
1903 if (equalValue(num, n)) {
1904 logln(UnicodeString("Ok \"") + str + "\" x " +
1905 pat + " = " +
1906 toString(num));
1907 } else {
1908 errln(UnicodeString("FAIL \"") + str + "\" x " +
1909 pat + " = " +
1910 toString(num) + ", expected " + toString(n));
1911 }
1912}
1913
1914void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
1915 const UnicodeString& exp, UBool rt) {
1916 UnicodeString saw;
1917 FieldPosition pos;
1918 UErrorCode status = U_ZERO_ERROR;
1919 fmt.format(n, saw, pos, status);
1920 CHECK(status, "NumberFormat::format");
1921 UnicodeString pat;
1922 ((DecimalFormat*) &fmt)->toPattern(pat);
1923 if (saw == exp) {
1924 logln(UnicodeString("Ok ") + toString(n) + " x " +
1925 escape(pat) + " = \"" +
1926 escape(saw) + "\"");
1927 // We should be able to round-trip the formatted string =>
1928 // number => string (but not the other way around: number
1929 // => string => number2, might have number2 != number):
1930 if (rt) {
1931 Formattable n2;
1932 fmt.parse(exp, n2, status);
1933 if (U_FAILURE(status)) {
1934 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
1935 return;
1936 }
1937 UnicodeString saw2;
1938 fmt.format(n2, saw2, pos, status);
1939 CHECK(status, "NumberFormat::format");
1940 if (saw2 != exp) {
1941 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
1942 " => \"" + saw2 + "\"");
1943 }
1944 }
1945 } else {
1946 errln(UnicodeString("FAIL ") + toString(n) + " x " +
1947 escape(pat) + " = \"" +
1948 escape(saw) + "\", expected \"" + exp + "\"");
1949 }
1950}
1951
1952void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
1953 const UnicodeString& exp,
1954 UErrorCode status) {
1955 if (U_FAILURE(status)) {
1956 errln("FAIL: NumberFormat constructor");
1957 } else {
1958 expect(*fmt, n, exp);
1959 }
1960 delete fmt;
1961}
1962
1963void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
1964 double value, const UnicodeString& string) {
1965 UErrorCode ec = U_ZERO_ERROR;
1966 DecimalFormat& fmt = * (DecimalFormat*) &nf;
1967 const UChar DEFAULT_CURR[] = {45/*-*/,0};
374ca955
A
1968 UChar curr[4];
1969 u_strcpy(curr, DEFAULT_CURR);
b75a7d8f 1970 if (*locale.getLanguage() != 0) {
374ca955
A
1971 ucurr_forLocale(locale.getName(), curr, 4, &ec);
1972 assertSuccess("ucurr_forLocale", ec);
1973 fmt.setCurrency(curr, ec);
1974 assertSuccess("DecimalFormat::setCurrency", ec);
b75a7d8f
A
1975 }
1976 UnicodeString s;
1977 fmt.format(value, s);
1978 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
1979
1980 // Default display of the number yields "1234.5599999999999"
1981 // instead of "1234.56". Use a formatter to fix this.
1982 NumberFormat* f =
1983 NumberFormat::createInstance(Locale::getUS(), ec);
1984 UnicodeString v;
1985 if (U_FAILURE(ec)) {
1986 // Oops; bad formatter. Use default op+= display.
1987 v = (UnicodeString)"" + value;
1988 } else {
1989 f->setMaximumFractionDigits(4);
1990 f->setGroupingUsed(FALSE);
1991 f->format(value, v);
1992 }
1993 delete f;
1994
1995 if (s == string) {
1996 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
1997 } else {
1998 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
1999 ", expected " + prettify(string));
2000 }
2001}
2002
2003void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
2004 UnicodeString pat;
2005 fmt.toPattern(pat);
2006 if (pat == exp) {
2007 logln(UnicodeString("Ok \"") + pat + "\"");
2008 } else {
2009 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
2010 }
2011}
2012
2013void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2014 int32_t pos) {
2015 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
2016}
2017void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2018 int32_t pos, int32_t width, UChar pad) {
2019 expectPad(fmt, pat, pos, width, UnicodeString(pad));
2020}
2021void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2022 int32_t pos, int32_t width, const UnicodeString& pad) {
2023 int32_t apos = 0, awidth = 0;
2024 UnicodeString apadStr;
2025 UErrorCode status = U_ZERO_ERROR;
2026 fmt.applyPattern(pat, status);
2027 if (U_SUCCESS(status)) {
2028 apos = fmt.getPadPosition();
2029 awidth = fmt.getFormatWidth();
2030 apadStr=fmt.getPadCharacterString();
2031 } else {
2032 apos = -1;
2033 awidth = width;
2034 apadStr = pad;
2035 }
2036 if (apos == pos && awidth == width && apadStr == pad) {
374ca955
A
2037 UnicodeString infoStr;
2038 if (pos == ILLEGAL) {
2039 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
2040 }
2041 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
b75a7d8f
A
2042 } else {
2043 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
2044 " width=" + awidth + " pad=" + apadStr +
2045 ", expected " + pos + " " + width + " " + pad);
2046 }
2047}
2048
2049#endif /* #if !UCONFIG_NO_FORMATTING */