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