crt: Extend t_time test for _localtime64 and _mktime64 Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/testcases/t_time.c b/mingw-w64-crt/testcases/t_time.c index 50b07d0..be912b8 100644 --- a/mingw-w64-crt/testcases/t_time.c +++ b/mingw-w64-crt/testcases/t_time.c
@@ -10,14 +10,17 @@ int main() { - time_t t; - __time32_t t32; - __time64_t t64; + time_t t, t_; + __time32_t t32, t32_; + __time64_t t64, t64_; struct timeb tb; struct _timeb tb_; struct __timeb32 tb32; struct __timeb64 tb64; struct tm *htm; + struct tm tm1; + struct tm tm2; + struct tm tm3; int ret1, ret2, ret3; const char *str; const wchar_t *wstr; @@ -95,8 +98,160 @@ assert (htm->tm_yday == 74); assert (htm->tm_isdst == 0); - /* ctime returns time string in local timezone, so set local timezone to UTC to have test timezone independent */ - putenv ("TZ=UTC"); + const time_t times[] = { + 1700000000 /* Tue Nov 14 22:13:20 UTC 2023 */, + 1600000000 /* Sun Sep 13 12:26:40 UTC 2020 */, + }; + for (size_t i = 0; i < sizeof(times)/sizeof(*times); i++) { + t = times[i]; + htm = localtime (&t); + tm1 = *htm; + printf ("localtime(%lld): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + (long long)t, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + t_ = mktime (htm); + printf ("mktime(): %lld sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + (long long)t_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (t_ == t); + assert (memcmp (htm, &tm1, sizeof(tm1)) == 0); + + t32 = t; + htm = _localtime32 (&t32); + tm2 = *htm; + printf ("_localtime32(%d): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t32, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + t32_ = _mktime32 (htm); + printf ("_mktime32(): %d sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t32_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (t32_ == t32); + assert (memcmp (htm, &tm2, sizeof(tm2)) == 0); + + t64 = t; + htm = _localtime64 (&t64); + tm3 = *htm; + printf ("_localtime64(%lld): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + t64_ = _mktime64 (htm); + printf ("_mktime64(): %lld sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (t64_ == t64); + assert (memcmp (htm, &tm3, sizeof(tm3)) == 0); + + assert (memcmp (&tm1, &tm2, sizeof(tm1)) == 0); + assert (memcmp (&tm2, &tm3, sizeof(tm2)) == 0); + } + + /* following tests are explicitly for Pacific Time Zone */ + putenv ("TZ=PST8PDT"); + _dstbias = -3600; /* tzset() does not change _dstbias when TZ= env is nonempty */ + tzset (); + const struct { + __time64_t time; + int year; int mon; int day; + int hour; int min; int sec; + int dst; + } pt_times[] = { + { 1112520600, 2005, 4, 3, 1, 30, 0, 0 }, /* Sun Apr 3 09:30:00 UTC 2005 == Sun Apr 3 01:30:00 PST 2005 */ + { 1112524200, 2005, 4, 3, 3, 30, 0, 1 }, /* Sun Apr 3 10:30:00 UTC 2005 == Sun Apr 3 03:30:00 PDT 2005 */ + { 1130657400, 2005, 10, 30, 0, 30, 0, 1 }, /* Sun Oct 30 07:30:00 UTC 2005 == Sun Oct 30 00:30:00 PDT 2005 */ + { 1130661000, 2005, 10, 30, 1, 30, 0, 1 }, /* Sun Oct 30 08:30:00 UTC 2005 == Sun Oct 30 01:30:00 PDT 2005 */ + { 1130664600, 2005, 10, 30, 1, 30, 0, 0 }, /* Sun Oct 30 09:30:00 UTC 2005 == Sun Oct 30 01:30:00 PST 2005 */ + { 1130668200, 2005, 10, 30, 2, 30, 0, 0 }, /* Sun Oct 30 10:30:00 UTC 2005 == Sun Oct 30 02:30:00 PST 2005 */ + { 1130671800, 2005, 10, 30, 3, 30, 0, 0 }, /* Sun Oct 30 11:30:00 UTC 2005 == Sun Oct 30 03:30:00 PST 2005 */ + }; + for (size_t i = 0; i < sizeof(pt_times)/sizeof(*pt_times); i++) { + int skip_mktime_check = 0; + + if (pt_times[i].time <= INT_MAX) { + t32 = pt_times[i].time; + htm = _localtime32 (&t32); + tm2 = *htm; + printf ("pacific _localtime32(%d): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t32, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (pt_times[i].year == htm->tm_year + 1900); + assert (pt_times[i].mon == htm->tm_mon + 1); + assert (pt_times[i].day == htm->tm_mday); + assert (pt_times[i].hour == htm->tm_hour); + assert (pt_times[i].min == htm->tm_min); + assert (pt_times[i].sec == htm->tm_sec); + assert (pt_times[i].dst == htm->tm_isdst); + t32_ = _mktime32 (htm); + printf ("pacific _mktime32(): %d sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t32_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); +#if __MSVCRT_VERSION__ < 0x800 + /* Versioned msvcrt libraries older than msvcr80 (and some system msvcrt version too) + * have broken native 32-bit mktime function for timestamps around the DST change. + * If the native 32-bit mktime function is broken then skip tests for 64-bit mktime function. + */ + if (t32_ != t32) + skip_mktime_check = 1; +#endif + if (!skip_mktime_check) { + assert (t32_ == t32); + assert (memcmp (htm, &tm2, sizeof(tm2)) == 0); + } else { + printf ("Skipping _mktime32 assert because of broken CRT library\n"); + } + } + + if (sizeof(t) >= 8 || pt_times[i].time <= INT_MAX) { + t = pt_times[i].time; + htm = localtime (&t); + tm1 = *htm; + printf ("pacific localtime(%lld): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + (long long)t, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (pt_times[i].year == htm->tm_year + 1900); + assert (pt_times[i].mon == htm->tm_mon + 1); + assert (pt_times[i].day == htm->tm_mday); + assert (pt_times[i].hour == htm->tm_hour); + assert (pt_times[i].min == htm->tm_min); + assert (pt_times[i].sec == htm->tm_sec); + assert (pt_times[i].dst == htm->tm_isdst); + t_ = mktime (htm); + printf ("pacific mktime(): %lld sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + (long long)t_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + if (!skip_mktime_check) { + assert (t_ == t); + assert (memcmp (htm, &tm1, sizeof(tm1)) == 0); + } else { + printf ("Skipping mktime assert because of broken CRT library\n"); + } + } + + t64 = pt_times[i].time; + htm = _localtime64 (&t64); + tm3 = *htm; + printf ("pacific _localtime64(%lld): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (pt_times[i].year == htm->tm_year + 1900); + assert (pt_times[i].mon == htm->tm_mon + 1); + assert (pt_times[i].day == htm->tm_mday); + assert (pt_times[i].hour == htm->tm_hour); + assert (pt_times[i].min == htm->tm_min); + assert (pt_times[i].sec == htm->tm_sec); + assert (pt_times[i].dst == htm->tm_isdst); + t64_ = _mktime64 (htm); + printf ("pacific _mktime64(): %lld sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + if (!skip_mktime_check) { + assert (t64_ == t64); + assert (memcmp (htm, &tm3, sizeof(tm3)) == 0); + } else { + printf ("Skipping _mktime64 assert because of broken CRT library\n"); + } + + if (sizeof(t) >= 8 || pt_times[i].time <= INT_MAX) + assert (memcmp (&tm1, &tm3, sizeof(tm1)) == 0); + + if (pt_times[i].time <= INT_MAX) + assert (memcmp (&tm1, &tm2, sizeof(tm1)) == 0); + + if (pt_times[i].time <= INT_MAX) + assert (memcmp (&tm2, &tm3, sizeof(tm2)) == 0); + } + + /* ctime, localtime and mktime returns time string in local timezone, so set local timezone to UTC to have test timezone independent */ + putenv ("TZ=UTC0"); + _dstbias = 0; /* tzset() does not change _dstbias when TZ= env is nonempty */ tzset (); t64 = 1ULL << 33; @@ -109,5 +264,48 @@ printf ("_wctime64(1<<33): %ls", wstr); assert (wcscmp (wstr, L"Wed Mar 16 12:56:32 2242\n") == 0); + t64 = 1ULL << 33; + htm = _localtime64( &t64 ); + printf ("_localtime64(1<<33): sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (htm->tm_sec == 32); + assert (htm->tm_min == 56); + assert (htm->tm_hour == 12); + assert (htm->tm_mday == 16); + assert (htm->tm_mon == 2); + assert (htm->tm_year == 342); + assert (htm->tm_wday == 3); + assert (htm->tm_yday == 74); + assert (htm->tm_isdst == 0); + + t64 = _mktime64 (htm); + printf ("_mktime64(): 0x%I64x sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (t64 == (1ULL << 33)); + assert (htm->tm_sec == 32); + assert (htm->tm_min == 56); + assert (htm->tm_hour == 12); + assert (htm->tm_mday == 16); + assert (htm->tm_mon == 2); + assert (htm->tm_year == 342); + assert (htm->tm_wday == 3); + assert (htm->tm_yday == 74); + assert (htm->tm_isdst == 0); + + htm->tm_min = 66; /* change 56 to 66 -> + 10 minutes */ + t64 = _mktime64 (htm); + printf ("_mktime64(): 0x%I64x sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d yday=%d isdst=%d\n", + t64, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst); + assert (t64 == (1ULL << 33) + 10*60); /* + 10 minutes */ + assert (htm->tm_sec == 32); + assert (htm->tm_min == 6); /* 66 is changed to 6 */ + assert (htm->tm_hour == 13); /* 12 is changed to 13 */ + assert (htm->tm_mday == 16); + assert (htm->tm_mon == 2); + assert (htm->tm_year == 342); + assert (htm->tm_wday == 3); + assert (htm->tm_yday == 74); + assert (htm->tm_isdst == 0); + return 0; }