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