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