]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/numfmtst.cpp
4371c668a223c160bb2453f8bd0a6071eb60480d
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2008, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6 /* Modification History:
7 * Date Name Description
8 * 07/15/99 helena Ported to HPUX 10/11 CC.
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 "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"
27 #include "winnmtst.h"
28 #include <float.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include "cstring.h"
32
33 static const UChar EUR[] = {69,85,82,0}; // "EUR"
34
35 // *****************************************************************************
36 // class NumberFormatTest
37 // *****************************************************************************
38
39 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
40
41 #define CHECK(status,str) if (U_FAILURE(status)) { errln(UnicodeString("FAIL: ") + str); return; }
42
43 void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
44 {
45 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
46 switch (index) {
47 CASE(0,TestCurrencySign);
48 CASE(1,TestCurrency);
49 CASE(2,TestParse);
50 CASE(3,TestRounding487);
51 CASE(4,TestQuotes);
52 CASE(5,TestExponential);
53 CASE(6,TestPatterns);
54
55 // Upgrade to alphaWorks - liu 5/99
56 CASE(7,TestExponent);
57 CASE(8,TestScientific);
58 CASE(9,TestPad);
59 CASE(10,TestPatterns2);
60 CASE(11,TestSecondaryGrouping);
61 CASE(12,TestSurrogateSupport);
62 CASE(13,TestAPI);
63
64 CASE(14,TestCurrencyObject);
65 CASE(15,TestCurrencyPatterns);
66 //CASE(16,TestDigitList);
67 CASE(16,TestWhiteSpaceParsing);
68 CASE(17,TestComplexCurrency);
69 CASE(18,TestRegCurrency);
70 CASE(19,TestSymbolsWithBadLocale);
71 CASE(20,TestAdoptDecimalFormatSymbols);
72
73 CASE(21,TestScientific2);
74 CASE(22,TestScientificGrouping);
75 CASE(23,TestInt64);
76
77 CASE(24,TestPerMill);
78 CASE(25,TestIllegalPatterns);
79 CASE(26,TestCases);
80
81 CASE(27,TestCurrencyNames);
82 CASE(28,TestCurrencyAmount);
83 CASE(29,TestCurrencyUnit);
84 CASE(30,TestCoverage);
85 CASE(31,TestJB3832);
86 CASE(32,TestHost);
87 CASE(33,TestHostClone);
88 CASE(34,TestCurrencyFormat);
89 CASE(35,TestRounding);
90 CASE(36,TestNonpositiveMultiplier);
91
92 CASE(37,TestLenientParse);
93 CASE(38,TestSpaceParsing);
94
95 default: name = ""; break;
96 }
97 }
98
99 // -------------------------------------
100
101 // Test API (increase code coverage)
102 void
103 NumberFormatTest::TestAPI(void)
104 {
105 logln("Test API");
106 UErrorCode status = U_ZERO_ERROR;
107 NumberFormat *test = NumberFormat::createInstance("root", status);
108 if(U_FAILURE(status)) {
109 errln("unable to create format object");
110 }
111 if(test != NULL) {
112 test->setMinimumIntegerDigits(10);
113 test->setMaximumIntegerDigits(2);
114
115 test->setMinimumFractionDigits(10);
116 test->setMaximumFractionDigits(2);
117
118 UnicodeString result;
119 FieldPosition pos;
120 Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
121 test->format(bla, result, pos, status);
122 if(U_SUCCESS(status)) {
123 errln("Yuck... Formatted a duck... As a number!");
124 } else {
125 status = U_ZERO_ERROR;
126 }
127
128 result.remove();
129 int64_t ll = 12;
130 test->format(ll, result);
131 if (result != "12.00"){
132 errln("format int64_t error");
133 }
134
135 delete test;
136 }
137 }
138
139 class StubNumberForamt :public NumberFormat{
140 public:
141 StubNumberForamt(){};
142 virtual UnicodeString& format(double ,UnicodeString& appendTo,FieldPosition& ) const {
143 return appendTo;
144 }
145 virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
146 return appendTo.append((UChar)0x0033);
147 }
148 virtual UnicodeString& format(int64_t number,UnicodeString& appendTo,FieldPosition& pos) const {
149 return NumberFormat::format(number, appendTo, pos);
150 }
151 virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
152 return appendTo;
153 }
154 virtual void parse(const UnicodeString& ,
155 Formattable& ,
156 ParsePosition& ) const {}
157 virtual void parse( const UnicodeString& ,
158 Formattable& ,
159 UErrorCode& ) const {}
160 virtual UClassID getDynamicClassID(void) const {
161 static char classID = 0;
162 return (UClassID)&classID;
163 }
164 virtual Format* clone() const {return NULL;}
165 };
166
167 void
168 NumberFormatTest::TestCoverage(void){
169 StubNumberForamt stub;
170 UnicodeString agent("agent");
171 FieldPosition pos;
172 int64_t num = 4;
173 if (stub.format(num, agent, pos) != UnicodeString("agent3")){
174 errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
175 };
176 }
177
178 // Test various patterns
179 void
180 NumberFormatTest::TestPatterns(void)
181 {
182 UErrorCode status = U_ZERO_ERROR;
183 DecimalFormatSymbols sym(Locale::getUS(), status);
184 if (U_FAILURE(status)) { errln("FAIL: Could not construct DecimalFormatSymbols"); return; }
185
186 const char* pat[] = { "#.#", "#.", ".#", "#" };
187 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
188 const char* newpat[] = { "#0.#", "#0.", "#.0", "#" };
189 const char* num[] = { "0", "0.", ".0", "0" };
190 for (int32_t i=0; i<pat_length; ++i)
191 {
192 status = U_ZERO_ERROR;
193 DecimalFormat fmt(pat[i], sym, status);
194 if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
195 UnicodeString newp; fmt.toPattern(newp);
196 if (!(newp == newpat[i]))
197 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
198 "; " + newp + " seen instead");
199
200 UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
201 if (!(s == num[i]))
202 {
203 errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
204 "; " + s + " seen instead");
205 logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
206 }
207 }
208 }
209
210 /*
211 icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
212 icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
213 icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
214 */
215 /*
216 void
217 NumberFormatTest::TestDigitList(void)
218 {
219 // API coverage for DigitList
220 DigitList list1;
221 list1.append('1');
222 list1.fDecimalAt = 1;
223 DigitList list2;
224 list2.set((int32_t)1);
225 if (list1 != list2) {
226 errln("digitlist append, operator!= or set failed ");
227 }
228 if (!(list1 == list2)) {
229 errln("digitlist append, operator== or set failed ");
230 }
231 }
232 */
233
234 // -------------------------------------
235
236 // Test exponential pattern
237 void
238 NumberFormatTest::TestExponential(void)
239 {
240 UErrorCode status = U_ZERO_ERROR;
241 DecimalFormatSymbols sym(Locale::getUS(), status);
242 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormatSymbols ct"); return; }
243 const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
244 int32_t pat_length = (int32_t)(sizeof(pat) / sizeof(pat[0]));
245
246 // The following #if statements allow this test to be built and run on
247 // platforms that do not have standard IEEE numerics. For example,
248 // S/390 doubles have an exponent range of -78 to +75. For the
249 // following #if statements to work, float.h must define
250 // DBL_MAX_10_EXP to be a compile-time constant.
251
252 // This section may be expanded as needed.
253
254 #if DBL_MAX_10_EXP > 300
255 double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
256 int32_t val_length = (int32_t)(sizeof(val) / sizeof(val[0]));
257 const char* valFormat[] =
258 {
259 // 0.####E0
260 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
261 // 00.000E00
262 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
263 // ##0.######E000
264 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
265 // 0.###E0;[0.###E0]
266 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
267 };
268 double valParse[] =
269 {
270 0.01234, 123460000, 1.23E300, -3.1416E-271,
271 0.01234, 123460000, 1.23E300, -3.1416E-271,
272 0.01234, 123456800, 1.23E300, -3.141593E-271,
273 0.01234, 123500000, 1.23E300, -3.142E-271,
274 };
275 #elif DBL_MAX_10_EXP > 70
276 double val[] = { 0.01234, 123456789, 1.23e70, -3.141592653e-71 };
277 int32_t val_length = sizeof(val) / sizeof(val[0]);
278 char* valFormat[] =
279 {
280 // 0.####E0
281 "1.234E-2", "1.2346E8", "1.23E70", "-3.1416E-71",
282 // 00.000E00
283 "12.340E-03", "12.346E07", "12.300E69", "-31.416E-72",
284 // ##0.######E000
285 "12.34E-003", "123.4568E006", "12.3E069", "-31.41593E-072",
286 // 0.###E0;[0.###E0]
287 "1.234E-2", "1.235E8", "1.23E70", "[3.142E-71]"
288 };
289 double valParse[] =
290 {
291 0.01234, 123460000, 1.23E70, -3.1416E-71,
292 0.01234, 123460000, 1.23E70, -3.1416E-71,
293 0.01234, 123456800, 1.23E70, -3.141593E-71,
294 0.01234, 123500000, 1.23E70, -3.142E-71,
295 };
296 #else
297 // Don't test double conversion
298 double* val = 0;
299 int32_t val_length = 0;
300 char** valFormat = 0;
301 double* valParse = 0;
302 logln("Warning: Skipping double conversion tests");
303 #endif
304
305 int32_t lval[] = { 0, -1, 1, 123456789 };
306 int32_t lval_length = (int32_t)(sizeof(lval) / sizeof(lval[0]));
307 const char* lvalFormat[] =
308 {
309 // 0.####E0
310 "0E0", "-1E0", "1E0", "1.2346E8",
311 // 00.000E00
312 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
313 // ##0.######E000
314 "0E000", "-1E000", "1E000", "123.4568E006",
315 // 0.###E0;[0.###E0]
316 "0E0", "[1E0]", "1E0", "1.235E8"
317 };
318 int32_t lvalParse[] =
319 {
320 0, -1, 1, 123460000,
321 0, -1, 1, 123460000,
322 0, -1, 1, 123456800,
323 0, -1, 1, 123500000,
324 };
325 int32_t ival = 0, ilval = 0;
326 for (int32_t p=0; p<pat_length; ++p)
327 {
328 DecimalFormat fmt(pat[p], sym, status);
329 if (U_FAILURE(status)) { errln("FAIL: Bad status returned by DecimalFormat ct"); continue; }
330 UnicodeString pattern;
331 logln((UnicodeString)"Pattern \"" + pat[p] + "\" -toPattern-> \"" +
332 fmt.toPattern(pattern) + "\"");
333 int32_t v;
334 for (v=0; v<val_length; ++v)
335 {
336 UnicodeString s; (*(NumberFormat*)&fmt).format(val[v], s);
337 logln((UnicodeString)" " + val[v] + " -format-> " + s);
338 if (s != valFormat[v+ival])
339 errln((UnicodeString)"FAIL: Expected " + valFormat[v+ival]);
340
341 ParsePosition pos(0);
342 Formattable af;
343 fmt.parse(s, af, pos);
344 double a;
345 UBool useEpsilon = FALSE;
346 if (af.getType() == Formattable::kLong)
347 a = af.getLong();
348 else if (af.getType() == Formattable::kDouble) {
349 a = af.getDouble();
350 #if defined(OS390) || defined(OS400)
351 // S/390 will show a failure like this:
352 //| -3.141592652999999e-271 -format-> -3.1416E-271
353 //| -parse-> -3.1416e-271
354 //| FAIL: Expected -3.141599999999999e-271
355 // To compensate, we use an epsilon-based equality
356 // test on S/390 only. We don't want to do this in
357 // general because it's less exacting.
358 useEpsilon = TRUE;
359 #endif
360 }
361 else {
362 errln((UnicodeString)"FAIL: Non-numeric Formattable returned");
363 continue;
364 }
365 if (pos.getIndex() == s.length())
366 {
367 logln((UnicodeString)" -parse-> " + a);
368 // Use epsilon comparison as necessary
369 if ((useEpsilon &&
370 (uprv_fabs(a - valParse[v+ival]) / a > (2*DBL_EPSILON))) ||
371 (!useEpsilon && a != valParse[v+ival]))
372 {
373 errln((UnicodeString)"FAIL: Expected " + valParse[v+ival]);
374 }
375 }
376 else {
377 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
378 errln((UnicodeString)" should be (" + s.length() + " chars) -> " + valParse[v+ival]);
379 }
380 }
381 for (v=0; v<lval_length; ++v)
382 {
383 UnicodeString s;
384 (*(NumberFormat*)&fmt).format(lval[v], s);
385 logln((UnicodeString)" " + lval[v] + "L -format-> " + s);
386 if (s != lvalFormat[v+ilval])
387 errln((UnicodeString)"ERROR: Expected " + lvalFormat[v+ilval] + " Got: " + s);
388
389 ParsePosition pos(0);
390 Formattable af;
391 fmt.parse(s, af, pos);
392 if (af.getType() == Formattable::kLong ||
393 af.getType() == Formattable::kInt64) {
394 UErrorCode status = U_ZERO_ERROR;
395 int32_t a = af.getLong(status);
396 if (pos.getIndex() == s.length())
397 {
398 logln((UnicodeString)" -parse-> " + a);
399 if (a != lvalParse[v+ilval])
400 errln((UnicodeString)"FAIL: Expected " + lvalParse[v+ilval]);
401 }
402 else
403 errln((UnicodeString)"FAIL: Partial parse (" + pos.getIndex() + " chars) -> " + a);
404 }
405 else
406 errln((UnicodeString)"FAIL: Non-long Formattable returned for " + s
407 + " Double: " + af.getDouble()
408 + ", Long: " + af.getLong());
409 }
410 ival += val_length;
411 ilval += lval_length;
412 }
413 }
414
415 void
416 NumberFormatTest::TestScientific2() {
417 // jb 2552
418 UErrorCode status = U_ZERO_ERROR;
419 DecimalFormat* fmt = (DecimalFormat*)NumberFormat::createCurrencyInstance("en_US", status);
420 if (U_SUCCESS(status)) {
421 double num = 12.34;
422 expect(*fmt, num, "$12.34");
423 fmt->setScientificNotation(TRUE);
424 expect(*fmt, num, "$1.23E1");
425 fmt->setScientificNotation(FALSE);
426 expect(*fmt, num, "$12.34");
427 }
428 delete fmt;
429 }
430
431 void
432 NumberFormatTest::TestScientificGrouping() {
433 // jb 2552
434 UErrorCode status = U_ZERO_ERROR;
435 DecimalFormat fmt("##0.00E0",status);
436 if (U_SUCCESS(status)) {
437 expect(fmt, .01234, "12.3E-3");
438 expect(fmt, .1234, "123E-3");
439 expect(fmt, 1.234, "1.23E0");
440 expect(fmt, 12.34, "12.3E0");
441 expect(fmt, 123.4, "123E0");
442 expect(fmt, 1234., "1.23E3");
443 }
444 }
445
446 /*static void setFromString(DigitList& dl, const char* str) {
447 char c;
448 UBool decimalSet = FALSE;
449 dl.clear();
450 while ((c = *str++)) {
451 if (c == '-') {
452 dl.fIsPositive = FALSE;
453 } else if (c == '+') {
454 dl.fIsPositive = TRUE;
455 } else if (c == '.') {
456 dl.fDecimalAt = dl.fCount;
457 decimalSet = TRUE;
458 } else {
459 dl.append(c);
460 }
461 }
462 if (!decimalSet) {
463 dl.fDecimalAt = dl.fCount;
464 }
465 }*/
466
467 void
468 NumberFormatTest::TestInt64() {
469 UErrorCode status = U_ZERO_ERROR;
470 DecimalFormat fmt("#.#E0",status);
471 fmt.setMaximumFractionDigits(20);
472 if (U_SUCCESS(status)) {
473 expect(fmt, (Formattable)(int64_t)0, "0E0");
474 expect(fmt, (Formattable)(int64_t)-1, "-1E0");
475 expect(fmt, (Formattable)(int64_t)1, "1E0");
476 expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
477 expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
478 expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
479 expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
480 }
481
482 // also test digitlist
483 /* int64_t int64max = U_INT64_MAX;
484 int64_t int64min = U_INT64_MIN;
485 const char* int64maxstr = "9223372036854775807";
486 const char* int64minstr = "-9223372036854775808";
487 UnicodeString fail("fail: ");
488
489 // test max int64 value
490 DigitList dl;
491 setFromString(dl, int64maxstr);
492 {
493 if (!dl.fitsIntoInt64(FALSE)) {
494 errln(fail + int64maxstr + " didn't fit");
495 }
496 int64_t int64Value = dl.getInt64();
497 if (int64Value != int64max) {
498 errln(fail + int64maxstr);
499 }
500 dl.set(int64Value);
501 int64Value = dl.getInt64();
502 if (int64Value != int64max) {
503 errln(fail + int64maxstr);
504 }
505 }
506 // test negative of max int64 value (1 shy of min int64 value)
507 dl.fIsPositive = FALSE;
508 {
509 if (!dl.fitsIntoInt64(FALSE)) {
510 errln(fail + "-" + int64maxstr + " didn't fit");
511 }
512 int64_t int64Value = dl.getInt64();
513 if (int64Value != -int64max) {
514 errln(fail + "-" + int64maxstr);
515 }
516 dl.set(int64Value);
517 int64Value = dl.getInt64();
518 if (int64Value != -int64max) {
519 errln(fail + "-" + int64maxstr);
520 }
521 }
522 // test min int64 value
523 setFromString(dl, int64minstr);
524 {
525 if (!dl.fitsIntoInt64(FALSE)) {
526 errln(fail + "-" + int64minstr + " didn't fit");
527 }
528 int64_t int64Value = dl.getInt64();
529 if (int64Value != int64min) {
530 errln(fail + int64minstr);
531 }
532 dl.set(int64Value);
533 int64Value = dl.getInt64();
534 if (int64Value != int64min) {
535 errln(fail + int64minstr);
536 }
537 }
538 // test negative of min int 64 value (1 more than max int64 value)
539 dl.fIsPositive = TRUE; // won't fit
540 {
541 if (dl.fitsIntoInt64(FALSE)) {
542 errln(fail + "-(" + int64minstr + ") didn't fit");
543 }
544 }*/
545 }
546
547 // -------------------------------------
548
549 // Test the handling of quotes
550 void
551 NumberFormatTest::TestQuotes(void)
552 {
553 UErrorCode status = U_ZERO_ERROR;
554 UnicodeString *pat;
555 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
556 pat = new UnicodeString("a'fo''o'b#");
557 DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
558 UnicodeString s;
559 ((NumberFormat*)fmt)->format((int32_t)123, s);
560 logln((UnicodeString)"Pattern \"" + *pat + "\"");
561 logln((UnicodeString)" Format 123 -> " + escape(s));
562 if (!(s=="afo'ob123"))
563 errln((UnicodeString)"FAIL: Expected afo'ob123");
564
565 s.truncate(0);
566 delete fmt;
567 delete pat;
568
569 pat = new UnicodeString("a''b#");
570 fmt = new DecimalFormat(*pat, *sym, status);
571 ((NumberFormat*)fmt)->format((int32_t)123, s);
572 logln((UnicodeString)"Pattern \"" + *pat + "\"");
573 logln((UnicodeString)" Format 123 -> " + escape(s));
574 if (!(s=="a'b123"))
575 errln((UnicodeString)"FAIL: Expected a'b123");
576 delete fmt;
577 delete pat;
578 delete sym;
579 }
580
581 /**
582 * Test the handling of the currency symbol in patterns.
583 */
584 void
585 NumberFormatTest::TestCurrencySign(void)
586 {
587 UErrorCode status = U_ZERO_ERROR;
588 DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale::getUS(), status);
589 UnicodeString pat;
590 UChar currency = 0x00A4;
591 // "\xA4#,##0.00;-\xA4#,##0.00"
592 pat.append(currency).append("#,##0.00;-").
593 append(currency).append("#,##0.00");
594 DecimalFormat *fmt = new DecimalFormat(pat, *sym, status);
595 UnicodeString s; ((NumberFormat*)fmt)->format(1234.56, s);
596 pat.truncate(0);
597 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
598 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
599 if (s != "$1,234.56") errln((UnicodeString)"FAIL: Expected $1,234.56");
600 s.truncate(0);
601 ((NumberFormat*)fmt)->format(- 1234.56, s);
602 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
603 if (s != "-$1,234.56") errln((UnicodeString)"FAIL: Expected -$1,234.56");
604 delete fmt;
605 pat.truncate(0);
606 // "\xA4\xA4 #,##0.00;\xA4\xA4 -#,##0.00"
607 pat.append(currency).append(currency).
608 append(" #,##0.00;").
609 append(currency).append(currency).
610 append(" -#,##0.00");
611 fmt = new DecimalFormat(pat, *sym, status);
612 s.truncate(0);
613 ((NumberFormat*)fmt)->format(1234.56, s);
614 logln((UnicodeString)"Pattern \"" + fmt->toPattern(pat) + "\"");
615 logln((UnicodeString)" Format " + 1234.56 + " -> " + escape(s));
616 if (s != "USD 1,234.56") errln((UnicodeString)"FAIL: Expected USD 1,234.56");
617 s.truncate(0);
618 ((NumberFormat*)fmt)->format(-1234.56, s);
619 logln((UnicodeString)" Format " + (-1234.56) + " -> " + escape(s));
620 if (s != "USD -1,234.56") errln((UnicodeString)"FAIL: Expected USD -1,234.56");
621 delete fmt;
622 delete sym;
623 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
624 }
625
626 // -------------------------------------
627
628 static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
629
630 UnicodeString&
631 NumberFormatTest::escape(UnicodeString& s)
632 {
633 UnicodeString buf;
634 for (int32_t i=0; i<s.length(); ++i)
635 {
636 UChar c = s[(int32_t)i];
637 if (c <= (UChar)0x7F) buf += c;
638 else {
639 buf += (UChar)0x5c; buf += (UChar)0x55;
640 buf += toHexString((c & 0xF000) >> 12);
641 buf += toHexString((c & 0x0F00) >> 8);
642 buf += toHexString((c & 0x00F0) >> 4);
643 buf += toHexString(c & 0x000F);
644 }
645 }
646 return (s = buf);
647 }
648
649
650 // -------------------------------------
651 static const char* testCases[][2]= {
652 /* locale ID */ /* expected */
653 {"ca_ES_PREEURO", "1.150\\u00A0\\u20A7" },
654 {"de_LU_PREEURO", "1,150\\u00A0F" },
655 {"el_GR_PREEURO", "1.150,50\\u00A0\\u0394\\u03C1\\u03C7" },
656 {"en_BE_PREEURO", "1.150,50\\u00A0BF" },
657 {"es_ES_PREEURO", "\\u20A7\\u00A01.150" },
658 {"eu_ES_PREEURO", "1.150\\u00A0\\u20A7" },
659 {"gl_ES_PREEURO", "1.150\\u00A0\\u20A7" },
660 {"it_IT_PREEURO", "\\u20A4\\u00A01.150" },
661 {"pt_PT_PREEURO", "1,150$50\\u00A0Esc."},
662 {"en_US@currency=JPY", "\\u00A51,150"}
663 };
664 /**
665 * Test localized currency patterns.
666 */
667 void
668 NumberFormatTest::TestCurrency(void)
669 {
670 UErrorCode status = U_ZERO_ERROR;
671 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
672 if (U_FAILURE(status)) {
673 dataerrln("Error calling NumberFormat::createCurrencyInstance()");
674 return;
675 }
676
677 UnicodeString s; currencyFmt->format(1.50, s);
678 logln((UnicodeString)"Un pauvre ici a..........." + s);
679 if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
680 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$");
681 delete currencyFmt;
682 s.truncate(0);
683 char loc[256]={0};
684 int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
685 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
686 currencyFmt->format(1.50, s);
687 logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
688 if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
689 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM");
690 delete currencyFmt;
691 s.truncate(0);
692 len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
693 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
694 currencyFmt->format(1.50, s);
695 logln((UnicodeString)"Un pauvre en France a....." + s);
696 if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
697 errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
698 delete currencyFmt;
699 if (U_FAILURE(status))
700 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
701
702 for(int i=0; i < (int)(sizeof(testCases)/sizeof(testCases[i])); i++){
703 status = U_ZERO_ERROR;
704 const char *localeID = testCases[i][0];
705 UnicodeString expected(testCases[i][1], -1, US_INV);
706 expected = expected.unescape();
707 s.truncate(0);
708 char loc[256]={0};
709 uloc_canonicalize(localeID, loc, 256, &status);
710 currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
711 if(U_FAILURE(status)){
712 errln("Could not create currency formatter for locale %s",localeID);
713 continue;
714 }
715 currencyFmt->format(1150.50, s);
716 if(s!=expected){
717 errln(UnicodeString("FAIL: Expected: ")+expected
718 + UnicodeString(" Got: ") + s
719 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
720 }
721 if (U_FAILURE(status)){
722 errln((UnicodeString)"FAIL: Status " + (int32_t)status);
723 }
724 delete currencyFmt;
725 }
726 }
727
728 // -------------------------------------
729
730 /**
731 * Test the Currency object handling, new as of ICU 2.2.
732 */
733 void NumberFormatTest::TestCurrencyObject() {
734 UErrorCode ec = U_ZERO_ERROR;
735 NumberFormat* fmt =
736 NumberFormat::createCurrencyInstance(Locale::getUS(), ec);
737
738 if (U_FAILURE(ec)) {
739 errln("FAIL: getCurrencyInstance(US)");
740 delete fmt;
741 return;
742 }
743
744 Locale null("", "", "");
745
746 expectCurrency(*fmt, null, 1234.56, "$1,234.56");
747
748 expectCurrency(*fmt, Locale::getFrance(),
749 1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro
750
751 expectCurrency(*fmt, Locale::getJapan(),
752 1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen
753
754 expectCurrency(*fmt, Locale("fr", "CH", ""),
755 1234.56, "Fr.1,234.55"); // 0.05 rounding
756
757 expectCurrency(*fmt, Locale::getUS(),
758 1234.56, "$1,234.56");
759
760 delete fmt;
761 fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);
762
763 if (U_FAILURE(ec)) {
764 errln("FAIL: getCurrencyInstance(FRANCE)");
765 delete fmt;
766 return;
767 }
768
769 expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1 234,56 \\u20AC"));
770
771 expectCurrency(*fmt, Locale::getJapan(),
772 1234.56, CharsToUnicodeString("1 235 \\u00A5JP")); // Yen
773
774 expectCurrency(*fmt, Locale("fr", "CH", ""),
775 1234.56, "1 234,55 sFr."); // 0.05 rounding
776
777 expectCurrency(*fmt, Locale::getUS(),
778 1234.56, "1 234,56 $US");
779
780 expectCurrency(*fmt, Locale::getFrance(),
781 1234.56, CharsToUnicodeString("1 234,56 \\u20AC")); // Euro
782
783 delete fmt;
784 }
785
786 // -------------------------------------
787
788 /**
789 * Do rudimentary testing of parsing.
790 */
791 void
792 NumberFormatTest::TestParse(void)
793 {
794 UErrorCode status = U_ZERO_ERROR;
795 UnicodeString arg("0");
796 DecimalFormat* format = new DecimalFormat("00", status);
797 //try {
798 Formattable n;
799
800 format->parse(arg, n, status);
801 logln((UnicodeString)"parse(" + arg + ") = " + n.getLong());
802 if (n.getType() != Formattable::kLong ||
803 n.getLong() != 0) errln((UnicodeString)"FAIL: Expected 0");
804 delete format;
805 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
806 //}
807 //catch(Exception e) {
808 // errln((UnicodeString)"Exception caught: " + e);
809 //}
810 }
811
812 // -------------------------------------
813
814 static const char *lenientAffixTestCases[] = {
815 "(1)",
816 "( 1)",
817 "(1 )",
818 "( 1 )"
819 };
820
821 static const char *lenientCurrencyTestCases[] = {
822 "$1,000",
823 "$ 1,000",
824 "$1000",
825 "$ 1000",
826 "$1 000.00",
827 "$ 1 000.00",
828 "$ 1\\u00A0000.00",
829 "1000.00"
830 };
831
832 static const char *lenientNegativeCurrencyTestCases[] = {
833 "($1,000)",
834 "($ 1,000)",
835 "($1000)",
836 "($ 1000)",
837 "($1 000.00)",
838 "($ 1 000.00)",
839 "( $ 1,000.00 )",
840 "($ 1\\u00A0000.00)",
841 "(1000.00)"
842 };
843
844 static const char *lenientPercentTestCases[] = {
845 "25%",
846 " 25%",
847 " 25 %",
848 "25 %",
849 "25\\u00A0%",
850 "25"
851 };
852
853 static const char *lenientNegativePercentTestCases[] = {
854 "-25%",
855 " -25%",
856 " - 25%",
857 "- 25 %",
858 " - 25 %",
859 "-25 %",
860 "-25\\u00A0%",
861 "-25",
862 "- 25"
863 };
864
865 static const char *strictFailureTestCases[] = {
866 " 1000",
867 #if 0
868 "10,00",
869 "1,000,.0"
870 #endif
871 };
872
873 #define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
874
875 /**
876 * Test lenient parsing.
877 */
878 void
879 NumberFormatTest::TestLenientParse(void)
880 {
881 UErrorCode status = U_ZERO_ERROR;
882 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
883 Formattable n;
884
885 format->setParseStrict(FALSE);
886 for (int32_t t = 0; t < ARRAY_SIZE (lenientAffixTestCases); t += 1) {
887 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
888
889 format->parse(testCase, n, status);
890 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
891
892 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
893 n.getLong() != 1) {
894 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
895 status = U_ZERO_ERROR;
896 }
897 }
898
899 delete format;
900
901 Locale locale("en_US");
902 NumberFormat *cFormat = NumberFormat::createCurrencyInstance(locale, status);
903
904 cFormat->setParseStrict(FALSE);
905 for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
906 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
907
908 cFormat->parse(testCase, n, status);
909 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
910
911 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
912 n.getLong() != 1000) {
913 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
914 status = U_ZERO_ERROR;
915 }
916 }
917
918 for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
919 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
920 ParsePosition pos(0);
921
922 cFormat->parse(testCase, n, /*status*/pos);
923 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
924
925 if (/*U_FAILURE(status)*/pos.getErrorIndex() >= 0 ||n.getType() != Formattable::kLong ||
926 n.getLong() != -1000) {
927 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\" parse position = " +
928 pos.getIndex() + ", " + pos.getErrorIndex());
929 status = U_ZERO_ERROR;
930 }
931 }
932
933 delete cFormat;
934
935 NumberFormat *pFormat = NumberFormat::createPercentInstance(locale, status);
936
937 pFormat->setParseStrict(FALSE);
938 for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
939 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
940
941 pFormat->parse(testCase, n, status);
942 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
943
944 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
945 n.getDouble() != 0.25) {
946 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
947 status = U_ZERO_ERROR;
948 }
949 }
950
951 for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
952 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
953
954 pFormat->parse(testCase, n, status);
955 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
956
957 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
958 n.getDouble() != -0.25) {
959 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
960 status = U_ZERO_ERROR;
961 }
962 }
963
964 delete pFormat;
965
966 // Test cases that should fail with a strict parse and pass with a
967 // lenient parse.
968 NumberFormat *nFormat = NumberFormat::createInstance(locale, status);
969
970 // first, make sure that they fail with a strict parse
971 for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
972 UnicodeString testCase = ctou(strictFailureTestCases[t]);
973
974 nFormat->parse(testCase, n, status);
975 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
976
977 if (! U_FAILURE(status)) {
978 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
979 }
980
981 status = U_ZERO_ERROR;
982 }
983
984 // then, make sure that they pass with a lenient parse
985 nFormat->setParseStrict(FALSE);
986 for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
987 UnicodeString testCase = ctou(strictFailureTestCases[t]);
988
989 nFormat->parse(testCase, n, status);
990 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
991
992 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
993 n.getLong() != 1000) {
994 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
995 status = U_ZERO_ERROR;
996 }
997 }
998
999 delete nFormat;
1000 }
1001
1002 // -------------------------------------
1003
1004 /**
1005 * Test proper rounding by the format method.
1006 */
1007 void
1008 NumberFormatTest::TestRounding487(void)
1009 {
1010 UErrorCode status = U_ZERO_ERROR;
1011 NumberFormat *nf = NumberFormat::createInstance(status);
1012 if (U_FAILURE(status)) {
1013 dataerrln("Error calling NumberFormat::createInstance()");
1014 return;
1015 }
1016
1017 roundingTest(*nf, 0.00159999, 4, "0.0016");
1018 roundingTest(*nf, 0.00995, 4, "0.01");
1019
1020 roundingTest(*nf, 12.3995, 3, "12.4");
1021
1022 roundingTest(*nf, 12.4999, 0, "12");
1023 roundingTest(*nf, - 19.5, 0, "-20");
1024 delete nf;
1025 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1026 }
1027
1028 /**
1029 * Test the functioning of the secondary grouping value.
1030 */
1031 void NumberFormatTest::TestSecondaryGrouping(void) {
1032 UErrorCode status = U_ZERO_ERROR;
1033 DecimalFormatSymbols US(Locale::getUS(), status);
1034 CHECK(status, "DecimalFormatSymbols ct");
1035
1036 DecimalFormat f("#,##,###", US, status);
1037 CHECK(status, "DecimalFormat ct");
1038
1039 expect2(f, (int32_t)123456789L, "12,34,56,789");
1040 expectPat(f, "#,##,###");
1041 f.applyPattern("#,###", status);
1042 CHECK(status, "applyPattern");
1043
1044 f.setSecondaryGroupingSize(4);
1045 expect2(f, (int32_t)123456789L, "12,3456,789");
1046 expectPat(f, "#,####,###");
1047 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1048 CHECK(status, "createInstance(hi_IN)");
1049
1050 UnicodeString out;
1051 int32_t l = (int32_t)1876543210L;
1052 g->format(l, out);
1053 delete g;
1054 // expect "1,87,65,43,210", but with Hindi digits
1055 // 01234567890123
1056 UBool ok = TRUE;
1057 if (out.length() != 14) {
1058 ok = FALSE;
1059 } else {
1060 for (int32_t i=0; i<out.length(); ++i) {
1061 UBool expectGroup = FALSE;
1062 switch (i) {
1063 case 1:
1064 case 4:
1065 case 7:
1066 case 10:
1067 expectGroup = TRUE;
1068 break;
1069 }
1070 // Later -- fix this to get the actual grouping
1071 // character from the resource bundle.
1072 UBool isGroup = (out.charAt(i) == 0x002C);
1073 if (isGroup != expectGroup) {
1074 ok = FALSE;
1075 break;
1076 }
1077 }
1078 }
1079 if (!ok) {
1080 errln((UnicodeString)"FAIL Expected " + l +
1081 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1082 escape(out) + "\"");
1083 } else {
1084 logln((UnicodeString)"Ok " + l +
1085 " x hi_IN -> \"" +
1086 escape(out) + "\"");
1087 }
1088 }
1089
1090 void NumberFormatTest::TestWhiteSpaceParsing(void) {
1091 UErrorCode ec = U_ZERO_ERROR;
1092 DecimalFormatSymbols US(Locale::getUS(), ec);
1093 DecimalFormat fmt("a b#0c ", US, ec);
1094 if (U_FAILURE(ec)) {
1095 errln("FAIL: Constructor");
1096 return;
1097 }
1098 int32_t n = 1234;
1099 expect(fmt, "a b1234c ", n);
1100 expect(fmt, "a b1234c ", n);
1101 }
1102
1103 /**
1104 * Test currencies whose display name is a ChoiceFormat.
1105 * Less useful now that INR is no longer a choice format! See cldrbug 1961 !
1106 */
1107 void NumberFormatTest::TestComplexCurrency() {
1108 UErrorCode ec = U_ZERO_ERROR;
1109 Locale loc("kn", "IN", "");
1110 NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1111 if (U_SUCCESS(ec)) {
1112 expect2(*fmt, 1.0, CharsToUnicodeString("Rs.\\u00A01.00"));
1113 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1114 expect(*fmt, 1.00390625, CharsToUnicodeString("Rs.\\u00A01.00")); // tricky
1115 expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1116 expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1117 expect2(*fmt, -1.0, CharsToUnicodeString("-Rs.\\u00A01.00"));
1118 expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1119 } else {
1120 errln("FAIL: getCurrencyInstance(kn_IN)");
1121 }
1122 delete fmt;
1123 }
1124
1125 // -------------------------------------
1126
1127 void
1128 NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1129 {
1130 nf.setMaximumFractionDigits(maxFractionDigits);
1131 UnicodeString out; nf.format(x, out);
1132 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1133 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1134 }
1135
1136 /**
1137 * Upgrade to alphaWorks
1138 */
1139 void NumberFormatTest::TestExponent(void) {
1140 UErrorCode status = U_ZERO_ERROR;
1141 DecimalFormatSymbols US(Locale::getUS(), status);
1142 CHECK(status, "DecimalFormatSymbols constructor");
1143 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1144 CHECK(status, "DecimalFormat(0.###E0)");
1145 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1146 CHECK(status, "DecimalFormat(0.###E+0)");
1147 int32_t n = 1234;
1148 expect2(fmt1, n, "1.234E3");
1149 expect2(fmt2, n, "1.234E+3");
1150 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1151 }
1152
1153 /**
1154 * Upgrade to alphaWorks
1155 */
1156 void NumberFormatTest::TestScientific(void) {
1157 UErrorCode status = U_ZERO_ERROR;
1158 DecimalFormatSymbols US(Locale::getUS(), status);
1159 CHECK(status, "DecimalFormatSymbols constructor");
1160
1161 // Test pattern round-trip
1162 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1163 "0.###E0;[0.###E0]" };
1164 int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
1165 int32_t DIGITS[] = {
1166 // min int, max int, min frac, max frac
1167 0, 1, 0, 0, // "#E0"
1168 1, 1, 0, 4, // "0.####E0"
1169 2, 2, 3, 3, // "00.000E00"
1170 1, 3, 0, 4, // "##0.####E000"
1171 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1172 };
1173 for (int32_t i=0; i<PAT_length; ++i) {
1174 UnicodeString pat(PAT[i]);
1175 DecimalFormat df(pat, US, status);
1176 CHECK(status, "DecimalFormat constructor");
1177 UnicodeString pat2;
1178 df.toPattern(pat2);
1179 if (pat == pat2) {
1180 logln(UnicodeString("Ok Pattern rt \"") +
1181 pat + "\" -> \"" +
1182 pat2 + "\"");
1183 } else {
1184 errln(UnicodeString("FAIL Pattern rt \"") +
1185 pat + "\" -> \"" +
1186 pat2 + "\"");
1187 }
1188 // Make sure digit counts match what we expect
1189 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1190 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1191 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1192 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1193 errln(UnicodeString("FAIL \"" + pat +
1194 "\" min/max int; min/max frac = ") +
1195 df.getMinimumIntegerDigits() + "/" +
1196 df.getMaximumIntegerDigits() + ";" +
1197 df.getMinimumFractionDigits() + "/" +
1198 df.getMaximumFractionDigits() + ", expect " +
1199 DIGITS[4*i] + "/" +
1200 DIGITS[4*i+1] + ";" +
1201 DIGITS[4*i+2] + "/" +
1202 DIGITS[4*i+3]);
1203 }
1204 }
1205
1206
1207 // Test the constructor for default locale. We have to
1208 // manually set the default locale, as there is no
1209 // guarantee that the default locale has the same
1210 // scientific format.
1211 Locale def = Locale::getDefault();
1212 Locale::setDefault(Locale::getUS(), status);
1213 expect2(NumberFormat::createScientificInstance(status),
1214 12345.678901,
1215 "1.2345678901E4", status);
1216 Locale::setDefault(def, status);
1217
1218 expect2(new DecimalFormat("#E0", US, status),
1219 12345.0,
1220 "1.2345E4", status);
1221 expect(new DecimalFormat("0E0", US, status),
1222 12345.0,
1223 "1E4", status);
1224 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1225 12345.678901,
1226 "1.2345678901E4", status);
1227 expect(new DecimalFormat("##0.###E0", US, status),
1228 12345.0,
1229 "12.34E3", status);
1230 expect(new DecimalFormat("##0.###E0", US, status),
1231 12345.00001,
1232 "12.35E3", status);
1233 expect2(new DecimalFormat("##0.####E0", US, status),
1234 (int32_t) 12345,
1235 "12.345E3", status);
1236 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1237 12345.678901,
1238 "1,2345678901E4", status);
1239 expect(new DecimalFormat("##0.####E0", US, status),
1240 789.12345e-9,
1241 "789.12E-9", status);
1242 expect2(new DecimalFormat("##0.####E0", US, status),
1243 780.e-9,
1244 "780E-9", status);
1245 expect(new DecimalFormat(".###E0", US, status),
1246 45678.0,
1247 ".457E5", status);
1248 expect2(new DecimalFormat(".###E0", US, status),
1249 (int32_t) 0,
1250 ".0E0", status);
1251 /*
1252 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1253 new DecimalFormat("##E0", US),
1254 new DecimalFormat("####E0", US),
1255 new DecimalFormat("0E0", US),
1256 new DecimalFormat("00E0", US),
1257 new DecimalFormat("000E0", US),
1258 },
1259 new Long(45678000),
1260 new String[] { "4.5678E7",
1261 "45.678E6",
1262 "4567.8E4",
1263 "5E7",
1264 "46E6",
1265 "457E5",
1266 }
1267 );
1268 !
1269 ! Unroll this test into individual tests below...
1270 !
1271 */
1272 expect2(new DecimalFormat("#E0", US, status),
1273 (int32_t) 45678000, "4.5678E7", status);
1274 expect2(new DecimalFormat("##E0", US, status),
1275 (int32_t) 45678000, "45.678E6", status);
1276 expect2(new DecimalFormat("####E0", US, status),
1277 (int32_t) 45678000, "4567.8E4", status);
1278 expect(new DecimalFormat("0E0", US, status),
1279 (int32_t) 45678000, "5E7", status);
1280 expect(new DecimalFormat("00E0", US, status),
1281 (int32_t) 45678000, "46E6", status);
1282 expect(new DecimalFormat("000E0", US, status),
1283 (int32_t) 45678000, "457E5", status);
1284 /*
1285 expect(new DecimalFormat("###E0", US, status),
1286 new Object[] { new Double(0.0000123), "12.3E-6",
1287 new Double(0.000123), "123E-6",
1288 new Double(0.00123), "1.23E-3",
1289 new Double(0.0123), "12.3E-3",
1290 new Double(0.123), "123E-3",
1291 new Double(1.23), "1.23E0",
1292 new Double(12.3), "12.3E0",
1293 new Double(123), "123E0",
1294 new Double(1230), "1.23E3",
1295 });
1296 !
1297 ! Unroll this test into individual tests below...
1298 !
1299 */
1300 expect2(new DecimalFormat("###E0", US, status),
1301 0.0000123, "12.3E-6", status);
1302 expect2(new DecimalFormat("###E0", US, status),
1303 0.000123, "123E-6", status);
1304 expect2(new DecimalFormat("###E0", US, status),
1305 0.00123, "1.23E-3", status);
1306 expect2(new DecimalFormat("###E0", US, status),
1307 0.0123, "12.3E-3", status);
1308 expect2(new DecimalFormat("###E0", US, status),
1309 0.123, "123E-3", status);
1310 expect2(new DecimalFormat("###E0", US, status),
1311 1.23, "1.23E0", status);
1312 expect2(new DecimalFormat("###E0", US, status),
1313 12.3, "12.3E0", status);
1314 expect2(new DecimalFormat("###E0", US, status),
1315 123.0, "123E0", status);
1316 expect2(new DecimalFormat("###E0", US, status),
1317 1230.0, "1.23E3", status);
1318 /*
1319 expect(new DecimalFormat("0.#E+00", US, status),
1320 new Object[] { new Double(0.00012), "1.2E-04",
1321 new Long(12000), "1.2E+04",
1322 });
1323 !
1324 ! Unroll this test into individual tests below...
1325 !
1326 */
1327 expect2(new DecimalFormat("0.#E+00", US, status),
1328 0.00012, "1.2E-04", status);
1329 expect2(new DecimalFormat("0.#E+00", US, status),
1330 (int32_t) 12000, "1.2E+04", status);
1331 }
1332
1333 /**
1334 * Upgrade to alphaWorks
1335 */
1336 void NumberFormatTest::TestPad(void) {
1337 UErrorCode status = U_ZERO_ERROR;
1338 DecimalFormatSymbols US(Locale::getUS(), status);
1339 CHECK(status, "DecimalFormatSymbols constructor");
1340
1341 expect2(new DecimalFormat("*^##.##", US, status),
1342 int32_t(0), "^^^^0", status);
1343 expect2(new DecimalFormat("*^##.##", US, status),
1344 -1.3, "^-1.3", status);
1345 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1346 int32_t(0), "0.0E0______ g-m/s^2", status);
1347 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1348 1.0/3, "333.333E-3_ g-m/s^2", status);
1349 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1350 int32_t(0), "0.0______ g-m/s^2", status);
1351 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1352 1.0/3, "0.33333__ g-m/s^2", status);
1353
1354 // Test padding before a sign
1355 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1356 expect2(new DecimalFormat(formatStr, US, status),
1357 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1358 expect2(new DecimalFormat(formatStr, US, status),
1359 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1360 expect2(new DecimalFormat(formatStr, US, status),
1361 int32_t(-1000000),"xxx(1,000,000.0)", status);
1362 expect2(new DecimalFormat(formatStr, US, status),
1363 -100.37, "xxxxxxxx(100.37)", status);
1364 expect2(new DecimalFormat(formatStr, US, status),
1365 -10456.37, "xxxxx(10,456.37)", status);
1366 expect2(new DecimalFormat(formatStr, US, status),
1367 -1120456.37, "xx(1,120,456.37)", status);
1368 expect2(new DecimalFormat(formatStr, US, status),
1369 -112045600.37, "(112,045,600.37)", status);
1370 expect2(new DecimalFormat(formatStr, US, status),
1371 -1252045600.37,"(1,252,045,600.37)", status);
1372
1373 expect2(new DecimalFormat(formatStr, US, status),
1374 int32_t(10), "xxxxxxxxxxxx10.0", status);
1375 expect2(new DecimalFormat(formatStr, US, status),
1376 int32_t(1000),"xxxxxxxxx1,000.0", status);
1377 expect2(new DecimalFormat(formatStr, US, status),
1378 int32_t(1000000),"xxxxx1,000,000.0", status);
1379 expect2(new DecimalFormat(formatStr, US, status),
1380 100.37, "xxxxxxxxxx100.37", status);
1381 expect2(new DecimalFormat(formatStr, US, status),
1382 10456.37, "xxxxxxx10,456.37", status);
1383 expect2(new DecimalFormat(formatStr, US, status),
1384 1120456.37, "xxxx1,120,456.37", status);
1385 expect2(new DecimalFormat(formatStr, US, status),
1386 112045600.37, "xx112,045,600.37", status);
1387 expect2(new DecimalFormat(formatStr, US, status),
1388 10252045600.37,"10,252,045,600.37", status);
1389
1390
1391 // Test padding between a sign and a number
1392 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1393 expect2(new DecimalFormat(formatStr2, US, status),
1394 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1395 expect2(new DecimalFormat(formatStr2, US, status),
1396 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1397 expect2(new DecimalFormat(formatStr2, US, status),
1398 int32_t(-1000000),"(1,000,000.0xxx)", status);
1399 expect2(new DecimalFormat(formatStr2, US, status),
1400 -100.37, "(100.37xxxxxxxx)", status);
1401 expect2(new DecimalFormat(formatStr2, US, status),
1402 -10456.37, "(10,456.37xxxxx)", status);
1403 expect2(new DecimalFormat(formatStr2, US, status),
1404 -1120456.37, "(1,120,456.37xx)", status);
1405 expect2(new DecimalFormat(formatStr2, US, status),
1406 -112045600.37, "(112,045,600.37)", status);
1407 expect2(new DecimalFormat(formatStr2, US, status),
1408 -1252045600.37,"(1,252,045,600.37)", status);
1409
1410 expect2(new DecimalFormat(formatStr2, US, status),
1411 int32_t(10), "10.0xxxxxxxxxxxx", status);
1412 expect2(new DecimalFormat(formatStr2, US, status),
1413 int32_t(1000),"1,000.0xxxxxxxxx", status);
1414 expect2(new DecimalFormat(formatStr2, US, status),
1415 int32_t(1000000),"1,000,000.0xxxxx", status);
1416 expect2(new DecimalFormat(formatStr2, US, status),
1417 100.37, "100.37xxxxxxxxxx", status);
1418 expect2(new DecimalFormat(formatStr2, US, status),
1419 10456.37, "10,456.37xxxxxxx", status);
1420 expect2(new DecimalFormat(formatStr2, US, status),
1421 1120456.37, "1,120,456.37xxxx", status);
1422 expect2(new DecimalFormat(formatStr2, US, status),
1423 112045600.37, "112,045,600.37xx", status);
1424 expect2(new DecimalFormat(formatStr2, US, status),
1425 10252045600.37,"10,252,045,600.37", status);
1426
1427 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1428 DecimalFormat fmt("#", US, status);
1429 CHECK(status, "DecimalFormat constructor");
1430 UnicodeString padString("P");
1431 fmt.setPadCharacter(padString);
1432 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1433 fmt.setPadCharacter((UnicodeString)"^");
1434 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1435 //commented untill implementation is complete
1436 /* fmt.setPadCharacter((UnicodeString)"^^^");
1437 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1438 padString.remove();
1439 padString.append((UChar)0x0061);
1440 padString.append((UChar)0x0302);
1441 fmt.setPadCharacter(padString);
1442 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1443 UnicodeString pattern(patternChars);
1444 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1445 */
1446
1447 }
1448
1449 /**
1450 * Upgrade to alphaWorks
1451 */
1452 void NumberFormatTest::TestPatterns2(void) {
1453 UErrorCode status = U_ZERO_ERROR;
1454 DecimalFormatSymbols US(Locale::getUS(), status);
1455 CHECK(status, "DecimalFormatSymbols constructor");
1456
1457 DecimalFormat fmt("#", US, status);
1458 CHECK(status, "DecimalFormat constructor");
1459
1460 UChar hat = 0x005E; /*^*/
1461
1462 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1463 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1464 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1465 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1466 expectPad(fmt, "$*^$#", ILLEGAL);
1467 expectPad(fmt, "#$*^$", ILLEGAL);
1468 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1469 12, (UChar)0x0078 /*x*/);
1470 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1471 3, (UChar)0x0078 /*x*/);
1472 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1473 10, (UChar)0x0061 /*a*/);
1474
1475 fmt.applyPattern("AA#,##0.00ZZ", status);
1476 CHECK(status, "applyPattern");
1477 fmt.setPadCharacter(hat);
1478
1479 fmt.setFormatWidth(10);
1480
1481 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1482 expectPat(fmt, "*^AA#,##0.00ZZ");
1483
1484 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1485 expectPat(fmt, "AA#,##0.00*^ZZ");
1486
1487 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1488 expectPat(fmt, "AA#,##0.00ZZ*^");
1489
1490 // 12 3456789012
1491 UnicodeString exp("AA*^#,##0.00ZZ", "");
1492 fmt.setFormatWidth(12);
1493 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1494 expectPat(fmt, exp);
1495
1496 fmt.setFormatWidth(13);
1497 // 12 34567890123
1498 expectPat(fmt, "AA*^##,##0.00ZZ");
1499
1500 fmt.setFormatWidth(14);
1501 // 12 345678901234
1502 expectPat(fmt, "AA*^###,##0.00ZZ");
1503
1504 fmt.setFormatWidth(15);
1505 // 12 3456789012345
1506 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1507
1508 fmt.setFormatWidth(16);
1509 // 12 34567890123456
1510 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1511 }
1512
1513 void NumberFormatTest::TestSurrogateSupport(void) {
1514 UErrorCode status = U_ZERO_ERROR;
1515 DecimalFormatSymbols custom(Locale::getUS(), status);
1516 CHECK(status, "DecimalFormatSymbols constructor");
1517
1518 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1519 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1520 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1521 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1522
1523 UnicodeString patternStr("*\\U00010000##.##", "");
1524 patternStr = patternStr.unescape();
1525 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1526 expStr = expStr.unescape();
1527 expect2(new DecimalFormat(patternStr, custom, status),
1528 int32_t(0), expStr, status);
1529
1530 status = U_ZERO_ERROR;
1531 expect2(new DecimalFormat("*^##.##", custom, status),
1532 int32_t(0), "^^^^0", status);
1533 status = U_ZERO_ERROR;
1534 expect2(new DecimalFormat("##.##", custom, status),
1535 -1.3, " minus 1decimal3", status);
1536 status = U_ZERO_ERROR;
1537 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1538 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1539 status = U_ZERO_ERROR;
1540 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1541 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1542 status = U_ZERO_ERROR;
1543 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1544 int32_t(0), "0decimal0 g-m/s^2", status);
1545 status = U_ZERO_ERROR;
1546 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1547 1.0/3, "0decimal33333 g-m/s^2", status);
1548
1549 UnicodeString zero((UChar32)0x10000);
1550 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1551 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1552 expStr = expStr.unescape();
1553 status = U_ZERO_ERROR;
1554 expect2(new DecimalFormat("##0.000", custom, status),
1555 1.25, expStr, status);
1556
1557 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1558 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1559 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1560 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1561 patternStr = patternStr.unescape();
1562 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1563 status = U_ZERO_ERROR;
1564 expect2(new DecimalFormat(patternStr, custom, status),
1565 int32_t(-20), expStr, status);
1566
1567 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1568 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1569 patternStr = patternStr.unescape();
1570 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1571 status = U_ZERO_ERROR;
1572 expect2(new DecimalFormat(patternStr, custom, status),
1573 int32_t(-20), expStr, status);
1574 }
1575
1576 void NumberFormatTest::TestCurrencyPatterns(void) {
1577 int32_t i, locCount;
1578 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1579 for (i=0; i<locCount; ++i) {
1580 UErrorCode ec = U_ZERO_ERROR;
1581 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1582 if (U_FAILURE(ec)) {
1583 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1584 } else {
1585 // Make sure currency formats do not have a variable number
1586 // of fraction digits
1587 int32_t min = nf->getMinimumFractionDigits();
1588 int32_t max = nf->getMaximumFractionDigits();
1589 if (min != max) {
1590 UnicodeString a, b;
1591 nf->format(1.0, a);
1592 nf->format(1.125, b);
1593 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1594 " min fraction digits != max fraction digits; "
1595 "x 1.0 => " + escape(a) +
1596 "; x 1.125 => " + escape(b));
1597 }
1598
1599 // Make sure EURO currency formats have exactly 2 fraction digits
1600 if (nf->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1601 DecimalFormat* df = (DecimalFormat*) nf;
1602 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1603 if (min != 2 || max != 2) {
1604 UnicodeString a;
1605 nf->format(1.0, a);
1606 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1607 " is a EURO format but it does not have 2 fraction digits; "
1608 "x 1.0 => " +
1609 escape(a));
1610 }
1611 }
1612 }
1613 }
1614 delete nf;
1615 }
1616 }
1617
1618 void NumberFormatTest::TestRegCurrency(void) {
1619 #if !UCONFIG_NO_SERVICE
1620 UErrorCode status = U_ZERO_ERROR;
1621 UChar USD[4];
1622 ucurr_forLocale("en_US", USD, 4, &status);
1623 UChar YEN[4];
1624 ucurr_forLocale("ja_JP", YEN, 4, &status);
1625 UChar TMP[4];
1626 static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
1627 if(U_FAILURE(status)) {
1628 errln("Unable to get currency for locale, error %s", u_errorName(status));
1629 return;
1630 }
1631
1632 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1633 UCurrRegistryKey enUSEUROkey = ucurr_register(QQQ, "en_US_EURO", &status);
1634
1635 ucurr_forLocale("en_US", TMP, 4, &status);
1636 if (u_strcmp(YEN, TMP) != 0) {
1637 errln("FAIL: didn't return YEN registered for en_US");
1638 }
1639
1640 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1641 if (u_strcmp(QQQ, TMP) != 0) {
1642 errln("FAIL: didn't return QQQ for en_US_EURO");
1643 }
1644
1645 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1646 if (fallbackLen) {
1647 errln("FAIL: tried to fallback en_XX_BAR");
1648 }
1649 status = U_ZERO_ERROR; // reset
1650
1651 if (!ucurr_unregister(enkey, &status)) {
1652 errln("FAIL: couldn't unregister enkey");
1653 }
1654
1655 ucurr_forLocale("en_US", TMP, 4, &status);
1656 if (u_strcmp(USD, TMP) != 0) {
1657 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1658 }
1659 status = U_ZERO_ERROR; // reset
1660
1661 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1662 if (u_strcmp(QQQ, TMP) != 0) {
1663 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1664 }
1665
1666 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1667 if (u_strcmp(USD, TMP) != 0) {
1668 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1669 }
1670 status = U_ZERO_ERROR; // reset
1671
1672 if (!ucurr_unregister(enUSEUROkey, &status)) {
1673 errln("FAIL: couldn't unregister enUSEUROkey");
1674 }
1675
1676 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1677 if (u_strcmp(EUR, TMP) != 0) {
1678 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1679 }
1680 status = U_ZERO_ERROR; // reset
1681 #endif
1682 }
1683
1684 void NumberFormatTest::TestCurrencyNames(void) {
1685 // Do a basic check of getName()
1686 // USD { "US$", "US Dollar" } // 04/04/1792-
1687 UErrorCode ec = U_ZERO_ERROR;
1688 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
1689 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
1690 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
1691 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
1692 UBool isChoiceFormat;
1693 int32_t len;
1694 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1695 // THE LOCALE DATA before diving into the code.
1696 assertEquals("USD.getName(SYMBOL_NAME)",
1697 UnicodeString("$"),
1698 UnicodeString(ucurr_getName(USD, "en",
1699 UCURR_SYMBOL_NAME,
1700 &isChoiceFormat, &len, &ec)));
1701 assertEquals("USD.getName(LONG_NAME)",
1702 UnicodeString("US Dollar"),
1703 UnicodeString(ucurr_getName(USD, "en",
1704 UCURR_LONG_NAME,
1705 &isChoiceFormat, &len, &ec)));
1706 assertEquals("CAD.getName(SYMBOL_NAME)",
1707 UnicodeString("CA$"),
1708 UnicodeString(ucurr_getName(CAD, "en",
1709 UCURR_SYMBOL_NAME,
1710 &isChoiceFormat, &len, &ec)));
1711 assertEquals("CAD.getName(SYMBOL_NAME)",
1712 UnicodeString("$"),
1713 UnicodeString(ucurr_getName(CAD, "en_CA",
1714 UCURR_SYMBOL_NAME,
1715 &isChoiceFormat, &len, &ec)));
1716 assertEquals("USD.getName(SYMBOL_NAME)",
1717 UnicodeString("US$"),
1718 UnicodeString(ucurr_getName(USD, "en_AU",
1719 UCURR_SYMBOL_NAME,
1720 &isChoiceFormat, &len, &ec)));
1721 assertEquals("CAD.getName(SYMBOL_NAME)",
1722 UnicodeString("CA$"),
1723 UnicodeString(ucurr_getName(CAD, "en_AU",
1724 UCURR_SYMBOL_NAME,
1725 &isChoiceFormat, &len, &ec)));
1726 assertEquals("USX.getName(LONG_NAME)",
1727 UnicodeString("USX"),
1728 UnicodeString(ucurr_getName(USX, "en_US",
1729 UCURR_LONG_NAME,
1730 &isChoiceFormat, &len, &ec)));
1731 assertSuccess("ucurr_getName", ec);
1732
1733 ec = U_ZERO_ERROR;
1734
1735 // Test that a default or fallback warning is being returned. JB 4239.
1736 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
1737 &len, &ec);
1738 assertTrue("ucurr_getName (fallback)",
1739 U_USING_FALLBACK_WARNING == ec, TRUE);
1740
1741 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
1742 &len, &ec);
1743 assertTrue("ucurr_getName (fallback)",
1744 U_USING_FALLBACK_WARNING == ec, TRUE);
1745
1746 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
1747 &len, &ec);
1748 assertTrue("ucurr_getName (default)",
1749 U_USING_DEFAULT_WARNING == ec, TRUE);
1750
1751 ucurr_getName(CAD, "vi", UCURR_LONG_NAME, &isChoiceFormat,
1752 &len, &ec);
1753 assertTrue("ucurr_getName (default)",
1754 U_USING_DEFAULT_WARNING == ec, TRUE);
1755
1756 // Test that a default warning is being returned when falling back to root. JB 4536.
1757 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
1758 &len, &ec);
1759 assertTrue("ucurr_getName (default to root)",
1760 U_USING_DEFAULT_WARNING == ec, TRUE);
1761
1762 // TODO add more tests later
1763 }
1764
1765 void NumberFormatTest::TestCurrencyUnit(void){
1766 UErrorCode ec = U_ZERO_ERROR;
1767 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
1768 CurrencyUnit cu(USD, ec);
1769 assertSuccess("CurrencyUnit", ec);
1770
1771 const UChar * r = cu.getISOCurrency(); // who is the buffer owner ?
1772 assertEquals("getISOCurrency()", USD, r);
1773
1774 CurrencyUnit cu2(cu);
1775 if (!(cu2 == cu)){
1776 errln("CurrencyUnit copy constructed object should be same");
1777 }
1778
1779 CurrencyUnit * cu3 = (CurrencyUnit *)cu.clone();
1780 if (!(*cu3 == cu)){
1781 errln("CurrencyUnit cloned object should be same");
1782 }
1783 delete cu3;
1784 }
1785
1786 void NumberFormatTest::TestCurrencyAmount(void){
1787 UErrorCode ec = U_ZERO_ERROR;
1788 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
1789 CurrencyAmount ca(9, USD, ec);
1790 assertSuccess("CurrencyAmount", ec);
1791
1792 CurrencyAmount ca2(ca);
1793 if (!(ca2 == ca)){
1794 errln("CurrencyAmount copy constructed object should be same");
1795 }
1796
1797 ca2=ca;
1798 if (!(ca2 == ca)){
1799 errln("CurrencyAmount assigned object should be same");
1800 }
1801
1802 CurrencyAmount *ca3 = (CurrencyAmount *)ca.clone();
1803 if (!(*ca3 == ca)){
1804 errln("CurrencyAmount cloned object should be same");
1805 }
1806 delete ca3;
1807 }
1808
1809 void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1810 Locale locDefault;
1811 Locale locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1812 UErrorCode status = U_ZERO_ERROR;
1813 UnicodeString intlCurrencySymbol((UChar)0xa4);
1814
1815 intlCurrencySymbol.append((UChar)0xa4);
1816
1817 logln("Current locale is %s", Locale::getDefault().getName());
1818 Locale::setDefault(locBad, status);
1819 logln("Current locale is %s", Locale::getDefault().getName());
1820 DecimalFormatSymbols mySymbols(status);
1821 if (status != U_USING_FALLBACK_WARNING) {
1822 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1823 }
1824 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
1825 errln("DecimalFormatSymbols does not have the right locale.");
1826 }
1827 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
1828 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
1829 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ")
1830 + prettify(mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum)));
1831
1832 if (mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum).length() == 0
1833 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
1834 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
1835 {
1836 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
1837 }
1838 }
1839 status = U_ZERO_ERROR;
1840 Locale::setDefault(locDefault, status);
1841 logln("Current locale is %s", Locale::getDefault().getName());
1842 }
1843
1844 /**
1845 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1846 * behave the same, except for memory ownership semantics. (No
1847 * version of this test on Java, since Java has only one method.)
1848 */
1849 void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1850 UErrorCode ec = U_ZERO_ERROR;
1851 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1852 if (U_FAILURE(ec)) {
1853 errln("Fail: DecimalFormatSymbols constructor");
1854 delete sym;
1855 return;
1856 }
1857 UnicodeString pat(" #,##0.00");
1858 pat.insert(0, (UChar)0x00A4);
1859 DecimalFormat fmt(pat, sym, ec);
1860 if (U_FAILURE(ec)) {
1861 errln("Fail: DecimalFormat constructor");
1862 return;
1863 }
1864
1865 UnicodeString str;
1866 fmt.format(2350.75, str);
1867 if (str == "$ 2,350.75") {
1868 logln(str);
1869 } else {
1870 errln("Fail: " + str + ", expected $ 2,350.75");
1871 }
1872
1873 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1874 if (U_FAILURE(ec)) {
1875 errln("Fail: DecimalFormatSymbols constructor");
1876 delete sym;
1877 return;
1878 }
1879 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1880 fmt.adoptDecimalFormatSymbols(sym);
1881
1882 str.truncate(0);
1883 fmt.format(2350.75, str);
1884 if (str == "Q 2,350.75") {
1885 logln(str);
1886 } else {
1887 errln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1888 }
1889
1890 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1891 if (U_FAILURE(ec)) {
1892 errln("Fail: DecimalFormatSymbols constructor");
1893 delete sym;
1894 return;
1895 }
1896 DecimalFormat fmt2(pat, sym, ec);
1897 if (U_FAILURE(ec)) {
1898 errln("Fail: DecimalFormat constructor");
1899 return;
1900 }
1901
1902 DecimalFormatSymbols sym2(Locale::getUS(), ec);
1903 if (U_FAILURE(ec)) {
1904 errln("Fail: DecimalFormatSymbols constructor");
1905 return;
1906 }
1907 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1908 fmt2.setDecimalFormatSymbols(sym2);
1909
1910 str.truncate(0);
1911 fmt2.format(2350.75, str);
1912 if (str == "Q 2,350.75") {
1913 logln(str);
1914 } else {
1915 errln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1916 }
1917 }
1918
1919 void NumberFormatTest::TestPerMill() {
1920 UErrorCode ec = U_ZERO_ERROR;
1921 UnicodeString str;
1922 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
1923 if (!assertSuccess("DecimalFormat ct", ec)) return;
1924 assertEquals("0.4857 x ###.###\\u2030",
1925 ctou("485.7\\u2030"), fmt.format(0.4857, str));
1926
1927 DecimalFormatSymbols sym(Locale::getUS(), ec);
1928 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
1929 DecimalFormat fmt2("", sym, ec);
1930 fmt2.applyLocalizedPattern("###.###m", ec);
1931 if (!assertSuccess("setup", ec)) return;
1932 str.truncate(0);
1933 assertEquals("0.4857 x ###.###m",
1934 "485.7m", fmt2.format(0.4857, str));
1935 }
1936
1937 /**
1938 * Generic test for patterns that should be legal/illegal.
1939 */
1940 void NumberFormatTest::TestIllegalPatterns() {
1941 // Test cases:
1942 // Prefix with "-:" for illegal patterns
1943 // Prefix with "+:" for legal patterns
1944 const char* DATA[] = {
1945 // Unquoted special characters in the suffix are illegal
1946 "-:000.000|###",
1947 "+:000.000'|###'",
1948 0
1949 };
1950 for (int32_t i=0; DATA[i]; ++i) {
1951 const char* pat=DATA[i];
1952 UBool valid = (*pat) == '+';
1953 pat += 2;
1954 UErrorCode ec = U_ZERO_ERROR;
1955 DecimalFormat fmt(pat, ec); // locale doesn't matter here
1956 if (U_SUCCESS(ec) == valid) {
1957 logln("Ok: pattern \"%s\": %s",
1958 pat, u_errorName(ec));
1959 } else {
1960 errln("FAIL: pattern \"%s\" should have %s; got %s",
1961 pat, (valid?"succeeded":"failed"),
1962 u_errorName(ec));
1963 }
1964 }
1965 }
1966
1967 //----------------------------------------------------------------------
1968
1969 static const char* KEYWORDS[] = {
1970 /*0*/ "ref=", // <reference pattern to parse numbers>
1971 /*1*/ "loc=", // <locale for formats>
1972 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
1973 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
1974 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
1975 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
1976 /*6*/ "perr:", // <pattern or '-'> <invalid string>
1977 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
1978 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
1979 0
1980 };
1981
1982 /**
1983 * Return an integer representing the next token from this
1984 * iterator. The integer will be an index into the given list, or
1985 * -1 if there are no more tokens, or -2 if the token is not on
1986 * the list.
1987 */
1988 static int32_t keywordIndex(const UnicodeString& tok) {
1989 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
1990 if (tok==KEYWORDS[i]) {
1991 return i;
1992 }
1993 }
1994 return -1;
1995 }
1996
1997 /**
1998 * Parse a CurrencyAmount using the given NumberFormat, with
1999 * the 'delim' character separating the number and the currency.
2000 */
2001 static void parseCurrencyAmount(const UnicodeString& str,
2002 const NumberFormat& fmt,
2003 UChar delim,
2004 Formattable& result,
2005 UErrorCode& ec) {
2006 UnicodeString num, cur;
2007 int32_t i = str.indexOf(delim);
2008 str.extractBetween(0, i, num);
2009 str.extractBetween(i+1, INT32_MAX, cur);
2010 Formattable n;
2011 fmt.parse(num, n, ec);
2012 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2013 }
2014
2015 void NumberFormatTest::TestCases() {
2016 UErrorCode ec = U_ZERO_ERROR;
2017 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2018 if (U_FAILURE(ec)) {
2019 dataerrln("[DATA] Couldn't open NumberFormatTestCases.txt");
2020 return;
2021 }
2022 TokenIterator tokens(&reader);
2023
2024 Locale loc("en", "US", "");
2025 DecimalFormat *ref = 0, *fmt = 0;
2026 MeasureFormat *mfmt = 0;
2027 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2028 Formattable n;
2029
2030 for (;;) {
2031 ec = U_ZERO_ERROR;
2032 if (!tokens.next(tok, ec)) {
2033 break;
2034 }
2035 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2036 int32_t cmd = keywordIndex(tok);
2037 switch (cmd) {
2038 case 0:
2039 // ref= <reference pattern>
2040 if (!tokens.next(tok, ec)) goto error;
2041 delete ref;
2042 ref = new DecimalFormat(tok,
2043 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2044 if (U_FAILURE(ec)) {
2045 dataerrln("Error constructing DecimalFormat");
2046 goto error;
2047 }
2048 break;
2049 case 1:
2050 // loc= <locale>
2051 if (!tokens.next(tok, ec)) goto error;
2052 loc = Locale::createFromName(CharString(tok));
2053 break;
2054 case 2: // f:
2055 case 3: // fp:
2056 case 4: // rt:
2057 case 5: // p:
2058 if (!tokens.next(tok, ec)) goto error;
2059 if (tok != "-") {
2060 pat = tok;
2061 delete fmt;
2062 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2063 if (U_FAILURE(ec)) {
2064 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2065 ec = U_ZERO_ERROR;
2066 if (!tokens.next(tok, ec)) goto error;
2067 if (!tokens.next(tok, ec)) goto error;
2068 if (cmd == 3) {
2069 if (!tokens.next(tok, ec)) goto error;
2070 }
2071 continue;
2072 }
2073 }
2074 if (cmd == 2 || cmd == 3 || cmd == 4) {
2075 // f: <pattern or '-'> <number> <exp. string>
2076 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2077 // rt: <pattern or '-'> <number> <string>
2078 UnicodeString num;
2079 if (!tokens.next(num, ec)) goto error;
2080 if (!tokens.next(str, ec)) goto error;
2081 ref->parse(num, n, ec);
2082 assertSuccess("parse", ec);
2083 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2084 str, fmt->format(n, out.remove(), ec));
2085 assertSuccess("format", ec);
2086 if (cmd == 3) { // fp:
2087 if (!tokens.next(num, ec)) goto error;
2088 ref->parse(num, n, ec);
2089 assertSuccess("parse", ec);
2090 }
2091 if (cmd != 2) { // != f:
2092 Formattable m;
2093 fmt->parse(str, m, ec);
2094 assertSuccess("parse", ec);
2095 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2096 n, m);
2097 }
2098 }
2099 // p: <pattern or '-'> <string to parse> <exp. number>
2100 else {
2101 UnicodeString expstr;
2102 if (!tokens.next(str, ec)) goto error;
2103 if (!tokens.next(expstr, ec)) goto error;
2104 Formattable exp, n;
2105 ref->parse(expstr, exp, ec);
2106 assertSuccess("parse", ec);
2107 fmt->parse(str, n, ec);
2108 assertSuccess("parse", ec);
2109 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2110 exp, n);
2111 }
2112 break;
2113 case 8: // fpc:
2114 if (!tokens.next(tok, ec)) goto error;
2115 if (tok != "-") {
2116 mloc = tok;
2117 delete mfmt;
2118 mfmt = MeasureFormat::createCurrencyFormat(
2119 Locale::createFromName(CharString(mloc)), ec);
2120 if (U_FAILURE(ec)) {
2121 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2122 ec = U_ZERO_ERROR;
2123 if (!tokens.next(tok, ec)) goto error;
2124 if (!tokens.next(tok, ec)) goto error;
2125 if (!tokens.next(tok, ec)) goto error;
2126 continue;
2127 }
2128 }
2129 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2130 if (!tokens.next(currAmt, ec)) goto error;
2131 if (!tokens.next(str, ec)) goto error;
2132 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2133 if (assertSuccess("parseCurrencyAmount", ec)) {
2134 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2135 str, mfmt->format(n, out.remove(), ec));
2136 assertSuccess("format", ec);
2137 }
2138 if (!tokens.next(currAmt, ec)) goto error;
2139 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2140 if (assertSuccess("parseCurrencyAmount", ec)) {
2141 Formattable m;
2142 mfmt->parseObject(str, m, ec);
2143 if (assertSuccess("parseCurrency", ec)) {
2144 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2145 n, m);
2146 }
2147 }
2148 break;
2149 case 6:
2150 // perr: <pattern or '-'> <invalid string>
2151 errln("FAIL: Under construction");
2152 goto done;
2153 case 7: {
2154 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2155 UnicodeString testpat;
2156 UnicodeString exppat;
2157 if (!tokens.next(testpat, ec)) goto error;
2158 if (!tokens.next(exppat, ec)) goto error;
2159 UBool err = exppat == "err";
2160 UBool existingPat = FALSE;
2161 if (testpat == "-") {
2162 if (err) {
2163 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2164 continue;
2165 }
2166 existingPat = TRUE;
2167 testpat = pat;
2168 }
2169 if (exppat == "-") exppat = testpat;
2170 DecimalFormat* f = 0;
2171 UErrorCode ec2 = U_ZERO_ERROR;
2172 if (existingPat) {
2173 f = fmt;
2174 } else {
2175 f = new DecimalFormat(testpat, ec2);
2176 }
2177 if (U_SUCCESS(ec2)) {
2178 if (err) {
2179 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2180 "\" was accepted");
2181 } else {
2182 UnicodeString pat2;
2183 assertEquals(where + "\"" + testpat + "\".toPattern()",
2184 exppat, f->toPattern(pat2));
2185 }
2186 } else {
2187 if (err) {
2188 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2189 "\" failed: " + u_errorName(ec2));
2190 } else {
2191 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2192 "\" failed: " + u_errorName(ec2));
2193 }
2194 }
2195 if (!existingPat) delete f;
2196 } break;
2197 case -1:
2198 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2199 goto done;
2200 }
2201 }
2202 goto done;
2203
2204 error:
2205 if (U_SUCCESS(ec)) {
2206 errln("FAIL: Unexpected EOF");
2207 } else {
2208 errln("FAIL: " + where + "Unexpected " + u_errorName(ec));
2209 }
2210
2211 done:
2212 delete mfmt;
2213 delete fmt;
2214 delete ref;
2215 }
2216
2217
2218 //----------------------------------------------------------------------
2219 // Support methods
2220 //----------------------------------------------------------------------
2221
2222 UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2223 if (a.getType() == b.getType()) {
2224 return a == b;
2225 }
2226
2227 if (a.getType() == Formattable::kLong) {
2228 if (b.getType() == Formattable::kInt64) {
2229 return a.getLong() == b.getLong();
2230 } else if (b.getType() == Formattable::kDouble) {
2231 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2232 }
2233 } else if (a.getType() == Formattable::kDouble) {
2234 if (b.getType() == Formattable::kLong) {
2235 return a.getDouble() == (double) b.getLong();
2236 } else if (b.getType() == Formattable::kInt64) {
2237 return a.getDouble() == (double)b.getInt64();
2238 }
2239 } else if (a.getType() == Formattable::kInt64) {
2240 if (b.getType() == Formattable::kLong) {
2241 return a.getInt64() == (int64_t)b.getLong();
2242 } else if (b.getType() == Formattable::kDouble) {
2243 return a.getInt64() == (int64_t)b.getDouble();
2244 }
2245 }
2246 return FALSE;
2247 }
2248
2249 void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2250 // Don't round-trip format test, since we explicitly do it
2251 expect(fmt, n, str, FALSE);
2252 expect(fmt, str, n);
2253 }
2254
2255 void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2256 const UnicodeString& exp,
2257 UErrorCode status) {
2258 if (U_FAILURE(status)) {
2259 errln("FAIL: NumberFormat constructor");
2260 } else {
2261 expect2(*fmt, n, exp);
2262 }
2263 delete fmt;
2264 }
2265
2266 void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2267 UErrorCode status = U_ZERO_ERROR;
2268 Formattable num;
2269 fmt.parse(str, num, status);
2270 if (U_FAILURE(status)) {
2271 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2272 return;
2273 }
2274 UnicodeString pat;
2275 ((DecimalFormat*) &fmt)->toPattern(pat);
2276 if (equalValue(num, n)) {
2277 logln(UnicodeString("Ok \"") + str + "\" x " +
2278 pat + " = " +
2279 toString(num));
2280 } else {
2281 errln(UnicodeString("FAIL \"") + str + "\" x " +
2282 pat + " = " +
2283 toString(num) + ", expected " + toString(n));
2284 }
2285 }
2286
2287 void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2288 const UnicodeString& exp, UBool rt) {
2289 UnicodeString saw;
2290 FieldPosition pos;
2291 UErrorCode status = U_ZERO_ERROR;
2292 fmt.format(n, saw, pos, status);
2293 CHECK(status, "NumberFormat::format");
2294 UnicodeString pat;
2295 ((DecimalFormat*) &fmt)->toPattern(pat);
2296 if (saw == exp) {
2297 logln(UnicodeString("Ok ") + toString(n) + " x " +
2298 escape(pat) + " = \"" +
2299 escape(saw) + "\"");
2300 // We should be able to round-trip the formatted string =>
2301 // number => string (but not the other way around: number
2302 // => string => number2, might have number2 != number):
2303 if (rt) {
2304 Formattable n2;
2305 fmt.parse(exp, n2, status);
2306 if (U_FAILURE(status)) {
2307 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2308 return;
2309 }
2310 UnicodeString saw2;
2311 fmt.format(n2, saw2, pos, status);
2312 CHECK(status, "NumberFormat::format");
2313 if (saw2 != exp) {
2314 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2315 " => \"" + saw2 + "\"");
2316 }
2317 }
2318 } else {
2319 errln(UnicodeString("FAIL ") + toString(n) + " x " +
2320 escape(pat) + " = \"" +
2321 escape(saw) + "\", expected \"" + exp + "\"");
2322 }
2323 }
2324
2325 void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2326 const UnicodeString& exp,
2327 UErrorCode status) {
2328 if (U_FAILURE(status)) {
2329 errln("FAIL: NumberFormat constructor");
2330 } else {
2331 expect(*fmt, n, exp);
2332 }
2333 delete fmt;
2334 }
2335
2336 void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2337 double value, const UnicodeString& string) {
2338 UErrorCode ec = U_ZERO_ERROR;
2339 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2340 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2341 UChar curr[4];
2342 u_strcpy(curr, DEFAULT_CURR);
2343 if (*locale.getLanguage() != 0) {
2344 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2345 assertSuccess("ucurr_forLocale", ec);
2346 fmt.setCurrency(curr, ec);
2347 assertSuccess("DecimalFormat::setCurrency", ec);
2348 fmt.setCurrency(curr); //Deprecated variant, for coverage only
2349 }
2350 UnicodeString s;
2351 fmt.format(value, s);
2352 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
2353
2354 // Default display of the number yields "1234.5599999999999"
2355 // instead of "1234.56". Use a formatter to fix this.
2356 NumberFormat* f =
2357 NumberFormat::createInstance(Locale::getUS(), ec);
2358 UnicodeString v;
2359 if (U_FAILURE(ec)) {
2360 // Oops; bad formatter. Use default op+= display.
2361 v = (UnicodeString)"" + value;
2362 } else {
2363 f->setMaximumFractionDigits(4);
2364 f->setGroupingUsed(FALSE);
2365 f->format(value, v);
2366 }
2367 delete f;
2368
2369 if (s == string) {
2370 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
2371 } else {
2372 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
2373 ", expected " + prettify(string));
2374 }
2375 }
2376
2377 void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
2378 UnicodeString pat;
2379 fmt.toPattern(pat);
2380 if (pat == exp) {
2381 logln(UnicodeString("Ok \"") + pat + "\"");
2382 } else {
2383 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
2384 }
2385 }
2386
2387 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2388 int32_t pos) {
2389 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
2390 }
2391 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2392 int32_t pos, int32_t width, UChar pad) {
2393 expectPad(fmt, pat, pos, width, UnicodeString(pad));
2394 }
2395 void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2396 int32_t pos, int32_t width, const UnicodeString& pad) {
2397 int32_t apos = 0, awidth = 0;
2398 UnicodeString apadStr;
2399 UErrorCode status = U_ZERO_ERROR;
2400 fmt.applyPattern(pat, status);
2401 if (U_SUCCESS(status)) {
2402 apos = fmt.getPadPosition();
2403 awidth = fmt.getFormatWidth();
2404 apadStr=fmt.getPadCharacterString();
2405 } else {
2406 apos = -1;
2407 awidth = width;
2408 apadStr = pad;
2409 }
2410 if (apos == pos && awidth == width && apadStr == pad) {
2411 UnicodeString infoStr;
2412 if (pos == ILLEGAL) {
2413 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
2414 }
2415 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
2416 } else {
2417 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
2418 " width=" + awidth + " pad=" + apadStr +
2419 ", expected " + pos + " " + width + " " + pad);
2420 }
2421 }
2422 void NumberFormatTest::TestJB3832(){
2423 const char* localeID = "pt_PT@currency=PTE";
2424 Locale loc(localeID);
2425 UErrorCode status = U_ZERO_ERROR;
2426 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
2427 UnicodeString s;
2428 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
2429 if(U_FAILURE(status)){
2430 errln("Could not create currency formatter for locale %s", localeID);
2431 return;
2432 }
2433 currencyFmt->format(1150.50, s);
2434 if(s!=expected){
2435 errln(UnicodeString("FAIL: Expected: ")+expected
2436 + UnicodeString(" Got: ") + s
2437 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
2438 }
2439 if (U_FAILURE(status)){
2440 errln("FAIL: Status %s", u_errorName(status));
2441 }
2442 delete currencyFmt;
2443 }
2444
2445 void NumberFormatTest::TestHost()
2446 {
2447 #ifdef U_WINDOWS
2448 Win32NumberTest::testLocales(this);
2449 #endif
2450 }
2451
2452 void NumberFormatTest::TestHostClone()
2453 {
2454 /*
2455 Verify that a cloned formatter gives the same results
2456 and is useable after the original has been deleted.
2457 */
2458 // This is mainly important on Windows.
2459 UErrorCode status = U_ZERO_ERROR;
2460 Locale loc("en_US@compat=host");
2461 UDate now = Calendar::getNow();
2462 NumberFormat *full = NumberFormat::createInstance(loc, status);
2463 if (full == NULL || U_FAILURE(status)) {
2464 errln("FAIL: Can't create Relative date instance");
2465 return;
2466 }
2467 UnicodeString result1;
2468 full->format(now, result1, status);
2469 Format *fullClone = full->clone();
2470 delete full;
2471 full = NULL;
2472
2473 UnicodeString result2;
2474 fullClone->format(now, result2, status);
2475 if (U_FAILURE(status)) {
2476 errln("FAIL: format failure.");
2477 }
2478 if (result1 != result2) {
2479 errln("FAIL: Clone returned different result from non-clone.");
2480 }
2481 delete fullClone;
2482 }
2483
2484 void NumberFormatTest::TestCurrencyFormat()
2485 {
2486 // This test is here to increase code coverage.
2487 UErrorCode status = U_ZERO_ERROR;
2488 MeasureFormat *cloneObj;
2489 UnicodeString str;
2490 Formattable toFormat, result;
2491 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
2492
2493 Locale saveDefaultLocale = Locale::getDefault();
2494 Locale::setDefault( Locale::getUK(), status );
2495 if (U_FAILURE(status)) {
2496 errln("couldn't set default Locale!");
2497 return;
2498 }
2499
2500 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
2501 Locale::setDefault( saveDefaultLocale, status );
2502 if (U_FAILURE(status)){
2503 errln("FAIL: Status %s", u_errorName(status));
2504 return;
2505 }
2506 cloneObj = (MeasureFormat *)measureObj->clone();
2507 if (cloneObj == NULL) {
2508 errln("Clone doesn't work");
2509 return;
2510 }
2511 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
2512 measureObj->format(toFormat, str, status);
2513 measureObj->parseObject(str, result, status);
2514 if (U_FAILURE(status)){
2515 errln("FAIL: Status %s", u_errorName(status));
2516 }
2517 if (result != toFormat) {
2518 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
2519 }
2520 status = U_ZERO_ERROR;
2521 str.truncate(0);
2522 cloneObj->format(toFormat, str, status);
2523 cloneObj->parseObject(str, result, status);
2524 if (U_FAILURE(status)){
2525 errln("FAIL: Status %s", u_errorName(status));
2526 }
2527 if (result != toFormat) {
2528 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
2529 }
2530 if (*measureObj != *cloneObj) {
2531 errln("Cloned object is not equal to the original object");
2532 }
2533 delete measureObj;
2534 delete cloneObj;
2535
2536 status = U_USELESS_COLLATOR_ERROR;
2537 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
2538 errln("createCurrencyFormat should have returned NULL.");
2539 }
2540 }
2541
2542 /* Port of ICU4J rounding test. */
2543 void NumberFormatTest::TestRounding() {
2544 UErrorCode status = U_ZERO_ERROR;
2545 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
2546
2547 if (U_FAILURE(status)) {
2548 errln("Unable to create decimal formatter.");
2549 return;
2550 }
2551
2552 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
2553 int testValues[]={0, 300};
2554
2555 for (int j=0; j<2; j++) {
2556 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
2557 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
2558 for (int increment=0; increment<6; increment++) {
2559 double base=testValues[j];
2560 double rInc=roundingIncrements[increment];
2561 checkRounding(df, base, 20, rInc);
2562 rInc=1.000000000/rInc;
2563 checkRounding(df, base, 20, rInc);
2564 }
2565 }
2566 }
2567 delete df;
2568 }
2569
2570 void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
2571 df->setRoundingIncrement(increment);
2572 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
2573 for (int i=-iterations; i<=iterations;i++) {
2574 double iValue=base+(increment*(i*0.1));
2575 double smallIncrement=0.00000001;
2576 if (iValue!=0) {
2577 smallIncrement*=iValue;
2578 }
2579 //we not only test the value, but some values in a small range around it
2580 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
2581 lastParsed=checkRound(df, iValue, lastParsed);
2582 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
2583 }
2584 }
2585
2586 double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
2587 UErrorCode status=U_ZERO_ERROR;
2588 UnicodeString formattedDecimal;
2589 double parsed;
2590 Formattable result;
2591 df->format(iValue, formattedDecimal, status);
2592
2593 if (U_FAILURE(status)) {
2594 errln("Error formatting number.");
2595 }
2596
2597 df->parse(formattedDecimal, result, status);
2598
2599 if (U_FAILURE(status)) {
2600 errln("Error parsing number.");
2601 }
2602
2603 parsed=result.getDouble();
2604
2605 if (lastParsed>parsed) {
2606 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
2607 }
2608
2609 return lastParsed;
2610 }
2611
2612 void NumberFormatTest::TestNonpositiveMultiplier() {
2613 UErrorCode status = U_ZERO_ERROR;
2614 DecimalFormatSymbols US(Locale::getUS(), status);
2615 CHECK(status, "DecimalFormatSymbols constructor");
2616 DecimalFormat df(UnicodeString("0"), US, status);
2617 CHECK(status, "DecimalFormat(0)");
2618
2619 // test zero multiplier
2620
2621 int32_t mult = df.getMultiplier();
2622 df.setMultiplier(0);
2623 if (df.getMultiplier() != mult) {
2624 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
2625 }
2626
2627 // test negative multiplier
2628
2629 df.setMultiplier(-1);
2630 if (df.getMultiplier() != -1) {
2631 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
2632 return;
2633 }
2634
2635 expect(df, "1122.123", -1122.123);
2636 expect(df, "-1122.123", 1122.123);
2637 expect(df, "1.2", -1.2);
2638 expect(df, "-1.2", 1.2);
2639
2640 // TODO: change all the following int64_t tests once BigInteger is ported
2641 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2642 static const char* posOutOfRange = "9223372036854780000";
2643 static const char* negOutOfRange = "-9223372036854780000";
2644
2645 expect(df, U_INT64_MIN, posOutOfRange);
2646 expect(df, U_INT64_MIN+1, "9223372036854775807");
2647 expect(df, (int64_t)-123, "123");
2648 expect(df, (int64_t)123, "-123");
2649 expect(df, U_INT64_MAX-1, "-9223372036854775806");
2650 expect(df, U_INT64_MAX, "-9223372036854775807");
2651
2652 df.setMultiplier(-2);
2653 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
2654 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
2655 expect(df, -(U_INT64_MIN/2)+1, negOutOfRange);
2656
2657 df.setMultiplier(-7);
2658 expect(df, -(U_INT64_MAX/7)-1, posOutOfRange);
2659 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
2660 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
2661
2662 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
2663 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2664 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
2665 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
2666 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
2667 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
2668
2669 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
2670 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2671 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2672 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2673 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2674 }
2675
2676 void
2677 NumberFormatTest::TestSpaceParsing() {
2678 // the data are:
2679 // the string to be parsed, parsed position, parsed error index
2680 const char* DATA[][3] = {
2681 {"$124", "4", "-1"},
2682 {"$124 $124", "4", "-1"},
2683 {"$124 ", "4", "-1"},
2684 {"$ 124 ", "5", "-1"},
2685 {"$\\u00A0124 ", "5", "-1"},
2686 {" $ 124 ", "6", "-1"},
2687 //{"124$", "4", "-1"}, // TODO: need to handle trailing currency correctly
2688 {"124$", "3", "-1"},
2689 //{"124 $", "5", "-1"}, // TODO: OK or not, need currency spacing rule
2690 {"124 $", "3", "-1"},
2691 };
2692
2693 UErrorCode status = U_ZERO_ERROR;
2694 Locale locale("en_US");
2695 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
2696 if (U_FAILURE(status)) {
2697 delete foo;
2698 return;
2699 }
2700
2701 foo->setParseStrict(FALSE);
2702 for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
2703 ParsePosition parsePosition(0);
2704 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
2705 int parsedPosition = atoi(DATA[i][1]);
2706 int errorIndex = atoi(DATA[i][2]);
2707 Formattable result;
2708 foo->parse(stringToBeParsed, result, parsePosition);
2709 if (parsePosition.getIndex() != parsedPosition ||
2710 parsePosition.getErrorIndex() != errorIndex) {
2711 errln("FAILED parse " + stringToBeParsed + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
2712 }
2713 if (parsePosition.getErrorIndex() == -1 &&
2714 result.getType() == Formattable::kLong &&
2715 result.getLong() != 124) {
2716 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
2717 }
2718 }
2719 delete foo;
2720 }
2721
2722 #endif /* #if !UCONFIG_NO_FORMATTING */