]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tsnmfmt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2012, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ***********************************************************************/
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
11 #include "unicode/decimfmt.h"
18 IntlTestNumberFormat::~IntlTestNumberFormat() {}
20 static const char * formattableTypeName(Formattable::Type t
)
23 case Formattable::kDate
: return "kDate";
24 case Formattable::kDouble
: return "kDouble";
25 case Formattable::kLong
: return "kLong";
26 case Formattable::kString
: return "kString";
27 case Formattable::kArray
: return "kArray";
28 case Formattable::kInt64
: return "kInt64";
29 default: return "??unknown??";
34 * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
37 void IntlTestNumberFormat::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
40 if (exec
) logln((UnicodeString
)"TestSuite NumberFormat");
42 case 0: name
= "createInstance";
46 fStatus
= U_ZERO_ERROR
;
47 fFormat
= NumberFormat::createInstance(fStatus
);
52 case 1: name
= "DefaultLocale";
53 if (exec
) testLocale(/*par, */Locale::getDefault(), name
);
56 case 2: name
= "testAvailableLocales";
59 testAvailableLocales(/*par*/);
63 case 3: name
= "monsterTest";
70 default: name
= ""; break;
75 IntlTestNumberFormat::testLocale(/* char* par, */const Locale
& locale
, const UnicodeString
& localeName
)
81 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
82 fStatus
= U_ZERO_ERROR
;
83 fFormat
= NumberFormat::createInstance(locale
, fStatus
);
84 testFormat(/* par */);
86 name
= "Currency test";
87 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
88 fStatus
= U_ZERO_ERROR
;
89 fFormat
= NumberFormat::createCurrencyInstance(locale
, fStatus
);
90 testFormat(/* par */);
92 name
= "Percent test";
93 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
94 fStatus
= U_ZERO_ERROR
;
95 fFormat
= NumberFormat::createPercentInstance(locale
, fStatus
);
96 testFormat(/* par */);
98 if (uprv_strcmp(locale
.getName(), "en_US_POSIX") != 0) {
99 name
= "Scientific test";
100 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
101 fStatus
= U_ZERO_ERROR
;
102 fFormat
= NumberFormat::createScientificInstance(locale
, fStatus
);
103 testFormat(/* par */);
107 double IntlTestNumberFormat::randDouble()
109 // Assume 8-bit (or larger) rand values. Also assume
110 // that the system rand() function is very poor, which it always is.
111 // Call srand(currentTime) in intltest to make it truly random.
114 char* poke
= (char*)&d
;
116 for (i
=0; i
< sizeof(double); ++i
)
118 poke
[i
] = (char)(rand() & 0xFF);
120 } while (uprv_isNaN(d
) || uprv_isInfinite(d
)
121 || !((-DBL_MAX
< d
&& d
< DBL_MAX
) || (d
< -DBL_MIN
&& DBL_MIN
< d
)));
127 * Return a random uint32_t
129 uint32_t IntlTestNumberFormat::randLong()
131 // Assume 8-bit (or larger) rand values. Also assume
132 // that the system rand() function is very poor, which it always is.
133 // Call srand(currentTime) in intltest to make it truly random.
136 char* poke
= (char*)&d
;
137 for (i
=0; i
< sizeof(uint32_t); ++i
)
139 poke
[i
] = (char)(rand() & 0xFF);
145 /* Make sure that we don't get something too large and multiply into infinity.
146 @param smallerThanMax the requested maximum value smaller than DBL_MAX */
147 double IntlTestNumberFormat::getSafeDouble(double smallerThanMax
) {
149 double high
= (DBL_MAX
/smallerThanMax
)/10.0;
153 } while (low
> it
|| it
> high
);
158 IntlTestNumberFormat::testFormat(/* char* par */)
160 if (U_FAILURE(fStatus
))
162 dataerrln((UnicodeString
)"**** FAIL: createXxxInstance failed. - " + u_errorName(fStatus
));
164 errln("**** FAIL: Non-null format returned by createXxxInstance upon failure.");
172 errln((UnicodeString
)"**** FAIL: Null format returned by createXxxInstance.");
178 // Assume it's a DecimalFormat and get some info
179 DecimalFormat
*s
= (DecimalFormat
*)fFormat
;
180 logln((UnicodeString
)" Pattern " + s
->toPattern(str
));
182 #if U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400
183 tryIt(-2.02147304840132e-68);
184 tryIt(3.88057859588817e-68); // Test rounding when only some digits are shown because exponent is close to -maxfrac
185 tryIt(-2.64651110485945e+65); // Overflows to +INF when shown as a percent
186 tryIt(9.29526819488338e+64); // Ok -- used to fail?
188 tryIt(-2.02147304840132e-100);
189 tryIt(3.88057859588817e-096); // Test rounding when only some digits are shown because exponent is close to -maxfrac
190 tryIt(-2.64651110485945e+306); // Overflows to +INF when shown as a percent
191 tryIt(9.29526819488338e+250); // Ok -- used to fail?
194 // These PASS now, with the sprintf/atof based format-parse.
196 // These fail due to round-off
197 // The least significant digit drops by one during each format-parse cycle.
198 // Both numbers DON'T have a round-off problem when multiplied by 100! (shown as %)
199 #if U_PLATFORM == U_PF_OS390
200 tryIt(-9.18228054496402e+64);
201 tryIt(-9.69413034454191e+64);
203 tryIt(-9.18228054496402e+255);
204 tryIt(-9.69413034454191e+273);
207 #if U_PLATFORM != U_PF_OS390
211 tryIt(uprv_getNaN());
212 tryIt(uprv_getInfinity());
213 tryIt(-uprv_getInfinity());
216 tryIt((int32_t)251887531);
220 tryIt(9.99999999999996);
221 tryIt(9.999999999999996);
225 tryIt((int32_t)INT32_MIN
);
226 tryIt((int32_t)INT32_MAX
);
227 tryIt((double)INT32_MIN
);
228 tryIt((double)INT32_MAX
);
229 tryIt((double)INT32_MIN
- 1.0);
230 tryIt((double)INT32_MAX
+ 1.0);
232 tryIt(5.0 / 9.0 * 1e-20);
233 tryIt(4.0 / 9.0 * 1e-20);
234 tryIt(5.0 / 9.0 * 1e+20);
235 tryIt(4.0 / 9.0 * 1e+20);
245 tryIt((int32_t)-100);
246 tryIt((int32_t)-1913860352);
248 for (int32_t z
=0; z
<10; ++z
)
250 double d
= randFraction() * 2e10
- 1e10
;
254 double it
= getSafeDouble(100000.0);
259 tryIt(uprv_floor(it
));
260 tryIt((int32_t)randLong());
263 it
= getSafeDouble(100.0);
265 tryIt(uprv_floor(it
));
266 tryIt((int32_t)randLong());
268 // try again with very large numbers
269 it
= getSafeDouble(100000000000.0);
272 // try again with very large numbers
273 // and without going outside of the int32_t range
274 it
= randFraction() * INT32_MAX
;
276 tryIt((int32_t)uprv_floor(it
));
282 IntlTestNumberFormat::tryIt(double aNumber
)
284 const int32_t DEPTH
= 10;
285 Formattable number
[DEPTH
];
286 UnicodeString string
[DEPTH
];
288 int32_t numberMatch
= 0;
289 int32_t stringMatch
= 0;
290 UnicodeString errMsg
;
292 for (i
=0; i
<DEPTH
; ++i
)
294 errMsg
.truncate(0); // if non-empty, we failed this iteration
295 UErrorCode status
= U_ZERO_ERROR
;
296 string
[i
] = "(n/a)"; // "format was never done" value
298 number
[i
].setDouble(aNumber
);
300 fFormat
->parse(string
[i
-1], number
[i
], status
);
301 if (U_FAILURE(status
)) {
302 number
[i
].setDouble(1234.5); // "parse failed" value
303 errMsg
= "**** FAIL: Parse of " + prettify(string
[i
-1]) + " failed.";
304 --i
; // don't show empty last line: "1234.5 F> (n/a) P>"
308 // Convert from long to double
309 if (number
[i
].getType() == Formattable::kLong
)
310 number
[i
].setDouble(number
[i
].getLong());
311 else if (number
[i
].getType() == Formattable::kInt64
)
312 number
[i
].setDouble((double)number
[i
].getInt64());
313 else if (number
[i
].getType() != Formattable::kDouble
)
315 errMsg
= ("**** FAIL: Parse of " + prettify(string
[i
-1])
316 + " returned non-numeric Formattable, type " + UnicodeString(formattableTypeName(number
[i
].getType()))
317 + ", Locale=" + UnicodeString(fLocale
.getName())
318 + ", longValue=" + number
[i
].getLong());
321 string
[i
].truncate(0);
322 fFormat
->format(number
[i
].getDouble(), string
[i
]);
325 if (numberMatch
== 0 && number
[i
] == number
[i
-1])
327 else if (numberMatch
> 0 && number
[i
] != number
[i
-1])
329 errMsg
= ("**** FAIL: Numeric mismatch after match.");
332 if (stringMatch
== 0 && string
[i
] == string
[i
-1])
334 else if (stringMatch
> 0 && string
[i
] != string
[i
-1])
336 errMsg
= ("**** FAIL: String mismatch after match.");
340 if (numberMatch
> 0 && stringMatch
> 0)
346 if (stringMatch
> 2 || numberMatch
> 2)
348 errMsg
= ("**** FAIL: No string and/or number match within 2 iterations.");
351 if (errMsg
.length() != 0)
353 for (int32_t k
=0; k
<=i
; ++k
)
355 logln((UnicodeString
)"" + k
+ ": " + number
[k
].getDouble() + " F> " +
356 prettify(string
[k
]) + " P> ");
363 IntlTestNumberFormat::tryIt(int32_t aNumber
)
365 Formattable
number(aNumber
);
366 UnicodeString stringNum
;
367 UErrorCode status
= U_ZERO_ERROR
;
369 fFormat
->format(number
, stringNum
, status
);
370 if (U_FAILURE(status
))
372 errln(UnicodeString("**** FAIL: Formatting ") + aNumber
);
375 fFormat
->parse(stringNum
, number
, status
);
376 if (U_FAILURE(status
))
378 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed.");
381 if (number
.getType() != Formattable::kLong
)
383 errln("**** FAIL: Parse of " + prettify(stringNum
)
384 + " returned non-long Formattable, type " + UnicodeString(formattableTypeName(number
.getType()))
385 + ", Locale=" + UnicodeString(fLocale
.getName())
386 + ", doubleValue=" + number
.getDouble()
387 + ", longValue=" + number
.getLong()
388 + ", origValue=" + aNumber
391 if (number
.getLong() != aNumber
) {
392 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed. Got:" + number
.getLong()
393 + " Expected:" + aNumber
);
397 void IntlTestNumberFormat::testAvailableLocales(/* char* par */)
400 const Locale
* locales
= NumberFormat::getAvailableLocales(count
);
401 logln((UnicodeString
)"" + count
+ " available locales");
402 if (locales
&& count
)
406 for (int32_t i
=0; i
<count
; ++i
)
410 all
+= locales
[i
].getName();
415 dataerrln((UnicodeString
)"**** FAIL: Zero available locales or null array pointer");
418 void IntlTestNumberFormat::monsterTest(/* char* par */)
420 const char *SEP
= "============================================================\n";
422 const Locale
* allLocales
= NumberFormat::getAvailableLocales(count
);
423 Locale
* locales
= (Locale
*)allLocales
;
424 Locale quickLocales
[6];
425 if (allLocales
&& count
)
427 if (quick
&& count
> 6) {
428 logln("quick test: testing just 6 locales!");
430 locales
= quickLocales
;
431 locales
[0] = allLocales
[0];
432 locales
[1] = allLocales
[1];
433 locales
[2] = allLocales
[2];
434 // In a quick test, make sure we test locales that use
435 // currency prefix, currency suffix, and choice currency
436 // logic. Otherwise bugs in these areas can slip through.
437 locales
[3] = Locale("ar", "AE", "");
438 locales
[4] = Locale("cs", "CZ", "");
439 locales
[5] = Locale("en", "IN", "");
441 for (int32_t i
=0; i
<count
; ++i
)
443 UnicodeString
name(locales
[i
].getName(), "");
445 testLocale(/* par, */locales
[i
], name
);
452 #endif /* #if !UCONFIG_NO_FORMATTING */