home *** CD-ROM | disk | FTP | other *** search
- /*
- *****************************************************************************************
- * *
- * COPYRIGHT: *
- * (C) Copyright Taligent, Inc., 1997 *
- * (C) Copyright International Business Machines Corporation, 1997-1998 *
- * Licensed Material - Program-Property of IBM - All Rights Reserved. *
- * US Government Users Restricted Rights - Use, duplication, or disclosure *
- * restricted by GSA ADP Schedule Contract with IBM Corp. *
- * *
- *****************************************************************************************
- */
-
- #include "utypes.h"
- #include "tsnmfmt.h"
-
- #include "decimfmt.h"
-
- #include <math.h>
- #include <float.h>
- #include <limits.h>
-
- /**
- * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
- * NumberFormat.
- */
- void IntlTestNumberFormat::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
- {
-
- if (exec) logln((UnicodeString)"TestSuite NumberFormat");
- switch (index) {
- case 0: name = "createInstance";
- if (exec)
- {
- logln(name);
- fStatus = U_ZERO_ERROR;
- fFormat = NumberFormat::createInstance(fStatus);
- testFormat(par);
- }
- break;
-
- case 1: name = "Default Locale";
- if (exec) testLocale(par, Locale::getDefault(), "Default Locale");
- break;
-
- case 2: name = "Determine Available Locales";
- if (exec) {
- logln(name);
- testAvailableLocales(par);
- }
- break;
-
- case 3: name = "Test Available Locales";
- if (exec) {
- logln(name);
- monsterTest(par);
- }
- break;
-
- default: name = ""; break;
- }
- }
-
- void
- IntlTestNumberFormat::testLocale(char* par, const Locale& locale, const UnicodeString& localeName)
- {
- const char* name;
-
- name = "Number test";
- logln((UnicodeString)name + " (" + localeName + ")");
- fStatus = U_ZERO_ERROR;
- fFormat = NumberFormat::createInstance(locale, fStatus);
- testFormat(par);
-
- name = "Currency test";
- logln((UnicodeString)name + " (" + localeName + ")");
- fStatus = U_ZERO_ERROR;
- fFormat = NumberFormat::createCurrencyInstance(locale, fStatus);
- testFormat(par);
-
- name = "Percent test";
- logln((UnicodeString)name + " (" + localeName + ")");
- fStatus = U_ZERO_ERROR;
- fFormat = NumberFormat::createPercentInstance(locale, fStatus);
- testFormat(par);
- }
-
- void
- IntlTestNumberFormat::testFormat(char *par)
- {
- if (U_FAILURE(fStatus))
- {
- errln((UnicodeString)"********** FAIL: createXxxInstance failed.");
- if (fFormat != 0) errln("********** FAIL: Non-null format returned by createXxxInstance upon failure.");
- delete fFormat;
- fFormat = 0;
- return;
- }
-
- if (fFormat == 0)
- {
- errln((UnicodeString)"********** FAIL: Null format returned by createXxxInstance.");
- return;
- }
-
- UnicodeString str;
-
- // Assume it's a DecimalFormat and get some info
- DecimalFormat *s = (DecimalFormat*)fFormat;
- logln((UnicodeString)" Pattern " + s->toPattern(str));
-
- if (1)
- {
- tryIt(-2.02147304840132e-100);
- tryIt(3.88057859588817e-096); // Test rounding when only some digits are shown because exponent is close to -maxfrac
- tryIt(-2.64651110485945e+306); // Overflows to +INF when shown as a percent
- tryIt(9.29526819488338e+250); // Ok -- used to fail?
- }
-
- if (1)
- {
- // These PASS now, with the sprintf/atof based format-parse.
-
- // These fail due to round-off
- // The least significant digit drops by one during each format-parse cycle.
- // Both numbers DON'T have a round-off problem when multiplied by 100! (shown as %)
- tryIt(-9.18228054496402e+255);
- tryIt(-9.69413034454191e+273);
- }
-
- if (1)
- {
- tryIt(T_INT32(251887531));
- tryIt(-2.3e-168);
-
- tryIt(icu_getNaN());
- tryIt(icu_getInfinity());
- tryIt(-icu_getInfinity());
-
- tryIt(5e-20 / 9);
- tryIt(5e20 / 9);
- tryIt(1.234e-200);
- tryIt(1.234e-50);
- tryIt(9.99999999999996);
- tryIt(9.999999999999996);
-
- tryIt((int32_t)LONG_MIN);
- tryIt((int32_t)LONG_MAX);
- tryIt((double)LONG_MIN);
- tryIt((double)LONG_MAX);
- tryIt((double)LONG_MIN - 1.0);
- tryIt((double)LONG_MAX + 1.0);
-
- tryIt(5.0 / 9.0 * 1e-20);
- tryIt(4.0 / 9.0 * 1e-20);
- tryIt(5.0 / 9.0 * 1e+20);
- tryIt(4.0 / 9.0 * 1e+20);
-
- tryIt(2147483647.);
- tryIt(T_INT32(0));
- tryIt(0.0);
- tryIt((int32_t)1);
- tryIt((int32_t)10);
- tryIt((int32_t)100);
- tryIt((int32_t)-1);
- tryIt((int32_t)-10);
- tryIt((int32_t)-100);
- }
-
- if (1)
- {
- for (int32_t z=0; z<10; ++z)
- {
- double d = randFraction() * 2e10 - 1e10;
- tryIt(d);
- }
-
- double it = randDouble() * 10000;
- tryIt(0.0);
- tryIt(it);
- tryIt(T_INT32(0));
- tryIt(T_INT32(icu_floor(it)));
-
- // try again
- it = randDouble() * 10;
- tryIt(it);
- tryIt(T_INT32(icu_floor(it)));
-
- // try again with very larget numbers
- it = randDouble() * 10000000000.0;
- tryIt(it);
- tryIt(T_INT32(icu_floor(it)));
- }
-
- delete fFormat;
- }
-
- void
- IntlTestNumberFormat::tryIt(double aNumber)
- {
- const int32_t DEPTH = 10;
- Formattable number[DEPTH];
- UnicodeString string[DEPTH];
-
- int32_t numberMatch = 0;
- int32_t stringMatch = 0;
- bool_t dump = FALSE;
- int32_t i;
- for (i=0; i<DEPTH; ++i)
- {
- UErrorCode status = U_ZERO_ERROR;
- if (i == 0) number[i].setDouble(aNumber);
- else fFormat->parse(string[i-1], number[i], status);
- if (U_FAILURE(status))
- {
- errln("********** FAIL: Parse of " + string[i-1] + " failed.");
- dump = TRUE;
- break;
- }
- // Convert from long to double
- if (number[i].getType() == Formattable::kLong) number[i].setDouble(number[i].getLong());
- else if (number[i].getType() != Formattable::kDouble)
- {
- errln("********** FAIL: Parse of " + string[i-1] + " returned non-numeric Formattable.");
- dump = TRUE;
- break;
- }
- fFormat->format(number[i].getDouble(), string[i]);
- if (i > 0)
- {
- if (numberMatch == 0 && number[i] == number[i-1]) numberMatch = i;
- else if (numberMatch > 0 && number[i] != number[i-1])
- {
- errln("********** FAIL: Numeric mismatch after match.");
- dump = TRUE;
- break;
- }
- if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
- else if (stringMatch > 0 && string[i] != string[i-1])
- {
- errln("********** FAIL: String mismatch after match.");
- dump = TRUE;
- break;
- }
- }
- if (numberMatch > 0 && stringMatch > 0) break;
- }
- if (i == DEPTH) --i;
-
- if (stringMatch > 2 || numberMatch > 2)
- {
- errln("********** FAIL: No string and/or number match within 2 iterations.");
- dump = TRUE;
- }
-
- if (dump)
- {
- for (int32_t k=0; k<=i; ++k)
- {
- logln((UnicodeString)"" + k + ": " + number[k].getDouble() + " F> " +
- string[k] + " P> ");
- }
- }
- }
-
- void
- IntlTestNumberFormat::tryIt(int32_t aNumber)
- {
- const int32_t DEPTH = 10;
- Formattable number[DEPTH];
- UnicodeString string[DEPTH];
-
- int32_t numberMatch = 0;
- int32_t stringMatch = 0;
- bool_t dump = FALSE;
- int32_t i;
- for (i=0; i<DEPTH; ++i)
- {
- UErrorCode status = U_ZERO_ERROR;
- if (i == 0) number[i].setLong(aNumber);
- else fFormat->parse(string[i-1], number[i], status);
- if (U_FAILURE(status))
- {
- errln("********** FAIL: Parse of " + string[i-1] + " failed.");
- dump = TRUE;
- break;
- }
- if (number[i].getType() != Formattable::kLong)
- {
- errln("********** FAIL: Parse of " + string[i-1] + " returned non-long Formattable.");
- dump = TRUE;
- break;
- }
- fFormat->format(number[i].getLong(), string[i]);
- if (i > 0)
- {
- if (numberMatch == 0 && number[i] == number[i-1]) numberMatch = i;
- else if (numberMatch > 0 && number[i] != number[i-1])
- {
- errln("********** FAIL: Numeric mismatch after match.");
- dump = TRUE;
- break;
- }
- if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
- else if (stringMatch > 0 && string[i] != string[i-1])
- {
- errln("********** FAIL: String mismatch after match.");
- dump = TRUE;
- break;
- }
- }
- if (numberMatch > 0 && stringMatch > 0) break;
- }
- if (i == DEPTH) --i;
-
- if (stringMatch > 2 || numberMatch > 2)
- {
- errln("********** FAIL: No string and/or number match within 2 iterations.");
- dump = TRUE;
- }
-
- if (dump)
- {
- for (int32_t k=0; k<=i; ++k)
- {
- logln((UnicodeString)"" + k + ": " + number[k].getLong() + " F> " +
- string[k] + " P> ");
- }
- }
- }
-
- void IntlTestNumberFormat::testAvailableLocales(char *par)
- {
- int32_t count = 0;
- const Locale* locales = NumberFormat::getAvailableLocales(count);
- logln((UnicodeString)"" + count + " available locales");
- if (locales && count)
- {
- UnicodeString name;
- UnicodeString all;
- for (int32_t i=0; i<count; ++i)
- {
- if (i!=0) all += ", ";
- all += locales[i].getName(name);
- }
- logln(all);
- }
- else errln((UnicodeString)"********** FAIL: Zero available locales or null array pointer");
- }
-
- void IntlTestNumberFormat::monsterTest(char *par)
- {
- const char *SEP = "============================================================\n";
- int32_t count;
- const Locale* locales = NumberFormat::getAvailableLocales(count);
- if (locales && count)
- {
- if (quick && count > 2) {
- logln("quick test: testing just 2 locales!");
- count = 2;
- }
- for (int32_t i=0; i<count; ++i)
- {
- UnicodeString name;
- locales[i].getName(name);
- logln(SEP);
- testLocale(par, locales[i], name);
- }
- }
-
- logln(SEP);
- }
-