Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6433 | siemargl | 1 | #define _XOPEN_SOURCE 700 |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | #include |
||
7 | #include |
||
8 | #include "test.h" |
||
9 | |||
10 | /* We use this instead of memcmp because some broken C libraries |
||
11 | * add additional nonstandard fields to struct tm... */ |
||
12 | |||
13 | int tm_cmp(struct tm tm1, struct tm tm2) |
||
14 | { |
||
15 | return tm1.tm_sec != tm2.tm_sec || |
||
16 | tm1.tm_min != tm2.tm_min || |
||
17 | tm1.tm_hour != tm2.tm_hour || |
||
18 | tm1.tm_mday != tm2.tm_mday || |
||
19 | tm1.tm_mon != tm2.tm_mon || |
||
20 | tm1.tm_year != tm2.tm_year || |
||
21 | tm1.tm_wday != tm2.tm_wday || |
||
22 | tm1.tm_yday != tm2.tm_yday || |
||
23 | tm1.tm_isdst!= tm2.tm_isdst; |
||
24 | } |
||
25 | |||
26 | char *tm_str(struct tm tm) |
||
27 | { |
||
28 | static int i; |
||
29 | static char b[4][64]; |
||
30 | i = (i+1)%4; |
||
31 | snprintf(b[i], sizeof b[i], |
||
32 | "s=%02d m=%02d h=%02d mday=%02d mon=%02d year=%04d wday=%d yday=%d isdst=%d", |
||
33 | tm.tm_sec, tm.tm_min, tm.tm_hour, |
||
34 | tm.tm_mday, tm.tm_mon, tm.tm_year, |
||
35 | tm.tm_wday, tm.tm_yday, tm.tm_isdst); |
||
36 | return b[i]; |
||
37 | } |
||
38 | |||
39 | #define TM(ss,mm,hh,md,mo,yr,wd,yd,dst) (struct tm){ \ |
||
40 | .tm_sec = ss, .tm_min = mm, .tm_hour = hh, \ |
||
41 | .tm_mday = md, .tm_mon = mo, .tm_year = yr, \ |
||
42 | .tm_wday = wd, .tm_yday = yd, .tm_isdst = dst } |
||
43 | |||
44 | #define TM_EPOCH TM(0,0,0,1,0,70,4,0,0) |
||
45 | #define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0) |
||
46 | #define TM_Y2038 TM(8,14,3,19,0,138,2,18,0) |
||
47 | |||
48 | static void sec2tm(time_t t, char *m) |
||
49 | { |
||
50 | struct tm *tm; |
||
51 | time_t r; |
||
52 | |||
53 | errno = 0; |
||
54 | tm = gmtime(&t); |
||
55 | if (errno != 0) |
||
56 | t_error("%s: gmtime((time_t)%lld) should not set errno, got %s\n", |
||
57 | m, (long long)t, strerror(errno)); |
||
58 | errno = 0; |
||
59 | r = mktime(tm); |
||
60 | if (errno != 0) |
||
61 | t_error("%s: mktime(%s) should not set errno, got %s\n", |
||
62 | m, tm_str(*tm), strerror(errno)); |
||
63 | if (t != r) |
||
64 | t_error("%s: mktime(gmtime(%lld)) roundtrip failed: got %lld (gmtime is %s)\n", |
||
65 | m, (long long)t, (long long)r, tm_str(*tm)); |
||
66 | } |
||
67 | |||
68 | static void tm2sec(struct tm *tm, int big, char *m) |
||
69 | { |
||
70 | struct tm *r; |
||
71 | time_t t; |
||
72 | int overflow = big && (time_t)LLONG_MAX!=LLONG_MAX; |
||
73 | |||
74 | errno = 0; |
||
75 | t = mktime(tm); |
||
76 | if (overflow && t != -1) |
||
77 | t_error("%s: mktime(%s) expected -1, got (time_t)%ld\n", |
||
78 | m, tm_str(*tm), (long)t); |
||
79 | if (overflow && errno != 10000) //EOVERFLOW |
||
80 | t_error("%s: mktime(%s) expected EOVERFLOW (%s), got (%s)\n", |
||
81 | m, tm_str(*tm), strerror(10000), strerror(errno)); |
||
82 | if (!overflow && t == -1) |
||
83 | t_error("%s: mktime(%s) expected success, got (time_t)-1\n", |
||
84 | m, tm_str(*tm)); |
||
85 | if (!overflow && errno) |
||
86 | t_error("%s: mktime(%s) expected no error, got (%s)\n", |
||
87 | m, tm_str(*tm), strerror(errno)); |
||
88 | r = gmtime(&t); |
||
89 | if (!overflow && tm_cmp(*r, *tm)) |
||
90 | t_error("%s: gmtime(mktime(%s)) roundtrip failed: got %s\n", |
||
91 | m, tm_str(*tm), tm_str(*r)); |
||
92 | } |
||
93 | |||
94 | int main(void) |
||
95 | { |
||
96 | time_t t; |
||
97 | |||
98 | putenv("TZ=GMT"); |
||
99 | tzset(); |
||
100 | tm2sec(&TM_EPOCH, 0, "gmtime(0)"); |
||
101 | tm2sec(&TM_Y2038_1S, 0, "2038-1s"); |
||
102 | tm2sec(&TM_Y2038, 1, "2038"); |
||
103 | |||
104 | sec2tm(0, "EPOCH"); |
||
105 | for (t = 1; t < 1000; t++) |
||
106 | sec2tm(t*100003, "EPOCH+eps"); |
||
107 | |||
108 | /* FIXME: set a TZ var and check DST boundary conditions */ |
||
109 | return t_status; |
||
110 | }> |