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