1 | #include <time.h> |
2 | #include <errno.h> |
3 | #include <limits.h> |
4 | #include <stdbool.h> |
5 | #include <stdio.h> |
6 | #include <string.h> |
7 | |
8 | static bool |
9 | equal_tm (struct tm const *t, struct tm const *u) |
10 | { |
11 | return (t->tm_sec == u->tm_sec && t->tm_min == u->tm_min |
12 | && t->tm_hour == u->tm_hour && t->tm_mday == u->tm_mday |
13 | && t->tm_mon == u->tm_mon && t->tm_year == u->tm_year |
14 | && t->tm_wday == u->tm_wday && t->tm_yday == u->tm_yday |
15 | && t->tm_isdst == u->tm_isdst && t->tm_gmtoff == u->tm_gmtoff |
16 | && t->tm_zone == u->tm_zone); |
17 | } |
18 | |
19 | static int |
20 | do_test (void) |
21 | { |
22 | /* Calculate minimum time_t value. This would be simpler with C11, |
23 | which has _Generic, but we cannot assume C11. It would also |
24 | be simpler with intprops.h, which has TYPE_MINIMUM, but it's |
25 | better not to use glibc internals. */ |
26 | time_t time_t_min = -1; |
27 | time_t_min = (0 < time_t_min ? 0 |
28 | : sizeof time_t_min == sizeof (long int) ? LONG_MIN |
29 | : sizeof time_t_min == sizeof (long long int) ? LLONG_MIN |
30 | : 1); |
31 | if (time_t_min == 1) |
32 | { |
33 | printf (format: "unknown time type\n" ); |
34 | return 1; |
35 | } |
36 | time_t ymin = time_t_min / 60 / 60 / 24 / 366; |
37 | bool mktime_should_fail = ymin == 0 || INT_MIN + 1900 < ymin + 1970; |
38 | |
39 | struct tm tm0 = { .tm_year = INT_MIN, .tm_mday = 1, .tm_wday = -1 }; |
40 | struct tm tm = tm0; |
41 | errno = 0; |
42 | time_t t = mktime (&tm); |
43 | long long int llt = t; |
44 | bool mktime_failed = tm.tm_wday == tm0.tm_wday; |
45 | |
46 | if (mktime_failed) |
47 | { |
48 | if (! mktime_should_fail) |
49 | { |
50 | printf (format: "mktime failed but should have succeeded\n" ); |
51 | return 1; |
52 | } |
53 | if (errno == 0) |
54 | { |
55 | printf (format: "mktime failed without setting errno" ); |
56 | return 1; |
57 | } |
58 | if (t != (time_t) -1) |
59 | { |
60 | printf (format: "mktime returned %lld but did not set tm_wday\n" , llt); |
61 | return 1; |
62 | } |
63 | if (! equal_tm (t: &tm, u: &tm0)) |
64 | { |
65 | printf (format: "mktime (P) failed but modified *P\n" ); |
66 | return 1; |
67 | } |
68 | } |
69 | else |
70 | { |
71 | if (mktime_should_fail) |
72 | { |
73 | printf (format: "mktime succeeded but should have failed\n" ); |
74 | return 1; |
75 | } |
76 | struct tm *lt = localtime (&t); |
77 | if (lt == NULL) |
78 | { |
79 | printf (format: "mktime returned a value rejected by localtime\n" ); |
80 | return 1; |
81 | } |
82 | if (! equal_tm (t: lt, u: &tm)) |
83 | { |
84 | printf (format: "mktime result does not match localtime result\n" ); |
85 | return 1; |
86 | } |
87 | } |
88 | return 0; |
89 | } |
90 | |
91 | #define TIMEOUT 1000 |
92 | #include "support/test-driver.c" |
93 | |