]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tsnmfmt.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2004, 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 */);
98 double IntlTestNumberFormat::randDouble()
100 // Assume 8-bit (or larger) rand values. Also assume
101 // that the system rand() function is very poor, which it always is.
102 // Call srand(currentTime) in intltest to make it truly random.
105 char* poke
= (char*)&d
;
107 for (i
=0; i
< sizeof(double); ++i
)
109 poke
[i
] = (char)(rand() & 0xFF);
111 } while (uprv_isNaN(d
) || uprv_isInfinite(d
)
112 || !((-DBL_MAX
< d
&& d
< DBL_MAX
) || (d
< -DBL_MIN
&& DBL_MIN
< d
)));
118 * Return a random uint32_t
120 uint32_t IntlTestNumberFormat::randLong()
122 // Assume 8-bit (or larger) rand values. Also assume
123 // that the system rand() function is very poor, which it always is.
124 // Call srand(currentTime) in intltest to make it truly random.
127 char* poke
= (char*)&d
;
128 for (i
=0; i
< sizeof(uint32_t); ++i
)
130 poke
[i
] = (char)(rand() & 0xFF);
136 /* Make sure that we don't get something too large and multiply into infinity.
137 @param smallerThanMax the requested maximum value smaller than DBL_MAX */
138 double IntlTestNumberFormat::getSafeDouble(double smallerThanMax
) {
140 double high
= (DBL_MAX
/smallerThanMax
)/10.0;
144 } while (low
> it
|| it
> high
);
149 IntlTestNumberFormat::testFormat(/* char* par */)
151 if (U_FAILURE(fStatus
))
153 errln((UnicodeString
)"**** FAIL: createXxxInstance failed.");
155 errln("**** FAIL: Non-null format returned by createXxxInstance upon failure.");
163 errln((UnicodeString
)"**** FAIL: Null format returned by createXxxInstance.");
169 // Assume it's a DecimalFormat and get some info
170 DecimalFormat
*s
= (DecimalFormat
*)fFormat
;
171 logln((UnicodeString
)" Pattern " + s
->toPattern(str
));
173 #if defined(OS390) || defined(OS400)
174 tryIt(-2.02147304840132e-68);
175 tryIt(3.88057859588817e-68); // Test rounding when only some digits are shown because exponent is close to -maxfrac
176 tryIt(-2.64651110485945e+65); // Overflows to +INF when shown as a percent
177 tryIt(9.29526819488338e+64); // Ok -- used to fail?
179 tryIt(-2.02147304840132e-100);
180 tryIt(3.88057859588817e-096); // Test rounding when only some digits are shown because exponent is close to -maxfrac
181 tryIt(-2.64651110485945e+306); // Overflows to +INF when shown as a percent
182 tryIt(9.29526819488338e+250); // Ok -- used to fail?
185 // These PASS now, with the sprintf/atof based format-parse.
187 // These fail due to round-off
188 // The least significant digit drops by one during each format-parse cycle.
189 // Both numbers DON'T have a round-off problem when multiplied by 100! (shown as %)
191 tryIt(-9.18228054496402e+64);
192 tryIt(-9.69413034454191e+64);
194 tryIt(-9.18228054496402e+255);
195 tryIt(-9.69413034454191e+273);
202 tryIt(uprv_getNaN());
203 tryIt(uprv_getInfinity());
204 tryIt(-uprv_getInfinity());
207 tryIt((int32_t)251887531);
211 tryIt(9.99999999999996);
212 tryIt(9.999999999999996);
214 tryIt((int32_t)INT32_MIN
);
215 tryIt((int32_t)INT32_MAX
);
216 tryIt((double)INT32_MIN
);
217 tryIt((double)INT32_MAX
);
218 tryIt((double)INT32_MIN
- 1.0);
219 tryIt((double)INT32_MAX
+ 1.0);
221 tryIt(5.0 / 9.0 * 1e-20);
222 tryIt(4.0 / 9.0 * 1e-20);
223 tryIt(5.0 / 9.0 * 1e+20);
224 tryIt(4.0 / 9.0 * 1e+20);
234 tryIt((int32_t)-100);
235 tryIt((int32_t)-1913860352);
237 for (int32_t z
=0; z
<10; ++z
)
239 double d
= randFraction() * 2e10
- 1e10
;
243 double it
= getSafeDouble(100000.0);
248 tryIt(uprv_floor(it
));
249 tryIt((int32_t)randLong());
252 it
= getSafeDouble(100.0);
254 tryIt(uprv_floor(it
));
255 tryIt((int32_t)randLong());
257 // try again with very large numbers
258 it
= getSafeDouble(100000000000.0);
261 // try again with very large numbers
262 // and without going outside of the int32_t range
263 it
= randFraction() * INT32_MAX
;
265 tryIt((int32_t)uprv_floor(it
));
271 IntlTestNumberFormat::tryIt(double aNumber
)
273 const int32_t DEPTH
= 10;
274 Formattable number
[DEPTH
];
275 UnicodeString string
[DEPTH
];
277 int32_t numberMatch
= 0;
278 int32_t stringMatch
= 0;
279 UnicodeString errMsg
;
281 for (i
=0; i
<DEPTH
; ++i
)
283 errMsg
.truncate(0); // if non-empty, we failed this iteration
284 UErrorCode status
= U_ZERO_ERROR
;
285 string
[i
] = "(n/a)"; // "format was never done" value
287 number
[i
].setDouble(aNumber
);
289 fFormat
->parse(string
[i
-1], number
[i
], status
);
290 if (U_FAILURE(status
)) {
291 number
[i
].setDouble(1234.5); // "parse failed" value
292 errMsg
= "**** FAIL: Parse of " + prettify(string
[i
-1]) + " failed.";
293 --i
; // don't show empty last line: "1234.5 F> (n/a) P>"
297 // Convert from long to double
298 if (number
[i
].getType() == Formattable::kLong
)
299 number
[i
].setDouble(number
[i
].getLong());
300 else if (number
[i
].getType() == Formattable::kInt64
)
301 number
[i
].setDouble((double)number
[i
].getInt64());
302 else if (number
[i
].getType() != Formattable::kDouble
)
304 errMsg
= ("**** FAIL: Parse of " + prettify(string
[i
-1])
305 + " returned non-numeric Formattable, type " + UnicodeString(formattableTypeName(number
[i
].getType()))
306 + ", Locale=" + UnicodeString(fLocale
.getName())
307 + ", longValue=" + number
[i
].getLong());
310 string
[i
].truncate(0);
311 fFormat
->format(number
[i
].getDouble(), string
[i
]);
314 if (numberMatch
== 0 && number
[i
] == number
[i
-1])
316 else if (numberMatch
> 0 && number
[i
] != number
[i
-1])
318 errMsg
= ("**** FAIL: Numeric mismatch after match.");
321 if (stringMatch
== 0 && string
[i
] == string
[i
-1])
323 else if (stringMatch
> 0 && string
[i
] != string
[i
-1])
325 errMsg
= ("**** FAIL: String mismatch after match.");
329 if (numberMatch
> 0 && stringMatch
> 0)
335 if (stringMatch
> 2 || numberMatch
> 2)
337 errMsg
= ("**** FAIL: No string and/or number match within 2 iterations.");
340 if (errMsg
.length() != 0)
342 for (int32_t k
=0; k
<=i
; ++k
)
344 logln((UnicodeString
)"" + k
+ ": " + number
[k
].getDouble() + " F> " +
345 prettify(string
[k
]) + " P> ");
352 IntlTestNumberFormat::tryIt(int32_t aNumber
)
354 Formattable
number(aNumber
);
355 UnicodeString stringNum
;
356 UErrorCode status
= U_ZERO_ERROR
;
358 fFormat
->format(number
, stringNum
, status
);
359 if (U_FAILURE(status
))
361 errln("**** FAIL: Formatting " + aNumber
);
364 fFormat
->parse(stringNum
, number
, status
);
365 if (U_FAILURE(status
))
367 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed.");
370 if (number
.getType() != Formattable::kLong
)
372 errln("**** FAIL: Parse of " + prettify(stringNum
)
373 + " returned non-long Formattable, type " + UnicodeString(formattableTypeName(number
.getType()))
374 + ", Locale=" + UnicodeString(fLocale
.getName())
375 + ", doubleValue=" + number
.getDouble()
376 + ", longValue=" + number
.getLong()
377 + ", origValue=" + aNumber
380 if (number
.getLong() != aNumber
) {
381 errln("**** FAIL: Parse of " + prettify(stringNum
) + " failed. Got:" + number
.getLong()
382 + " Expected:" + aNumber
);
386 void IntlTestNumberFormat::testAvailableLocales(/* char* par */)
389 const Locale
* locales
= NumberFormat::getAvailableLocales(count
);
390 logln((UnicodeString
)"" + count
+ " available locales");
391 if (locales
&& count
)
395 for (int32_t i
=0; i
<count
; ++i
)
399 all
+= locales
[i
].getName();
404 errln((UnicodeString
)"**** FAIL: Zero available locales or null array pointer");
407 void IntlTestNumberFormat::monsterTest(/* char* par */)
409 const char *SEP
= "============================================================\n";
411 const Locale
* allLocales
= NumberFormat::getAvailableLocales(count
);
412 Locale
* locales
= (Locale
*)allLocales
;
413 Locale quickLocales
[6];
414 if (allLocales
&& count
)
416 if (quick
&& count
> 6) {
417 logln("quick test: testing just 6 locales!");
419 locales
= quickLocales
;
420 locales
[0] = allLocales
[0];
421 locales
[1] = allLocales
[1];
422 locales
[2] = allLocales
[2];
423 // In a quick test, make sure we test locales that use
424 // currency prefix, currency suffix, and choice currency
425 // logic. Otherwise bugs in these areas can slip through.
426 locales
[3] = Locale("ar", "AE", "");
427 locales
[4] = Locale("cs", "CZ", "");
428 locales
[5] = Locale("en", "IN", "");
430 for (int32_t i
=0; i
<count
; ++i
)
432 UnicodeString
name(locales
[i
].getName(), "");
434 testLocale(/* par, */locales
[i
], name
);
441 #endif /* #if !UCONFIG_NO_FORMATTING */