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