Home | History | Annotate | Download | only in intltest
      1 /***********************************************************************
      2  * Copyright (c) 1997-2009, International Business Machines Corporation
      3  * and others. All Rights Reserved.
      4  ***********************************************************************/
      5 
      6 #include "unicode/utypes.h"
      7 
      8 #if !UCONFIG_NO_FORMATTING
      9 
     10 #include "unicode/datefmt.h"
     11 #include "unicode/smpdtfmt.h"
     12 #include "tsdate.h"
     13 #include "putilimp.h"
     14 
     15 #include <float.h>
     16 #include <stdlib.h>
     17 #include <math.h>
     18 
     19 const double IntlTestDateFormat::ONEYEAR = 365.25 * ONEDAY; // Approximate
     20 
     21 IntlTestDateFormat::~IntlTestDateFormat() {}
     22 
     23 /**
     24  * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
     25  * DateFormat.
     26  */
     27 // par is ignored throughout this file
     28 void IntlTestDateFormat::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
     29 {
     30     if (exec) logln("TestSuite DateFormat");
     31     switch (index) {
     32         case 0: name = "GenericTest";
     33             if (exec) {
     34                 logln(name);
     35                 fFormat = DateFormat::createInstance();
     36                 fTestName = "createInstance";
     37                 fLimit = 3;
     38                 testFormat(/* par */);
     39             }
     40             break;
     41         case 1: name = "DefaultLocale";
     42             if (exec) {
     43                 logln(name);
     44                 testLocale(/*par, */Locale::getDefault(), "Default Locale");
     45             }
     46             break;
     47 
     48         case 2: name = "TestAvailableLocales";
     49             if (exec) {
     50                 logln(name);
     51                 testAvailableLocales(/* par */);
     52             }
     53             break;
     54 
     55         case 3: name = "MonsterTest";
     56             if (exec) {
     57                 logln(name);
     58                 monsterTest(/*par*/);
     59             }
     60             break;
     61 
     62         default: name = ""; break;
     63     }
     64 }
     65 
     66 void
     67 IntlTestDateFormat::testLocale(/*char* par, */const Locale& locale, const UnicodeString& localeName)
     68 {
     69     DateFormat::EStyle timeStyle, dateStyle;
     70 
     71     // For patterns including only time information and a timezone, it may take
     72     // up to three iterations, since the timezone may shift as the year number
     73     // is determined.  For other patterns, 2 iterations should suffice.
     74     fLimit = 3;
     75 
     76     for(timeStyle = (DateFormat::EStyle)0;
     77         timeStyle < (DateFormat::EStyle)4;
     78         timeStyle = (DateFormat::EStyle) (timeStyle+1))
     79     {
     80         fTestName = (UnicodeString) "Time test " + (int32_t) timeStyle + " (" + localeName + ")";
     81         fFormat = DateFormat::createTimeInstance(timeStyle, locale);
     82         testFormat(/* par */);
     83     }
     84 
     85     fLimit = 2;
     86 
     87     for(dateStyle = (DateFormat::EStyle)0;
     88         dateStyle < (DateFormat::EStyle)4;
     89         dateStyle = (DateFormat::EStyle) (dateStyle+1))
     90     {
     91         fTestName = (UnicodeString) "Date test " + (int32_t) dateStyle + " (" + localeName + ")";
     92         fFormat = DateFormat::createDateInstance(dateStyle, locale);
     93         testFormat(/* par */);
     94     }
     95 
     96     for(dateStyle = (DateFormat::EStyle)0;
     97         dateStyle < (DateFormat::EStyle)4;
     98         dateStyle = (DateFormat::EStyle) (dateStyle+1))
     99     {
    100         for(timeStyle = (DateFormat::EStyle)0;
    101             timeStyle < (DateFormat::EStyle)4;
    102             timeStyle = (DateFormat::EStyle) (timeStyle+1))
    103         {
    104             fTestName = (UnicodeString) "DateTime test " + (int32_t) dateStyle + "/" + (int32_t) timeStyle + " (" + localeName + ")";
    105             fFormat = DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale);
    106             testFormat(/* par */);
    107         }
    108     }
    109 }
    110 
    111 void IntlTestDateFormat::testFormat(/* char* par */)
    112 {
    113     if (fFormat == 0)
    114     {
    115         dataerrln("FAIL: DateFormat creation failed");
    116         return;
    117     }
    118 
    119     describeTest();
    120 
    121     UDate now = Calendar::getNow();
    122     tryDate(0);
    123     tryDate(1278161801778.0);
    124     tryDate(5264498352317.0);   // Sunday, October 28, 2136 8:39:12 AM PST
    125     tryDate(9516987689250.0);   // In the year 2271
    126     tryDate(now);
    127     // Shift 6 months into the future, AT THE SAME TIME OF DAY.
    128     // This will test the DST handling.
    129     tryDate(now + 6.0*30*ONEDAY);
    130 
    131     UDate limit = now * 10; // Arbitrary limit
    132     for (int32_t i=0; i<3; ++i)
    133         tryDate(uprv_floor(randDouble() * limit));
    134 
    135     delete fFormat;
    136 }
    137 
    138 void
    139 IntlTestDateFormat::describeTest()
    140 {
    141     // Assume it's a SimpleDateFormat and get some info
    142     SimpleDateFormat *s = (SimpleDateFormat*)fFormat;
    143     UnicodeString str;
    144     logln(fTestName + " Pattern " + s->toPattern(str));
    145 }
    146 
    147 void IntlTestDateFormat::tryDate(UDate theDate)
    148 {
    149     const int32_t DEPTH = 10;
    150     UDate date[DEPTH];
    151     UnicodeString string[DEPTH];
    152 
    153     int32_t dateMatch = 0;
    154     int32_t stringMatch = 0;
    155     UBool dump = FALSE;
    156 #if defined (U_CAL_DEBUG)
    157     dump = TRUE;
    158 #endif
    159     int32_t i;
    160 
    161     date[0] = theDate;
    162     fFormat->format(theDate, string[0]);
    163 
    164     for (i=1; i<DEPTH; ++i)
    165     {
    166         UErrorCode status = U_ZERO_ERROR;
    167         date[i] = fFormat->parse(string[i-1], status);
    168         if (U_FAILURE(status))
    169         {
    170             describeTest();
    171             errln("**** FAIL: Parse of " + prettify(string[i-1], FALSE) + " failed.");
    172             dump = TRUE;
    173             break;
    174         }
    175         fFormat->format(date[i], string[i]);
    176         if (dateMatch == 0 && date[i] == date[i-1])
    177             dateMatch = i;
    178         else if (dateMatch > 0 && date[i] != date[i-1])
    179         {
    180             describeTest();
    181             errln("**** FAIL: Date mismatch after match for " + string[i]);
    182             dump = TRUE;
    183             break;
    184         }
    185         if (stringMatch == 0 && string[i] == string[i-1])
    186             stringMatch = i;
    187         else if (stringMatch > 0 && string[i] != string[i-1])
    188         {
    189             describeTest();
    190             errln("**** FAIL: String mismatch after match for " + string[i]);
    191             dump = TRUE;
    192             break;
    193         }
    194         if (dateMatch > 0 && stringMatch > 0)
    195             break;
    196     }
    197     if (i == DEPTH)
    198         --i;
    199 
    200     if (stringMatch > fLimit || dateMatch > fLimit)
    201     {
    202         describeTest();
    203         errln((UnicodeString)"**** FAIL: No string and/or date match within " + fLimit
    204             + " iterations for the Date " + string[0] + "\t(" + theDate + ").");
    205         dump = TRUE;
    206     }
    207 
    208     if (dump)
    209     {
    210         for (int32_t k=0; k<=i; ++k)
    211         {
    212             logln((UnicodeString)"" + k + ": " + date[k] + " F> " +
    213                   string[k] + " P> ");
    214         }
    215     }
    216 }
    217 
    218 // Return a random double from 0.01 to 1, inclusive
    219 double IntlTestDateFormat::randDouble()
    220 {
    221     // Assume 8-bit (or larger) rand values.  Also assume
    222     // that the system rand() function is very poor, which it always is.
    223     double d=0.0;
    224     uint32_t i;
    225     char* poke = (char*)&d;
    226     do {
    227         do {
    228             for (i=0; i < sizeof(double); ++i)
    229             {
    230                 poke[i] = (char)(rand() & 0xFF);
    231             }
    232         } while (uprv_isNaN(d) || uprv_isInfinite(d));
    233 
    234         if (d < 0.0)
    235             d = -d;
    236         if (d > 0.0)
    237         {
    238             double e = uprv_floor(log10(d));
    239             if (e < -2.0)
    240                 d *= uprv_pow10((int32_t)(-e-2));
    241             else if (e > -1.0)
    242                 d /= uprv_pow10((int32_t)(e+1));
    243         }
    244     // While this is not a real normalized number make another one.
    245     } while (uprv_isNaN(d) || uprv_isInfinite(d)
    246         || !((-DBL_MAX < d && d < DBL_MAX) || (d < -DBL_MIN && DBL_MIN < d)));
    247     return d;
    248 }
    249 
    250 void IntlTestDateFormat::testAvailableLocales(/* char* par */)
    251 {
    252     int32_t count = 0;
    253     const Locale* locales = DateFormat::getAvailableLocales(count);
    254     logln((UnicodeString)"" + count + " available locales");
    255     if (locales && count)
    256     {
    257         UnicodeString name;
    258         UnicodeString all;
    259         for (int32_t i=0; i<count; ++i)
    260         {
    261             if (i!=0) all += ", ";
    262             all += locales[i].getName();
    263         }
    264         logln(all);
    265     }
    266     else dataerrln((UnicodeString)"**** FAIL: Zero available locales or null array pointer");
    267 }
    268 
    269 void IntlTestDateFormat::monsterTest(/*char *par*/)
    270 {
    271     int32_t count;
    272     const Locale* locales = DateFormat::getAvailableLocales(count);
    273     if (locales && count)
    274     {
    275         if (quick && count > 3) {
    276             logln("quick test: testing just 3 locales!");
    277             count = 3;
    278         }
    279         for (int32_t i=0; i<count; ++i)
    280         {
    281             UnicodeString name = UnicodeString(locales[i].getName(), "");
    282             logln((UnicodeString)"Testing " + name + "...");
    283             testLocale(/*par, */locales[i], name);
    284         }
    285     }
    286 }
    287 
    288 #endif /* #if !UCONFIG_NO_FORMATTING */
    289