]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/numfmtst.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2003, 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.
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"
20 #include <float.h>
21 #include <string.h>
22 #include "digitlst.h"
23
24 static const UChar EUR[] = {69,85,82,0}; // "EUR"
25
26 // *****************************************************************************
27 // class NumberFormatTest
28 // *****************************************************************************
29
30 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
31
32 #define CHECK(status,str) if (U_FAILURE(status)) { errln(UnicodeString("FAIL: ") + str); return; }
33
34 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
35 {
36 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
37 switch (index) {
38 CASE(0,TestCurrencySign);
39 CASE(1,TestCurrency);
40 CASE(2,TestParse);
41 CASE(3,TestRounding487);
42 CASE(4,TestQuotes);
43 CASE(5,TestExponential);
44 CASE(6,TestPatterns);
45
46 // Upgrade to alphaWorks - liu 5/99
47 CASE(7,TestExponent);
48 CASE(8,TestScientific);
49 CASE(9,TestPad);
50 CASE(10,TestPatterns2);
51 CASE(11,TestSecondaryGrouping);
52 CASE(12,TestSurrogateSupport);
53 CASE(13,TestAPI);
54
55 CASE(14,TestCurrencyObject);
56 CASE(15,TestCurrencyPatterns);
57 CASE(16,TestDigitList);
58 CASE(17,TestWhiteSpaceParsing);
59 CASE(18,TestComplexCurrency);
60 CASE(19,TestRegCurrency);
61 CASE(20,TestSymbolsWithBadLocale);
62 CASE(21,TestAdoptDecimalFormatSymbols);
63
64 default: name = ""; break;
65 }
66 }
67
68 // -------------------------------------
69
70 // Test API (increase code coverage)
71 void
72 NumberFormatTest::TestAPI(void)
73 {
74 logln("Test API");
75 UErrorCode status = U_ZERO_ERROR;
76 NumberFormat *test = NumberFormat::createInstance("root", status);
77 if(U_FAILURE(status)) {
78 errln("unable to create format object");
79 }
80 if(test != NULL) {
81 test->setMinimumIntegerDigits(10);
82 test->setMaximumIntegerDigits(2);
83
84 test->setMinimumFractionDigits(10);
85 test->setMaximumFractionDigits(2);
86
87 UnicodeString result;
88 FieldPosition pos;
89 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
90 test->format(bla, result, pos, status);
91 if(U_SUCCESS(status)) {
92 errln("Yuck... Formatted a duck... As a number!");
93 } else {
94 status = U_ZERO_ERROR;
95 }
96
97 delete test;
98 }
99
100
101
102 }
103
104 // Test various patterns
105 void
106 NumberFormatTest::TestPatterns(void)
107 {
108 UErrorCode status = U_ZERO_ERROR;
109 DecimalFormatSymbols sym(Locale::getUS(), status);
110 if (U_FAILURE(status)) { errln("FAIL: Could not construct DecimalFormatSymbols"); return; }
111
112 const char* pat[] = { "#.#", "#.", ".#", "#" };
113 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
114 const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
115 const char* num[] = { "0", "0.", ".0", "0" };
116 for (int32_t i=0; i<pat_length; ++i)
117 {
118 status = U_ZERO_ERROR;
119 DecimalFormat fmt(pat[i], sym, status);
120 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
121 UnicodeString newp; fmt.toPattern(newp);
122 if (!(newp == newpat[i]))
123 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
124 "; " + newp + " seen instead");
125
126 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
127 if (!(s == num[i]))
128 {
129 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
130 "; " + s + " seen instead");
131 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
132 }
133 }
134 }
135
136 void
137 NumberFormatTest::TestDigitList(void)
138 {
139 // API coverage for DigitList
140 /*
141 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
142 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
143 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
144 */
145 DigitList list1;
146 list1.append('1');
147 list1.fDecimalAt = 1;
148 DigitList list2;
149 list2.set(1);
150 if (list1 != list2) {
151 errln("digitlist append, operator!= or set failed ");
152 }
153 if (!(list1 == list2)) {
154 errln("digitlist append, operator== or set failed ");
155 }
156 }
157
158 // -------------------------------------
159
160 // Test exponential pattern
161 void
162 NumberFormatTest::TestExponential(void)
163 {
164 UErrorCode status = U_ZERO_ERROR;
165 DecimalFormatSymbols sym(Locale::getUS(), status);
166 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormatSymbols ct"); return; }
167 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
168 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
169
170 // The following #if statements allow this test to be built and run on
171 // platforms that do not have standard IEEE numerics. For example,
172 // S/390 doubles have an exponent range of -78 to +75. For the
173 // following #if statements to work, float.h must define
174 // DBL_MAX_10_EXP to be a compile-time constant.
175
176 // This section may be expanded as needed.
177
178 #if DBL_MAX_10_EXP > 300
179 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
180 int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
181 const char* valFormat[] =
182 {
183 // 0.####E0
184 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
185 // 00.000E00
186 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
187 // ##0.######E000
188 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
189 // 0.###E0;[0.###E0]
190 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
191 };
192 double valParse[] =
193 {
194 0.01234, 123460000, 1.23E300, -3.1416E-271,
195 0.01234, 123460000, 1.23E300, -3.1416E-271,
196 0.01234, 123456800, 1.23E300, -3.141593E-271,
197 0.01234, 123500000, 1.23E300, -3.142E-271,
198 };
199 #elif DBL_MAX_10_EXP > 70
200 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
201 int32_t val_length = sizeof(val) / sizeof(val[0]);
202 char* valFormat[] =
203 {
204 // 0.####E0
205 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
206 // 00.000E00
207 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
208 // ##0.######E000
209 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
210 // 0.###E0;[0.###E0]
211 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
212 };
213 double valParse[] =
214 {
215 0.01234, 123460000, 1.23E70, -3.1416E-71,
216 0.01234, 123460000, 1.23E70, -3.1416E-71,
217 0.01234, 123456800, 1.23E70, -3.141593E-71,
218 0.01234, 123500000, 1.23E70, -3.142E-71,
219 };
220 #else
221 // Don't test double conversion
222 double* val = 0;
223 int32_t val_length = 0;
224 char** valFormat = 0;
225 double* valParse = 0;
226 logln("Warning: Skipping double conversion tests");
227 #endif
228
229 int32_t lval[] = { 0, -1, 1, 123456789 };
230 int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
231 const char* lvalFormat[] =
232 {
233 // 0.####E0
234 "0E0", "-1E0", "1E0", "1.2346E8",
235 // 00.000E00
236 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
237 // ##0.######E000
238 "0E000", "-1E000", "1E000", "123.4568E006",
239 // 0.###E0;[0.###E0]
240 "0E0", "[1E0]", "1E0", "1.235E8"
241 };
242 int32_t lvalParse[] =
243 {
244 0, -1, 1, 123460000,
245 0, -1, 1, 123460000,
246 0, -1, 1, 123456800,
247 0, -1, 1, 123500000,
248 };
249 int32_t ival = 0, ilval = 0;
250 for (int32_t p=0; p<pat_length; ++p)
251 {
252 DecimalFormat fmt(pat[p], sym, status);
253 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
254 UnicodeString pattern;
255 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
256 fmt.toPattern(pattern) + "\"");
257 int32_t v;
258 for (v=0; v<val_length; ++v)
259 {
260 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
261 logln((UnicodeString)" " + val[v] + " -format-> " + s);
262 if (s != valFormat[v+ival])
263 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
264
265 ParsePosition pos(0);
266 Formattable af;
267 fmt.parse(s, af, pos);
268 double a;
269 UBool useEpsilon = FALSE;
270 if (af.getType() == Formattable::kLong)
271 a = af.getLong();
272 else if (af.getType() == Formattable::kDouble) {
273 a = af.getDouble();
274 #if defined(OS390) || defined(OS400)
275 // S/390 will show a failure like this:
276 //| -3.141592652999999e-271 -format-> -3.1416E-271
277 //| -parse-> -3.1416e-271
278 //| FAIL: Expected -3.141599999999999e-271
279 // To compensate, we use an epsilon-based equality
280 // test on S/390 only. We don't want to do this in
281 // general because it's less exacting.
282 useEpsilon = TRUE;
283 #endif
284 }
285 else {
286 errln((UnicodeString)"FAIL: Non-numeric Formattable returned");
287 continue;
288 }
289 if (pos.getIndex() == s.length())
290 {
291 logln((UnicodeString)" -parse-> " + a);
292 // Use epsilon comparison as necessary
293 if ((useEpsilon &&
294 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
295 (!useEpsilon && a != valParse[v+ival]))
296 {
297 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival]);
298 }
299 }
300 else {
301 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
302 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
303 }
304 }
305 for (v=0; v<lval_length; ++v)
306 {
307 UnicodeString s;
308 (*(NumberFormat*)&fmt).format(lval[v], s);
309 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
310 if (s != lvalFormat[v+ilval])
311 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
312
313 ParsePosition pos(0);
314 Formattable af;
315 fmt.parse(s, af, pos);
316 if (af.getType() == Formattable::kLong) {
317 int32_t a = af.getLong();
318 if (pos.getIndex() == s.length())
319 {
320 logln((UnicodeString)" -parse-> " + a);
321 if (a != lvalParse[v+ilval])
322 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval]);
323 }
324 else
325 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
326 }
327 else
328 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
329 + " Double: " + af.getDouble()
330 + ", Long: " + af.getLong());
331 }
332 ival += val_length;
333 ilval += lval_length;
334 }
335 }
336
337 // -------------------------------------
338
339 // Test the handling of quotes
340 void
341 NumberFormatTest::TestQuotes(void)
342 {
343 UErrorCode status = U_ZERO_ERROR;
344 UnicodeString *pat;
345 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
346 pat = new UnicodeString("a'fo''o'b#");
347 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
348 UnicodeString s;
349 ((NumberFormat*)fmt)->format((int32_t)123, s);
350 logln((UnicodeString)"Pattern \"" + *pat + "\"");
351 logln((UnicodeString)" Format 123 -> " + escape(s));
352 if (!(s=="afo'ob123"))
353 errln((UnicodeString)"FAIL: Expected afo'ob123");
354
355 s.truncate(0);
356 delete fmt;
357 delete pat;
358
359 pat = new UnicodeString("a''b#");
360 fmt = new DecimalFormat(*pat, *sym, status);
361 ((NumberFormat*)fmt)->format((int32_t)123, s);
362 logln((UnicodeString)"Pattern \"" + *pat + "\"");
363 logln((UnicodeString)" Format 123 -> " + escape(s));
364 if (!(s=="a'b123"))
365 errln((UnicodeString)"FAIL: Expected a'b123");
366 delete fmt;
367 delete pat;
368 delete sym;
369 }
370
371 /**
372 * Test the handling of the currency symbol in patterns.
373 */
374 void
375 NumberFormatTest::TestCurrencySign(void)
376 {
377 UErrorCode status = U_ZERO_ERROR;
378 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
379 UnicodeString pat;
380 UChar currency = 0x00A4;
381 // "\xA4#,##0.00;-\xA4#,##0.00"
382 pat.append(currency).append("#,##0.00;-").
383 append(currency).append("#,##0.00");
384 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
385 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
386 pat.truncate(0);
387 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
388 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
389 if (s != "$1,234.56") errln((UnicodeString)"FAIL: Expected $1,234.56");
390 s.truncate(0);
391 ((NumberFormat*)fmt)->format(- 1234.56, s);
392 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
393 if (s != "-$1,234.56") errln((UnicodeString)"FAIL: Expected -$1,234.56");
394 delete fmt;
395 pat.truncate(0);
396 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
397 pat.append(currency).append(currency).
398 append(" #,##0.00;").
399 append(currency).append(currency).
400 append(" -#,##0.00");
401 fmt = new DecimalFormat(pat, *sym, status);
402 s.truncate(0);
403 ((NumberFormat*)fmt)->format(1234.56, s);
404 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
405 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
406 if (s != "USD 1,234.56") errln((UnicodeString)"FAIL: Expected USD 1,234.56");
407 s.truncate(0);
408 ((NumberFormat*)fmt)->format(-1234.56, s);
409 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
410 if (s != "USD -1,234.56") errln((UnicodeString)"FAIL: Expected USD -1,234.56");
411 delete fmt;
412 delete sym;
413 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
414 }
415
416 // -------------------------------------
417
418 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
419
420 UnicodeString&
421 NumberFormatTest::escape(UnicodeString& s)
422 {
423 UnicodeString buf;
424 for (int32_t i=0; i<s.length(); ++i)
425 {
426 UChar c = s[(int32_t)i];
427 if (c <= (UChar)0x7F) buf += c;
428 else {
429 buf += (UChar)0x5c; buf += (UChar)0x55;
430 buf += toHexString((c & 0xF000) >> 12);
431 buf += toHexString((c & 0x0F00) >> 8);
432 buf += toHexString((c & 0x00F0) >> 4);
433 buf += toHexString(c & 0x000F);
434 }
435 }
436 return (s = buf);
437 }
438
439
440 // -------------------------------------
441
442 /**
443 * Test localized currency patterns.
444 */
445 void
446 NumberFormatTest::TestCurrency(void)
447 {
448 UErrorCode status = U_ZERO_ERROR;
449 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
450 UnicodeString s; currencyFmt->format(1.50, s);
451 logln((UnicodeString)"Un pauvre ici a..........." + s);
452 if (!(s=="1,50 $"))
453 errln((UnicodeString)"FAIL: Expected 1,50 $");
454 delete currencyFmt;
455 s.truncate(0);
456 currencyFmt = NumberFormat::createCurrencyInstance(Locale("de_DE_PREEURO"),status);
457 currencyFmt->format(1.50, s);
458 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
459 if (!(s=="1,50 DM"))
460 errln((UnicodeString)"FAIL: Expected 1,50 DM");
461 delete currencyFmt;
462 s.truncate(0);
463 currencyFmt = NumberFormat::createCurrencyInstance(Locale("fr_FR_PREEURO"), status);
464 currencyFmt->format(1.50, s);
465 logln((UnicodeString)"Un pauvre en France a....." + s);
466 if (!(s=="1,50 F"))
467 errln((UnicodeString)"FAIL: Expected 1,50 F");
468 delete currencyFmt;
469 if (U_FAILURE(status))
470 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
471 }
472
473 // -------------------------------------
474
475 /**
476 * Test the Currency object handling, new as of ICU 2.2.
477 */
478 void NumberFormatTest::TestCurrencyObject() {
479 UErrorCode ec = U_ZERO_ERROR;
480 NumberFormat* fmt =
481 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
482
483 if (U_FAILURE(ec)) {
484 errln("FAIL: getCurrencyInstance(US)");
485 delete fmt;
486 return;
487 }
488
489 Locale null("", "", "");
490
491 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
492
493 expectCurrency(*fmt, Locale::getFrance(),
494 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
495
496 expectCurrency(*fmt, Locale::getJapan(),
497 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
498
499 expectCurrency(*fmt, Locale("fr", "CH", ""),
500 1234.56, "SwF1,234.55"); // 0.05 rounding
501
502 expectCurrency(*fmt, Locale::getUS(),
503 1234.56, "$1,234.56");
504
505 delete fmt;
506 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
507
508 if (U_FAILURE(ec)) {
509 errln("FAIL: getCurrencyInstance(FRANCE)");
510 delete fmt;
511 return;
512 }
513
514 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
515
516 expectCurrency(*fmt, Locale::getJapan(),
517 1234.56, CharsToUnicodeString("1 235 \\u00A5")); // Yen
518
519 expectCurrency(*fmt, Locale("fr", "CH", ""),
520 1234.56, "1 234,55 sFr."); // 0.05 rounding
521
522 expectCurrency(*fmt, Locale::getUS(),
523 1234.56, "1 234,56 $");
524
525 expectCurrency(*fmt, Locale::getFrance(),
526 1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
527
528 delete fmt;
529 }
530
531 // -------------------------------------
532
533 /**
534 * Do rudimentary testing of parsing.
535 */
536 void
537 NumberFormatTest::TestParse(void)
538 {
539 UErrorCode status = U_ZERO_ERROR;
540 UnicodeString arg("0");
541 DecimalFormat* format = new DecimalFormat("00", status);
542 //try {
543 Formattable n; format->parse(arg, n, status);
544 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
545 if (n.getType() != Formattable::kLong ||
546 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
547 delete format;
548 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
549 //}
550 //catch(Exception e) {
551 // errln((UnicodeString)"Exception caught: " + e);
552 //}
553 }
554
555 // -------------------------------------
556
557 /**
558 * Test proper rounding by the format method.
559 */
560 void
561 NumberFormatTest::TestRounding487(void)
562 {
563 UErrorCode status = U_ZERO_ERROR;
564 NumberFormat *nf = NumberFormat::createInstance(status);
565 roundingTest(*nf, 0.00159999, 4, "0.0016");
566 roundingTest(*nf, 0.00995, 4, "0.01");
567
568 roundingTest(*nf, 12.3995, 3, "12.4");
569
570 roundingTest(*nf, 12.4999, 0, "12");
571 roundingTest(*nf, - 19.5, 0, "-20");
572 delete nf;
573 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
574 }
575
576 /**
577 * Test the functioning of the secondary grouping value.
578 */
579 void NumberFormatTest::TestSecondaryGrouping(void) {
580 UErrorCode status = U_ZERO_ERROR;
581 DecimalFormatSymbols US(Locale::getUS(), status);
582 CHECK(status, "DecimalFormatSymbols ct");
583
584 DecimalFormat f("#,##,###", US, status);
585 CHECK(status, "DecimalFormat ct");
586
587 expect2(f, (int32_t)123456789L, "12,34,56,789");
588 expectPat(f, "#,##,###");
589 f.applyPattern("#,###", status);
590 CHECK(status, "applyPattern");
591
592 f.setSecondaryGroupingSize(4);
593 expect2(f, (int32_t)123456789L, "12,3456,789");
594 expectPat(f, "#,####,###");
595 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
596 CHECK(status, "createInstance(hi_IN)");
597
598 UnicodeString out;
599 int32_t l = (int32_t)1876543210L;
600 g->format(l, out);
601 delete g;
602 // expect "1,87,65,43,210", but with Hindi digits
603 // 01234567890123
604 UBool ok = TRUE;
605 if (out.length() != 14) {
606 ok = FALSE;
607 } else {
608 for (int32_t i=0; i<out.length(); ++i) {
609 UBool expectGroup = FALSE;
610 switch (i) {
611 case 1:
612 case 4:
613 case 7:
614 case 10:
615 expectGroup = TRUE;
616 break;
617 }
618 // Later -- fix this to get the actual grouping
619 // character from the resource bundle.
620 UBool isGroup = (out.charAt(i) == 0x002C);
621 if (isGroup != expectGroup) {
622 ok = FALSE;
623 break;
624 }
625 }
626 }
627 if (!ok) {
628 errln((UnicodeString)"FAIL Expected " + l +
629 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
630 escape(out) + "\"");
631 } else {
632 logln((UnicodeString)"Ok " + l +
633 " x hi_IN -> \"" +
634 escape(out) + "\"");
635 }
636 }
637
638 void NumberFormatTest::TestWhiteSpaceParsing(void) {
639 UErrorCode ec = U_ZERO_ERROR;
640 DecimalFormatSymbols US(Locale::getUS(), ec);
641 DecimalFormat fmt("a b#0c ", US, ec);
642 if (U_FAILURE(ec)) {
643 errln("FAIL: Constructor");
644 return;
645 }
646 int32_t n = 1234;
647 expect(fmt, "a b1234c ", n);
648 expect(fmt, "a b1234c ", n);
649 }
650
651 /**
652 * Test currencies whose display name is a ChoiceFormat.
653 */
654 void NumberFormatTest::TestComplexCurrency() {
655 UErrorCode ec = U_ZERO_ERROR;
656 Locale loc("en", "IN", "");
657 NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
658 if (U_SUCCESS(ec)) {
659 expect2(*fmt, 1.0, "Re. 1.00");
660 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
661 expect(*fmt, 1.00390625, "Re. 1.00"); // tricky
662 expect2(*fmt, 12345678.0, "Rs. 1,23,45,678.00");
663 expect2(*fmt, 0.5, "Rs. 0.50");
664 expect2(*fmt, -1.0, "-Re. 1.00");
665 expect2(*fmt, -10.0, "-Rs. 10.00");
666 } else {
667 errln("FAIL: getCurrencyInstance(en_IN)");
668 }
669 delete fmt;
670 }
671
672 // -------------------------------------
673
674 void
675 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
676 {
677 nf.setMaximumFractionDigits(maxFractionDigits);
678 UnicodeString out; nf.format(x, out);
679 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
680 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
681 }
682
683 /**
684 * Upgrade to alphaWorks
685 */
686 void NumberFormatTest::TestExponent(void) {
687 UErrorCode status = U_ZERO_ERROR;
688 DecimalFormatSymbols US(Locale::getUS(), status);
689 CHECK(status, "DecimalFormatSymbols constructor");
690 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
691 CHECK(status, "DecimalFormat(0.###E0)");
692 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
693 CHECK(status, "DecimalFormat(0.###E+0)");
694 int32_t n = 1234;
695 expect2(fmt1, n, "1.234E3");
696 expect2(fmt2, n, "1.234E+3");
697 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
698 }
699
700 /**
701 * Upgrade to alphaWorks
702 */
703 void NumberFormatTest::TestScientific(void) {
704 UErrorCode status = U_ZERO_ERROR;
705 DecimalFormatSymbols US(Locale::getUS(), status);
706 CHECK(status, "DecimalFormatSymbols constructor");
707
708 // Test pattern round-trip
709 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
710 "0.###E0;[0.###E0]" };
711 int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
712 int32_t DIGITS[] = {
713 // min int, max int, min frac, max frac
714 0, 1, 0, 0, // "#E0"
715 1, 1, 0, 4, // "0.####E0"
716 2, 2, 3, 3, // "00.000E00"
717 1, 3, 0, 4, // "##0.####E000"
718 1, 1, 0, 3, // "0.###E0;[0.###E0]"
719 };
720 for (int32_t i=0; i<PAT_length; ++i) {
721 UnicodeString pat(PAT[i]);
722 DecimalFormat df(pat, US, status);
723 CHECK(status, "DecimalFormat constructor");
724 UnicodeString pat2;
725 df.toPattern(pat2);
726 if (pat == pat2) {
727 logln(UnicodeString("Ok Pattern rt \"") +
728 pat + "\" -> \"" +
729 pat2 + "\"");
730 } else {
731 errln(UnicodeString("FAIL Pattern rt \"") +
732 pat + "\" -> \"" +
733 pat2 + "\"");
734 }
735 // Make sure digit counts match what we expect
736 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
737 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
738 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
739 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
740 errln(UnicodeString("FAIL \"" + pat +
741 "\" min/max int; min/max frac = ") +
742 df.getMinimumIntegerDigits() + "/" +
743 df.getMaximumIntegerDigits() + ";" +
744 df.getMinimumFractionDigits() + "/" +
745 df.getMaximumFractionDigits() + ", expect " +
746 DIGITS[4*i] + "/" +
747 DIGITS[4*i+1] + ";" +
748 DIGITS[4*i+2] + "/" +
749 DIGITS[4*i+3]);
750 }
751 }
752
753
754 // Test the constructor for default locale. We have to
755 // manually set the default locale, as there is no
756 // guarantee that the default locale has the same
757 // scientific format.
758 Locale def = Locale::getDefault();
759 Locale::setDefault(Locale::getUS(), status);
760 expect2(NumberFormat::createScientificInstance(status),
761 12345.678901,
762 "1.2345678901E4", status);
763 Locale::setDefault(def, status);
764
765 expect2(new DecimalFormat("#E0", US, status),
766 12345.0,
767 "1.2345E4", status);
768 expect(new DecimalFormat("0E0", US, status),
769 12345.0,
770 "1E4", status);
771 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
772 12345.678901,
773 "1.2345678901E4", status);
774 expect(new DecimalFormat("##0.###E0", US, status),
775 12345.0,
776 "12.34E3", status);
777 expect(new DecimalFormat("##0.###E0", US, status),
778 12345.00001,
779 "12.35E3", status);
780 expect2(new DecimalFormat("##0.####E0", US, status),
781 (int32_t) 12345,
782 "12.345E3", status);
783 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
784 12345.678901,
785 "1,2345678901E4", status);
786 expect(new DecimalFormat("##0.####E0", US, status),
787 789.12345e-9,
788 "789.12E-9", status);
789 expect2(new DecimalFormat("##0.####E0", US, status),
790 780.e-9,
791 "780E-9", status);
792 expect(new DecimalFormat(".###E0", US, status),
793 45678.0,
794 ".457E5", status);
795 expect2(new DecimalFormat(".###E0", US, status),
796 (int32_t) 0,
797 ".0E0", status);
798 /*
799 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
800 new DecimalFormat("##E0", US),
801 new DecimalFormat("####E0", US),
802 new DecimalFormat("0E0", US),
803 new DecimalFormat("00E0", US),
804 new DecimalFormat("000E0", US),
805 },
806 new Long(45678000),
807 new String[] { "4.5678E7",
808 "45.678E6",
809 "4567.8E4",
810 "5E7",
811 "46E6",
812 "457E5",
813 }
814 );
815 !
816 ! Unroll this test into individual tests below...
817 !
818 */
819 expect2(new DecimalFormat("#E0", US, status),
820 (int32_t) 45678000, "4.5678E7", status);
821 expect2(new DecimalFormat("##E0", US, status),
822 (int32_t) 45678000, "45.678E6", status);
823 expect2(new DecimalFormat("####E0", US, status),
824 (int32_t) 45678000, "4567.8E4", status);
825 expect(new DecimalFormat("0E0", US, status),
826 (int32_t) 45678000, "5E7", status);
827 expect(new DecimalFormat("00E0", US, status),
828 (int32_t) 45678000, "46E6", status);
829 expect(new DecimalFormat("000E0", US, status),
830 (int32_t) 45678000, "457E5", status);
831 /*
832 expect(new DecimalFormat("###E0", US, status),
833 new Object[] { new Double(0.0000123), "12.3E-6",
834 new Double(0.000123), "123E-6",
835 new Double(0.00123), "1.23E-3",
836 new Double(0.0123), "12.3E-3",
837 new Double(0.123), "123E-3",
838 new Double(1.23), "1.23E0",
839 new Double(12.3), "12.3E0",
840 new Double(123), "123E0",
841 new Double(1230), "1.23E3",
842 });
843 !
844 ! Unroll this test into individual tests below...
845 !
846 */
847 expect2(new DecimalFormat("###E0", US, status),
848 0.0000123, "12.3E-6", status);
849 expect2(new DecimalFormat("###E0", US, status),
850 0.000123, "123E-6", status);
851 expect2(new DecimalFormat("###E0", US, status),
852 0.00123, "1.23E-3", status);
853 expect2(new DecimalFormat("###E0", US, status),
854 0.0123, "12.3E-3", status);
855 expect2(new DecimalFormat("###E0", US, status),
856 0.123, "123E-3", status);
857 expect2(new DecimalFormat("###E0", US, status),
858 1.23, "1.23E0", status);
859 expect2(new DecimalFormat("###E0", US, status),
860 12.3, "12.3E0", status);
861 expect2(new DecimalFormat("###E0", US, status),
862 123.0, "123E0", status);
863 expect2(new DecimalFormat("###E0", US, status),
864 1230.0, "1.23E3", status);
865 /*
866 expect(new DecimalFormat("0.#E+00", US, status),
867 new Object[] { new Double(0.00012), "1.2E-04",
868 new Long(12000), "1.2E+04",
869 });
870 !
871 ! Unroll this test into individual tests below...
872 !
873 */
874 expect2(new DecimalFormat("0.#E+00", US, status),
875 0.00012, "1.2E-04", status);
876 expect2(new DecimalFormat("0.#E+00", US, status),
877 (int32_t) 12000, "1.2E+04", status);
878 }
879
880 /**
881 * Upgrade to alphaWorks
882 */
883 void NumberFormatTest::TestPad(void) {
884 UErrorCode status = U_ZERO_ERROR;
885 DecimalFormatSymbols US(Locale::getUS(), status);
886 CHECK(status, "DecimalFormatSymbols constructor");
887
888 expect2(new DecimalFormat("*^##.##", US, status),
889 int32_t(0), "^^^^0", status);
890 expect2(new DecimalFormat("*^##.##", US, status),
891 -1.3, "^-1.3", status);
892 expect2(new DecimalFormat("##0.0####E0*_ g-m/s^2", US, status),
893 int32_t(0), "0.0E0______ g-m/s^2", status);
894 expect(new DecimalFormat("##0.0####E0*_ g-m/s^2", US, status),
895 1.0/3, "333.333E-3_ g-m/s^2", status);
896 expect2(new DecimalFormat("##0.0####*_ g-m/s^2", US, status),
897 int32_t(0), "0.0______ g-m/s^2", status);
898 expect(new DecimalFormat("##0.0####*_ g-m/s^2", US, status),
899 1.0/3, "0.33333__ g-m/s^2", status);
900
901 // Test padding before a sign
902 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
903 expect2(new DecimalFormat(formatStr, US, status),
904 int32_t(-10), "xxxxxxxxxx(10.0)", status);
905 expect2(new DecimalFormat(formatStr, US, status),
906 int32_t(-1000),"xxxxxxx(1,000.0)", status);
907 expect2(new DecimalFormat(formatStr, US, status),
908 int32_t(-1000000),"xxx(1,000,000.0)", status);
909 expect2(new DecimalFormat(formatStr, US, status),
910 -100.37, "xxxxxxxx(100.37)", status);
911 expect2(new DecimalFormat(formatStr, US, status),
912 -10456.37, "xxxxx(10,456.37)", status);
913 expect2(new DecimalFormat(formatStr, US, status),
914 -1120456.37, "xx(1,120,456.37)", status);
915 expect2(new DecimalFormat(formatStr, US, status),
916 -112045600.37, "(112,045,600.37)", status);
917 expect2(new DecimalFormat(formatStr, US, status),
918 -1252045600.37,"(1,252,045,600.37)", status);
919
920 expect2(new DecimalFormat(formatStr, US, status),
921 int32_t(10), "xxxxxxxxxxxx10.0", status);
922 expect2(new DecimalFormat(formatStr, US, status),
923 int32_t(1000),"xxxxxxxxx1,000.0", status);
924 expect2(new DecimalFormat(formatStr, US, status),
925 int32_t(1000000),"xxxxx1,000,000.0", status);
926 expect2(new DecimalFormat(formatStr, US, status),
927 100.37, "xxxxxxxxxx100.37", status);
928 expect2(new DecimalFormat(formatStr, US, status),
929 10456.37, "xxxxxxx10,456.37", status);
930 expect2(new DecimalFormat(formatStr, US, status),
931 1120456.37, "xxxx1,120,456.37", status);
932 expect2(new DecimalFormat(formatStr, US, status),
933 112045600.37, "xx112,045,600.37", status);
934 expect2(new DecimalFormat(formatStr, US, status),
935 10252045600.37,"10,252,045,600.37", status);
936
937
938 // Test padding between a sign and a number
939 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
940 expect2(new DecimalFormat(formatStr2, US, status),
941 int32_t(-10), "(10.0xxxxxxxxxx)", status);
942 expect2(new DecimalFormat(formatStr2, US, status),
943 int32_t(-1000),"(1,000.0xxxxxxx)", status);
944 expect2(new DecimalFormat(formatStr2, US, status),
945 int32_t(-1000000),"(1,000,000.0xxx)", status);
946 expect2(new DecimalFormat(formatStr2, US, status),
947 -100.37, "(100.37xxxxxxxx)", status);
948 expect2(new DecimalFormat(formatStr2, US, status),
949 -10456.37, "(10,456.37xxxxx)", status);
950 expect2(new DecimalFormat(formatStr2, US, status),
951 -1120456.37, "(1,120,456.37xx)", status);
952 expect2(new DecimalFormat(formatStr2, US, status),
953 -112045600.37, "(112,045,600.37)", status);
954 expect2(new DecimalFormat(formatStr2, US, status),
955 -1252045600.37,"(1,252,045,600.37)", status);
956
957 expect2(new DecimalFormat(formatStr2, US, status),
958 int32_t(10), "10.0xxxxxxxxxxxx", status);
959 expect2(new DecimalFormat(formatStr2, US, status),
960 int32_t(1000),"1,000.0xxxxxxxxx", status);
961 expect2(new DecimalFormat(formatStr2, US, status),
962 int32_t(1000000),"1,000,000.0xxxxx", status);
963 expect2(new DecimalFormat(formatStr2, US, status),
964 100.37, "100.37xxxxxxxxxx", status);
965 expect2(new DecimalFormat(formatStr2, US, status),
966 10456.37, "10,456.37xxxxxxx", status);
967 expect2(new DecimalFormat(formatStr2, US, status),
968 1120456.37, "1,120,456.37xxxx", status);
969 expect2(new DecimalFormat(formatStr2, US, status),
970 112045600.37, "112,045,600.37xx", status);
971 expect2(new DecimalFormat(formatStr2, US, status),
972 10252045600.37,"10,252,045,600.37", status);
973
974 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
975 DecimalFormat fmt("#", US, status);
976 CHECK(status, "DecimalFormat constructor");
977 UnicodeString padString("P");
978 fmt.setPadCharacter(padString);
979 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
980 fmt.setPadCharacter((UnicodeString)"^");
981 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
982 //commented untill implementation is complete
983 /* fmt.setPadCharacter((UnicodeString)"^^^");
984 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
985 padString.remove();
986 padString.append((UChar)0x0061);
987 padString.append((UChar)0x0302);
988 fmt.setPadCharacter(padString);
989 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
990 UnicodeString pattern(patternChars);
991 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
992 */
993
994 }
995
996 /**
997 * Upgrade to alphaWorks
998 */
999 void NumberFormatTest::TestPatterns2(void) {
1000 UErrorCode status = U_ZERO_ERROR;
1001 DecimalFormatSymbols US(Locale::getUS(), status);
1002 CHECK(status, "DecimalFormatSymbols constructor");
1003
1004 DecimalFormat fmt("#", US, status);
1005 CHECK(status, "DecimalFormat constructor");
1006
1007 UChar hat = 0x005E; /*^*/
1008
1009 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1010 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1011 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1012 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1013 expectPad(fmt, "$*^$#", ILLEGAL);
1014 expectPad(fmt, "#$*^$", ILLEGAL);
1015 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1016 12, (UChar)0x0078 /*x*/);
1017 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1018 3, (UChar)0x0078 /*x*/);
1019 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1020 10, (UChar)0x0061 /*a*/);
1021
1022 fmt.applyPattern("AA#,##0.00ZZ", status);
1023 CHECK(status, "applyPattern");
1024 fmt.setPadCharacter(hat);
1025
1026 fmt.setFormatWidth(10);
1027
1028 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1029 expectPat(fmt, "*^AA#,##0.00ZZ");
1030
1031 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1032 expectPat(fmt, "AA#,##0.00*^ZZ");
1033
1034 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1035 expectPat(fmt, "AA#,##0.00ZZ*^");
1036
1037 // 12 3456789012
1038 UnicodeString exp("AA*^#,##0.00ZZ", "");
1039 fmt.setFormatWidth(12);
1040 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1041 expectPat(fmt, exp);
1042
1043 fmt.setFormatWidth(13);
1044 // 12 34567890123
1045 expectPat(fmt, "AA*^##,##0.00ZZ");
1046
1047 fmt.setFormatWidth(14);
1048 // 12 345678901234
1049 expectPat(fmt, "AA*^###,##0.00ZZ");
1050
1051 fmt.setFormatWidth(15);
1052 // 12 3456789012345
1053 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1054
1055 fmt.setFormatWidth(16);
1056 // 12 34567890123456
1057 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1058 }
1059
1060 void NumberFormatTest::TestSurrogateSupport(void) {
1061 UErrorCode status = U_ZERO_ERROR;
1062 DecimalFormatSymbols custom(Locale::getUS(), status);
1063 CHECK(status, "DecimalFormatSymbols constructor");
1064
1065 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1066 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1067 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1068 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1069
1070 UnicodeString patternStr("*\\U00010000##.##", "");
1071 patternStr = patternStr.unescape();
1072 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1073 expStr = expStr.unescape();
1074 expect2(new DecimalFormat(patternStr, custom, status),
1075 int32_t(0), expStr, status);
1076
1077 status = U_ZERO_ERROR;
1078 expect2(new DecimalFormat("*^##.##", custom, status),
1079 int32_t(0), "^^^^0", status);
1080 status = U_ZERO_ERROR;
1081 expect2(new DecimalFormat("##.##", custom, status),
1082 -1.3, " minus 1decimal3", status);
1083 status = U_ZERO_ERROR;
1084 expect2(new DecimalFormat("##0.0####E0 g'-'m/s^2", custom, status),
1085 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1086 status = U_ZERO_ERROR;
1087 expect(new DecimalFormat("##0.0####E0 g'-'m/s^2", custom, status),
1088 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1089 status = U_ZERO_ERROR;
1090 expect2(new DecimalFormat("##0.0#### g'-'m/s^2", custom, status),
1091 int32_t(0), "0decimal0 g-m/s^2", status);
1092 status = U_ZERO_ERROR;
1093 expect(new DecimalFormat("##0.0#### g'-'m/s^2", custom, status),
1094 1.0/3, "0decimal33333 g-m/s^2", status);
1095
1096 UnicodeString zero((UChar32)0x10000);
1097 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1098 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1099 expStr = expStr.unescape();
1100 status = U_ZERO_ERROR;
1101 expect2(new DecimalFormat("##0.000", custom, status),
1102 1.25, expStr, status);
1103
1104 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1105 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1106 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1107 patternStr = "0.00 \\u00A4' in your bank account'";
1108 patternStr = patternStr.unescape();
1109 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1110 status = U_ZERO_ERROR;
1111 expect2(new DecimalFormat(patternStr, custom, status),
1112 int32_t(-20), expStr, status);
1113
1114 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1115 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1116 patternStr = patternStr.unescape();
1117 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1118 status = U_ZERO_ERROR;
1119 expect2(new DecimalFormat(patternStr, custom, status),
1120 int32_t(-20), expStr, status);
1121 }
1122
1123 void NumberFormatTest::TestCurrencyPatterns(void) {
1124 int32_t i, locCount;
1125 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1126 for (i=0; i<locCount; ++i) {
1127 UErrorCode ec = U_ZERO_ERROR;
1128 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1129 if (U_FAILURE(ec)) {
1130 errln("FAIL: Can't create NumberFormat");
1131 } else {
1132 // Make sure currency formats do not have a variable number
1133 // of fraction digits
1134 int32_t min = nf->getMinimumFractionDigits();
1135 int32_t max = nf->getMaximumFractionDigits();
1136 if (min != max) {
1137 UnicodeString a, b;
1138 nf->format(1.0, a);
1139 nf->format(1.125, b);
1140 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1141 " min fraction digits != max fraction digits; "
1142 "x 1.0 => " + escape(a) +
1143 "; x 1.125 => " + escape(b));
1144 }
1145
1146 // Make sure EURO currency formats have exactly 2 fraction digits
1147 if (nf->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1148 DecimalFormat* df = (DecimalFormat*) nf;
1149 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1150 if (min != 2 || max != 2) {
1151 UnicodeString a;
1152 nf->format(1.0, a);
1153 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1154 " is a EURO format but it does not have 2 fraction digits; "
1155 "x 1.0 => " +
1156 escape(a));
1157 }
1158 }
1159 }
1160 }
1161 delete nf;
1162 }
1163 }
1164
1165 void NumberFormatTest::TestRegCurrency(void) {
1166 UErrorCode status = U_ZERO_ERROR;
1167 const UChar* USD = ucurr_forLocale("en_US", &status);
1168 const UChar* YEN = ucurr_forLocale("ja_JP", &status);
1169 if(U_FAILURE(status)) {
1170 errln("Unable to get currency for locale, error %s", u_errorName(status));
1171 return;
1172 }
1173
1174 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1175 UCurrRegistryKey enUSEUROkey = ucurr_register(EUR, "en_US_EURO", &status);
1176
1177 if (u_strcmp(YEN, ucurr_forLocale("en_US", &status)) != 0) {
1178 errln("FAIL: didn't return YEN registered for en_US");
1179 }
1180
1181 if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
1182 errln("FAIL: didn't return EUR for en_US_EURO");
1183 }
1184
1185 if (ucurr_forLocale("en_XX_BAR", &status) != NULL) {
1186 errln("FAIL: tried to fallback en_XX_BAR");
1187 }
1188 status = U_ZERO_ERROR; // reset
1189
1190 if (!ucurr_unregister(enkey, &status)) {
1191 errln("FAIL: couldn't unregister enkey");
1192 }
1193
1194 if (u_strcmp(USD, ucurr_forLocale("en_US", &status)) != 0) {
1195 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1196 }
1197 status = U_ZERO_ERROR; // reset
1198
1199 if (u_strcmp(EUR, ucurr_forLocale("en_US_EURO", &status)) != 0) {
1200 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US");
1201 }
1202
1203 if (u_strcmp(USD, ucurr_forLocale("en_US_BLAH", &status)) != 0) {
1204 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1205 }
1206 status = U_ZERO_ERROR; // reset
1207
1208 if (!ucurr_unregister(enUSEUROkey, &status)) {
1209 errln("FAIL: couldn't unregister enUSEUROkey");
1210 }
1211
1212 if (ucurr_forLocale("en_US_EURO", &status) != NULL) {
1213 errln("FAIL: didn't return NULL for en_US_EURO after unregister of en_US_EURO");
1214 }
1215 status = U_ZERO_ERROR; // reset
1216 }
1217
1218 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1219 Locale locDefault;
1220 Locale locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1221 UErrorCode status = U_ZERO_ERROR;
1222 UnicodeString intlCurrencySymbol((UChar)0xa4);
1223
1224 intlCurrencySymbol.append((UChar)0xa4);
1225
1226 logln("Current locale is %s", Locale::getDefault().getName());
1227 Locale::setDefault(locBad, status);
1228 logln("Current locale is %s", Locale::getDefault().getName());
1229 DecimalFormatSymbols mySymbols(status);
1230 if (status != U_USING_FALLBACK_WARNING) {
1231 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1232 }
1233 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
1234 errln("DecimalFormatSymbols does not have the right locale.");
1235 }
1236 DecimalFormatSymbols::ENumberFormatSymbol symbolEnum;
1237 int *symbolEnumPtr = (int*)(&symbolEnum);
1238 for (symbolEnum = DecimalFormatSymbols::kDecimalSeparatorSymbol; symbolEnum < DecimalFormatSymbols::kFormatSymbolCount; (*symbolEnumPtr)++) {
1239 if (mySymbols.getSymbol(symbolEnum).length() == 0 && symbolEnum != DecimalFormatSymbols::kGroupingSeparatorSymbol) {
1240 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
1241 }
1242 }
1243 status = U_ZERO_ERROR;
1244 Locale::setDefault(locDefault, status);
1245 logln("Current locale is %s", Locale::getDefault().getName());
1246 }
1247
1248 /**
1249 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1250 * behave the same, except for memory ownership semantics. (No
1251 * version of this test on Java, since Java has only one method.)
1252 */
1253 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1254 UErrorCode ec = U_ZERO_ERROR;
1255 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1256 if (U_FAILURE(ec)) {
1257 errln("Fail: DecimalFormatSymbols constructor");
1258 delete sym;
1259 return;
1260 }
1261 UnicodeString pat(" #,##0.00");
1262 pat.insert(0, (UChar)0x00A4);
1263 DecimalFormat fmt(pat, sym, ec);
1264 if (U_FAILURE(ec)) {
1265 errln("Fail: DecimalFormat constructor");
1266 return;
1267 }
1268
1269 UnicodeString str;
1270 fmt.format(2350.75, str);
1271 if (str == "$ 2,350.75") {
1272 logln(str);
1273 } else {
1274 errln("Fail: " + str + ", expected $ 2,350.75");
1275 }
1276
1277 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1278 if (U_FAILURE(ec)) {
1279 errln("Fail: DecimalFormatSymbols constructor");
1280 delete sym;
1281 return;
1282 }
1283 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1284 fmt.adoptDecimalFormatSymbols(sym);
1285
1286 str.truncate(0);
1287 fmt.format(2350.75, str);
1288 if (str == "Q 2,350.75") {
1289 logln(str);
1290 } else {
1291 errln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1292 }
1293
1294 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1295 if (U_FAILURE(ec)) {
1296 errln("Fail: DecimalFormatSymbols constructor");
1297 delete sym;
1298 return;
1299 }
1300 DecimalFormat fmt2(pat, sym, ec);
1301 if (U_FAILURE(ec)) {
1302 errln("Fail: DecimalFormat constructor");
1303 return;
1304 }
1305
1306 DecimalFormatSymbols sym2(Locale::getUS(), ec);
1307 if (U_FAILURE(ec)) {
1308 errln("Fail: DecimalFormatSymbols constructor");
1309 return;
1310 }
1311 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1312 fmt2.setDecimalFormatSymbols(sym2);
1313
1314 str.truncate(0);
1315 fmt2.format(2350.75, str);
1316 if (str == "Q 2,350.75") {
1317 logln(str);
1318 } else {
1319 errln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1320 }
1321 }
1322
1323 //----------------------------------------------------------------------
1324 // Support methods
1325 //----------------------------------------------------------------------
1326
1327 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
1328 if (a.getType() == Formattable::kLong) {
1329 if (b.getType() == Formattable::kLong) {
1330 return a.getLong() == b.getLong();
1331 } else if (b.getType() == Formattable::kDouble) {
1332 return (double) a.getLong() == b.getDouble();
1333 }
1334 } else if (a.getType() == Formattable::kDouble) {
1335 if (b.getType() == Formattable::kLong) {
1336 return a.getDouble() == (double) b.getLong();
1337 } else if (b.getType() == Formattable::kDouble) {
1338 return a.getDouble() == b.getDouble();
1339 }
1340 }
1341 return FALSE;
1342 }
1343
1344 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
1345 // Don't round-trip format test, since we explicitly do it
1346 expect(fmt, n, str, FALSE);
1347 expect(fmt, str, n);
1348 }
1349
1350 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
1351 const UnicodeString& exp,
1352 UErrorCode status) {
1353 if (U_FAILURE(status)) {
1354 errln("FAIL: NumberFormat constructor");
1355 } else {
1356 expect2(*fmt, n, exp);
1357 }
1358 delete fmt;
1359 }
1360
1361 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
1362 UErrorCode status = U_ZERO_ERROR;
1363 Formattable num;
1364 fmt.parse(str, num, status);
1365 if (U_FAILURE(status)) {
1366 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
1367 return;
1368 }
1369 UnicodeString pat;
1370 ((DecimalFormat*) &fmt)->toPattern(pat);
1371 if (equalValue(num, n)) {
1372 logln(UnicodeString("Ok \"") + str + "\" x " +
1373 pat + " = " +
1374 toString(num));
1375 } else {
1376 errln(UnicodeString("FAIL \"") + str + "\" x " +
1377 pat + " = " +
1378 toString(num) + ", expected " + toString(n));
1379 }
1380 }
1381
1382 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
1383 const UnicodeString& exp, UBool rt) {
1384 UnicodeString saw;
1385 FieldPosition pos;
1386 UErrorCode status = U_ZERO_ERROR;
1387 fmt.format(n, saw, pos, status);
1388 CHECK(status, "NumberFormat::format");
1389 UnicodeString pat;
1390 ((DecimalFormat*) &fmt)->toPattern(pat);
1391 if (saw == exp) {
1392 logln(UnicodeString("Ok ") + toString(n) + " x " +
1393 escape(pat) + " = \"" +
1394 escape(saw) + "\"");
1395 // We should be able to round-trip the formatted string =>
1396 // number => string (but not the other way around: number
1397 // => string => number2, might have number2 != number):
1398 if (rt) {
1399 Formattable n2;
1400 fmt.parse(exp, n2, status);
1401 if (U_FAILURE(status)) {
1402 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
1403 return;
1404 }
1405 UnicodeString saw2;
1406 fmt.format(n2, saw2, pos, status);
1407 CHECK(status, "NumberFormat::format");
1408 if (saw2 != exp) {
1409 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
1410 " => \"" + saw2 + "\"");
1411 }
1412 }
1413 } else {
1414 errln(UnicodeString("FAIL ") + toString(n) + " x " +
1415 escape(pat) + " = \"" +
1416 escape(saw) + "\", expected \"" + exp + "\"");
1417 }
1418 }
1419
1420 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
1421 const UnicodeString& exp,
1422 UErrorCode status) {
1423 if (U_FAILURE(status)) {
1424 errln("FAIL: NumberFormat constructor");
1425 } else {
1426 expect(*fmt, n, exp);
1427 }
1428 delete fmt;
1429 }
1430
1431 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
1432 double value, const UnicodeString& string) {
1433 UErrorCode ec = U_ZERO_ERROR;
1434 DecimalFormat& fmt = * (DecimalFormat*) &nf;
1435 const UChar DEFAULT_CURR[] = {45/*-*/,0};
1436 const UChar* curr = DEFAULT_CURR;
1437 if (*locale.getLanguage() != 0) {
1438 curr = ucurr_forLocale(locale.getName(), &ec);
1439 if (U_FAILURE(ec)) {
1440 errln("FAIL: UCurrency::forLocale");
1441 return;
1442 }
1443 fmt.setCurrency(curr);
1444 }
1445 UnicodeString s;
1446 fmt.format(value, s);
1447 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
1448
1449 // Default display of the number yields "1234.5599999999999"
1450 // instead of "1234.56". Use a formatter to fix this.
1451 NumberFormat* f =
1452 NumberFormat::createInstance(Locale::getUS(), ec);
1453 UnicodeString v;
1454 if (U_FAILURE(ec)) {
1455 // Oops; bad formatter. Use default op+= display.
1456 v = (UnicodeString)"" + value;
1457 } else {
1458 f->setMaximumFractionDigits(4);
1459 f->setGroupingUsed(FALSE);
1460 f->format(value, v);
1461 }
1462 delete f;
1463
1464 if (s == string) {
1465 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
1466 } else {
1467 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
1468 ", expected " + prettify(string));
1469 }
1470 }
1471
1472 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
1473 UnicodeString pat;
1474 fmt.toPattern(pat);
1475 if (pat == exp) {
1476 logln(UnicodeString("Ok \"") + pat + "\"");
1477 } else {
1478 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
1479 }
1480 }
1481
1482 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
1483 int32_t pos) {
1484 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
1485 }
1486 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
1487 int32_t pos, int32_t width, UChar pad) {
1488 expectPad(fmt, pat, pos, width, UnicodeString(pad));
1489 }
1490 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
1491 int32_t pos, int32_t width, const UnicodeString& pad) {
1492 int32_t apos = 0, awidth = 0;
1493 UnicodeString apadStr;
1494 UErrorCode status = U_ZERO_ERROR;
1495 fmt.applyPattern(pat, status);
1496 if (U_SUCCESS(status)) {
1497 apos = fmt.getPadPosition();
1498 awidth = fmt.getFormatWidth();
1499 apadStr=fmt.getPadCharacterString();
1500 } else {
1501 apos = -1;
1502 awidth = width;
1503 apadStr = pad;
1504 }
1505 if (apos == pos && awidth == width && apadStr == pad) {
1506 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos +
1507 ((pos == ILLEGAL) ? UnicodeString() :
1508 (UnicodeString(" width=") + awidth + " pad=" + apadStr)));
1509 } else {
1510 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
1511 " width=" + awidth + " pad=" + apadStr +
1512 ", expected " + pos + " " + width + " " + pad);
1513 }
1514 }
1515
1516 #endif /* #if !UCONFIG_NO_FORMATTING */