home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / test / intltest / tsnmfmt.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  10.8 KB  |  373 lines

  1. /*
  2. *****************************************************************************************
  3. *                                                                                       *
  4. * COPYRIGHT:                                                                            *
  5. *   (C) Copyright Taligent, Inc.,  1997                                                 *
  6. *   (C) Copyright International Business Machines Corporation,  1997-1998               *
  7. *   Licensed Material - Program-Property of IBM - All Rights Reserved.                  *
  8. *   US Government Users Restricted Rights - Use, duplication, or disclosure             *
  9. *   restricted by GSA ADP Schedule Contract with IBM Corp.                              *
  10. *                                                                                       *
  11. *****************************************************************************************
  12. */
  13.  
  14. #include "utypes.h"
  15. #include "tsnmfmt.h"
  16.  
  17. #include "decimfmt.h"
  18.  
  19. #include <math.h>
  20. #include <float.h>
  21. #include <limits.h>
  22.  
  23. /**
  24.  * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
  25.  * NumberFormat.
  26.  */
  27. void IntlTestNumberFormat::runIndexedTest( int32_t index, bool_t exec, char* &name, char* par )
  28. {
  29.  
  30.     if (exec) logln((UnicodeString)"TestSuite NumberFormat");
  31.     switch (index) {
  32.         case 0: name = "createInstance"; 
  33.             if (exec)
  34.             {
  35.                 logln(name);
  36.                 fStatus = U_ZERO_ERROR;
  37.                 fFormat = NumberFormat::createInstance(fStatus);
  38.                 testFormat(par);
  39.             }
  40.             break;
  41.  
  42.         case 1: name = "Default Locale";
  43.             if (exec) testLocale(par, Locale::getDefault(), "Default Locale");
  44.             break;
  45.  
  46.         case 2: name = "Determine Available Locales"; 
  47.             if (exec) {
  48.                 logln(name);
  49.                 testAvailableLocales(par);
  50.             }
  51.             break;
  52.  
  53.         case 3: name = "Test Available Locales"; 
  54.             if (exec) {
  55.                 logln(name);
  56.                 monsterTest(par);
  57.             }
  58.             break;
  59.  
  60.         default: name = ""; break;
  61.     }
  62. }
  63.  
  64. void
  65. IntlTestNumberFormat::testLocale(char* par, const Locale& locale, const UnicodeString& localeName)
  66. {
  67.     const char* name;
  68.     
  69.     name = "Number test";
  70.     logln((UnicodeString)name + " (" + localeName + ")");
  71.     fStatus = U_ZERO_ERROR;
  72.     fFormat = NumberFormat::createInstance(locale, fStatus);
  73.     testFormat(par);
  74.  
  75.     name = "Currency test";
  76.     logln((UnicodeString)name + " (" + localeName + ")");
  77.     fStatus = U_ZERO_ERROR;
  78.     fFormat = NumberFormat::createCurrencyInstance(locale, fStatus);
  79.     testFormat(par);
  80.  
  81.     name = "Percent test";
  82.     logln((UnicodeString)name + " (" + localeName + ")");
  83.     fStatus = U_ZERO_ERROR;
  84.     fFormat = NumberFormat::createPercentInstance(locale, fStatus);
  85.     testFormat(par);
  86. }
  87.  
  88. void
  89. IntlTestNumberFormat::testFormat(char *par)
  90. {
  91.     if (U_FAILURE(fStatus))
  92.     { 
  93.         errln((UnicodeString)"********** FAIL: createXxxInstance failed.");
  94.         if (fFormat != 0) errln("********** FAIL: Non-null format returned by createXxxInstance upon failure.");
  95.         delete fFormat;
  96.         fFormat = 0;
  97.         return;
  98.     }
  99.                     
  100.     if (fFormat == 0)
  101.     {
  102.         errln((UnicodeString)"********** FAIL: Null format returned by createXxxInstance.");
  103.         return;
  104.     }
  105.  
  106.     UnicodeString str;
  107.  
  108.     // Assume it's a DecimalFormat and get some info
  109.     DecimalFormat *s = (DecimalFormat*)fFormat;
  110.     logln((UnicodeString)"  Pattern " + s->toPattern(str));
  111.  
  112.     if (1)
  113.     {
  114.         tryIt(-2.02147304840132e-100);
  115.         tryIt(3.88057859588817e-096); // Test rounding when only some digits are shown because exponent is close to -maxfrac
  116.         tryIt(-2.64651110485945e+306); // Overflows to +INF when shown as a percent
  117.         tryIt(9.29526819488338e+250); // Ok -- used to fail?
  118.     }
  119.  
  120.     if (1)
  121.     {
  122.         // These PASS now, with the sprintf/atof based format-parse.
  123.  
  124.         // These fail due to round-off
  125.         // The least significant digit drops by one during each format-parse cycle.
  126.         // Both numbers DON'T have a round-off problem when multiplied by 100! (shown as %)
  127.         tryIt(-9.18228054496402e+255);
  128.         tryIt(-9.69413034454191e+273);
  129.     }
  130.  
  131.     if (1)
  132.     {
  133.         tryIt(T_INT32(251887531));
  134.         tryIt(-2.3e-168);
  135.  
  136.         tryIt(icu_getNaN());
  137.         tryIt(icu_getInfinity());
  138.         tryIt(-icu_getInfinity());
  139.  
  140.         tryIt(5e-20 / 9);
  141.         tryIt(5e20 / 9);
  142.         tryIt(1.234e-200);
  143.         tryIt(1.234e-50);
  144.         tryIt(9.99999999999996);
  145.         tryIt(9.999999999999996);
  146.  
  147.         tryIt((int32_t)LONG_MIN);
  148.         tryIt((int32_t)LONG_MAX);
  149.         tryIt((double)LONG_MIN);
  150.         tryIt((double)LONG_MAX);
  151.         tryIt((double)LONG_MIN - 1.0);
  152.         tryIt((double)LONG_MAX + 1.0);
  153.  
  154.         tryIt(5.0 / 9.0 * 1e-20);
  155.         tryIt(4.0 / 9.0 * 1e-20);
  156.         tryIt(5.0 / 9.0 * 1e+20);
  157.         tryIt(4.0 / 9.0 * 1e+20);
  158.  
  159.         tryIt(2147483647.);
  160.         tryIt(T_INT32(0));
  161.         tryIt(0.0);
  162.         tryIt((int32_t)1);
  163.         tryIt((int32_t)10);
  164.         tryIt((int32_t)100);
  165.         tryIt((int32_t)-1);
  166.         tryIt((int32_t)-10);
  167.         tryIt((int32_t)-100);
  168.     }
  169.  
  170.     if (1)
  171.     {
  172.         for (int32_t z=0; z<10; ++z)
  173.         {
  174.             double d = randFraction() * 2e10 - 1e10;
  175.             tryIt(d);
  176.         }
  177.  
  178.         double it = randDouble() * 10000;
  179.         tryIt(0.0);
  180.         tryIt(it);
  181.         tryIt(T_INT32(0));
  182.         tryIt(T_INT32(icu_floor(it)));
  183.  
  184.         // try again
  185.         it = randDouble() * 10;
  186.         tryIt(it);
  187.         tryIt(T_INT32(icu_floor(it)));
  188.  
  189.         // try again with very larget numbers
  190.         it = randDouble() * 10000000000.0;
  191.         tryIt(it);
  192.         tryIt(T_INT32(icu_floor(it)));
  193.     }
  194.  
  195.     delete fFormat;
  196. }
  197.  
  198. void 
  199. IntlTestNumberFormat::tryIt(double aNumber)
  200. {
  201.     const int32_t DEPTH = 10;
  202.     Formattable number[DEPTH];
  203.     UnicodeString string[DEPTH];
  204.  
  205.     int32_t numberMatch = 0;
  206.     int32_t stringMatch = 0;
  207.     bool_t dump = FALSE;
  208.     int32_t i;
  209.     for (i=0; i<DEPTH; ++i)
  210.     {
  211.         UErrorCode status = U_ZERO_ERROR;
  212.         if (i == 0) number[i].setDouble(aNumber);
  213.         else fFormat->parse(string[i-1], number[i], status);
  214.         if (U_FAILURE(status))
  215.         {
  216.             errln("********** FAIL: Parse of " + string[i-1] + " failed.");
  217.             dump = TRUE;
  218.             break;
  219.         }
  220.         // Convert from long to double
  221.         if (number[i].getType() == Formattable::kLong) number[i].setDouble(number[i].getLong());
  222.         else if (number[i].getType() != Formattable::kDouble)
  223.         {
  224.             errln("********** FAIL: Parse of " + string[i-1] + " returned non-numeric Formattable.");
  225.             dump = TRUE;
  226.             break;
  227.         }
  228.         fFormat->format(number[i].getDouble(), string[i]);
  229.         if (i > 0)
  230.         {
  231.             if (numberMatch == 0 && number[i] == number[i-1]) numberMatch = i;
  232.             else if (numberMatch > 0 && number[i] != number[i-1])
  233.             {
  234.                 errln("********** FAIL: Numeric mismatch after match.");
  235.                 dump = TRUE;
  236.                 break;
  237.             }
  238.             if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
  239.             else if (stringMatch > 0 && string[i] != string[i-1])
  240.             {
  241.                 errln("********** FAIL: String mismatch after match.");
  242.                 dump = TRUE;
  243.                 break;
  244.             }
  245.         }
  246.         if (numberMatch > 0 && stringMatch > 0) break;
  247.     }
  248.     if (i == DEPTH) --i;
  249.  
  250.     if (stringMatch > 2 || numberMatch > 2)
  251.     {
  252.         errln("********** FAIL: No string and/or number match within 2 iterations.");
  253.         dump = TRUE;
  254.     }
  255.  
  256.     if (dump)
  257.     {
  258.         for (int32_t k=0; k<=i; ++k)
  259.         {
  260.             logln((UnicodeString)"" + k + ": " + number[k].getDouble() + " F> " +
  261.                   string[k] + " P> ");
  262.         }
  263.     }
  264. }
  265.  
  266. void 
  267. IntlTestNumberFormat::tryIt(int32_t aNumber)
  268. {
  269.     const int32_t DEPTH = 10;
  270.     Formattable number[DEPTH];
  271.     UnicodeString string[DEPTH];
  272.  
  273.     int32_t numberMatch = 0;
  274.     int32_t stringMatch = 0;
  275.     bool_t dump = FALSE;
  276.     int32_t i;
  277.     for (i=0; i<DEPTH; ++i)
  278.     {
  279.         UErrorCode status = U_ZERO_ERROR;
  280.         if (i == 0) number[i].setLong(aNumber);
  281.         else fFormat->parse(string[i-1], number[i], status);
  282.         if (U_FAILURE(status))
  283.         {
  284.             errln("********** FAIL: Parse of " + string[i-1] + " failed.");
  285.             dump = TRUE;
  286.             break;
  287.         }
  288.         if (number[i].getType() != Formattable::kLong)
  289.         {
  290.             errln("********** FAIL: Parse of " + string[i-1] + " returned non-long Formattable.");
  291.             dump = TRUE;
  292.             break;
  293.         }
  294.         fFormat->format(number[i].getLong(), string[i]);
  295.         if (i > 0)
  296.         {
  297.             if (numberMatch == 0 && number[i] == number[i-1]) numberMatch = i;
  298.             else if (numberMatch > 0 && number[i] != number[i-1])
  299.             {
  300.                 errln("********** FAIL: Numeric mismatch after match.");
  301.                 dump = TRUE;
  302.                 break;
  303.             }
  304.             if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
  305.             else if (stringMatch > 0 && string[i] != string[i-1])
  306.             {
  307.                 errln("********** FAIL: String mismatch after match.");
  308.                 dump = TRUE;
  309.                 break;
  310.             }
  311.         }
  312.         if (numberMatch > 0 && stringMatch > 0) break;
  313.     }
  314.     if (i == DEPTH) --i;
  315.  
  316.     if (stringMatch > 2 || numberMatch > 2)
  317.     {
  318.         errln("********** FAIL: No string and/or number match within 2 iterations.");
  319.         dump = TRUE;
  320.     }
  321.  
  322.     if (dump)
  323.     {
  324.         for (int32_t k=0; k<=i; ++k)
  325.         {
  326.             logln((UnicodeString)"" + k + ": " + number[k].getLong() + " F> " +
  327.                   string[k] + " P> ");
  328.         }
  329.     }
  330. }
  331.  
  332. void IntlTestNumberFormat::testAvailableLocales(char *par)
  333. {
  334.     int32_t count = 0;
  335.     const Locale* locales = NumberFormat::getAvailableLocales(count);
  336.     logln((UnicodeString)"" + count + " available locales");
  337.     if (locales && count)
  338.     {
  339.         UnicodeString name;
  340.         UnicodeString all;
  341.         for (int32_t i=0; i<count; ++i)
  342.         {
  343.             if (i!=0) all += ", ";
  344.             all += locales[i].getName(name);
  345.         }
  346.         logln(all);
  347.     }
  348.     else errln((UnicodeString)"********** FAIL: Zero available locales or null array pointer");
  349. }
  350.  
  351. void IntlTestNumberFormat::monsterTest(char *par)
  352. {
  353.     const char *SEP = "============================================================\n";
  354.     int32_t count;
  355.     const Locale* locales = NumberFormat::getAvailableLocales(count);
  356.     if (locales && count)
  357.     {
  358.         if (quick && count > 2) {
  359.             logln("quick test: testing just 2 locales!");
  360.             count = 2;
  361.         }
  362.         for (int32_t i=0; i<count; ++i)
  363.         {
  364.             UnicodeString name;
  365.             locales[i].getName(name);
  366.             logln(SEP);
  367.             testLocale(par, locales[i], name);
  368.         }
  369.     }
  370.  
  371.     logln(SEP);
  372. }
  373.