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