OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * Copyright (C) 2007-2010, International Business Machines Corporation and * |
| 4 * others. All Rights Reserved. * |
| 5 ******************************************************************************* |
| 6 */ |
| 7 #include "unicode/utypes.h" |
| 8 |
| 9 #if !UCONFIG_NO_FORMATTING |
| 10 |
| 11 #include "tzfmttst.h" |
| 12 |
| 13 #include "simplethread.h" |
| 14 #include "unicode/timezone.h" |
| 15 #include "unicode/simpletz.h" |
| 16 #include "unicode/calendar.h" |
| 17 #include "unicode/strenum.h" |
| 18 #include "unicode/smpdtfmt.h" |
| 19 #include "unicode/uchar.h" |
| 20 #include "unicode/basictz.h" |
| 21 #include "cstring.h" |
| 22 |
| 23 static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VV
VV"}; |
| 24 static const int NUM_PATTERNS = sizeof(PATTERNS)/sizeof(const char*); |
| 25 |
| 26 void |
| 27 TimeZoneFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name
, char* /*par*/ ) |
| 28 { |
| 29 if (exec) { |
| 30 logln("TestSuite TimeZoneFormatTest"); |
| 31 } |
| 32 switch (index) { |
| 33 TESTCASE(0, TestTimeZoneRoundTrip); |
| 34 TESTCASE(1, TestTimeRoundTrip); |
| 35 default: name = ""; break; |
| 36 } |
| 37 } |
| 38 |
| 39 void |
| 40 TimeZoneFormatTest::TestTimeZoneRoundTrip(void) { |
| 41 UErrorCode status = U_ZERO_ERROR; |
| 42 |
| 43 SimpleTimeZone unknownZone(-31415, (UnicodeString)"Etc/Unknown"); |
| 44 int32_t badDstOffset = -1234; |
| 45 int32_t badZoneOffset = -2345; |
| 46 |
| 47 int32_t testDateData[][3] = { |
| 48 {2007, 1, 15}, |
| 49 {2007, 6, 15}, |
| 50 {1990, 1, 15}, |
| 51 {1990, 6, 15}, |
| 52 {1960, 1, 15}, |
| 53 {1960, 6, 15}, |
| 54 }; |
| 55 |
| 56 Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeSt
ring)"UTC"), status); |
| 57 if (U_FAILURE(status)) { |
| 58 dataerrln("Calendar::createInstance failed: %s", u_errorName(status)); |
| 59 return; |
| 60 } |
| 61 |
| 62 // Set up rule equivalency test range |
| 63 UDate low, high; |
| 64 cal->set(1900, UCAL_JANUARY, 1); |
| 65 low = cal->getTime(status); |
| 66 cal->set(2040, UCAL_JANUARY, 1); |
| 67 high = cal->getTime(status); |
| 68 if (U_FAILURE(status)) { |
| 69 errln("getTime failed"); |
| 70 return; |
| 71 } |
| 72 |
| 73 // Set up test dates |
| 74 UDate DATES[(sizeof(testDateData)/sizeof(int32_t))/3]; |
| 75 const int32_t nDates = (sizeof(testDateData)/sizeof(int32_t))/3; |
| 76 cal->clear(); |
| 77 for (int32_t i = 0; i < nDates; i++) { |
| 78 cal->set(testDateData[i][0], testDateData[i][1], testDateData[i][2]); |
| 79 DATES[i] = cal->getTime(status); |
| 80 if (U_FAILURE(status)) { |
| 81 errln("getTime failed"); |
| 82 return; |
| 83 } |
| 84 } |
| 85 |
| 86 // Set up test locales |
| 87 const Locale testLocales[] = { |
| 88 Locale("en"), |
| 89 Locale("en_CA"), |
| 90 Locale("fr"), |
| 91 Locale("zh_Hant") |
| 92 }; |
| 93 |
| 94 const Locale *LOCALES; |
| 95 int32_t nLocales; |
| 96 |
| 97 if (quick) { |
| 98 LOCALES = testLocales; |
| 99 nLocales = sizeof(testLocales)/sizeof(Locale); |
| 100 } else { |
| 101 LOCALES = Locale::getAvailableLocales(nLocales); |
| 102 } |
| 103 |
| 104 StringEnumeration *tzids = TimeZone::createEnumeration(); |
| 105 if (U_FAILURE(status)) { |
| 106 errln("tzids->count failed"); |
| 107 return; |
| 108 } |
| 109 |
| 110 int32_t inRaw, inDst; |
| 111 int32_t outRaw, outDst; |
| 112 |
| 113 // Run the roundtrip test |
| 114 for (int32_t locidx = 0; locidx < nLocales; locidx++) { |
| 115 for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) { |
| 116 |
| 117 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)PATTERNS
[patidx], LOCALES[locidx], status); |
| 118 if (U_FAILURE(status)) { |
| 119 errcheckln(status, (UnicodeString)"new SimpleDateFormat failed f
or pattern " + |
| 120 PATTERNS[patidx] + " for locale " + LOCALES[locidx].getName(
) + " - " + u_errorName(status)); |
| 121 status = U_ZERO_ERROR; |
| 122 continue; |
| 123 } |
| 124 |
| 125 tzids->reset(status); |
| 126 const UnicodeString *tzid; |
| 127 while ((tzid = tzids->snext(status))) { |
| 128 TimeZone *tz = TimeZone::createTimeZone(*tzid); |
| 129 |
| 130 for (int32_t datidx = 0; datidx < nDates; datidx++) { |
| 131 UnicodeString tzstr; |
| 132 FieldPosition fpos(0); |
| 133 // Format |
| 134 sdf->setTimeZone(*tz); |
| 135 sdf->format(DATES[datidx], tzstr, fpos); |
| 136 |
| 137 // Before parse, set unknown zone to SimpleDateFormat instan
ce |
| 138 // just for making sure that it does not depends on the time
zone |
| 139 // originally set. |
| 140 sdf->setTimeZone(unknownZone); |
| 141 |
| 142 // Parse |
| 143 ParsePosition pos(0); |
| 144 Calendar *outcal = Calendar::createInstance(unknownZone, sta
tus); |
| 145 if (U_FAILURE(status)) { |
| 146 errln("Failed to create an instance of calendar for rece
iving parse result."); |
| 147 status = U_ZERO_ERROR; |
| 148 continue; |
| 149 } |
| 150 outcal->set(UCAL_DST_OFFSET, badDstOffset); |
| 151 outcal->set(UCAL_ZONE_OFFSET, badZoneOffset); |
| 152 |
| 153 sdf->parse(tzstr, *outcal, pos); |
| 154 |
| 155 // Check the result |
| 156 const TimeZone &outtz = outcal->getTimeZone(); |
| 157 UnicodeString outtzid; |
| 158 outtz.getID(outtzid); |
| 159 |
| 160 tz->getOffset(DATES[datidx], false, inRaw, inDst, status); |
| 161 if (U_FAILURE(status)) { |
| 162 errln((UnicodeString)"Failed to get offsets from time zo
ne" + *tzid); |
| 163 status = U_ZERO_ERROR; |
| 164 } |
| 165 outtz.getOffset(DATES[datidx], false, outRaw, outDst, status
); |
| 166 if (U_FAILURE(status)) { |
| 167 errln((UnicodeString)"Failed to get offsets from time zo
ne" + outtzid); |
| 168 status = U_ZERO_ERROR; |
| 169 } |
| 170 |
| 171 if (uprv_strcmp(PATTERNS[patidx], "VVVV") == 0) { |
| 172 // Location: time zone rule must be preserved except |
| 173 // zones not actually associated with a specific locatio
n. |
| 174 // Time zones in this category do not have "/" in its ID
. |
| 175 UnicodeString canonical; |
| 176 TimeZone::getCanonicalID(*tzid, canonical, status); |
| 177 if (U_FAILURE(status)) { |
| 178 // Uknown ID - we should not get here |
| 179 errln((UnicodeString)"Unknown ID " + *tzid); |
| 180 status = U_ZERO_ERROR; |
| 181 } else if (outtzid != canonical) { |
| 182 // Canonical ID did not match - check the rules |
| 183 if (!((BasicTimeZone*)&outtz)->hasEquivalentTransiti
ons((BasicTimeZone&)*tz, low, high, TRUE, status)) { |
| 184 if (canonical.indexOf((UChar)0x27 /*'/'*/) == -1
) { |
| 185 // Exceptional cases, such as CET, EET, MET
and WET |
| 186 logln("Canonical round trip failed (as expec
ted); tz=" + *tzid |
| 187 + ", locale=" + LOCALES[locidx].getN
ame() + ", pattern=" + PATTERNS[patidx] |
| 188 + ", time=" + DATES[datidx] + ", str
=" + tzstr |
| 189 + ", outtz=" + outtzid); |
| 190 } else { |
| 191 errln("Canonical round trip failed; tz=" + *
tzid |
| 192 + ", locale=" + LOCALES[locidx].getName(
) + ", pattern=" + PATTERNS[patidx] |
| 193 + ", time=" + DATES[datidx] + ", str=" +
tzstr |
| 194 + ", outtz=" + outtzid); |
| 195 } |
| 196 if (U_FAILURE(status)) { |
| 197 errln("hasEquivalentTransitions failed"); |
| 198 status = U_ZERO_ERROR; |
| 199 } |
| 200 } |
| 201 } |
| 202 |
| 203 } else { |
| 204 // Check if localized GMT format or RFC format is used. |
| 205 int32_t numDigits = 0; |
| 206 for (int n = 0; n < tzstr.length(); n++) { |
| 207 if (u_isdigit(tzstr.charAt(n))) { |
| 208 numDigits++; |
| 209 } |
| 210 } |
| 211 if (numDigits >= 3) { |
| 212 // Localized GMT or RFC: total offset (raw + dst) mu
st be preserved. |
| 213 int32_t inOffset = inRaw + inDst; |
| 214 int32_t outOffset = outRaw + outDst; |
| 215 if (inOffset != outOffset) { |
| 216 errln((UnicodeString)"Offset round trip failed;
tz=" + *tzid |
| 217 + ", locale=" + LOCALES[locidx].getName() +
", pattern=" + PATTERNS[patidx] |
| 218 + ", time=" + DATES[datidx] + ", str=" + tzs
tr |
| 219 + ", inOffset=" + inOffset + ", outOffset="
+ outOffset); |
| 220 } |
| 221 } else { |
| 222 // Specific or generic: raw offset must be preserved
. |
| 223 if (inRaw != outRaw) { |
| 224 errln((UnicodeString)"Raw offset round trip fail
ed; tz=" + *tzid |
| 225 + ", locale=" + LOCALES[locidx].getName() +
", pattern=" + PATTERNS[patidx] |
| 226 + ", time=" + DATES[datidx] + ", str=" + tzs
tr |
| 227 + ", inRawOffset=" + inRaw + ", outRawOffset
=" + outRaw); |
| 228 } |
| 229 } |
| 230 } |
| 231 delete outcal; |
| 232 } |
| 233 delete tz; |
| 234 } |
| 235 delete sdf; |
| 236 } |
| 237 } |
| 238 delete cal; |
| 239 delete tzids; |
| 240 } |
| 241 |
| 242 struct LocaleData { |
| 243 int32_t index; |
| 244 int32_t testCounts; |
| 245 UDate *times; |
| 246 const Locale* locales; // Static |
| 247 int32_t nLocales; // Static |
| 248 UBool quick; // Static |
| 249 UDate START_TIME; // Static |
| 250 UDate END_TIME; // Static |
| 251 int32_t numDone; |
| 252 }; |
| 253 |
| 254 class TestTimeRoundTripThread: public SimpleThread { |
| 255 public: |
| 256 TestTimeRoundTripThread(IntlTest& tlog, LocaleData &ld, int32_t i) |
| 257 : log(tlog), data(ld), index(i) {} |
| 258 virtual void run() { |
| 259 UErrorCode status = U_ZERO_ERROR; |
| 260 UBool REALLY_VERBOSE = FALSE; |
| 261 |
| 262 // Whether each pattern is ambiguous at DST->STD local time overlap |
| 263 UBool AMBIGUOUS_DST_DECESSION[] = { FALSE, FALSE, FALSE, FALSE, TRUE, TR
UE, FALSE, TRUE }; |
| 264 // Whether each pattern is ambiguous at STD->STD/DST->DST local time ove
rlap |
| 265 UBool AMBIGUOUS_NEGATIVE_SHIFT[] = { TRUE, TRUE, FALSE, FALSE, TRUE, TRU
E, TRUE, TRUE }; |
| 266 |
| 267 // Workaround for #6338 |
| 268 //UnicodeString BASEPATTERN("yyyy-MM-dd'T'HH:mm:ss.SSS"); |
| 269 UnicodeString BASEPATTERN("yyyy.MM.dd HH:mm:ss.SSS"); |
| 270 |
| 271 // timer for performance analysis |
| 272 UDate timer; |
| 273 UDate testTimes[4]; |
| 274 UBool expectedRoundTrip[4]; |
| 275 int32_t testLen = 0; |
| 276 |
| 277 StringEnumeration *tzids = TimeZone::createEnumeration(); |
| 278 if (U_FAILURE(status)) { |
| 279 log.errln("tzids->count failed"); |
| 280 return; |
| 281 } |
| 282 |
| 283 int32_t locidx = -1; |
| 284 UDate times[NUM_PATTERNS]; |
| 285 for (int32_t i = 0; i < NUM_PATTERNS; i++) { |
| 286 times[i] = 0; |
| 287 } |
| 288 |
| 289 int32_t testCounts = 0; |
| 290 |
| 291 while (true) { |
| 292 umtx_lock(NULL); // Lock to increment the index |
| 293 for (int32_t i = 0; i < NUM_PATTERNS; i++) { |
| 294 data.times[i] += times[i]; |
| 295 data.testCounts += testCounts; |
| 296 } |
| 297 if (data.index < data.nLocales) { |
| 298 locidx = data.index; |
| 299 data.index++; |
| 300 } else { |
| 301 locidx = -1; |
| 302 } |
| 303 umtx_unlock(NULL); // Unlock for other threads to use |
| 304 |
| 305 if (locidx == -1) { |
| 306 log.logln((UnicodeString) "Thread " + index + " is done."); |
| 307 break; |
| 308 } |
| 309 |
| 310 log.logln((UnicodeString) "\nThread " + index + ": Locale: " + Unico
deString(data.locales[locidx].getName())); |
| 311 |
| 312 for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) { |
| 313 log.logln((UnicodeString) " Pattern: " + PATTERNS[patidx]); |
| 314 times[patidx] = 0; |
| 315 |
| 316 UnicodeString pattern(BASEPATTERN); |
| 317 pattern.append(" ").append(PATTERNS[patidx]); |
| 318 |
| 319 SimpleDateFormat *sdf = new SimpleDateFormat(pattern, data.local
es[locidx], status); |
| 320 if (U_FAILURE(status)) { |
| 321 log.errcheckln(status, (UnicodeString) "new SimpleDateFormat
failed for pattern " + |
| 322 pattern + " for locale " + data.locales[locidx].getName(
) + " - " + u_errorName(status)); |
| 323 status = U_ZERO_ERROR; |
| 324 continue; |
| 325 } |
| 326 |
| 327 tzids->reset(status); |
| 328 const UnicodeString *tzid; |
| 329 |
| 330 timer = Calendar::getNow(); |
| 331 |
| 332 while ((tzid = tzids->snext(status))) { |
| 333 UnicodeString canonical; |
| 334 TimeZone::getCanonicalID(*tzid, canonical, status); |
| 335 if (U_FAILURE(status)) { |
| 336 // Unknown ID - we should not get here |
| 337 status = U_ZERO_ERROR; |
| 338 continue; |
| 339 } |
| 340 if (*tzid != canonical) { |
| 341 // Skip aliases |
| 342 continue; |
| 343 } |
| 344 BasicTimeZone *tz = (BasicTimeZone*) TimeZone::createTimeZon
e(*tzid); |
| 345 sdf->setTimeZone(*tz); |
| 346 |
| 347 UDate t = data.START_TIME; |
| 348 TimeZoneTransition tzt; |
| 349 UBool tztAvail = FALSE; |
| 350 UBool middle = TRUE; |
| 351 |
| 352 while (t < data.END_TIME) { |
| 353 if (!tztAvail) { |
| 354 testTimes[0] = t; |
| 355 expectedRoundTrip[0] = TRUE; |
| 356 testLen = 1; |
| 357 } else { |
| 358 int32_t fromOffset = tzt.getFrom()->getRawOffset() +
tzt.getFrom()->getDSTSavings(); |
| 359 int32_t toOffset = tzt.getTo()->getRawOffset() + tzt
.getTo()->getDSTSavings(); |
| 360 int32_t delta = toOffset - fromOffset; |
| 361 if (delta < 0) { |
| 362 UBool isDstDecession = tzt.getFrom()->getDSTSavi
ngs() > 0 && tzt.getTo()->getDSTSavings() == 0; |
| 363 testTimes[0] = t + delta - 1; |
| 364 expectedRoundTrip[0] = TRUE; |
| 365 testTimes[1] = t + delta; |
| 366 expectedRoundTrip[1] = isDstDecession ? !AMBIGUO
US_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx]; |
| 367 testTimes[2] = t - 1; |
| 368 expectedRoundTrip[2] = isDstDecession ? !AMBIGUO
US_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx]; |
| 369 testTimes[3] = t; |
| 370 expectedRoundTrip[3] = TRUE; |
| 371 testLen = 4; |
| 372 } else { |
| 373 testTimes[0] = t - 1; |
| 374 expectedRoundTrip[0] = TRUE; |
| 375 testTimes[1] = t; |
| 376 expectedRoundTrip[1] = TRUE; |
| 377 testLen = 2; |
| 378 } |
| 379 } |
| 380 for (int32_t testidx = 0; testidx < testLen; testidx++)
{ |
| 381 if (data.quick) { |
| 382 // reduce regular test time |
| 383 if (!expectedRoundTrip[testidx]) { |
| 384 continue; |
| 385 } |
| 386 } |
| 387 |
| 388 testCounts++; |
| 389 |
| 390 UnicodeString text; |
| 391 FieldPosition fpos(0); |
| 392 sdf->format(testTimes[testidx], text, fpos); |
| 393 |
| 394 UDate parsedDate = sdf->parse(text, status); |
| 395 if (U_FAILURE(status)) { |
| 396 log.errln((UnicodeString) "Parse failure for tex
t=" + text + ", tzid=" + *tzid + ", locale=" + data.locales[locidx].getName() |
| 397 + ", pattern=" + PATTERNS[patidx] + ", t
ime=" + testTimes[testidx]); |
| 398 status = U_ZERO_ERROR; |
| 399 continue; |
| 400 } |
| 401 if (parsedDate != testTimes[testidx]) { |
| 402 UnicodeString msg = (UnicodeString) "Time round
trip failed for " + "tzid=" + *tzid + ", locale=" + data.locales[locidx].getName
() + ", pattern=" + PATTERNS[patidx] |
| 403 + ", text=" + text + ", time=" + testTim
es[testidx] + ", restime=" + parsedDate + ", diff=" + (parsedDate - testTimes[te
stidx]); |
| 404 if (expectedRoundTrip[testidx]) { |
| 405 log.errln((UnicodeString) "FAIL: " + msg); |
| 406 } else if (REALLY_VERBOSE) { |
| 407 log.logln(msg); |
| 408 } |
| 409 } |
| 410 } |
| 411 tztAvail = tz->getNextTransition(t, FALSE, tzt); |
| 412 if (!tztAvail) { |
| 413 break; |
| 414 } |
| 415 if (middle) { |
| 416 // Test the date in the middle of two transitions. |
| 417 t += (int64_t) ((tzt.getTime() - t) / 2); |
| 418 middle = FALSE; |
| 419 tztAvail = FALSE; |
| 420 } else { |
| 421 t = tzt.getTime(); |
| 422 } |
| 423 } |
| 424 delete tz; |
| 425 } |
| 426 times[patidx] += (Calendar::getNow() - timer); |
| 427 delete sdf; |
| 428 } |
| 429 umtx_lock(NULL); |
| 430 data.numDone++; |
| 431 umtx_unlock(NULL); |
| 432 } |
| 433 delete tzids; |
| 434 } |
| 435 private: |
| 436 IntlTest& log; |
| 437 LocaleData& data; |
| 438 int32_t index; |
| 439 }; |
| 440 |
| 441 void |
| 442 TimeZoneFormatTest::TestTimeRoundTrip(void) { |
| 443 int32_t nThreads = threadCount; |
| 444 const Locale *LOCALES; |
| 445 int32_t nLocales; |
| 446 int32_t testCounts = 0; |
| 447 |
| 448 UErrorCode status = U_ZERO_ERROR; |
| 449 Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeSt
ring) "UTC"), status); |
| 450 if (U_FAILURE(status)) { |
| 451 dataerrln("Calendar::createInstance failed: %s", u_errorName(status)); |
| 452 return; |
| 453 } |
| 454 |
| 455 const char* testAllProp = getProperty("TimeZoneRoundTripAll"); |
| 456 UBool bTestAll = (testAllProp && uprv_strcmp(testAllProp, "true") == 0); |
| 457 |
| 458 UDate START_TIME, END_TIME; |
| 459 if (bTestAll || !quick) { |
| 460 cal->set(1900, UCAL_JANUARY, 1); |
| 461 } else { |
| 462 cal->set(1990, UCAL_JANUARY, 1); |
| 463 } |
| 464 START_TIME = cal->getTime(status); |
| 465 |
| 466 cal->set(2015, UCAL_JANUARY, 1); |
| 467 END_TIME = cal->getTime(status); |
| 468 |
| 469 if (U_FAILURE(status)) { |
| 470 errln("getTime failed"); |
| 471 return; |
| 472 } |
| 473 |
| 474 UDate times[NUM_PATTERNS]; |
| 475 for (int32_t i = 0; i < NUM_PATTERNS; i++) { |
| 476 times[i] = 0; |
| 477 } |
| 478 |
| 479 // Set up test locales |
| 480 const Locale locales1[] = {Locale("en")}; |
| 481 const Locale locales2[] = { |
| 482 Locale("ar_EG"), Locale("bg_BG"), Locale("ca_ES"), Locale("da_DK"), Loca
le("de"), |
| 483 Locale("de_DE"), Locale("el_GR"), Locale("en"), Locale("en_AU"), Locale(
"en_CA"), |
| 484 Locale("en_US"), Locale("es"), Locale("es_ES"), Locale("es_MX"), Locale(
"fi_FI"), |
| 485 Locale("fr"), Locale("fr_CA"), Locale("fr_FR"), Locale("he_IL"), Locale(
"hu_HU"), |
| 486 Locale("it"), Locale("it_IT"), Locale("ja"), Locale("ja_JP"), Locale("ko
"), |
| 487 Locale("ko_KR"), Locale("nb_NO"), Locale("nl_NL"), Locale("nn_NO"), Loca
le("pl_PL"), |
| 488 Locale("pt"), Locale("pt_BR"), Locale("pt_PT"), Locale("ru_RU"), Locale(
"sv_SE"), |
| 489 Locale("th_TH"), Locale("tr_TR"), Locale("zh"), Locale("zh_Hans"), Local
e("zh_Hans_CN"), |
| 490 Locale("zh_Hant"), Locale("zh_Hant_TW") |
| 491 }; |
| 492 |
| 493 if (bTestAll) { |
| 494 LOCALES = Locale::getAvailableLocales(nLocales); |
| 495 } else if (quick) { |
| 496 LOCALES = locales1; |
| 497 nLocales = sizeof(locales1)/sizeof(Locale); |
| 498 } else { |
| 499 LOCALES = locales2; |
| 500 nLocales = sizeof(locales2)/sizeof(Locale); |
| 501 } |
| 502 |
| 503 LocaleData data; |
| 504 data.index = 0; |
| 505 data.testCounts = testCounts; |
| 506 data.times = times; |
| 507 data.locales = LOCALES; |
| 508 data.nLocales = nLocales; |
| 509 data.quick = quick; |
| 510 data.START_TIME = START_TIME; |
| 511 data.END_TIME = END_TIME; |
| 512 data.numDone = 0; |
| 513 |
| 514 #if (ICU_USE_THREADS==0) |
| 515 TestTimeRoundTripThread fakeThread(*this, data, 0); |
| 516 fakeThread.run(); |
| 517 #else |
| 518 TestTimeRoundTripThread **threads = new TestTimeRoundTripThread*[threadCount
]; |
| 519 int32_t i; |
| 520 for (i = 0; i < nThreads; i++) { |
| 521 threads[i] = new TestTimeRoundTripThread(*this, data, i); |
| 522 if (threads[i]->start() != 0) { |
| 523 errln("Error starting thread %d", i); |
| 524 } |
| 525 } |
| 526 |
| 527 UBool done = false; |
| 528 while (true) { |
| 529 umtx_lock(NULL); |
| 530 if (data.numDone == nLocales) { |
| 531 done = true; |
| 532 } |
| 533 umtx_unlock(NULL); |
| 534 if (done) |
| 535 break; |
| 536 SimpleThread::sleep(1000); |
| 537 } |
| 538 |
| 539 for (i = 0; i < nThreads; i++) { |
| 540 delete threads[i]; |
| 541 } |
| 542 delete [] threads; |
| 543 |
| 544 #endif |
| 545 UDate total = 0; |
| 546 logln("### Elapsed time by patterns ###"); |
| 547 for (int32_t i = 0; i < NUM_PATTERNS; i++) { |
| 548 logln(UnicodeString("") + data.times[i] + "ms (" + PATTERNS[i] + ")"); |
| 549 total += data.times[i]; |
| 550 } |
| 551 logln((UnicodeString) "Total: " + total + "ms"); |
| 552 logln((UnicodeString) "Iteration: " + data.testCounts); |
| 553 |
| 554 delete cal; |
| 555 } |
| 556 |
| 557 #endif /* #if !UCONFIG_NO_FORMATTING */ |
OLD | NEW |