]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/test/intltest/numfmtst.cpp
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / test / intltest / numfmtst.cpp
... / ...
CommitLineData
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
33static 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
43void 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)
102void
103NumberFormatTest::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
139class StubNumberForamt :public NumberFormat{
140public:
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
167void
168NumberFormatTest::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
179void
180NumberFormatTest::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/*
211icu_2_4::DigitList::operator== 0 0 2 icuuc24d.dll digitlst.cpp Doug
212icu_2_4::DigitList::append 0 0 4 icuin24d.dll digitlst.h Doug
213icu_2_4::DigitList::operator!= 0 0 1 icuuc24d.dll digitlst.h Doug
214*/
215/*
216void
217NumberFormatTest::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
237void
238NumberFormatTest::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
415void
416NumberFormatTest::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
431void
432NumberFormatTest::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
467void
468NumberFormatTest::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
550void
551NumberFormatTest::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 */
584void
585NumberFormatTest::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
628static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
629
630UnicodeString&
631NumberFormatTest::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// -------------------------------------
651static 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 */
667void
668NumberFormatTest::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 */
733void 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 */
791void
792NumberFormatTest::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
814static const char *lenientAffixTestCases[] = {
815 "(1)",
816 "( 1)",
817 "(1 )",
818 "( 1 )"
819};
820
821static const char *lenientMinusTestCases[] = {
822 "-5",
823 "\\u22125",
824 "\\u20105"
825};
826
827static const char *lenientCurrencyTestCases[] = {
828 "$1,000",
829 "$ 1,000",
830 "$1000",
831 "$ 1000",
832 "$1 000.00",
833 "$ 1 000.00",
834 "$ 1\\u00A0000.00",
835 "1000.00"
836};
837
838static const char *lenientNegativeCurrencyTestCases[] = {
839 "($1,000)",
840 "($ 1,000)",
841 "($1000)",
842 "($ 1000)",
843 "($1 000.00)",
844 "($ 1 000.00)",
845 "( $ 1,000.00 )",
846 "($ 1\\u00A0000.00)",
847 "(1000.00)"
848};
849
850static const char *lenientPercentTestCases[] = {
851 "25%",
852 " 25%",
853 " 25 %",
854 "25 %",
855 "25\\u00A0%",
856 "25"
857};
858
859static const char *lenientNegativePercentTestCases[] = {
860 "-25%",
861 " -25%",
862 " - 25%",
863 "- 25 %",
864 " - 25 %",
865 "-25 %",
866 "-25\\u00A0%",
867 "-25",
868 "- 25"
869};
870
871static const char *strictFailureTestCases[] = {
872 " 1000",
873#if 0
874 "10,00",
875 "1,000,.0"
876#endif
877};
878
879#define ARRAY_SIZE(array) ((int32_t) (sizeof (array) / sizeof(array[0])))
880
881/**
882 * Test lenient parsing.
883 */
884void
885NumberFormatTest::TestLenientParse(void)
886{
887 UErrorCode status = U_ZERO_ERROR;
888 DecimalFormat *format = new DecimalFormat("(#,##0)", status);
889 Formattable n;
890
891 format->setParseStrict(FALSE);
892 for (int32_t t = 0; t < ARRAY_SIZE (lenientAffixTestCases); t += 1) {
893 UnicodeString testCase = ctou(lenientAffixTestCases[t]);
894
895 format->parse(testCase, n, status);
896 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
897
898 if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
899 n.getLong() != 1) {
900 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t] + (UnicodeString) "\"");
901 status = U_ZERO_ERROR;
902 }
903 }
904
905 delete format;
906
907 Locale en_US("en_US");
908 Locale sv_SE("sv_SE");
909
910 NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, status);
911
912 mFormat->setParseStrict(FALSE);
913 for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
914 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
915
916 mFormat->parse(testCase, n, status);
917 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
918
919 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
920 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
921 status = U_ZERO_ERROR;
922 }
923 }
924
925 delete mFormat;
926
927 mFormat = NumberFormat::createInstance(en_US, status);
928
929 mFormat->setParseStrict(FALSE);
930 for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
931 UnicodeString testCase = ctou(lenientMinusTestCases[t]);
932
933 mFormat->parse(testCase, n, status);
934 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
935
936 if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
937 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
938 status = U_ZERO_ERROR;
939 }
940 }
941
942 delete mFormat;
943
944 NumberFormat *cFormat = NumberFormat::createCurrencyInstance(en_US, status);
945
946 cFormat->setParseStrict(FALSE);
947 for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
948 UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);
949
950 cFormat->parse(testCase, n, status);
951 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
952
953 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
954 n.getLong() != 1000) {
955 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t] + (UnicodeString) "\"");
956 status = U_ZERO_ERROR;
957 }
958 }
959
960 for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativeCurrencyTestCases); t += 1) {
961 UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);
962 ParsePosition pos(0);
963
964 cFormat->parse(testCase, n, /*status*/pos);
965 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
966
967 if (/*U_FAILURE(status)*/pos.getErrorIndex() >= 0 ||n.getType() != Formattable::kLong ||
968 n.getLong() != -1000) {
969 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t] + (UnicodeString) "\" parse position = " +
970 pos.getIndex() + ", " + pos.getErrorIndex());
971 status = U_ZERO_ERROR;
972 }
973 }
974
975 delete cFormat;
976
977 NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
978
979 pFormat->setParseStrict(FALSE);
980 for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
981 UnicodeString testCase = ctou(lenientPercentTestCases[t]);
982
983 pFormat->parse(testCase, n, status);
984 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
985
986 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
987 n.getDouble() != 0.25) {
988 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t] + (UnicodeString) "\"");
989 status = U_ZERO_ERROR;
990 }
991 }
992
993 for (int32_t t = 0; t < ARRAY_SIZE (lenientNegativePercentTestCases); t += 1) {
994 UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);
995
996 pFormat->parse(testCase, n, status);
997 logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());
998
999 if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
1000 n.getDouble() != -0.25) {
1001 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t] + (UnicodeString) "\"");
1002 status = U_ZERO_ERROR;
1003 }
1004 }
1005
1006 delete pFormat;
1007
1008 // Test cases that should fail with a strict parse and pass with a
1009 // lenient parse.
1010 NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
1011
1012 // first, make sure that they fail with a strict parse
1013 for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
1014 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1015
1016 nFormat->parse(testCase, n, status);
1017 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1018
1019 if (! U_FAILURE(status)) {
1020 errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
1021 }
1022
1023 status = U_ZERO_ERROR;
1024 }
1025
1026 // then, make sure that they pass with a lenient parse
1027 nFormat->setParseStrict(FALSE);
1028 for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {
1029 UnicodeString testCase = ctou(strictFailureTestCases[t]);
1030
1031 nFormat->parse(testCase, n, status);
1032 logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
1033
1034 if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
1035 n.getLong() != 1000) {
1036 errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t] + (UnicodeString) "\"");
1037 status = U_ZERO_ERROR;
1038 }
1039 }
1040
1041 delete nFormat;
1042}
1043
1044// -------------------------------------
1045
1046/**
1047 * Test proper rounding by the format method.
1048 */
1049void
1050NumberFormatTest::TestRounding487(void)
1051{
1052 UErrorCode status = U_ZERO_ERROR;
1053 NumberFormat *nf = NumberFormat::createInstance(status);
1054 if (U_FAILURE(status)) {
1055 dataerrln("Error calling NumberFormat::createInstance()");
1056 return;
1057 }
1058
1059 roundingTest(*nf, 0.00159999, 4, "0.0016");
1060 roundingTest(*nf, 0.00995, 4, "0.01");
1061
1062 roundingTest(*nf, 12.3995, 3, "12.4");
1063
1064 roundingTest(*nf, 12.4999, 0, "12");
1065 roundingTest(*nf, - 19.5, 0, "-20");
1066 delete nf;
1067 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
1068}
1069
1070/**
1071 * Test the functioning of the secondary grouping value.
1072 */
1073void NumberFormatTest::TestSecondaryGrouping(void) {
1074 UErrorCode status = U_ZERO_ERROR;
1075 DecimalFormatSymbols US(Locale::getUS(), status);
1076 CHECK(status, "DecimalFormatSymbols ct");
1077
1078 DecimalFormat f("#,##,###", US, status);
1079 CHECK(status, "DecimalFormat ct");
1080
1081 expect2(f, (int32_t)123456789L, "12,34,56,789");
1082 expectPat(f, "#,##,###");
1083 f.applyPattern("#,###", status);
1084 CHECK(status, "applyPattern");
1085
1086 f.setSecondaryGroupingSize(4);
1087 expect2(f, (int32_t)123456789L, "12,3456,789");
1088 expectPat(f, "#,####,###");
1089 NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
1090 CHECK(status, "createInstance(hi_IN)");
1091
1092 UnicodeString out;
1093 int32_t l = (int32_t)1876543210L;
1094 g->format(l, out);
1095 delete g;
1096 // expect "1,87,65,43,210", but with Hindi digits
1097 // 01234567890123
1098 UBool ok = TRUE;
1099 if (out.length() != 14) {
1100 ok = FALSE;
1101 } else {
1102 for (int32_t i=0; i<out.length(); ++i) {
1103 UBool expectGroup = FALSE;
1104 switch (i) {
1105 case 1:
1106 case 4:
1107 case 7:
1108 case 10:
1109 expectGroup = TRUE;
1110 break;
1111 }
1112 // Later -- fix this to get the actual grouping
1113 // character from the resource bundle.
1114 UBool isGroup = (out.charAt(i) == 0x002C);
1115 if (isGroup != expectGroup) {
1116 ok = FALSE;
1117 break;
1118 }
1119 }
1120 }
1121 if (!ok) {
1122 errln((UnicodeString)"FAIL Expected " + l +
1123 " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
1124 escape(out) + "\"");
1125 } else {
1126 logln((UnicodeString)"Ok " + l +
1127 " x hi_IN -> \"" +
1128 escape(out) + "\"");
1129 }
1130}
1131
1132void NumberFormatTest::TestWhiteSpaceParsing(void) {
1133 UErrorCode ec = U_ZERO_ERROR;
1134 DecimalFormatSymbols US(Locale::getUS(), ec);
1135 DecimalFormat fmt("a b#0c ", US, ec);
1136 if (U_FAILURE(ec)) {
1137 errln("FAIL: Constructor");
1138 return;
1139 }
1140 int32_t n = 1234;
1141 expect(fmt, "a b1234c ", n);
1142 expect(fmt, "a b1234c ", n);
1143}
1144
1145/**
1146 * Test currencies whose display name is a ChoiceFormat.
1147 * Less useful now that INR is no longer a choice format! See cldrbug 1961 !
1148 */
1149void NumberFormatTest::TestComplexCurrency() {
1150 UErrorCode ec = U_ZERO_ERROR;
1151 Locale loc("kn", "IN", "");
1152 NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
1153 if (U_SUCCESS(ec)) {
1154 expect2(*fmt, 1.0, CharsToUnicodeString("Rs.\\u00A01.00"));
1155 // Use .00392625 because that's 2^-8. Any value less than 0.005 is fine.
1156 expect(*fmt, 1.00390625, CharsToUnicodeString("Rs.\\u00A01.00")); // tricky
1157 expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
1158 expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
1159 expect2(*fmt, -1.0, CharsToUnicodeString("-Rs.\\u00A01.00"));
1160 expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
1161 } else {
1162 errln("FAIL: getCurrencyInstance(kn_IN)");
1163 }
1164 delete fmt;
1165}
1166
1167// -------------------------------------
1168
1169void
1170NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
1171{
1172 nf.setMaximumFractionDigits(maxFractionDigits);
1173 UnicodeString out; nf.format(x, out);
1174 logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
1175 if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
1176}
1177
1178/**
1179 * Upgrade to alphaWorks
1180 */
1181void NumberFormatTest::TestExponent(void) {
1182 UErrorCode status = U_ZERO_ERROR;
1183 DecimalFormatSymbols US(Locale::getUS(), status);
1184 CHECK(status, "DecimalFormatSymbols constructor");
1185 DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
1186 CHECK(status, "DecimalFormat(0.###E0)");
1187 DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
1188 CHECK(status, "DecimalFormat(0.###E+0)");
1189 int32_t n = 1234;
1190 expect2(fmt1, n, "1.234E3");
1191 expect2(fmt2, n, "1.234E+3");
1192 expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
1193}
1194
1195/**
1196 * Upgrade to alphaWorks
1197 */
1198void NumberFormatTest::TestScientific(void) {
1199 UErrorCode status = U_ZERO_ERROR;
1200 DecimalFormatSymbols US(Locale::getUS(), status);
1201 CHECK(status, "DecimalFormatSymbols constructor");
1202
1203 // Test pattern round-trip
1204 const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
1205 "0.###E0;[0.###E0]" };
1206 int32_t PAT_length = (int32_t)(sizeof(PAT) / sizeof(PAT[0]));
1207 int32_t DIGITS[] = {
1208 // min int, max int, min frac, max frac
1209 0, 1, 0, 0, // "#E0"
1210 1, 1, 0, 4, // "0.####E0"
1211 2, 2, 3, 3, // "00.000E00"
1212 1, 3, 0, 4, // "##0.####E000"
1213 1, 1, 0, 3, // "0.###E0;[0.###E0]"
1214 };
1215 for (int32_t i=0; i<PAT_length; ++i) {
1216 UnicodeString pat(PAT[i]);
1217 DecimalFormat df(pat, US, status);
1218 CHECK(status, "DecimalFormat constructor");
1219 UnicodeString pat2;
1220 df.toPattern(pat2);
1221 if (pat == pat2) {
1222 logln(UnicodeString("Ok Pattern rt \"") +
1223 pat + "\" -> \"" +
1224 pat2 + "\"");
1225 } else {
1226 errln(UnicodeString("FAIL Pattern rt \"") +
1227 pat + "\" -> \"" +
1228 pat2 + "\"");
1229 }
1230 // Make sure digit counts match what we expect
1231 if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
1232 df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
1233 df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
1234 df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
1235 errln(UnicodeString("FAIL \"" + pat +
1236 "\" min/max int; min/max frac = ") +
1237 df.getMinimumIntegerDigits() + "/" +
1238 df.getMaximumIntegerDigits() + ";" +
1239 df.getMinimumFractionDigits() + "/" +
1240 df.getMaximumFractionDigits() + ", expect " +
1241 DIGITS[4*i] + "/" +
1242 DIGITS[4*i+1] + ";" +
1243 DIGITS[4*i+2] + "/" +
1244 DIGITS[4*i+3]);
1245 }
1246 }
1247
1248
1249 // Test the constructor for default locale. We have to
1250 // manually set the default locale, as there is no
1251 // guarantee that the default locale has the same
1252 // scientific format.
1253 Locale def = Locale::getDefault();
1254 Locale::setDefault(Locale::getUS(), status);
1255 expect2(NumberFormat::createScientificInstance(status),
1256 12345.678901,
1257 "1.2345678901E4", status);
1258 Locale::setDefault(def, status);
1259
1260 expect2(new DecimalFormat("#E0", US, status),
1261 12345.0,
1262 "1.2345E4", status);
1263 expect(new DecimalFormat("0E0", US, status),
1264 12345.0,
1265 "1E4", status);
1266 expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
1267 12345.678901,
1268 "1.2345678901E4", status);
1269 expect(new DecimalFormat("##0.###E0", US, status),
1270 12345.0,
1271 "12.34E3", status);
1272 expect(new DecimalFormat("##0.###E0", US, status),
1273 12345.00001,
1274 "12.35E3", status);
1275 expect2(new DecimalFormat("##0.####E0", US, status),
1276 (int32_t) 12345,
1277 "12.345E3", status);
1278 expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
1279 12345.678901,
1280 "1,2345678901E4", status);
1281 expect(new DecimalFormat("##0.####E0", US, status),
1282 789.12345e-9,
1283 "789.12E-9", status);
1284 expect2(new DecimalFormat("##0.####E0", US, status),
1285 780.e-9,
1286 "780E-9", status);
1287 expect(new DecimalFormat(".###E0", US, status),
1288 45678.0,
1289 ".457E5", status);
1290 expect2(new DecimalFormat(".###E0", US, status),
1291 (int32_t) 0,
1292 ".0E0", status);
1293 /*
1294 expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
1295 new DecimalFormat("##E0", US),
1296 new DecimalFormat("####E0", US),
1297 new DecimalFormat("0E0", US),
1298 new DecimalFormat("00E0", US),
1299 new DecimalFormat("000E0", US),
1300 },
1301 new Long(45678000),
1302 new String[] { "4.5678E7",
1303 "45.678E6",
1304 "4567.8E4",
1305 "5E7",
1306 "46E6",
1307 "457E5",
1308 }
1309 );
1310 !
1311 ! Unroll this test into individual tests below...
1312 !
1313 */
1314 expect2(new DecimalFormat("#E0", US, status),
1315 (int32_t) 45678000, "4.5678E7", status);
1316 expect2(new DecimalFormat("##E0", US, status),
1317 (int32_t) 45678000, "45.678E6", status);
1318 expect2(new DecimalFormat("####E0", US, status),
1319 (int32_t) 45678000, "4567.8E4", status);
1320 expect(new DecimalFormat("0E0", US, status),
1321 (int32_t) 45678000, "5E7", status);
1322 expect(new DecimalFormat("00E0", US, status),
1323 (int32_t) 45678000, "46E6", status);
1324 expect(new DecimalFormat("000E0", US, status),
1325 (int32_t) 45678000, "457E5", status);
1326 /*
1327 expect(new DecimalFormat("###E0", US, status),
1328 new Object[] { new Double(0.0000123), "12.3E-6",
1329 new Double(0.000123), "123E-6",
1330 new Double(0.00123), "1.23E-3",
1331 new Double(0.0123), "12.3E-3",
1332 new Double(0.123), "123E-3",
1333 new Double(1.23), "1.23E0",
1334 new Double(12.3), "12.3E0",
1335 new Double(123), "123E0",
1336 new Double(1230), "1.23E3",
1337 });
1338 !
1339 ! Unroll this test into individual tests below...
1340 !
1341 */
1342 expect2(new DecimalFormat("###E0", US, status),
1343 0.0000123, "12.3E-6", status);
1344 expect2(new DecimalFormat("###E0", US, status),
1345 0.000123, "123E-6", status);
1346 expect2(new DecimalFormat("###E0", US, status),
1347 0.00123, "1.23E-3", status);
1348 expect2(new DecimalFormat("###E0", US, status),
1349 0.0123, "12.3E-3", status);
1350 expect2(new DecimalFormat("###E0", US, status),
1351 0.123, "123E-3", status);
1352 expect2(new DecimalFormat("###E0", US, status),
1353 1.23, "1.23E0", status);
1354 expect2(new DecimalFormat("###E0", US, status),
1355 12.3, "12.3E0", status);
1356 expect2(new DecimalFormat("###E0", US, status),
1357 123.0, "123E0", status);
1358 expect2(new DecimalFormat("###E0", US, status),
1359 1230.0, "1.23E3", status);
1360 /*
1361 expect(new DecimalFormat("0.#E+00", US, status),
1362 new Object[] { new Double(0.00012), "1.2E-04",
1363 new Long(12000), "1.2E+04",
1364 });
1365 !
1366 ! Unroll this test into individual tests below...
1367 !
1368 */
1369 expect2(new DecimalFormat("0.#E+00", US, status),
1370 0.00012, "1.2E-04", status);
1371 expect2(new DecimalFormat("0.#E+00", US, status),
1372 (int32_t) 12000, "1.2E+04", status);
1373}
1374
1375/**
1376 * Upgrade to alphaWorks
1377 */
1378void NumberFormatTest::TestPad(void) {
1379 UErrorCode status = U_ZERO_ERROR;
1380 DecimalFormatSymbols US(Locale::getUS(), status);
1381 CHECK(status, "DecimalFormatSymbols constructor");
1382
1383 expect2(new DecimalFormat("*^##.##", US, status),
1384 int32_t(0), "^^^^0", status);
1385 expect2(new DecimalFormat("*^##.##", US, status),
1386 -1.3, "^-1.3", status);
1387 expect2(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1388 int32_t(0), "0.0E0______ g-m/s^2", status);
1389 expect(new DecimalFormat("##0.0####E0*_ 'g-m/s^2'", US, status),
1390 1.0/3, "333.333E-3_ g-m/s^2", status);
1391 expect2(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1392 int32_t(0), "0.0______ g-m/s^2", status);
1393 expect(new DecimalFormat("##0.0####*_ 'g-m/s^2'", US, status),
1394 1.0/3, "0.33333__ g-m/s^2", status);
1395
1396 // Test padding before a sign
1397 const char *formatStr = "*x#,###,###,##0.0#;*x(###,###,##0.0#)";
1398 expect2(new DecimalFormat(formatStr, US, status),
1399 int32_t(-10), "xxxxxxxxxx(10.0)", status);
1400 expect2(new DecimalFormat(formatStr, US, status),
1401 int32_t(-1000),"xxxxxxx(1,000.0)", status);
1402 expect2(new DecimalFormat(formatStr, US, status),
1403 int32_t(-1000000),"xxx(1,000,000.0)", status);
1404 expect2(new DecimalFormat(formatStr, US, status),
1405 -100.37, "xxxxxxxx(100.37)", status);
1406 expect2(new DecimalFormat(formatStr, US, status),
1407 -10456.37, "xxxxx(10,456.37)", status);
1408 expect2(new DecimalFormat(formatStr, US, status),
1409 -1120456.37, "xx(1,120,456.37)", status);
1410 expect2(new DecimalFormat(formatStr, US, status),
1411 -112045600.37, "(112,045,600.37)", status);
1412 expect2(new DecimalFormat(formatStr, US, status),
1413 -1252045600.37,"(1,252,045,600.37)", status);
1414
1415 expect2(new DecimalFormat(formatStr, US, status),
1416 int32_t(10), "xxxxxxxxxxxx10.0", status);
1417 expect2(new DecimalFormat(formatStr, US, status),
1418 int32_t(1000),"xxxxxxxxx1,000.0", status);
1419 expect2(new DecimalFormat(formatStr, US, status),
1420 int32_t(1000000),"xxxxx1,000,000.0", status);
1421 expect2(new DecimalFormat(formatStr, US, status),
1422 100.37, "xxxxxxxxxx100.37", status);
1423 expect2(new DecimalFormat(formatStr, US, status),
1424 10456.37, "xxxxxxx10,456.37", status);
1425 expect2(new DecimalFormat(formatStr, US, status),
1426 1120456.37, "xxxx1,120,456.37", status);
1427 expect2(new DecimalFormat(formatStr, US, status),
1428 112045600.37, "xx112,045,600.37", status);
1429 expect2(new DecimalFormat(formatStr, US, status),
1430 10252045600.37,"10,252,045,600.37", status);
1431
1432
1433 // Test padding between a sign and a number
1434 const char *formatStr2 = "#,###,###,##0.0#*x;(###,###,##0.0#*x)";
1435 expect2(new DecimalFormat(formatStr2, US, status),
1436 int32_t(-10), "(10.0xxxxxxxxxx)", status);
1437 expect2(new DecimalFormat(formatStr2, US, status),
1438 int32_t(-1000),"(1,000.0xxxxxxx)", status);
1439 expect2(new DecimalFormat(formatStr2, US, status),
1440 int32_t(-1000000),"(1,000,000.0xxx)", status);
1441 expect2(new DecimalFormat(formatStr2, US, status),
1442 -100.37, "(100.37xxxxxxxx)", status);
1443 expect2(new DecimalFormat(formatStr2, US, status),
1444 -10456.37, "(10,456.37xxxxx)", status);
1445 expect2(new DecimalFormat(formatStr2, US, status),
1446 -1120456.37, "(1,120,456.37xx)", status);
1447 expect2(new DecimalFormat(formatStr2, US, status),
1448 -112045600.37, "(112,045,600.37)", status);
1449 expect2(new DecimalFormat(formatStr2, US, status),
1450 -1252045600.37,"(1,252,045,600.37)", status);
1451
1452 expect2(new DecimalFormat(formatStr2, US, status),
1453 int32_t(10), "10.0xxxxxxxxxxxx", status);
1454 expect2(new DecimalFormat(formatStr2, US, status),
1455 int32_t(1000),"1,000.0xxxxxxxxx", status);
1456 expect2(new DecimalFormat(formatStr2, US, status),
1457 int32_t(1000000),"1,000,000.0xxxxx", status);
1458 expect2(new DecimalFormat(formatStr2, US, status),
1459 100.37, "100.37xxxxxxxxxx", status);
1460 expect2(new DecimalFormat(formatStr2, US, status),
1461 10456.37, "10,456.37xxxxxxx", status);
1462 expect2(new DecimalFormat(formatStr2, US, status),
1463 1120456.37, "1,120,456.37xxxx", status);
1464 expect2(new DecimalFormat(formatStr2, US, status),
1465 112045600.37, "112,045,600.37xx", status);
1466 expect2(new DecimalFormat(formatStr2, US, status),
1467 10252045600.37,"10,252,045,600.37", status);
1468
1469 //testing the setPadCharacter(UnicodeString) and getPadCharacterString()
1470 DecimalFormat fmt("#", US, status);
1471 CHECK(status, "DecimalFormat constructor");
1472 UnicodeString padString("P");
1473 fmt.setPadCharacter(padString);
1474 expectPad(fmt, "*P##.##", DecimalFormat::kPadBeforePrefix, 5, padString);
1475 fmt.setPadCharacter((UnicodeString)"^");
1476 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, (UnicodeString)"^");
1477 //commented untill implementation is complete
1478 /* fmt.setPadCharacter((UnicodeString)"^^^");
1479 expectPad(fmt, "*^^^#", DecimalFormat::kPadBeforePrefix, 3, (UnicodeString)"^^^");
1480 padString.remove();
1481 padString.append((UChar)0x0061);
1482 padString.append((UChar)0x0302);
1483 fmt.setPadCharacter(padString);
1484 UChar patternChars[]={0x002a, 0x0061, 0x0302, 0x0061, 0x0302, 0x0023, 0x0000};
1485 UnicodeString pattern(patternChars);
1486 expectPad(fmt, pattern , DecimalFormat::kPadBeforePrefix, 4, padString);
1487 */
1488
1489}
1490
1491/**
1492 * Upgrade to alphaWorks
1493 */
1494void NumberFormatTest::TestPatterns2(void) {
1495 UErrorCode status = U_ZERO_ERROR;
1496 DecimalFormatSymbols US(Locale::getUS(), status);
1497 CHECK(status, "DecimalFormatSymbols constructor");
1498
1499 DecimalFormat fmt("#", US, status);
1500 CHECK(status, "DecimalFormat constructor");
1501
1502 UChar hat = 0x005E; /*^*/
1503
1504 expectPad(fmt, "*^#", DecimalFormat::kPadBeforePrefix, 1, hat);
1505 expectPad(fmt, "$*^#", DecimalFormat::kPadAfterPrefix, 2, hat);
1506 expectPad(fmt, "#*^", DecimalFormat::kPadBeforeSuffix, 1, hat);
1507 expectPad(fmt, "#$*^", DecimalFormat::kPadAfterSuffix, 2, hat);
1508 expectPad(fmt, "$*^$#", ILLEGAL);
1509 expectPad(fmt, "#$*^$", ILLEGAL);
1510 expectPad(fmt, "'pre'#,##0*x'post'", DecimalFormat::kPadBeforeSuffix,
1511 12, (UChar)0x0078 /*x*/);
1512 expectPad(fmt, "''#0*x", DecimalFormat::kPadBeforeSuffix,
1513 3, (UChar)0x0078 /*x*/);
1514 expectPad(fmt, "'I''ll'*a###.##", DecimalFormat::kPadAfterPrefix,
1515 10, (UChar)0x0061 /*a*/);
1516
1517 fmt.applyPattern("AA#,##0.00ZZ", status);
1518 CHECK(status, "applyPattern");
1519 fmt.setPadCharacter(hat);
1520
1521 fmt.setFormatWidth(10);
1522
1523 fmt.setPadPosition(DecimalFormat::kPadBeforePrefix);
1524 expectPat(fmt, "*^AA#,##0.00ZZ");
1525
1526 fmt.setPadPosition(DecimalFormat::kPadBeforeSuffix);
1527 expectPat(fmt, "AA#,##0.00*^ZZ");
1528
1529 fmt.setPadPosition(DecimalFormat::kPadAfterSuffix);
1530 expectPat(fmt, "AA#,##0.00ZZ*^");
1531
1532 // 12 3456789012
1533 UnicodeString exp("AA*^#,##0.00ZZ", "");
1534 fmt.setFormatWidth(12);
1535 fmt.setPadPosition(DecimalFormat::kPadAfterPrefix);
1536 expectPat(fmt, exp);
1537
1538 fmt.setFormatWidth(13);
1539 // 12 34567890123
1540 expectPat(fmt, "AA*^##,##0.00ZZ");
1541
1542 fmt.setFormatWidth(14);
1543 // 12 345678901234
1544 expectPat(fmt, "AA*^###,##0.00ZZ");
1545
1546 fmt.setFormatWidth(15);
1547 // 12 3456789012345
1548 expectPat(fmt, "AA*^####,##0.00ZZ"); // This is the interesting case
1549
1550 fmt.setFormatWidth(16);
1551 // 12 34567890123456
1552 expectPat(fmt, "AA*^#,###,##0.00ZZ");
1553}
1554
1555void NumberFormatTest::TestSurrogateSupport(void) {
1556 UErrorCode status = U_ZERO_ERROR;
1557 DecimalFormatSymbols custom(Locale::getUS(), status);
1558 CHECK(status, "DecimalFormatSymbols constructor");
1559
1560 custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
1561 custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
1562 custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
1563 custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");
1564
1565 UnicodeString patternStr("*\\U00010000##.##", "");
1566 patternStr = patternStr.unescape();
1567 UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
1568 expStr = expStr.unescape();
1569 expect2(new DecimalFormat(patternStr, custom, status),
1570 int32_t(0), expStr, status);
1571
1572 status = U_ZERO_ERROR;
1573 expect2(new DecimalFormat("*^##.##", custom, status),
1574 int32_t(0), "^^^^0", status);
1575 status = U_ZERO_ERROR;
1576 expect2(new DecimalFormat("##.##", custom, status),
1577 -1.3, " minus 1decimal3", status);
1578 status = U_ZERO_ERROR;
1579 expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1580 int32_t(0), "0decimal0exponent0 g-m/s^2", status);
1581 status = U_ZERO_ERROR;
1582 expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
1583 1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
1584 status = U_ZERO_ERROR;
1585 expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1586 int32_t(0), "0decimal0 g-m/s^2", status);
1587 status = U_ZERO_ERROR;
1588 expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
1589 1.0/3, "0decimal33333 g-m/s^2", status);
1590
1591 UnicodeString zero((UChar32)0x10000);
1592 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
1593 expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
1594 expStr = expStr.unescape();
1595 status = U_ZERO_ERROR;
1596 expect2(new DecimalFormat("##0.000", custom, status),
1597 1.25, expStr, status);
1598
1599 custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
1600 custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
1601 custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
1602 patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
1603 patternStr = patternStr.unescape();
1604 expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
1605 status = U_ZERO_ERROR;
1606 expect2(new DecimalFormat(patternStr, custom, status),
1607 int32_t(-20), expStr, status);
1608
1609 custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
1610 patternStr = "'You''ve lost ' -0.00 %' of your money today'";
1611 patternStr = patternStr.unescape();
1612 expStr = UnicodeString(" minus You've lost minus 2000decimal00 percent of your money today", "");
1613 status = U_ZERO_ERROR;
1614 expect2(new DecimalFormat(patternStr, custom, status),
1615 int32_t(-20), expStr, status);
1616}
1617
1618void NumberFormatTest::TestCurrencyPatterns(void) {
1619 int32_t i, locCount;
1620 const Locale* locs = NumberFormat::getAvailableLocales(locCount);
1621 for (i=0; i<locCount; ++i) {
1622 UErrorCode ec = U_ZERO_ERROR;
1623 NumberFormat* nf = NumberFormat::createCurrencyInstance(locs[i], ec);
1624 if (U_FAILURE(ec)) {
1625 errln("FAIL: Can't create NumberFormat(%s) - %s", locs[i].getName(), u_errorName(ec));
1626 } else {
1627 // Make sure currency formats do not have a variable number
1628 // of fraction digits
1629 int32_t min = nf->getMinimumFractionDigits();
1630 int32_t max = nf->getMaximumFractionDigits();
1631 if (min != max) {
1632 UnicodeString a, b;
1633 nf->format(1.0, a);
1634 nf->format(1.125, b);
1635 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1636 " min fraction digits != max fraction digits; "
1637 "x 1.0 => " + escape(a) +
1638 "; x 1.125 => " + escape(b));
1639 }
1640
1641 // Make sure EURO currency formats have exactly 2 fraction digits
1642 if (nf->getDynamicClassID() == DecimalFormat::getStaticClassID()) {
1643 DecimalFormat* df = (DecimalFormat*) nf;
1644 if (u_strcmp(EUR, df->getCurrency()) == 0) {
1645 if (min != 2 || max != 2) {
1646 UnicodeString a;
1647 nf->format(1.0, a);
1648 errln((UnicodeString)"FAIL: " + locs[i].getName() +
1649 " is a EURO format but it does not have 2 fraction digits; "
1650 "x 1.0 => " +
1651 escape(a));
1652 }
1653 }
1654 }
1655 }
1656 delete nf;
1657 }
1658}
1659
1660void NumberFormatTest::TestRegCurrency(void) {
1661#if !UCONFIG_NO_SERVICE
1662 UErrorCode status = U_ZERO_ERROR;
1663 UChar USD[4];
1664 ucurr_forLocale("en_US", USD, 4, &status);
1665 UChar YEN[4];
1666 ucurr_forLocale("ja_JP", YEN, 4, &status);
1667 UChar TMP[4];
1668 static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
1669 if(U_FAILURE(status)) {
1670 errln("Unable to get currency for locale, error %s", u_errorName(status));
1671 return;
1672 }
1673
1674 UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
1675 UCurrRegistryKey enUSEUROkey = ucurr_register(QQQ, "en_US_EURO", &status);
1676
1677 ucurr_forLocale("en_US", TMP, 4, &status);
1678 if (u_strcmp(YEN, TMP) != 0) {
1679 errln("FAIL: didn't return YEN registered for en_US");
1680 }
1681
1682 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1683 if (u_strcmp(QQQ, TMP) != 0) {
1684 errln("FAIL: didn't return QQQ for en_US_EURO");
1685 }
1686
1687 int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
1688 if (fallbackLen) {
1689 errln("FAIL: tried to fallback en_XX_BAR");
1690 }
1691 status = U_ZERO_ERROR; // reset
1692
1693 if (!ucurr_unregister(enkey, &status)) {
1694 errln("FAIL: couldn't unregister enkey");
1695 }
1696
1697 ucurr_forLocale("en_US", TMP, 4, &status);
1698 if (u_strcmp(USD, TMP) != 0) {
1699 errln("FAIL: didn't return USD for en_US after unregister of en_US");
1700 }
1701 status = U_ZERO_ERROR; // reset
1702
1703 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1704 if (u_strcmp(QQQ, TMP) != 0) {
1705 errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
1706 }
1707
1708 ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
1709 if (u_strcmp(USD, TMP) != 0) {
1710 errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
1711 }
1712 status = U_ZERO_ERROR; // reset
1713
1714 if (!ucurr_unregister(enUSEUROkey, &status)) {
1715 errln("FAIL: couldn't unregister enUSEUROkey");
1716 }
1717
1718 ucurr_forLocale("en_US_EURO", TMP, 4, &status);
1719 if (u_strcmp(EUR, TMP) != 0) {
1720 errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
1721 }
1722 status = U_ZERO_ERROR; // reset
1723#endif
1724}
1725
1726void NumberFormatTest::TestCurrencyNames(void) {
1727 // Do a basic check of getName()
1728 // USD { "US$", "US Dollar" } // 04/04/1792-
1729 UErrorCode ec = U_ZERO_ERROR;
1730 static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
1731 static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
1732 static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
1733 static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
1734 UBool isChoiceFormat;
1735 int32_t len;
1736 // Warning: HARD-CODED LOCALE DATA in this test. If it fails, CHECK
1737 // THE LOCALE DATA before diving into the code.
1738 assertEquals("USD.getName(SYMBOL_NAME)",
1739 UnicodeString("$"),
1740 UnicodeString(ucurr_getName(USD, "en",
1741 UCURR_SYMBOL_NAME,
1742 &isChoiceFormat, &len, &ec)));
1743 assertEquals("USD.getName(LONG_NAME)",
1744 UnicodeString("US Dollar"),
1745 UnicodeString(ucurr_getName(USD, "en",
1746 UCURR_LONG_NAME,
1747 &isChoiceFormat, &len, &ec)));
1748 assertEquals("CAD.getName(SYMBOL_NAME)",
1749 UnicodeString("CA$"),
1750 UnicodeString(ucurr_getName(CAD, "en",
1751 UCURR_SYMBOL_NAME,
1752 &isChoiceFormat, &len, &ec)));
1753 assertEquals("CAD.getName(SYMBOL_NAME)",
1754 UnicodeString("$"),
1755 UnicodeString(ucurr_getName(CAD, "en_CA",
1756 UCURR_SYMBOL_NAME,
1757 &isChoiceFormat, &len, &ec)));
1758 assertEquals("USD.getName(SYMBOL_NAME)",
1759 UnicodeString("US$"),
1760 UnicodeString(ucurr_getName(USD, "en_AU",
1761 UCURR_SYMBOL_NAME,
1762 &isChoiceFormat, &len, &ec)));
1763 assertEquals("CAD.getName(SYMBOL_NAME)",
1764 UnicodeString("CA$"),
1765 UnicodeString(ucurr_getName(CAD, "en_AU",
1766 UCURR_SYMBOL_NAME,
1767 &isChoiceFormat, &len, &ec)));
1768 assertEquals("USX.getName(LONG_NAME)",
1769 UnicodeString("USX"),
1770 UnicodeString(ucurr_getName(USX, "en_US",
1771 UCURR_LONG_NAME,
1772 &isChoiceFormat, &len, &ec)));
1773 assertSuccess("ucurr_getName", ec);
1774
1775 ec = U_ZERO_ERROR;
1776
1777 // Test that a default or fallback warning is being returned. JB 4239.
1778 ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
1779 &len, &ec);
1780 assertTrue("ucurr_getName (fallback)",
1781 U_USING_FALLBACK_WARNING == ec, TRUE);
1782
1783 ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
1784 &len, &ec);
1785 assertTrue("ucurr_getName (fallback)",
1786 U_USING_FALLBACK_WARNING == ec, TRUE);
1787
1788 ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
1789 &len, &ec);
1790 assertTrue("ucurr_getName (default)",
1791 U_USING_DEFAULT_WARNING == ec, TRUE);
1792
1793 ucurr_getName(CAD, "vi", UCURR_LONG_NAME, &isChoiceFormat,
1794 &len, &ec);
1795 assertTrue("ucurr_getName (default)",
1796 U_USING_DEFAULT_WARNING == ec, TRUE);
1797
1798 // Test that a default warning is being returned when falling back to root. JB 4536.
1799 ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
1800 &len, &ec);
1801 assertTrue("ucurr_getName (default to root)",
1802 U_USING_DEFAULT_WARNING == ec, TRUE);
1803
1804 // TODO add more tests later
1805}
1806
1807void NumberFormatTest::TestCurrencyUnit(void){
1808 UErrorCode ec = U_ZERO_ERROR;
1809 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
1810 CurrencyUnit cu(USD, ec);
1811 assertSuccess("CurrencyUnit", ec);
1812
1813 const UChar * r = cu.getISOCurrency(); // who is the buffer owner ?
1814 assertEquals("getISOCurrency()", USD, r);
1815
1816 CurrencyUnit cu2(cu);
1817 if (!(cu2 == cu)){
1818 errln("CurrencyUnit copy constructed object should be same");
1819 }
1820
1821 CurrencyUnit * cu3 = (CurrencyUnit *)cu.clone();
1822 if (!(*cu3 == cu)){
1823 errln("CurrencyUnit cloned object should be same");
1824 }
1825 delete cu3;
1826}
1827
1828void NumberFormatTest::TestCurrencyAmount(void){
1829 UErrorCode ec = U_ZERO_ERROR;
1830 static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
1831 CurrencyAmount ca(9, USD, ec);
1832 assertSuccess("CurrencyAmount", ec);
1833
1834 CurrencyAmount ca2(ca);
1835 if (!(ca2 == ca)){
1836 errln("CurrencyAmount copy constructed object should be same");
1837 }
1838
1839 ca2=ca;
1840 if (!(ca2 == ca)){
1841 errln("CurrencyAmount assigned object should be same");
1842 }
1843
1844 CurrencyAmount *ca3 = (CurrencyAmount *)ca.clone();
1845 if (!(*ca3 == ca)){
1846 errln("CurrencyAmount cloned object should be same");
1847 }
1848 delete ca3;
1849}
1850
1851void NumberFormatTest::TestSymbolsWithBadLocale(void) {
1852 Locale locDefault;
1853 Locale locBad("x-crazy_ZZ_MY_SPECIAL_ADMINISTRATION_REGION_NEEDS_A_SPECIAL_VARIANT_WITH_A_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_REALLY_LONG_NAME");
1854 UErrorCode status = U_ZERO_ERROR;
1855 UnicodeString intlCurrencySymbol((UChar)0xa4);
1856
1857 intlCurrencySymbol.append((UChar)0xa4);
1858
1859 logln("Current locale is %s", Locale::getDefault().getName());
1860 Locale::setDefault(locBad, status);
1861 logln("Current locale is %s", Locale::getDefault().getName());
1862 DecimalFormatSymbols mySymbols(status);
1863 if (status != U_USING_FALLBACK_WARNING) {
1864 errln("DecimalFormatSymbols should returned U_USING_FALLBACK_WARNING.");
1865 }
1866 if (strcmp(mySymbols.getLocale().getName(), locBad.getName()) != 0) {
1867 errln("DecimalFormatSymbols does not have the right locale.");
1868 }
1869 int symbolEnum = (int)DecimalFormatSymbols::kDecimalSeparatorSymbol;
1870 for (; symbolEnum < (int)DecimalFormatSymbols::kFormatSymbolCount; symbolEnum++) {
1871 logln(UnicodeString("DecimalFormatSymbols[") + symbolEnum + UnicodeString("] = ")
1872 + prettify(mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum)));
1873
1874 if (mySymbols.getSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbolEnum).length() == 0
1875 && symbolEnum != (int)DecimalFormatSymbols::kGroupingSeparatorSymbol
1876 && symbolEnum != (int)DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol)
1877 {
1878 errln("DecimalFormatSymbols has an empty string at index %d.", symbolEnum);
1879 }
1880 }
1881 status = U_ZERO_ERROR;
1882 Locale::setDefault(locDefault, status);
1883 logln("Current locale is %s", Locale::getDefault().getName());
1884}
1885
1886/**
1887 * Check that adoptDecimalFormatSymbols and setDecimalFormatSymbols
1888 * behave the same, except for memory ownership semantics. (No
1889 * version of this test on Java, since Java has only one method.)
1890 */
1891void NumberFormatTest::TestAdoptDecimalFormatSymbols(void) {
1892 UErrorCode ec = U_ZERO_ERROR;
1893 DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1894 if (U_FAILURE(ec)) {
1895 errln("Fail: DecimalFormatSymbols constructor");
1896 delete sym;
1897 return;
1898 }
1899 UnicodeString pat(" #,##0.00");
1900 pat.insert(0, (UChar)0x00A4);
1901 DecimalFormat fmt(pat, sym, ec);
1902 if (U_FAILURE(ec)) {
1903 errln("Fail: DecimalFormat constructor");
1904 return;
1905 }
1906
1907 UnicodeString str;
1908 fmt.format(2350.75, str);
1909 if (str == "$ 2,350.75") {
1910 logln(str);
1911 } else {
1912 errln("Fail: " + str + ", expected $ 2,350.75");
1913 }
1914
1915 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1916 if (U_FAILURE(ec)) {
1917 errln("Fail: DecimalFormatSymbols constructor");
1918 delete sym;
1919 return;
1920 }
1921 sym->setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1922 fmt.adoptDecimalFormatSymbols(sym);
1923
1924 str.truncate(0);
1925 fmt.format(2350.75, str);
1926 if (str == "Q 2,350.75") {
1927 logln(str);
1928 } else {
1929 errln("Fail: adoptDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1930 }
1931
1932 sym = new DecimalFormatSymbols(Locale::getUS(), ec);
1933 if (U_FAILURE(ec)) {
1934 errln("Fail: DecimalFormatSymbols constructor");
1935 delete sym;
1936 return;
1937 }
1938 DecimalFormat fmt2(pat, sym, ec);
1939 if (U_FAILURE(ec)) {
1940 errln("Fail: DecimalFormat constructor");
1941 return;
1942 }
1943
1944 DecimalFormatSymbols sym2(Locale::getUS(), ec);
1945 if (U_FAILURE(ec)) {
1946 errln("Fail: DecimalFormatSymbols constructor");
1947 return;
1948 }
1949 sym2.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "Q");
1950 fmt2.setDecimalFormatSymbols(sym2);
1951
1952 str.truncate(0);
1953 fmt2.format(2350.75, str);
1954 if (str == "Q 2,350.75") {
1955 logln(str);
1956 } else {
1957 errln("Fail: setDecimalFormatSymbols -> " + str + ", expected Q 2,350.75");
1958 }
1959}
1960
1961void NumberFormatTest::TestPerMill() {
1962 UErrorCode ec = U_ZERO_ERROR;
1963 UnicodeString str;
1964 DecimalFormat fmt(ctou("###.###\\u2030"), ec);
1965 if (!assertSuccess("DecimalFormat ct", ec)) return;
1966 assertEquals("0.4857 x ###.###\\u2030",
1967 ctou("485.7\\u2030"), fmt.format(0.4857, str));
1968
1969 DecimalFormatSymbols sym(Locale::getUS(), ec);
1970 sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
1971 DecimalFormat fmt2("", sym, ec);
1972 fmt2.applyLocalizedPattern("###.###m", ec);
1973 if (!assertSuccess("setup", ec)) return;
1974 str.truncate(0);
1975 assertEquals("0.4857 x ###.###m",
1976 "485.7m", fmt2.format(0.4857, str));
1977}
1978
1979/**
1980 * Generic test for patterns that should be legal/illegal.
1981 */
1982void NumberFormatTest::TestIllegalPatterns() {
1983 // Test cases:
1984 // Prefix with "-:" for illegal patterns
1985 // Prefix with "+:" for legal patterns
1986 const char* DATA[] = {
1987 // Unquoted special characters in the suffix are illegal
1988 "-:000.000|###",
1989 "+:000.000'|###'",
1990 0
1991 };
1992 for (int32_t i=0; DATA[i]; ++i) {
1993 const char* pat=DATA[i];
1994 UBool valid = (*pat) == '+';
1995 pat += 2;
1996 UErrorCode ec = U_ZERO_ERROR;
1997 DecimalFormat fmt(pat, ec); // locale doesn't matter here
1998 if (U_SUCCESS(ec) == valid) {
1999 logln("Ok: pattern \"%s\": %s",
2000 pat, u_errorName(ec));
2001 } else {
2002 errln("FAIL: pattern \"%s\" should have %s; got %s",
2003 pat, (valid?"succeeded":"failed"),
2004 u_errorName(ec));
2005 }
2006 }
2007}
2008
2009//----------------------------------------------------------------------
2010
2011static const char* KEYWORDS[] = {
2012 /*0*/ "ref=", // <reference pattern to parse numbers>
2013 /*1*/ "loc=", // <locale for formats>
2014 /*2*/ "f:", // <pattern or '-'> <number> <exp. string>
2015 /*3*/ "fp:", // <pattern or '-'> <number> <exp. string> <exp. number>
2016 /*4*/ "rt:", // <pattern or '-'> <(exp.) number> <(exp.) string>
2017 /*5*/ "p:", // <pattern or '-'> <string> <exp. number>
2018 /*6*/ "perr:", // <pattern or '-'> <invalid string>
2019 /*7*/ "pat:", // <pattern or '-'> <exp. toPattern or '-' or 'err'>
2020 /*8*/ "fpc:", // <pattern or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2021 0
2022};
2023
2024/**
2025 * Return an integer representing the next token from this
2026 * iterator. The integer will be an index into the given list, or
2027 * -1 if there are no more tokens, or -2 if the token is not on
2028 * the list.
2029 */
2030static int32_t keywordIndex(const UnicodeString& tok) {
2031 for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
2032 if (tok==KEYWORDS[i]) {
2033 return i;
2034 }
2035 }
2036 return -1;
2037}
2038
2039/**
2040 * Parse a CurrencyAmount using the given NumberFormat, with
2041 * the 'delim' character separating the number and the currency.
2042 */
2043static void parseCurrencyAmount(const UnicodeString& str,
2044 const NumberFormat& fmt,
2045 UChar delim,
2046 Formattable& result,
2047 UErrorCode& ec) {
2048 UnicodeString num, cur;
2049 int32_t i = str.indexOf(delim);
2050 str.extractBetween(0, i, num);
2051 str.extractBetween(i+1, INT32_MAX, cur);
2052 Formattable n;
2053 fmt.parse(num, n, ec);
2054 result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
2055}
2056
2057void NumberFormatTest::TestCases() {
2058 UErrorCode ec = U_ZERO_ERROR;
2059 TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
2060 if (U_FAILURE(ec)) {
2061 dataerrln("[DATA] Couldn't open NumberFormatTestCases.txt");
2062 return;
2063 }
2064 TokenIterator tokens(&reader);
2065
2066 Locale loc("en", "US", "");
2067 DecimalFormat *ref = 0, *fmt = 0;
2068 MeasureFormat *mfmt = 0;
2069 UnicodeString pat, tok, mloc, str, out, where, currAmt;
2070 Formattable n;
2071
2072 for (;;) {
2073 ec = U_ZERO_ERROR;
2074 if (!tokens.next(tok, ec)) {
2075 break;
2076 }
2077 where = UnicodeString("(") + tokens.getLineNumber() + ") ";
2078 int32_t cmd = keywordIndex(tok);
2079 switch (cmd) {
2080 case 0:
2081 // ref= <reference pattern>
2082 if (!tokens.next(tok, ec)) goto error;
2083 delete ref;
2084 ref = new DecimalFormat(tok,
2085 new DecimalFormatSymbols(Locale::getUS(), ec), ec);
2086 if (U_FAILURE(ec)) {
2087 dataerrln("Error constructing DecimalFormat");
2088 goto error;
2089 }
2090 break;
2091 case 1:
2092 // loc= <locale>
2093 if (!tokens.next(tok, ec)) goto error;
2094 loc = Locale::createFromName(CharString(tok));
2095 break;
2096 case 2: // f:
2097 case 3: // fp:
2098 case 4: // rt:
2099 case 5: // p:
2100 if (!tokens.next(tok, ec)) goto error;
2101 if (tok != "-") {
2102 pat = tok;
2103 delete fmt;
2104 fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
2105 if (U_FAILURE(ec)) {
2106 errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
2107 ec = U_ZERO_ERROR;
2108 if (!tokens.next(tok, ec)) goto error;
2109 if (!tokens.next(tok, ec)) goto error;
2110 if (cmd == 3) {
2111 if (!tokens.next(tok, ec)) goto error;
2112 }
2113 continue;
2114 }
2115 }
2116 if (cmd == 2 || cmd == 3 || cmd == 4) {
2117 // f: <pattern or '-'> <number> <exp. string>
2118 // fp: <pattern or '-'> <number> <exp. string> <exp. number>
2119 // rt: <pattern or '-'> <number> <string>
2120 UnicodeString num;
2121 if (!tokens.next(num, ec)) goto error;
2122 if (!tokens.next(str, ec)) goto error;
2123 ref->parse(num, n, ec);
2124 assertSuccess("parse", ec);
2125 assertEquals(where + "\"" + pat + "\".format(" + num + ")",
2126 str, fmt->format(n, out.remove(), ec));
2127 assertSuccess("format", ec);
2128 if (cmd == 3) { // fp:
2129 if (!tokens.next(num, ec)) goto error;
2130 ref->parse(num, n, ec);
2131 assertSuccess("parse", ec);
2132 }
2133 if (cmd != 2) { // != f:
2134 Formattable m;
2135 fmt->parse(str, m, ec);
2136 assertSuccess("parse", ec);
2137 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2138 n, m);
2139 }
2140 }
2141 // p: <pattern or '-'> <string to parse> <exp. number>
2142 else {
2143 UnicodeString expstr;
2144 if (!tokens.next(str, ec)) goto error;
2145 if (!tokens.next(expstr, ec)) goto error;
2146 Formattable exp, n;
2147 ref->parse(expstr, exp, ec);
2148 assertSuccess("parse", ec);
2149 fmt->parse(str, n, ec);
2150 assertSuccess("parse", ec);
2151 assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
2152 exp, n);
2153 }
2154 break;
2155 case 8: // fpc:
2156 if (!tokens.next(tok, ec)) goto error;
2157 if (tok != "-") {
2158 mloc = tok;
2159 delete mfmt;
2160 mfmt = MeasureFormat::createCurrencyFormat(
2161 Locale::createFromName(CharString(mloc)), ec);
2162 if (U_FAILURE(ec)) {
2163 errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
2164 ec = U_ZERO_ERROR;
2165 if (!tokens.next(tok, ec)) goto error;
2166 if (!tokens.next(tok, ec)) goto error;
2167 if (!tokens.next(tok, ec)) goto error;
2168 continue;
2169 }
2170 }
2171 // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
2172 if (!tokens.next(currAmt, ec)) goto error;
2173 if (!tokens.next(str, ec)) goto error;
2174 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2175 if (assertSuccess("parseCurrencyAmount", ec)) {
2176 assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
2177 str, mfmt->format(n, out.remove(), ec));
2178 assertSuccess("format", ec);
2179 }
2180 if (!tokens.next(currAmt, ec)) goto error;
2181 parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
2182 if (assertSuccess("parseCurrencyAmount", ec)) {
2183 Formattable m;
2184 mfmt->parseObject(str, m, ec);
2185 if (assertSuccess("parseCurrency", ec)) {
2186 assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
2187 n, m);
2188 }
2189 }
2190 break;
2191 case 6:
2192 // perr: <pattern or '-'> <invalid string>
2193 errln("FAIL: Under construction");
2194 goto done;
2195 case 7: {
2196 // pat: <pattern> <exp. toPattern, or '-' or 'err'>
2197 UnicodeString testpat;
2198 UnicodeString exppat;
2199 if (!tokens.next(testpat, ec)) goto error;
2200 if (!tokens.next(exppat, ec)) goto error;
2201 UBool err = exppat == "err";
2202 UBool existingPat = FALSE;
2203 if (testpat == "-") {
2204 if (err) {
2205 errln("FAIL: " + where + "Invalid command \"pat: - err\"");
2206 continue;
2207 }
2208 existingPat = TRUE;
2209 testpat = pat;
2210 }
2211 if (exppat == "-") exppat = testpat;
2212 DecimalFormat* f = 0;
2213 UErrorCode ec2 = U_ZERO_ERROR;
2214 if (existingPat) {
2215 f = fmt;
2216 } else {
2217 f = new DecimalFormat(testpat, ec2);
2218 }
2219 if (U_SUCCESS(ec2)) {
2220 if (err) {
2221 errln("FAIL: " + where + "Invalid pattern \"" + testpat +
2222 "\" was accepted");
2223 } else {
2224 UnicodeString pat2;
2225 assertEquals(where + "\"" + testpat + "\".toPattern()",
2226 exppat, f->toPattern(pat2));
2227 }
2228 } else {
2229 if (err) {
2230 logln("Ok: " + where + "Invalid pattern \"" + testpat +
2231 "\" failed: " + u_errorName(ec2));
2232 } else {
2233 errln("FAIL: " + where + "Valid pattern \"" + testpat +
2234 "\" failed: " + u_errorName(ec2));
2235 }
2236 }
2237 if (!existingPat) delete f;
2238 } break;
2239 case -1:
2240 errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
2241 goto done;
2242 }
2243 }
2244 goto done;
2245
2246 error:
2247 if (U_SUCCESS(ec)) {
2248 errln("FAIL: Unexpected EOF");
2249 } else {
2250 errln("FAIL: " + where + "Unexpected " + u_errorName(ec));
2251 }
2252
2253 done:
2254 delete mfmt;
2255 delete fmt;
2256 delete ref;
2257}
2258
2259
2260//----------------------------------------------------------------------
2261// Support methods
2262//----------------------------------------------------------------------
2263
2264UBool NumberFormatTest::equalValue(const Formattable& a, const Formattable& b) {
2265 if (a.getType() == b.getType()) {
2266 return a == b;
2267 }
2268
2269 if (a.getType() == Formattable::kLong) {
2270 if (b.getType() == Formattable::kInt64) {
2271 return a.getLong() == b.getLong();
2272 } else if (b.getType() == Formattable::kDouble) {
2273 return (double) a.getLong() == b.getDouble(); // TODO check use of double instead of long
2274 }
2275 } else if (a.getType() == Formattable::kDouble) {
2276 if (b.getType() == Formattable::kLong) {
2277 return a.getDouble() == (double) b.getLong();
2278 } else if (b.getType() == Formattable::kInt64) {
2279 return a.getDouble() == (double)b.getInt64();
2280 }
2281 } else if (a.getType() == Formattable::kInt64) {
2282 if (b.getType() == Formattable::kLong) {
2283 return a.getInt64() == (int64_t)b.getLong();
2284 } else if (b.getType() == Formattable::kDouble) {
2285 return a.getInt64() == (int64_t)b.getDouble();
2286 }
2287 }
2288 return FALSE;
2289}
2290
2291void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
2292 // Don't round-trip format test, since we explicitly do it
2293 expect(fmt, n, str, FALSE);
2294 expect(fmt, str, n);
2295}
2296
2297void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
2298 const UnicodeString& exp,
2299 UErrorCode status) {
2300 if (U_FAILURE(status)) {
2301 errln("FAIL: NumberFormat constructor");
2302 } else {
2303 expect2(*fmt, n, exp);
2304 }
2305 delete fmt;
2306}
2307
2308void NumberFormatTest::expect(NumberFormat& fmt, const UnicodeString& str, const Formattable& n) {
2309 UErrorCode status = U_ZERO_ERROR;
2310 Formattable num;
2311 fmt.parse(str, num, status);
2312 if (U_FAILURE(status)) {
2313 errln(UnicodeString("FAIL: Parse failed for \"") + str + "\"");
2314 return;
2315 }
2316 UnicodeString pat;
2317 ((DecimalFormat*) &fmt)->toPattern(pat);
2318 if (equalValue(num, n)) {
2319 logln(UnicodeString("Ok \"") + str + "\" x " +
2320 pat + " = " +
2321 toString(num));
2322 } else {
2323 errln(UnicodeString("FAIL \"") + str + "\" x " +
2324 pat + " = " +
2325 toString(num) + ", expected " + toString(n));
2326 }
2327}
2328
2329void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
2330 const UnicodeString& exp, UBool rt) {
2331 UnicodeString saw;
2332 FieldPosition pos;
2333 UErrorCode status = U_ZERO_ERROR;
2334 fmt.format(n, saw, pos, status);
2335 CHECK(status, "NumberFormat::format");
2336 UnicodeString pat;
2337 ((DecimalFormat*) &fmt)->toPattern(pat);
2338 if (saw == exp) {
2339 logln(UnicodeString("Ok ") + toString(n) + " x " +
2340 escape(pat) + " = \"" +
2341 escape(saw) + "\"");
2342 // We should be able to round-trip the formatted string =>
2343 // number => string (but not the other way around: number
2344 // => string => number2, might have number2 != number):
2345 if (rt) {
2346 Formattable n2;
2347 fmt.parse(exp, n2, status);
2348 if (U_FAILURE(status)) {
2349 errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
2350 return;
2351 }
2352 UnicodeString saw2;
2353 fmt.format(n2, saw2, pos, status);
2354 CHECK(status, "NumberFormat::format");
2355 if (saw2 != exp) {
2356 errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
2357 " => \"" + saw2 + "\"");
2358 }
2359 }
2360 } else {
2361 errln(UnicodeString("FAIL ") + toString(n) + " x " +
2362 escape(pat) + " = \"" +
2363 escape(saw) + "\", expected \"" + exp + "\"");
2364 }
2365}
2366
2367void NumberFormatTest::expect(NumberFormat* fmt, const Formattable& n,
2368 const UnicodeString& exp,
2369 UErrorCode status) {
2370 if (U_FAILURE(status)) {
2371 errln("FAIL: NumberFormat constructor");
2372 } else {
2373 expect(*fmt, n, exp);
2374 }
2375 delete fmt;
2376}
2377
2378void NumberFormatTest::expectCurrency(NumberFormat& nf, const Locale& locale,
2379 double value, const UnicodeString& string) {
2380 UErrorCode ec = U_ZERO_ERROR;
2381 DecimalFormat& fmt = * (DecimalFormat*) &nf;
2382 const UChar DEFAULT_CURR[] = {45/*-*/,0};
2383 UChar curr[4];
2384 u_strcpy(curr, DEFAULT_CURR);
2385 if (*locale.getLanguage() != 0) {
2386 ucurr_forLocale(locale.getName(), curr, 4, &ec);
2387 assertSuccess("ucurr_forLocale", ec);
2388 fmt.setCurrency(curr, ec);
2389 assertSuccess("DecimalFormat::setCurrency", ec);
2390 fmt.setCurrency(curr); //Deprecated variant, for coverage only
2391 }
2392 UnicodeString s;
2393 fmt.format(value, s);
2394 s.findAndReplace((UChar32)0x00A0, (UChar32)0x0020);
2395
2396 // Default display of the number yields "1234.5599999999999"
2397 // instead of "1234.56". Use a formatter to fix this.
2398 NumberFormat* f =
2399 NumberFormat::createInstance(Locale::getUS(), ec);
2400 UnicodeString v;
2401 if (U_FAILURE(ec)) {
2402 // Oops; bad formatter. Use default op+= display.
2403 v = (UnicodeString)"" + value;
2404 } else {
2405 f->setMaximumFractionDigits(4);
2406 f->setGroupingUsed(FALSE);
2407 f->format(value, v);
2408 }
2409 delete f;
2410
2411 if (s == string) {
2412 logln((UnicodeString)"Ok: " + v + " x " + curr + " => " + prettify(s));
2413 } else {
2414 errln((UnicodeString)"FAIL: " + v + " x " + curr + " => " + prettify(s) +
2415 ", expected " + prettify(string));
2416 }
2417}
2418
2419void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
2420 UnicodeString pat;
2421 fmt.toPattern(pat);
2422 if (pat == exp) {
2423 logln(UnicodeString("Ok \"") + pat + "\"");
2424 } else {
2425 errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
2426 }
2427}
2428
2429void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2430 int32_t pos) {
2431 expectPad(fmt, pat, pos, 0, (UnicodeString)"");
2432}
2433void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2434 int32_t pos, int32_t width, UChar pad) {
2435 expectPad(fmt, pat, pos, width, UnicodeString(pad));
2436}
2437void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
2438 int32_t pos, int32_t width, const UnicodeString& pad) {
2439 int32_t apos = 0, awidth = 0;
2440 UnicodeString apadStr;
2441 UErrorCode status = U_ZERO_ERROR;
2442 fmt.applyPattern(pat, status);
2443 if (U_SUCCESS(status)) {
2444 apos = fmt.getPadPosition();
2445 awidth = fmt.getFormatWidth();
2446 apadStr=fmt.getPadCharacterString();
2447 } else {
2448 apos = -1;
2449 awidth = width;
2450 apadStr = pad;
2451 }
2452 if (apos == pos && awidth == width && apadStr == pad) {
2453 UnicodeString infoStr;
2454 if (pos == ILLEGAL) {
2455 infoStr = UnicodeString(" width=", "") + awidth + UnicodeString(" pad=", "") + apadStr;
2456 }
2457 logln(UnicodeString("Ok \"") + pat + "\" pos=" + apos + infoStr);
2458 } else {
2459 errln(UnicodeString("FAIL \"") + pat + "\" pos=" + apos +
2460 " width=" + awidth + " pad=" + apadStr +
2461 ", expected " + pos + " " + width + " " + pad);
2462 }
2463}
2464void NumberFormatTest::TestJB3832(){
2465 const char* localeID = "pt_PT@currency=PTE";
2466 Locale loc(localeID);
2467 UErrorCode status = U_ZERO_ERROR;
2468 UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0Esc."));
2469 UnicodeString s;
2470 NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
2471 if(U_FAILURE(status)){
2472 errln("Could not create currency formatter for locale %s", localeID);
2473 return;
2474 }
2475 currencyFmt->format(1150.50, s);
2476 if(s!=expected){
2477 errln(UnicodeString("FAIL: Expected: ")+expected
2478 + UnicodeString(" Got: ") + s
2479 + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
2480 }
2481 if (U_FAILURE(status)){
2482 errln("FAIL: Status %s", u_errorName(status));
2483 }
2484 delete currencyFmt;
2485}
2486
2487void NumberFormatTest::TestHost()
2488{
2489#ifdef U_WINDOWS
2490 Win32NumberTest::testLocales(this);
2491#endif
2492}
2493
2494void NumberFormatTest::TestHostClone()
2495{
2496 /*
2497 Verify that a cloned formatter gives the same results
2498 and is useable after the original has been deleted.
2499 */
2500 // This is mainly important on Windows.
2501 UErrorCode status = U_ZERO_ERROR;
2502 Locale loc("en_US@compat=host");
2503 UDate now = Calendar::getNow();
2504 NumberFormat *full = NumberFormat::createInstance(loc, status);
2505 if (full == NULL || U_FAILURE(status)) {
2506 errln("FAIL: Can't create Relative date instance");
2507 return;
2508 }
2509 UnicodeString result1;
2510 full->format(now, result1, status);
2511 Format *fullClone = full->clone();
2512 delete full;
2513 full = NULL;
2514
2515 UnicodeString result2;
2516 fullClone->format(now, result2, status);
2517 if (U_FAILURE(status)) {
2518 errln("FAIL: format failure.");
2519 }
2520 if (result1 != result2) {
2521 errln("FAIL: Clone returned different result from non-clone.");
2522 }
2523 delete fullClone;
2524}
2525
2526void NumberFormatTest::TestCurrencyFormat()
2527{
2528 // This test is here to increase code coverage.
2529 UErrorCode status = U_ZERO_ERROR;
2530 MeasureFormat *cloneObj;
2531 UnicodeString str;
2532 Formattable toFormat, result;
2533 static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};
2534
2535 Locale saveDefaultLocale = Locale::getDefault();
2536 Locale::setDefault( Locale::getUK(), status );
2537 if (U_FAILURE(status)) {
2538 errln("couldn't set default Locale!");
2539 return;
2540 }
2541
2542 MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
2543 Locale::setDefault( saveDefaultLocale, status );
2544 if (U_FAILURE(status)){
2545 errln("FAIL: Status %s", u_errorName(status));
2546 return;
2547 }
2548 cloneObj = (MeasureFormat *)measureObj->clone();
2549 if (cloneObj == NULL) {
2550 errln("Clone doesn't work");
2551 return;
2552 }
2553 toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
2554 measureObj->format(toFormat, str, status);
2555 measureObj->parseObject(str, result, status);
2556 if (U_FAILURE(status)){
2557 errln("FAIL: Status %s", u_errorName(status));
2558 }
2559 if (result != toFormat) {
2560 errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
2561 }
2562 status = U_ZERO_ERROR;
2563 str.truncate(0);
2564 cloneObj->format(toFormat, str, status);
2565 cloneObj->parseObject(str, result, status);
2566 if (U_FAILURE(status)){
2567 errln("FAIL: Status %s", u_errorName(status));
2568 }
2569 if (result != toFormat) {
2570 errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
2571 }
2572 if (*measureObj != *cloneObj) {
2573 errln("Cloned object is not equal to the original object");
2574 }
2575 delete measureObj;
2576 delete cloneObj;
2577
2578 status = U_USELESS_COLLATOR_ERROR;
2579 if (MeasureFormat::createCurrencyFormat(status) != NULL) {
2580 errln("createCurrencyFormat should have returned NULL.");
2581 }
2582}
2583
2584/* Port of ICU4J rounding test. */
2585void NumberFormatTest::TestRounding() {
2586 UErrorCode status = U_ZERO_ERROR;
2587 DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
2588
2589 if (U_FAILURE(status)) {
2590 errln("Unable to create decimal formatter.");
2591 return;
2592 }
2593
2594 int roundingIncrements[]={1, 2, 5, 20, 50, 100};
2595 int testValues[]={0, 300};
2596
2597 for (int j=0; j<2; j++) {
2598 for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
2599 df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
2600 for (int increment=0; increment<6; increment++) {
2601 double base=testValues[j];
2602 double rInc=roundingIncrements[increment];
2603 checkRounding(df, base, 20, rInc);
2604 rInc=1.000000000/rInc;
2605 checkRounding(df, base, 20, rInc);
2606 }
2607 }
2608 }
2609 delete df;
2610}
2611
2612void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
2613 df->setRoundingIncrement(increment);
2614 double lastParsed=INT32_MIN; //Intger.MIN_VALUE
2615 for (int i=-iterations; i<=iterations;i++) {
2616 double iValue=base+(increment*(i*0.1));
2617 double smallIncrement=0.00000001;
2618 if (iValue!=0) {
2619 smallIncrement*=iValue;
2620 }
2621 //we not only test the value, but some values in a small range around it
2622 lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
2623 lastParsed=checkRound(df, iValue, lastParsed);
2624 lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
2625 }
2626}
2627
2628double NumberFormatTest::checkRound(DecimalFormat* df, double iValue, double lastParsed) {
2629 UErrorCode status=U_ZERO_ERROR;
2630 UnicodeString formattedDecimal;
2631 double parsed;
2632 Formattable result;
2633 df->format(iValue, formattedDecimal, status);
2634
2635 if (U_FAILURE(status)) {
2636 errln("Error formatting number.");
2637 }
2638
2639 df->parse(formattedDecimal, result, status);
2640
2641 if (U_FAILURE(status)) {
2642 errln("Error parsing number.");
2643 }
2644
2645 parsed=result.getDouble();
2646
2647 if (lastParsed>parsed) {
2648 errln("Rounding wrong direction! %d > %d", lastParsed, parsed);
2649 }
2650
2651 return lastParsed;
2652}
2653
2654void NumberFormatTest::TestNonpositiveMultiplier() {
2655 UErrorCode status = U_ZERO_ERROR;
2656 DecimalFormatSymbols US(Locale::getUS(), status);
2657 CHECK(status, "DecimalFormatSymbols constructor");
2658 DecimalFormat df(UnicodeString("0"), US, status);
2659 CHECK(status, "DecimalFormat(0)");
2660
2661 // test zero multiplier
2662
2663 int32_t mult = df.getMultiplier();
2664 df.setMultiplier(0);
2665 if (df.getMultiplier() != mult) {
2666 errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
2667 }
2668
2669 // test negative multiplier
2670
2671 df.setMultiplier(-1);
2672 if (df.getMultiplier() != -1) {
2673 errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
2674 return;
2675 }
2676
2677 expect(df, "1122.123", -1122.123);
2678 expect(df, "-1122.123", 1122.123);
2679 expect(df, "1.2", -1.2);
2680 expect(df, "-1.2", 1.2);
2681
2682 // TODO: change all the following int64_t tests once BigInteger is ported
2683 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2684 static const char* posOutOfRange = "9223372036854780000";
2685 static const char* negOutOfRange = "-9223372036854780000";
2686
2687 expect(df, U_INT64_MIN, posOutOfRange);
2688 expect(df, U_INT64_MIN+1, "9223372036854775807");
2689 expect(df, (int64_t)-123, "123");
2690 expect(df, (int64_t)123, "-123");
2691 expect(df, U_INT64_MAX-1, "-9223372036854775806");
2692 expect(df, U_INT64_MAX, "-9223372036854775807");
2693
2694 df.setMultiplier(-2);
2695 expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
2696 expect(df, -(U_INT64_MIN/2), "-9223372036854775808");
2697 expect(df, -(U_INT64_MIN/2)+1, negOutOfRange);
2698
2699 df.setMultiplier(-7);
2700 expect(df, -(U_INT64_MAX/7)-1, posOutOfRange);
2701 expect(df, -(U_INT64_MAX/7), "9223372036854775807");
2702 expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");
2703
2704 // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
2705 // (right now the big numbers get turned into doubles and lose tons of accuracy)
2706 //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
2707 //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
2708 //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
2709 //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));
2710
2711 // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
2712 //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2713 //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2714 //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
2715 //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
2716}
2717
2718void
2719NumberFormatTest::TestSpaceParsing() {
2720 // the data are:
2721 // the string to be parsed, parsed position, parsed error index
2722 const char* DATA[][3] = {
2723 {"$124", "4", "-1"},
2724 {"$124 $124", "4", "-1"},
2725 {"$124 ", "4", "-1"},
2726 {"$ 124 ", "5", "-1"},
2727 {"$\\u00A0124 ", "5", "-1"},
2728 {" $ 124 ", "6", "-1"},
2729 //{"124$", "4", "-1"}, // TODO: need to handle trailing currency correctly
2730 {"124$", "3", "-1"},
2731 //{"124 $", "5", "-1"}, // TODO: OK or not, need currency spacing rule
2732 {"124 $", "3", "-1"},
2733 };
2734
2735 UErrorCode status = U_ZERO_ERROR;
2736 Locale locale("en_US");
2737 NumberFormat* foo = NumberFormat::createCurrencyInstance(locale, status);
2738 if (U_FAILURE(status)) {
2739 delete foo;
2740 return;
2741 }
2742
2743 foo->setParseStrict(FALSE);
2744 for (uint32_t i = 0; i < sizeof(DATA)/sizeof(DATA[0]); ++i) {
2745 ParsePosition parsePosition(0);
2746 UnicodeString stringToBeParsed = ctou(DATA[i][0]);
2747 int parsedPosition = atoi(DATA[i][1]);
2748 int errorIndex = atoi(DATA[i][2]);
2749 Formattable result;
2750 foo->parse(stringToBeParsed, result, parsePosition);
2751 if (parsePosition.getIndex() != parsedPosition ||
2752 parsePosition.getErrorIndex() != errorIndex) {
2753 errln("FAILED parse " + stringToBeParsed + "; wrong position, expected: (" + parsedPosition + ", " + errorIndex + "); got (" + parsePosition.getIndex() + ", " + parsePosition.getErrorIndex() + ")");
2754 }
2755 if (parsePosition.getErrorIndex() == -1 &&
2756 result.getType() == Formattable::kLong &&
2757 result.getLong() != 124) {
2758 errln("FAILED parse " + stringToBeParsed + "; wrong number, expect: 124, got " + result.getLong());
2759 }
2760 }
2761 delete foo;
2762}
2763
2764#endif /* #if !UCONFIG_NO_FORMATTING */