| OLD | NEW |
| (Empty) |
| 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 Unicod
eString& 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, l
ocale); | |
| 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) + " fail
ed."); | |
| 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 arr
ay 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 */ | |
| OLD | NEW |