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 size_t (__cdecl
*p_strftime
)(char *, size_t, const char *, const struct tm
*);
50 static size_t (__cdecl
*p_wcsftime
)(wchar_t *, size_t, const wchar_t *, const struct tm
*);
52 static void init(void)
54 HMODULE hmod
= LoadLibrary("msvcrt.dll");
56 p_gmtime32
= (void*)GetProcAddress(hmod
, "_gmtime32");
57 p_gmtime
= (void*)GetProcAddress(hmod
, "gmtime");
58 p_gmtime32_s
= (void*)GetProcAddress(hmod
, "_gmtime32_s");
59 p_mkgmtime32
= (void*)GetProcAddress(hmod
, "_mkgmtime32");
60 p_strtime_s
= (void*)GetProcAddress(hmod
, "_strtime_s");
61 p_strdate_s
= (void*)GetProcAddress(hmod
, "_strdate_s");
62 p_localtime32_s
= (void*)GetProcAddress(hmod
, "_localtime32_s");
63 p_localtime64_s
= (void*)GetProcAddress(hmod
, "_localtime64_s");
64 p__daylight
= (void*)GetProcAddress(hmod
, "__daylight");
65 p___p__daylight
= (void*)GetProcAddress(hmod
, "__p__daylight");
66 p_strftime
= (void*)GetProcAddress(hmod
, "strftime");
67 p_wcsftime
= (void*)GetProcAddress(hmod
, "wcsftime");
70 static int get_test_year(time_t *start
)
72 time_t now
= time(NULL
);
73 struct tm
*tm
= localtime(&now
);
75 /* compute start of year in seconds */
76 *start
= SECSPERDAY
* ((tm
->tm_year
- 70) * 365 +
77 (tm
->tm_year
- 69) / 4 -
78 (tm
->tm_year
- 1) / 100 +
79 (tm
->tm_year
+ 299) / 400);
83 static void test_ctime(void)
87 ret
= ctime(&badtime
);
88 ok(ret
== NULL
, "expected ctime to return NULL, got %s\n", ret
);
90 static void test_gmtime(void)
92 __time32_t valid
, gmt
;
93 struct tm
* gmt_tm
, gmt_tm_s
;
97 win_skip("Skipping _gmtime32 tests\n");
101 gmt_tm
= p_gmtime32(NULL
);
102 ok(gmt_tm
== NULL
, "gmt_tm != NULL\n");
105 gmt_tm
= p_gmtime32(&gmt
);
106 ok(gmt_tm
== NULL
, "gmt_tm != NULL\n");
109 gmt_tm
= p_gmtime32(&gmt
);
111 ok(0, "_gmtime32() failed\n");
115 ok(((gmt_tm
->tm_year
== 70) && (gmt_tm
->tm_mon
== 0) && (gmt_tm
->tm_yday
== 0) &&
116 (gmt_tm
->tm_mday
== 1) && (gmt_tm
->tm_wday
== 4) && (gmt_tm
->tm_hour
== 0) &&
117 (gmt_tm
->tm_min
== 0) && (gmt_tm
->tm_sec
== 0) && (gmt_tm
->tm_isdst
== 0)),
118 "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n",
119 gmt_tm
->tm_year
, gmt_tm
->tm_mon
, gmt_tm
->tm_yday
, gmt_tm
->tm_mday
, gmt_tm
->tm_wday
,
120 gmt_tm
->tm_hour
, gmt_tm
->tm_min
, gmt_tm
->tm_sec
, gmt_tm
->tm_isdst
);
123 win_skip("Skipping _mkgmtime32 tests\n");
127 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
128 gmt
= p_mkgmtime32(gmt_tm
);
129 ok(gmt
== valid
, "gmt = %u\n", gmt
);
130 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
131 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
133 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
134 gmt_tm
->tm_isdst
= -1;
135 gmt
= p_mkgmtime32(gmt_tm
);
136 ok(gmt
== valid
, "gmt = %u\n", gmt
);
137 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
138 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
140 gmt_tm
->tm_wday
= gmt_tm
->tm_yday
= 0;
141 gmt_tm
->tm_isdst
= 1;
142 gmt
= p_mkgmtime32(gmt_tm
);
143 ok(gmt
== valid
, "gmt = %u\n", gmt
);
144 ok(gmt_tm
->tm_wday
== 4, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
145 ok(gmt_tm
->tm_yday
== 0, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
147 gmt
= valid
= 173921;
148 gmt_tm
= p_gmtime32(&gmt
);
150 ok(0, "_gmtime32() failed\n");
154 gmt_tm
->tm_isdst
= -1;
155 gmt
= p_mkgmtime32(gmt_tm
);
156 ok(gmt
== valid
, "gmt = %u\n", gmt
);
157 ok(gmt_tm
->tm_wday
== 6, "gmt_tm->tm_wday = %d\n", gmt_tm
->tm_wday
);
158 ok(gmt_tm
->tm_yday
== 2, "gmt_tm->tm_yday = %d\n", gmt_tm
->tm_yday
);
160 gmt_tm
->tm_isdst
= 1;
161 gmt
= p_mkgmtime32(gmt_tm
);
162 ok(gmt
== valid
, "gmt = %u\n", gmt
);
165 win_skip("Skipping _gmtime32_s tests\n");
171 err
= p_gmtime32_s(NULL
, &gmt
);
172 ok(err
== EINVAL
, "err = %d\n", err
);
173 ok(errno
== EINVAL
, "errno = %d\n", errno
);
177 err
= p_gmtime32_s(&gmt_tm_s
, &gmt
);
178 ok(err
== EINVAL
, "err = %d\n", err
);
179 ok(errno
== EINVAL
, "errno = %d\n", errno
);
180 ok(gmt_tm_s
.tm_year
== -1, "tm_year = %d\n", gmt_tm_s
.tm_year
);
183 static void test_mktime(void)
185 TIME_ZONE_INFORMATION tzinfo
;
186 DWORD res
= GetTimeZoneInformation(&tzinfo
);
187 struct tm my_tm
, sav_tm
;
188 time_t nulltime
, local_time
;
194 year
= get_test_year( &ref
);
197 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
198 WideCharToMultiByte( CP_ACP
, 0, tzinfo
.StandardName
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
199 trace( "bias %d std %d dst %d zone %s\n",
200 tzinfo
.Bias
, tzinfo
.StandardBias
, tzinfo
.DaylightBias
, buffer
);
201 /* Bias may be positive or negative, to use offset of one day */
202 my_tm
= *localtime(&ref
); /* retrieve current dst flag */
203 secs
= SECSPERDAY
- tzinfo
.Bias
* SECSPERMIN
;
204 secs
-= (my_tm
.tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
205 my_tm
.tm_mday
= 1 + secs
/SECSPERDAY
;
206 secs
= secs
% SECSPERDAY
;
207 my_tm
.tm_hour
= secs
/ SECSPERHOUR
;
208 secs
= secs
% SECSPERHOUR
;
209 my_tm
.tm_min
= secs
/ SECSPERMIN
;
210 secs
= secs
% SECSPERMIN
;
213 my_tm
.tm_year
= year
;
218 local_time
= mktime(&my_tm
);
219 ok(local_time
== ref
, "mktime returned %u, expected %u\n",
220 (DWORD
)local_time
, (DWORD
)ref
);
221 /* now test some unnormalized struct tm's */
225 local_time
= mktime(&my_tm
);
226 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
227 (DWORD
)local_time
, (DWORD
)ref
);
228 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
229 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
230 my_tm
.tm_sec
== sav_tm
.tm_sec
,
231 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
232 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
233 my_tm
.tm_hour
,my_tm
.tm_sec
,
234 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
235 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
239 local_time
= mktime(&my_tm
);
240 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
241 (DWORD
)local_time
, (DWORD
)ref
);
242 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
243 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
244 my_tm
.tm_sec
== sav_tm
.tm_sec
,
245 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
246 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
247 my_tm
.tm_hour
,my_tm
.tm_sec
,
248 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
249 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
253 local_time
= mktime(&my_tm
);
254 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
255 (DWORD
)local_time
, (DWORD
)ref
);
256 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
257 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
258 my_tm
.tm_sec
== sav_tm
.tm_sec
,
259 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
260 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
261 my_tm
.tm_hour
,my_tm
.tm_sec
,
262 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
263 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
267 local_time
= mktime(&my_tm
);
268 ok(local_time
== ref
, "Unnormalized mktime returned %u, expected %u\n",
269 (DWORD
)local_time
, (DWORD
)ref
);
270 ok( my_tm
.tm_year
== sav_tm
.tm_year
&& my_tm
.tm_mon
== sav_tm
.tm_mon
&&
271 my_tm
.tm_mday
== sav_tm
.tm_mday
&& my_tm
.tm_hour
== sav_tm
.tm_hour
&&
272 my_tm
.tm_sec
== sav_tm
.tm_sec
,
273 "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n",
274 my_tm
.tm_year
,my_tm
.tm_mon
,my_tm
.tm_mday
,
275 my_tm
.tm_hour
,my_tm
.tm_sec
,
276 sav_tm
.tm_year
,sav_tm
.tm_mon
,sav_tm
.tm_mday
,
277 sav_tm
.tm_hour
,sav_tm
.tm_sec
);
278 /* now a bad time example */
281 local_time
= mktime(&my_tm
);
282 ok((local_time
== -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time
);
285 /* TEST that we are independent from the TZ variable */
286 /*Argh, msvcrt doesn't have setenv() */
287 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
289 nulltime
= mktime(&my_tm
);
290 ok(nulltime
== ref
,"mktime returned 0x%08x\n",(DWORD
)nulltime
);
294 static void test_localtime(void)
296 TIME_ZONE_INFORMATION tzinfo
;
297 DWORD res
= GetTimeZoneInformation(&tzinfo
);
302 int year
= get_test_year( &ref
);
303 int is_leap
= !(year
% 4) && ((year
% 100) || !((year
+ 300) % 400));
305 gmt
= ref
+ SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
306 ok (res
!= TIME_ZONE_ID_INVALID
, "GetTimeZoneInformation failed\n");
307 lt
= localtime(&gmt
);
308 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
309 lt
= localtime(&gmt
);
310 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
311 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
312 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
313 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
314 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
315 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
317 _snprintf(TZ_env
,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):""));
319 lt
= localtime(&gmt
);
320 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 0) && (lt
->tm_yday
== 1) &&
321 (lt
->tm_mday
== 2) && (lt
->tm_hour
== 0) &&
322 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
323 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
324 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
325 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
329 gmt
= ref
+ 202 * SECSPERDAY
+ tzinfo
.Bias
* SECSPERMIN
;
330 lt
= localtime(&gmt
);
331 gmt
+= (lt
->tm_isdst
? tzinfo
.DaylightBias
: tzinfo
.StandardBias
) * SECSPERMIN
;
332 lt
= localtime(&gmt
);
333 ok(((lt
->tm_year
== year
) && (lt
->tm_mon
== 6) && (lt
->tm_yday
== 202) &&
334 (lt
->tm_mday
== 22 - is_leap
) && (lt
->tm_hour
== 0) &&
335 (lt
->tm_min
== 0) && (lt
->tm_sec
== 0)),
336 "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n",
337 lt
->tm_year
, lt
->tm_mon
, lt
->tm_yday
, lt
->tm_mday
, lt
->tm_wday
, lt
->tm_hour
,
338 lt
->tm_min
, lt
->tm_sec
, lt
->tm_isdst
);
341 static void test_strdate(void)
343 char date
[16], * result
;
344 int month
, day
, year
, count
, len
;
347 result
= _strdate(date
);
348 ok(result
== date
, "Wrong return value\n");
350 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
351 count
= sscanf(date
, "%02d/%02d/%02d", &month
, &day
, &year
);
352 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
355 win_skip("Skipping _strdate_s tests\n");
360 err
= p_strdate_s(NULL
, 1);
361 ok(err
== EINVAL
, "err = %d\n", err
);
362 ok(errno
== EINVAL
, "errno = %d\n", errno
);
366 err
= p_strdate_s(date
, 8);
367 ok(err
== ERANGE
, "err = %d\n", err
);
368 ok(errno
== ERANGE
, "errno = %d\n", errno
);
369 ok(date
[0] == '\0', "date[0] != '\\0'\n");
370 ok(date
[1] == 'x', "date[1] != 'x'\n");
372 err
= p_strdate_s(date
, 9);
373 ok(err
== 0, "err = %x\n", err
);
376 static void test_strtime(void)
378 char time
[16], * result
;
379 int hour
, minute
, second
, count
, len
;
382 result
= _strtime(time
);
383 ok(result
== time
, "Wrong return value\n");
385 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
386 count
= sscanf(time
, "%02d:%02d:%02d", &hour
, &minute
, &second
);
387 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
390 win_skip("Skipping _strtime_s tests\n");
395 err
= p_strtime_s(NULL
, 0);
396 ok(err
== EINVAL
, "err = %d\n", err
);
397 ok(errno
== EINVAL
, "errno = %d\n", errno
);
399 err
= p_strtime_s(NULL
, 1);
400 ok(err
== EINVAL
, "err = %d\n", err
);
401 ok(errno
== EINVAL
, "errno = %d\n", errno
);
404 err
= p_strtime_s(time
, 8);
405 ok(err
== ERANGE
, "err = %d\n", err
);
406 ok(errno
== ERANGE
, "errno = %d\n", errno
);
407 ok(time
[0] == '\0', "time[0] != '\\0'\n");
409 err
= p_strtime_s(time
, 9);
410 ok(err
== 0, "err = %x\n", err
);
413 static void test_wstrdate(void)
415 wchar_t date
[16], * result
;
416 int month
, day
, year
, count
, len
;
417 wchar_t format
[] = { '%','0','2','d','/','%','0','2','d','/','%','0','2','d',0 };
419 result
= _wstrdate(date
);
420 ok(result
== date
, "Wrong return value\n");
422 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
423 count
= swscanf(date
, format
, &month
, &day
, &year
);
424 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
427 static void test_wstrtime(void)
429 wchar_t time
[16], * result
;
430 int hour
, minute
, second
, count
, len
;
431 wchar_t format
[] = { '%','0','2','d',':','%','0','2','d',':','%','0','2','d',0 };
433 result
= _wstrtime(time
);
434 ok(result
== time
, "Wrong return value\n");
436 ok(len
== 8, "Wrong length: returned %d, should be 8\n", len
);
437 count
= swscanf(time
, format
, &hour
, &minute
, &second
);
438 ok(count
== 3, "Wrong format: count = %d, should be 3\n", count
);
441 static void test_localtime32_s(void)
447 if (!p_localtime32_s
)
449 win_skip("Skipping _localtime32_s tests\n");
454 err
= p_localtime32_s(NULL
, NULL
);
455 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
456 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
460 err
= p_localtime32_s(NULL
, &time
);
461 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
462 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
464 memset(&tm
, 0, sizeof(tm
));
466 err
= p_localtime32_s(&tm
, NULL
);
467 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
468 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
469 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
470 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
471 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
472 "Expected tm structure members to be initialized to -1, got "
473 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
474 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
477 memset(&tm
, 0, sizeof(tm
));
480 err
= p_localtime32_s(&tm
, &time
);
481 ok(err
== EINVAL
, "Expected _localtime32_s to return EINVAL, got %d\n", err
);
482 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
483 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
484 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
485 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
486 "Expected tm structure members to be initialized to -1, got "
487 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
488 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
492 static void test_localtime64_s(void)
498 if (!p_localtime64_s
)
500 win_skip("Skipping _localtime64_s tests\n");
505 err
= p_localtime64_s(NULL
, NULL
);
506 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
507 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
511 err
= p_localtime64_s(NULL
, &time
);
512 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
513 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
515 memset(&tm
, 0, sizeof(tm
));
517 err
= p_localtime64_s(&tm
, NULL
);
518 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
519 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
520 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
521 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
522 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
523 "Expected tm structure members to be initialized to -1, got "
524 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
525 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
528 memset(&tm
, 0, sizeof(tm
));
531 err
= p_localtime64_s(&tm
, &time
);
532 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
533 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
534 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
535 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
536 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
537 "Expected tm structure members to be initialized to -1, got "
538 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
539 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
542 memset(&tm
, 0, sizeof(tm
));
543 time
= _MAX__TIME64_T
+ 1;
545 err
= p_localtime64_s(&tm
, &time
);
546 ok(err
== EINVAL
, "Expected _localtime64_s to return EINVAL, got %d\n", err
);
547 ok(errno
== EINVAL
, "Expected errno to be EINVAL, got %d\n", errno
);
548 ok(tm
.tm_sec
== -1 && tm
.tm_min
== -1 && tm
.tm_hour
== -1 &&
549 tm
.tm_mday
== -1 && tm
.tm_mon
== -1 && tm
.tm_year
== -1 &&
550 tm
.tm_wday
== -1 && tm
.tm_yday
== -1 && tm
.tm_isdst
== -1,
551 "Expected tm structure members to be initialized to -1, got "
552 "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm
.tm_sec
, tm
.tm_min
,
553 tm
.tm_hour
, tm
.tm_mday
, tm
.tm_mon
, tm
.tm_year
, tm
.tm_wday
, tm
.tm_yday
,
557 static void test_daylight(void)
563 win_skip("__daylight() not available\n");
567 if (!p___p__daylight
)
569 win_skip("__p__daylight not available\n");
573 ret1
= p__daylight();
574 ret2
= p___p__daylight();
575 ok(ret1
&& ret1
== ret2
, "got %p\n", ret1
);
578 static void test_strftime(void)
580 static const wchar_t cW
[] = { '%','c',0 };
581 static const char expected
[] = "01/01/70 00:00:00";
584 char buf
[256], bufA
[256];
588 if (!p_strftime
|| !p_wcsftime
|| !p_gmtime
)
590 win_skip("strftime, wcsftime or gmtime is not available\n");
594 setlocale(LC_TIME
, "C");
597 gmt_tm
= p_gmtime(&gmt
);
598 ok(gmt_tm
!= NULL
, "gmtime failed\n");
600 retA
= strftime(bufA
, 256, "%c", gmt_tm
);
602 ok(retA
== 17, "expected 17, got %ld\n", retA
);
603 ok(strcmp(bufA
, expected
) == 0, "expected %s, got %s\n", expected
, bufA
);
605 retW
= wcsftime(bufW
, 256, cW
, gmt_tm
);
607 ok(retW
== 17, "expected 17, got %ld\n", retW
);
608 ok(retA
== retW
, "expected %ld, got %ld\n", retA
, retW
);
610 retA
= WideCharToMultiByte(CP_ACP
, 0, bufW
, retW
, buf
, 256, NULL
, NULL
);
612 ok(strcmp(bufA
, buf
) == 0, "expected %s, got %s\n", bufA
, buf
);
628 test_localtime32_s();
629 test_localtime64_s();