]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tsnmfmt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2009, 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"
17 IntlTestNumberFormat::~IntlTestNumberFormat() {}
19 static const char * formattableTypeName(Formattable::Type t
)
22 case Formattable::kDate
: return "kDate";
23 case Formattable::kDouble
: return "kDouble";
24 case Formattable::kLong
: return "kLong";
25 case Formattable::kString
: return "kString";
26 case Formattable::kArray
: return "kArray";
27 case Formattable::kInt64
: return "kInt64";
28 default: return "??unknown??";
33 * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
36 void IntlTestNumberFormat::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
39 if (exec
) logln((UnicodeString
)"TestSuite NumberFormat");
41 case 0: name
= "createInstance";
45 fStatus
= U_ZERO_ERROR
;
46 fFormat
= NumberFormat::createInstance(fStatus
);
51 case 1: name
= "DefaultLocale";
52 if (exec
) testLocale(/*par, */Locale::getDefault(), name
);
55 case 2: name
= "testAvailableLocales";
58 testAvailableLocales(/*par*/);
62 case 3: name
= "monsterTest";
69 default: name
= ""; break;
74 IntlTestNumberFormat::testLocale(/* char* par, */const Locale
& locale
, const UnicodeString
& localeName
)
80 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
81 fStatus
= U_ZERO_ERROR
;
82 fFormat
= NumberFormat::createInstance(locale
, fStatus
);
83 testFormat(/* par */);
85 name
= "Currency test";
86 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
87 fStatus
= U_ZERO_ERROR
;
88 fFormat
= NumberFormat::createCurrencyInstance(locale
, fStatus
);
89 testFormat(/* par */);
91 name
= "Percent test";
92 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
93 fStatus
= U_ZERO_ERROR
;
94 fFormat
= NumberFormat::createPercentInstance(locale
, fStatus
);
95 testFormat(/* par */);
97 name
= "Scientific test";
98 logln((UnicodeString
)name
+ " (" + localeName
+ ")");
99 fStatus
= U_ZERO_ERROR
;
100 fFormat
= NumberFormat::createScientificInstance(locale
, fStatus
);
101 testFormat(/* par */);
104 double IntlTestNumberFormat::randDouble()
106 // Assume 8-bit (or larger) rand values. Also assume
107 // that the system rand() function is very poor, which it always is.
108 // Call srand(currentTime) in intltest to make it truly random.
111 char* poke
= (char*)&d
;
113 for (i
=0; i
< sizeof(double); ++i
)
115 poke
[i
] = (char)(rand() & 0xFF);
117 } while (uprv_isNaN(d
) || uprv_isInfinite(d
)
118 || !((-DBL_MAX
< d
&& d
< DBL_MAX
) || (d
< -DBL_MIN
&& DBL_MIN
< d
)));
124 * Return a random uint32_t
126 uint32_t IntlTestNumberFormat::randLong()
128 // Assume 8-bit (or larger) rand values. Also assume
129 // that the system rand() function is very poor, which it always is.
130 // Call srand(currentTime) in intltest to make it truly random.
133 char* poke
= (char*)&d
;
134 for (i
=0; i
< sizeof(uint32_t); ++i
)
136 poke
[i
] = (char)(rand() & 0xFF);
142 /* Make sure that we don't get something too large and multiply into infinity.
143 @param smallerThanMax the requested maximum value smaller than DBL_MAX */
144 double IntlTestNumberFormat::getSafeDouble(double smallerThanMax
) {
146 double high
= (DBL_MAX
/smallerThanMax
)/10.0;
150 } while (low
> it
|| it
> high
);
155 IntlTestNumberFormat::testFormat(/* char* par */)
157 if (U_FAILURE(fStatus
))
159 dataerrln((UnicodeString
)"**** FAIL: createXxxInstance failed. - " + u_errorName(fStatus
));
161 errln("**** FAIL: Non-null format returned by createXxxInstance upon failure.");
169 errln((UnicodeString
)"**** FAIL: Null format returned by createXxxInstance.");
175 // Assume it's a DecimalFormat and get some info
176 DecimalFormat
*s
= (DecimalFormat
*)fFormat
;
177 logln((UnicodeString
)" Pattern " + s
->toPattern(str
));
179 #if defined(OS390) || defined(OS400)
180 tryIt(-2.02147304840132e-68);
181 tryIt(3.88057859588817e-68); // Test rounding when only some digits are shown because exponent is close to -maxfrac
182 tryIt(-2.64651110485945e+65); // Overflows to +INF when shown as a percent
183 tryIt(9.29526819488338e+64); // Ok -- used to fail?
185 tryIt(-2.02147304840132e-100);
186 tryIt(3.88057859588817e-096); // Test rounding when only some digits are shown because exponent is close to -maxfrac
187 tryIt(-2.64651110485945e+306); // Overflows to +INF when shown as a percent
188 tryIt(9.29526819488338e+250); // Ok -- used to fail?
191 // These PASS now, with the sprintf/atof based format-parse.
193 // These fail due to round-off
194 // The least significant digit drops by one during each format-parse cycle.
195 // Both numbers DON'T have a round-off problem when multiplied by 100! (shown as %)
197 tryIt(-9.18228054496402e+64);
198 tryIt(-9.69413034454191e+64);
200 tryIt(-9.18228054496402e+255);
201 tryIt(-9.69413034454191e+273);
208 tryIt(uprv_getNaN());
209 tryIt(uprv_getInfinity());
210 tryIt(-uprv_getInfinity());
213 tryIt((int32_t)251887531);
217 tryIt(9.99999999999996);
218 tryIt(9.999999999999996);
222 tryIt((int32_t)INT32_MIN
);
223 tryIt((int32_t)INT32_MAX
);
224 tryIt((double)INT32_MIN
);
225 tryIt((double)INT32_MAX
);
226 tryIt((double)INT32_MIN
- 1.0);
227 tryIt((double)INT32_MAX
+ 1.0);
229 tryIt(5.0 / 9.0 * 1e-20);
230 tryIt(4.0 / 9.0 * 1e-20);
231 tryIt(5.0 / 9.0 * 1e+20);
232 tryIt(4.0 / 9.0 * 1e+20);
242 tryIt((int32_t)-100);
243 tryIt((int32_t)-1913860352);
245 for (int32_t z
=0; z
<10; ++z
)
247 double d
= randFraction() * 2e10
- 1e10
;
251 double it
= getSafeDouble(100000.0);
256 tryIt(uprv_floor(it
));
257 tryIt((int32_t)randLong());
260 it
= getSafeDouble(100.0);
262 tryIt(uprv_floor(it
));
263 tryIt((int32_t)randLong());
265 // try again with very large numbers
266 it
= getSafeDouble(100000000000.0);
269 // try again with very large numbers
270 // and without going outside of the int32_t range
271 it
= randFraction() * INT32_MAX
;
273 tryIt((int32_t)uprv_floor(it
));
279 IntlTestNumberFormat::tryIt(double aNumber
)
281 const int32_t DEPTH
= 10;
282 Formattable number
[DEPTH
];
283 UnicodeString string
[DEPTH
];
285 int32_t numberMatch
= 0;
286 int32_t stringMatch
= 0;
287 UnicodeString errMsg
;
289 for (i
=0; i
<DEPTH
; ++i
)
291 errMsg
.truncate(0); // if non-empty, we failed this iteration
292 UErrorCode status
= U_ZERO_ERROR
;
293 string
[i
] = "(n/a)"; // "format was never done" value
295 number
[i
].setDouble(aNumber
);
297 fFormat
->parse(string
[i
-1], number
[i
], status
);
298 if (U_FAILURE(status
)) {
299 number
[i
].setDouble(1234.5); // "parse failed" value
300 errMsg
= "**** FAIL: Parse of " + prettify(string
[i
-1]) + " failed.";
301 --i
; // don't show empty last line: "1234.5 F> (n/a) P>"
305 // Convert from long to double
306 if (number
[i
].getType() == Formattable::kLong
)
307 number
[i
].setDouble(number
[i
].getLong());
308 else if (number
[i
].getType() == Formattable::kInt64
)
309 number
[i
].setDouble((double)number
[i
].getInt64());
310 else if (number
[i
].getType() != Formattable::kDouble
)
312 errMsg
= ("**** FAIL: Parse of " + prettify(string
[i
-1])
313 + " returned non-numeric Formattable, type " + UnicodeString(formattableTypeName(number
[i
].getType()))
314 + ", Locale=" + UnicodeString(fLocale
.getName())
315 + ", longValue=" + number
[i
].getLong());
318 string
[i
].truncate(0);
319 fFormat
->format(number
[i
].getDouble(), string
[i
]);
322 if (numberMatch
== 0 && number
[i
] == number
[i
-1])
324 else if (numberMatch
> 0 && number
[i
] != number
[i
-1])
326 errMsg
= ("**** FAIL: Numeric mismatch after match.");
329 if (stringMatch
== 0 && string
[i
] == string
[i
-1])
331 else if (stringMatch
> 0 && string
[i
] != string
[i
-1])
333 errMsg
= ("**** FAIL: String mismatch after match.");
337 if (numberMatch
> 0 && stringMatch
> 0)
343 if (stringMatch
> 2 || numberMatch
> 2)
345 errMsg
= ("**** FAIL: No string and/or number match within 2 iterations.");
348 if (errMsg
.length() != 0)
350 for (int32_t k
=0; k
<=i
; ++k
)
352 logln((UnicodeString
)"" + k
+ ": " + number
[k
].getDouble() + " F> " +
353 prettify(string
[k
]) + " P> ");
360 IntlTestNumberFormat::tryIt(int32_t aNumber
)
362 Formattable
number(aNumber
);
363 UnicodeString stringNum
;
364 UErrorCode status
= U_ZERO_ERROR
;
366 fFormat
->format(number
, stringNum
, status
);
367 if (U_FAILURE(status
))
369 errln("**** FAIL: Formatting " + aNumber
);
372 fFormat
->parse(stringNum
, number
, status
);
373 if (U_FAILURE(status
))
375 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed.");
378 if (number
.getType() != Formattable::kLong
)
380 errln("**** FAIL: Parse of " + prettify(stringNum
)
381 + " returned non-long Formattable, type " + UnicodeString(formattableTypeName(number
.getType()))
382 + ", Locale=" + UnicodeString(fLocale
.getName())
383 + ", doubleValue=" + number
.getDouble()
384 + ", longValue=" + number
.getLong()
385 + ", origValue=" + aNumber
388 if (number
.getLong() != aNumber
) {
389 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed. Got:" + number
.getLong()
390 + " Expected:" + aNumber
);
394 void IntlTestNumberFormat::testAvailableLocales(/* char* par */)
397 const Locale
* locales
= NumberFormat::getAvailableLocales(count
);
398 logln((UnicodeString
)"" + count
+ " available locales");
399 if (locales
&& count
)
403 for (int32_t i
=0; i
<count
; ++i
)
407 all
+= locales
[i
].getName();
412 dataerrln((UnicodeString
)"**** FAIL: Zero available locales or null array pointer");
415 void IntlTestNumberFormat::monsterTest(/* char* par */)
417 const char *SEP
= "============================================================\n";
419 const Locale
* allLocales
= NumberFormat::getAvailableLocales(count
);
420 Locale
* locales
= (Locale
*)allLocales
;
421 Locale quickLocales
[6];
422 if (allLocales
&& count
)
424 if (quick
&& count
> 6) {
425 logln("quick test: testing just 6 locales!");
427 locales
= quickLocales
;
428 locales
[0] = allLocales
[0];
429 locales
[1] = allLocales
[1];
430 locales
[2] = allLocales
[2];
431 // In a quick test, make sure we test locales that use
432 // currency prefix, currency suffix, and choice currency
433 // logic. Otherwise bugs in these areas can slip through.
434 locales
[3] = Locale("ar", "AE", "");
435 locales
[4] = Locale("cs", "CZ", "");
436 locales
[5] = Locale("en", "IN", "");
438 for (int32_t i
=0; i
<count
; ++i
)
440 UnicodeString
name(locales
[i
].getName(), "");
442 testLocale(/* par, */locales
[i
], name
);
449 #endif /* #if !UCONFIG_NO_FORMATTING */