2 * Unit test suite for time functions.
4 * Copyright 2004 Uwe Bonnes
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "wine/test.h"
26 #include <stdlib.h> /*setenv*/
27 #include <stdio.h> /*printf*/
31 #define _MAX__TIME64_T (((__time64_t)0x00000007 << 32) | 0x93406FFF)
33 #define SECSPERDAY 86400
34 #define SECSPERHOUR 3600
36 #define MINSPERHOUR 60
37 #define HOURSPERDAY 24
39 static __time32_t (__cdecl
*p_mkgmtime32
)(struct tm
*);
40 static struct tm
* (__cdecl
*p_gmtime32
)(__time32_t
*);
41 static struct tm
* (__cdecl
*p_gmtime
)(time_t*);
42 static errno_t (__cdecl
*p_gmtime32_s
)(struct tm
*, __time32_t
*);
43 static errno_t (__cdecl
*p_strtime_s
)(char*,size_t);
44 static errno_t (__cdecl
*p_strdate_s
)(char*,size_t);
45 static errno_t (__cdecl
*p_localtime32_s
)(struct tm
*, __time32_t
*);
46 static errno_t (__cdecl
*p_localtime64_s
)(struct tm
*, __time64_t
*);
47 static int* (__cdecl
*p__daylight
)(void);
48 static int* (__cdecl
*p___p__daylight
)(void);
49 static long* (__cdecl
*p___p__dstbias
)(void);
50 static long* (__cdecl
*p__dstbias
)(void);
51 static long* (__cdecl
*p___p__timezone
)(void);
52 static size_t (__cdecl
*p_strftime
)(char *, size_t, const char *, const struct tm
*);
53 static size_t (__cdecl
*p_wcsftime
)(wchar_t *, size_t, const wchar_t *, const struct tm
*);
54 static char* (__cdecl
*p_asctime
)(const struct tm
*);
56 static void init(void)
58 HMODULE hmod
= LoadLibraryA("msvcrt.dll");
60 p_gmtime32
= (void*)GetProcAddress(hmod
, "_gmtime32");
61 p_gmtime
= (void*)GetProcAddress(hmod
, "gmtime");
62 p_gmtime32_s
= (void*)GetProcAddress(hmod
, "_gmtime32_s");
63 p_mkgmtime32
= (void*)GetProcAddress(hmod
, "_mkgmtime32");
64 p_strtime_s
= (void*)GetProcAddress(hmod
, "_strtime_s");
65 p_strdate_s
= (void*)GetProcAddress(hmod
, "_strdate_s");
66 p_localtime32_s
= (void*)GetProcAddress(hmod
, "_localtime32_s");
67 p_localtime64_s
= (void*)GetProcAddress(hmod
, "_localtime64_s");
68 p__daylight
= (void*)GetProcAddress(hmod
, "__daylight");
69 p___p__daylight
= (void*)GetProcAddress(hmod
, "__p__daylight");
70 p___p__dstbias
= (void*)GetProcAddress(hmod
, "__p__dstbias");
71 p__dstbias
= (void*)GetProcAddress(hmod
, "__dstbias");
72 p___p__timezone
= (void*)GetProcAddress(hmod
, "__p__timezone");
73 p_strftime
= (void*)GetProcAddress(hmod
, "strftime");
74 p_wcsftime
= (void*)GetProcAddress(hmod
, "wcsftime");
75 p_asctime
= (void*)GetProcAddress(hmod
, "asctime");
78 static int get_test_year(time_t *start
)
80 time_t now
= time(NULL
);
81 struct tm
*tm
= localtime(&now
);
83 /* compute start of year in seconds */
84 *start
= SECSPERDAY
* ((tm
->tm_year
- 70) * 365 +
85 (tm
->tm_year
- 69) / 4 -
86 (tm
->tm_year
- 1) / 100 +
87 (tm
->tm_year
+ 299) / 400);
91 static void test_ctime(void)
95 ret
= ctime(&badtime
);
96 ok(ret
== NULL
, "expected ctime to return NULL, got %s\n", ret
);
98 static void test_gmtime(void)
100 __time32_t valid
, gmt
;
101 struct tm
* gmt_tm
, gmt_tm_s
;
105 win_skip("Skipping _gmtime32 tests\n");
109 gmt_tm
= p_gmtime32(NULL
);
110 ok(gmt_tm
== NULL
, "gmt_tm != NULL\n");
113 gmt_tm
= p_gmtime32(&gmt
);
114 ok(gmt_tm
==NULL
|| broken(gmt_tm
->tm_year
==70 && gmt_tm
->tm_sec
<0), "gmt_tm != NULL\n");
117 gmt_tm
= p_gmtime32(&gmt
);
119 ok(0, "_gmtime32() failed\n");
123 ok(((gmt_tm
->tm_year
== 70) && (gmt_tm
->tm_mon
== 0) && (gmt_tm
->tm_yday
== 0) &&
124 (gmt_tm
->tm_mday
== 1) && (gmt_tm
->tm_wday
== 4) && (gmt_tm
->tm_hour
== 0) &&
125 (gmt_tm
->tm_min
== 0) && (gmt_tm
->tm_sec
== 0) && (gmt_tm
->tm_isdst
== 0)),
126 "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
127 gmt_tm
->tm_year
, gmt_tm
->tm_mon
, gmt_tm
->tm_yday
, gmt_tm
->tm_mday
, gmt_tm
->tm_wday
,
128 gmt_tm
->tm_hour
, gmt_tm
->tm_min
, gmt_tm
->tm_sec
, gmt_tm
->tm_isdst
);
131 win_skip("Skipping _mkgmtime32 tests\n");
135 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
136 gmt
= p_mkgmtime32(gmt_tm
);
137 ok(gmt
== valid
, "gmt = %u\n", gmt
);
138 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
139 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
141 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
142 gmt_tm
->tm_isdst
= -1;
143 gmt
= p_mkgmtime32(gmt_tm
);
144 ok(gmt
== valid
, "gmt = %u\n", gmt
);
145 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
146 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
148 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
149 gmt_tm
->tm_isdst
= 1;
150 gmt
= p_mkgmtime32(gmt_tm
);
151 ok(gmt
== valid
, "gmt = %u\n", gmt
);
152 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
153 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
155 gmt
= valid
= 173921;
156 gmt_tm
= p_gmtime32(&gmt
);
158 ok(0, "_gmtime32() failed\n");
162 gmt_tm
->tm_isdst
= -1;
163 gmt
= p_mkgmtime32(gmt_tm
);
164 ok(gmt
== valid
, "gmt = %u\n", gmt
);
165 ok(gmt_tm
->tm_wday
== 6, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
166 ok(gmt_tm
->tm_yday
== 2, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
168 gmt_tm
->tm_isdst
= 1;
169 gmt
= p_mkgmtime32(gmt_tm
);
170 ok(gmt
== valid
, "gmt = %u\n", gmt
);
173 win_skip("Skipping _gmtime32_s tests\n");
179 err
= p_gmtime32_s(NULL
, &gmt
);
180 ok(err
== EINVAL
, "err = %d\n", err
);
181 ok(errno
== EINVAL
, "errno = %d\n", errno
);
185 err
= p_gmtime32_s(&gmt_tm_s
, &gmt
);
186 ok(gmt_tm_s
.tm_year
== -1 || broken(gmt_tm_s
.tm_year
== 70 && gmt_tm_s
.tm_sec
< 0),
187 "tm_year = %d, tm_sec = %d\n", gmt_tm_s
.tm_year
, gmt_tm_s
.tm_sec
);
188 if(gmt_tm_s
.tm_year
== -1) {
189 ok(err
==EINVAL
, "err = %d\n", err
);
190 ok(errno
==EINVAL
, "errno = %d\n", errno
);
194 static void test_mktime(void)
196 TIME_ZONE_INFORMATION tzinfo
;
197 DWORD res
= GetTimeZoneInformation(&tzinfo
);
198 struct tm my_tm
, sav_tm
;
199 time_t nulltime
, local_time
;
205 year
= get_test_year( &ref
);
208 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
209 WideCharToMultiByte( CP_ACP
, 0, tzinfo
.StandardName
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
210 trace( "bias %d std %d dst %d zone %s\n",
211 tzinfo
.Bias
, tzinfo
.StandardBias
, tzinfo
.DaylightBias
, buffer
);
212 /* Bias may be positive or negative, to use offset of one day */
213 my_tm
= *localtime(&ref
); /* retrieve current dst flag */
214 secs
= SECSPERDAY
- tzinfo
.Bias
* SECSPERMIN
;
215 secs
-= (my_tm
.tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
216 my_tm
.tm_mday
= 1 + secs
/SECSPERDAY
;
217 secs
= secs
% SECSPERDAY
;
218 my_tm
.tm_hour
= secs
/ SECSPERHOUR
;
219 secs
= secs
% SECSPERHOUR
;
220 my_tm
.tm_min
= secs
/ SECSPERMIN
;
221 secs
= secs
% SECSPERMIN
;
224 my_tm
.tm_year
= year
;
229 local_time
= mktime(&my_tm
);
230 ok(local_time
== ref
, "mktime returned %u, expected %u\n",
231 (DWORD
)local_time
, (DWORD
)ref
);
232 /* now test some unnormalized struct tm's */
236 local_time
= mktime(&my_tm
);
237 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
238 (DWORD
)local_time
, (DWORD
)ref
);
239 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
240 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
241 my_tm
.tm_sec
== sav_tm
.tm_sec
,
242 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
243 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
244 my_tm
.tm_hour
,my_tm
.tm_sec
,
245 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
246 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
250 local_time
= mktime(&my_tm
);
251 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
252 (DWORD
)local_time
, (DWORD
)ref
);
253 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
254 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
255 my_tm
.tm_sec
== sav_tm
.tm_sec
,
256 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
257 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
258 my_tm
.tm_hour
,my_tm
.tm_sec
,
259 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
260 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
264 local_time
= mktime(&my_tm
);
265 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
266 (DWORD
)local_time
, (DWORD
)ref
);
267 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
268 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
269 my_tm
.tm_sec
== sav_tm
.tm_sec
,
270 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
271 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
272 my_tm
.tm_hour
,my_tm
.tm_sec
,
273 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
274 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
278 local_time
= mktime(&my_tm
);
279 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
280 (DWORD
)local_time
, (DWORD
)ref
);
281 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
282 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
283 my_tm
.tm_sec
== sav_tm
.tm_sec
,
284 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
285 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
286 my_tm
.tm_hour
,my_tm
.tm_sec
,
287 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
288 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
289 /* now a bad time example */
292 local_time
= mktime(&my_tm
);
293 ok((local_time
== -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time
);
296 /* TEST that we are independent from the TZ variable */
297 /*Argh, msvcrt doesn't have setenv() */
298 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
300 nulltime
= mktime(&my_tm
);
301 ok(nulltime
== ref
,"mktime returned 0x%08x\n",(DWORD
)nulltime
);
305 static void test_localtime(void)
307 TIME_ZONE_INFORMATION tzinfo
;
308 DWORD res
= GetTimeZoneInformation(&tzinfo
);
313 int year
= get_test_year( &ref
);
314 int is_leap
= !(year
% 4) && ((year
% 100) || !((year
+ 300) % 400));
316 gmt
= ref
+ SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
317 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
318 lt
= localtime(&gmt
);
319 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
320 lt
= localtime(&gmt
);
321 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
322 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
323 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
324 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
325 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
326 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
328 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
330 lt
= localtime(&gmt
);
331 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
332 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
333 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
334 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
335 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
336 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
340 gmt
= ref
+ 202 * SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
341 lt
= localtime(&gmt
);
342 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
343 lt
= localtime(&gmt
);
344 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 6) && (lt
->tm_yday
== 202) &&
345 (lt
->tm_mday
== 22 - is_leap
) && (lt
->tm_hour
== 0) &&
346 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
347 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
348 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
349 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
352 static void test_strdate(void)
354 char date
[16], * result
;
355 int month
, day
, year
, count
, len
;
358 result
= _strdate(date
);
359 ok(result
== date
, "Wrong return value\n");
361 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
362 count
= sscanf(date
, "%02d/%02d/%02d", &month
, &day
, &year
);
363 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
366 win_skip("Skipping _strdate_s tests\n");
371 err
= p_strdate_s(NULL
, 1);
372 ok(err
== EINVAL
, "err = %d\n", err
);
373 ok(errno
== EINVAL
, "errno = %d\n", errno
);
377 err
= p_strdate_s(date
, 8);
378 ok(err
== ERANGE
, "err = %d\n", err
);
379 ok(errno
== ERANGE
, "errno = %d\n", errno
);
380 ok(date
[0] == '\0', "date[0] != '\\0'\n");
381 ok(date
[1] == 'x', "date[1] != 'x'\n");
383 err
= p_strdate_s(date
, 9);
384 ok(err
== 0, "err = %x\n", err
);
387 static void test_strtime(void)
389 char time
[16], * result
;
390 int hour
, minute
, second
, count
, len
;
393 result
= _strtime(time
);
394 ok(result
== time
, "Wrong return value\n");
396 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
397 count
= sscanf(time
, "%02d:%02d:%02d", &hour
, &minute
, &second
);
398 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
401 win_skip("Skipping _strtime_s tests\n");
406 err
= p_strtime_s(NULL
, 0);
407 ok(err
== EINVAL
, "err = %d\n", err
);
408 ok(errno
== EINVAL
, "errno = %d\n", errno
);
410 err
= p_strtime_s(NULL
, 1);
411 ok(err
== EINVAL
, "err = %d\n", err
);
412 ok(errno
== EINVAL
, "errno = %d\n", errno
);
415 err
= p_strtime_s(time
, 8);
416 ok(err
== ERANGE
, "err = %d\n", err
);
417 ok(errno
== ERANGE
, "errno = %d\n", errno
);
418 ok(time
[0] == '\0', "time[0] != '\\0'\n");
420 err
= p_strtime_s(time
, 9);
421 ok(err
== 0, "err = %x\n", err
);
424 static void test_wstrdate(void)
426 wchar_t date
[16], * result
;
427 int month
, day
, year
, count
, len
;
428 wchar_t format
[] = { '%','0','2','d','/','%','0','2','d','/','%','0','2','d',0 };
430 result
= _wstrdate(date
);
431 ok(result
== date
, "Wrong return value\n");
433 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
434 count
= swscanf(date
, format
, &month
, &day
, &year
);
435 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
438 static void test_wstrtime(void)
440 wchar_t time
[16], * result
;
441 int hour
, minute
, second
, count
, len
;
442 wchar_t format
[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',0 };
444 result
= _wstrtime(time
);
445 ok(result
== time
, "Wrong return value\n");
447 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
448 count
= swscanf(time
, format
, &hour
, &minute
, &second
);
449 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
452 static void test_localtime32_s(void)
458 if (!p_localtime32_s
)
460 win_skip("Skipping _localtime32_s tests\n");
465 err
= p_localtime32_s(NULL
, NULL
);
466 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
467 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
471 err
= p_localtime32_s(NULL
, &time
);
472 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
473 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
475 memset(&tm
, 0, sizeof(tm
));
477 err
= p_localtime32_s(&tm
, NULL
);
478 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
479 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
480 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
481 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
482 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
483 "Expected tm structure members to be initialized to -1, got "
484 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
485 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
488 memset(&tm
, 0, sizeof(tm
));
491 err
= p_localtime32_s(&tm
, &time
);
492 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
493 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
494 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
495 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
496 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
497 "Expected tm structure members to be initialized to -1, got "
498 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
499 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
503 static void test_localtime64_s(void)
509 if (!p_localtime64_s
)
511 win_skip("Skipping _localtime64_s tests\n");
516 err
= p_localtime64_s(NULL
, NULL
);
517 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
518 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
522 err
= p_localtime64_s(NULL
, &time
);
523 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
524 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
526 memset(&tm
, 0, sizeof(tm
));
528 err
= p_localtime64_s(&tm
, NULL
);
529 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
530 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
531 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
532 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
533 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
534 "Expected tm structure members to be initialized to -1, got "
535 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
536 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
539 memset(&tm
, 0, sizeof(tm
));
542 err
= p_localtime64_s(&tm
, &time
);
543 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
544 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
545 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
546 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
547 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
548 "Expected tm structure members to be initialized to -1, got "
549 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
550 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
553 memset(&tm
, 0, sizeof(tm
));
554 time
= _MAX__TIME64_T
+ 1;
556 err
= p_localtime64_s(&tm
, &time
);
557 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
558 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
559 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
560 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
561 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
562 "Expected tm structure members to be initialized to -1, got "
563 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
564 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
568 static void test_daylight(void)
574 win_skip("__daylight() not available\n");
578 if (!p___p__daylight
)
580 win_skip("__p__daylight not available\n");
584 ret1
= p__daylight();
585 ret2
= p___p__daylight();
586 ok(ret1
&& ret1
== ret2
, "got %p\n", ret1
);
589 static void test_strftime(void)
591 static const wchar_t cW
[] = { '%','c',0 };
592 static const char expected
[] = "01/01/70 00:00:00";
595 char buf
[256], bufA
[256];
599 if (!p_strftime
|| !p_wcsftime
|| !p_gmtime
)
601 win_skip("strftime, wcsftime or gmtime is not available\n");
605 setlocale(LC_TIME
, "C");
608 gmt_tm
= p_gmtime(&gmt
);
609 ok(gmt_tm
!= NULL
, "gmtime failed\n");
612 retA
= strftime(NULL
, 0, "copy", gmt_tm
);
613 ok(retA
== 0, "expected 0, got %ld\n", retA
);
614 ok(errno
==EINVAL
|| broken(errno
==0xdeadbeef), "errno = %d\n", errno
);
616 retA
= strftime(bufA
, 256, "copy", NULL
);
617 ok(retA
== 4, "expected 4, got %ld\n", retA
);
618 ok(!strcmp(bufA
, "copy"), "got %s\n", bufA
);
620 retA
= strftime(bufA
, 256, "copy it", gmt_tm
);
621 ok(retA
== 7, "expected 7, got %ld\n", retA
);
622 ok(!strcmp(bufA
, "copy it"), "got %s\n", bufA
);
625 retA
= strftime(bufA
, 2, "copy", gmt_tm
);
626 ok(retA
== 0, "expected 0, got %ld\n", retA
);
627 ok(!strcmp(bufA
, "") || broken(!strcmp(bufA
, "copy it")), "got %s\n", bufA
);
628 ok(errno
==ERANGE
|| errno
==0xdeadbeef, "errno = %d\n", errno
);
631 retA
= strftime(bufA
, 256, "a%e", gmt_tm
);
632 ok(retA
==0 || broken(retA
==1), "expected 0, got %ld\n", retA
);
633 ok(!strcmp(bufA
, "") || broken(!strcmp(bufA
, "a")), "got %s\n", bufA
);
634 ok(errno
==EINVAL
|| broken(errno
==0xdeadbeef), "errno = %d\n", errno
);
636 if(0) { /* crashes on Win2k */
638 retA
= strftime(bufA
, 256, "%c", NULL
);
639 ok(retA
== 0, "expected 0, got %ld\n", retA
);
640 ok(!strcmp(bufA
, ""), "got %s\n", bufA
);
641 ok(errno
== EINVAL
, "errno = %d\n", errno
);
644 retA
= strftime(bufA
, 256, "e%#%e", gmt_tm
);
645 ok(retA
== 3, "expected 3, got %ld\n", retA
);
646 ok(!strcmp(bufA
, "e%e"), "got %s\n", bufA
);
648 retA
= strftime(bufA
, 256, "%c", gmt_tm
);
649 ok(retA
== 17, "expected 17, got %ld\n", retA
);
650 ok(strcmp(bufA
, expected
) == 0, "expected %s, got %s\n", expected
, bufA
);
652 retW
= wcsftime(bufW
, 256, cW
, gmt_tm
);
653 ok(retW
== 17, "expected 17, got %ld\n", retW
);
654 ok(retA
== retW
, "expected %ld, got %ld\n", retA
, retW
);
656 retA
= WideCharToMultiByte(CP_ACP
, 0, bufW
, retW
, buf
, 256, NULL
, NULL
);
658 ok(strcmp(bufA
, buf
) == 0, "expected %s, got %s\n", bufA
, buf
);
660 retA
= strftime(bufA
, 256, "%x", gmt_tm
);
661 ok(retA
== 8, "expected 8, got %ld\n", retA
);
662 ok(!strcmp(bufA
, "01/01/70"), "got %s\n", bufA
);
664 retA
= strftime(bufA
, 256, "%X", gmt_tm
);
665 ok(retA
== 8, "expected 8, got %ld\n", retA
);
666 ok(!strcmp(bufA
, "00:00:00"), "got %s\n", bufA
);
668 retA
= strftime(bufA
, 256, "%a", gmt_tm
);
669 ok(retA
== 3, "expected 3, got %ld\n", retA
);
670 ok(!strcmp(bufA
, "Thu"), "got %s\n", bufA
);
672 retA
= strftime(bufA
, 256, "%A", gmt_tm
);
673 ok(retA
== 8, "expected 8, got %ld\n", retA
);
674 ok(!strcmp(bufA
, "Thursday"), "got %s\n", bufA
);
676 retA
= strftime(bufA
, 256, "%b", gmt_tm
);
677 ok(retA
== 3, "expected 3, got %ld\n", retA
);
678 ok(!strcmp(bufA
, "Jan"), "got %s\n", bufA
);
680 retA
= strftime(bufA
, 256, "%B", gmt_tm
);
681 ok(retA
== 7, "expected 7, got %ld\n", retA
);
682 ok(!strcmp(bufA
, "January"), "got %s\n", bufA
);
684 retA
= strftime(bufA
, 256, "%d", gmt_tm
);
685 ok(retA
== 2, "expected 2, got %ld\n", retA
);
686 ok(!strcmp(bufA
, "01"), "got %s\n", bufA
);
688 retA
= strftime(bufA
, 256, "%#d", gmt_tm
);
689 ok(retA
== 1, "expected 1, got %ld\n", retA
);
690 ok(!strcmp(bufA
, "1"), "got %s\n", bufA
);
692 retA
= strftime(bufA
, 256, "%H", gmt_tm
);
693 ok(retA
== 2, "expected 2, got %ld\n", retA
);
694 ok(!strcmp(bufA
, "00"), "got %s\n", bufA
);
696 retA
= strftime(bufA
, 256, "%I", gmt_tm
);
697 ok(retA
== 2, "expected 2, got %ld\n", retA
);
698 ok(!strcmp(bufA
, "12"), "got %s\n", bufA
);
700 retA
= strftime(bufA
, 256, "%j", gmt_tm
);
701 ok(retA
== 3, "expected 3, got %ld\n", retA
);
702 ok(!strcmp(bufA
, "001"), "got %s\n", bufA
);
704 retA
= strftime(bufA
, 256, "%m", gmt_tm
);
705 ok(retA
== 2, "expected 2, got %ld\n", retA
);
706 ok(!strcmp(bufA
, "01"), "got %s\n", bufA
);
708 retA
= strftime(bufA
, 256, "%#M", gmt_tm
);
709 ok(retA
== 1, "expected 1, got %ld\n", retA
);
710 ok(!strcmp(bufA
, "0"), "got %s\n", bufA
);
712 retA
= strftime(bufA
, 256, "%p", gmt_tm
);
713 ok(retA
== 2, "expected 2, got %ld\n", retA
);
714 ok(!strcmp(bufA
, "AM"), "got %s\n", bufA
);
716 retA
= strftime(bufA
, 256, "%U", gmt_tm
);
717 ok(retA
== 2, "expected 2, got %ld\n", retA
);
718 ok(!strcmp(bufA
, "00"), "got %s\n", bufA
);
720 retA
= strftime(bufA
, 256, "%W", gmt_tm
);
721 ok(retA
== 2, "expected 2, got %ld\n", retA
);
722 ok(!strcmp(bufA
, "00"), "got %s\n", bufA
);
725 retA
= strftime(bufA
, 256, "%U", gmt_tm
);
726 ok(retA
== 2, "expected 2, got %ld\n", retA
);
727 ok(!strcmp(bufA
, "01"), "got %s\n", bufA
);
729 retA
= strftime(bufA
, 256, "%W", gmt_tm
);
730 ok(retA
== 2, "expected 2, got %ld\n", retA
);
731 ok(!strcmp(bufA
, "00"), "got %s\n", bufA
);
733 gmt_tm
->tm_yday
= 365;
734 retA
= strftime(bufA
, 256, "%U", gmt_tm
);
735 ok(retA
== 2, "expected 2, got %ld\n", retA
);
736 ok(!strcmp(bufA
, "53"), "got %s\n", bufA
);
738 retA
= strftime(bufA
, 256, "%W", gmt_tm
);
739 ok(retA
== 2, "expected 2, got %ld\n", retA
);
740 ok(!strcmp(bufA
, "52"), "got %s\n", bufA
);
743 gmt_tm
->tm_mday
= 30;
744 retA
= strftime(bufA
, 256, "%c", gmt_tm
);
746 ok(retA
== 17, "expected 17, got %ld\n", retA
);
747 ok(!strcmp(bufA
, "02/30/70 00:00:00"), "got %s\n", bufA
);
751 static void test_asctime(void)
757 if(!p_asctime
|| !p_gmtime
)
759 win_skip("asctime or gmtime is not available\n");
764 gmt_tm
= p_gmtime(&gmt
);
765 ret
= p_asctime(gmt_tm
);
766 ok(!strcmp(ret
, "Thu Jan 01 00:00:00 1970\n"), "asctime retunred %s\n", ret
);
769 gmt_tm
= p_gmtime(&gmt
);
770 ret
= p_asctime(gmt_tm
);
771 ok(!strcmp(ret
, "Mon Nov 26 02:58:41 1979\n"), "asctime retunred %s\n", ret
);
773 /* Week day is only checked if it's in 0..6 range */
775 ret
= p_asctime(gmt_tm
);
776 ok(!strcmp(ret
, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret
);
780 ret
= p_asctime(gmt_tm
);
781 ok(!ret
|| broken(!ret
[0]), "asctime returned %s\n", ret
);
782 ok(errno
==EINVAL
|| broken(errno
==0xdeadbeef), "errno = %d\n", errno
);
784 /* Year day is ignored */
786 gmt_tm
->tm_yday
= 1300;
787 ret
= p_asctime(gmt_tm
);
788 ok(!strcmp(ret
, "Wed Nov 26 02:58:41 1979\n"), "asctime returned %s\n", ret
);
790 /* Dates that can't be displayed using 26 characters are broken */
791 gmt_tm
->tm_mday
= 28;
792 gmt_tm
->tm_year
= 8100;
793 ret
= p_asctime(gmt_tm
);
794 ok(!strcmp(ret
, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret
);
796 gmt_tm
->tm_year
= 264100;
797 ret
= p_asctime(gmt_tm
);
798 ok(!strcmp(ret
, "Wed Nov 28 02:58:41 :000\n"), "asctime returned %s\n", ret
);
800 /* asctime works from year 1900 */
802 gmt_tm
->tm_year
= -1;
803 ret
= p_asctime(gmt_tm
);
804 ok(!ret
|| broken(!strcmp(ret
, "Wed Nov 28 02:58:41 190/\n")), "asctime returned %s\n", ret
);
805 ok(errno
==EINVAL
|| broken(errno
== 0xdeadbeef), "errno = %d\n", errno
);
809 gmt_tm
->tm_mday
= 30;
810 gmt_tm
->tm_year
= 79;
811 ret
= p_asctime(gmt_tm
);
812 ok(!ret
|| broken(!strcmp(ret
, "Wed Feb 30 02:58:41 1979\n")), "asctime returned %s\n", ret
);
813 ok(errno
==EINVAL
|| broken(errno
==0xdeadbeef), "errno = %d\n", errno
);
816 static void test__tzset(void)
821 if(!p___p__daylight
|| !p___p__timezone
|| !p___p__dstbias
) {
822 win_skip("__p__daylight, __p__timezone or __p__dstbias is not available\n");
828 ok(ret
== -3600, "*__dstbias() = %d\n", ret
);
829 ret
= *p___p__dstbias();
830 ok(ret
== -3600, "*__p__dstbias() = %d\n", ret
);
833 win_skip("__dstbias() is not available.\n");
835 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
837 ret
= *p___p__daylight();
838 ok(ret
== 1, "*__p__daylight() = %d\n", ret
);
839 ret
= *p___p__timezone();
840 ok(ret
== 28800, "*__p__timezone() = %d\n", ret
);
841 ret
= *p___p__dstbias();
842 ok(ret
== -3600, "*__p__dstbias() = %d\n", ret
);
844 _putenv("TZ=xxx+1yyy");
846 ret
= *p___p__daylight();
847 ok(ret
== 121, "*__p__daylight() = %d\n", ret
);
848 ret
= *p___p__timezone();
849 ok(ret
== 3600, "*__p__timezone() = %d\n", ret
);
850 ret
= *p___p__dstbias();
851 ok(ret
== -3600, "*__p__dstbias() = %d\n", ret
);
853 *p___p__dstbias() = 0;
854 _putenv("TZ=xxx+1:3:5zzz");
856 ret
= *p___p__daylight();
857 ok(ret
== 122, "*__p__daylight() = %d\n", ret
);
858 ret
= *p___p__timezone();
859 ok(ret
== 3785, "*__p__timezone() = %d\n", ret
);
860 ret
= *p___p__dstbias();
861 ok(ret
== 0, "*__p__dstbias() = %d\n", ret
);
866 static void test_clock(void)
868 static const int THRESH
= 50;
872 for (i
= 0; i
< 10; i
++)
878 ok(abs((e
-s
) - 1000) < THRESH
, "clock off on loop %i: %i\n", i
, e
-s
);
896 test_localtime32_s();
897 test_localtime64_s();