1 /*
2 * tests for mktime(), mkgmtime(), timespec_to_iso8601() and
3 * iso8601_to_timespec().
4 * mktime() is a libc function, why test it?
5 *
6 * This file is Copyright (c) 2010-2019 by the GPSD project
7 * SPDX-License-Identifier: BSD-2-clause
8 */
9 #include <limits.h>
10 #include <math.h> /* for fabs() */
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <time.h>
16
17 #include "../gps.h"
18 #include "../compiler.h"
19 #include "../timespec.h"
20
21 static struct
22 {
23 struct tm t;
24 time_t result;
25 } tests[] = {
26 /* *INDENT-OFF* */
27 /* sec, min, h, md, mon, year, wd, yd, isdst, gmtoff, zone,
28 * time_t what */
29
30 /* lower limit */
31 {{ 0, 0, 0, 1, 0, 70, 0, 0, 0, 0, 0}, 0},
32 /* upper limit */
33 {{ 7, 14, 3, 19, 0, 138, 0, 0, 0, 0, 0}, 0x7fffffff},
34 /* leap year */
35 {{ 0, 0, 12, 1, 0, 99, 0, 0, 0, 0, 0}, 915192000},
36 /* leap year */
37 {{ 0, 0, 12, 1, 1, 99, 0, 0, 0, 0, 0}, 917870400},
38 /* leap year */
39 {{ 0, 0, 12, 1, 2, 99, 0, 0, 0, 0, 0}, 920289600},
40 /* leap year */
41 {{ 0, 0, 12, 1, 8, 99, 0, 0, 0, 0, 0}, 936187200},
42 /* leap year */
43 {{ 0, 0, 12, 1, 0, 100, 0, 0, 0, 0, 0}, 946728000},
44 /* leap year */
45 {{ 0, 0, 12, 1, 1, 100, 0, 0, 0, 0, 0}, 949406400},
46 /* leap year */
47 {{ 0, 0, 12, 1, 2, 100, 0, 0, 0, 0, 0}, 951912000},
48 /* leap year */
49 {{ 0, 0, 12, 1, 8, 100, 0, 0, 0, 0, 0}, 967809600},
50 /* leap year */
51 {{ 0, 0, 12, 1, 0, 101, 0, 0, 0, 0, 0}, 978350400},
52 /* leap year */
53 {{ 0, 0, 12, 1, 1, 101, 0, 0, 0, 0, 0}, 981028800},
54 /* leap year */
55 {{ 0, 0, 12, 1, 2, 101, 0, 0, 0, 0, 0}, 983448000},
56 /* leap year */
57 {{ 0, 0, 12, 1, 8, 101, 0, 0, 0, 0, 0}, 999345600},
58 /* leap year */
59 {{ 0, 0, 12, 1, 0, 102, 0, 0, 0, 0, 0}, 1009886400},
60 /* leap year */
61 {{ 0, 0, 12, 1, 1, 102, 0, 0, 0, 0, 0}, 1012564800},
62 /* leap year */
63 {{ 0, 0, 12, 1, 2, 102, 0, 0, 0, 0, 0}, 1014984000},
64 /* leap year */
65 {{ 0, 0, 12, 1, 8, 102, 0, 0, 0, 0, 0}, 1030881600},
66 /* leap year */
67 {{ 0, 0, 12, 1, 0, 103, 0, 0, 0, 0, 0}, 1041422400},
68 /* leap year */
69 {{ 0, 0, 12, 1, 1, 103, 0, 0, 0, 0, 0}, 1044100800},
70 /* leap year */
71 {{ 0, 0, 12, 1, 2, 103, 0, 0, 0, 0, 0}, 1046520000},
72 /* leap year */
73 {{ 0, 0, 12, 1, 8, 103, 0, 0, 0, 0, 0}, 1062417600},
74 /* leap year */
75 {{ 0, 0, 12, 1, 0, 104, 0, 0, 0, 0, 0}, 1072958400},
76 /* leap year */
77 {{ 0, 0, 12, 1, 1, 104, 0, 0, 0, 0, 0}, 1075636800},
78 /* leap year */
79 {{ 0, 0, 12, 1, 2, 104, 0, 0, 0, 0, 0}, 1078142400},
80 {{ 0, 0, 12, 1, 2, 104, 0, 0, 0, 0, 0}, 1078142400},
81 /* leap year */
82 {{ 0, 0, 12, 1, 8, 104, 0, 0, 0, 0, 0}, 1094040000},
83 /* leap year */
84 {{ 0, 0, 12, 1, 0, 108, 0, 0, 0, 0, 0}, 1199188800},
85 /* leap year */
86 {{ 0, 0, 12, 1, 1, 108, 0, 0, 0, 0, 0}, 1201867200},
87 /* leap year */
88 {{ 0, 0, 12, 1, 2, 108, 0, 0, 0, 0, 0}, 1204372800},
89 /* leap year */
90 {{ 0, 0, 12, 1, 8, 108, 0, 0, 0, 0, 0}, 1220270400},
91 /* year wrap */
92 {{ 59, 59, 23, 31, 12, 110, 0, 0, 0, 0, 0}, 1296518399},
93 /* year wrap */
94 {{ 0, 0, 0, 1, 0, 111, 0, 0, 0, 0, 0}, 1293840000},
95 /* year wrap */
96 {{ 59, 59, 23, 31, 12, 111, 0, 0, 0, 0, 0}, 1328054399},
97 /* year wrap */
98 {{ 0, 0, 0, 1, 0, 112, 0, 0, 0, 0, 0}, 1325376000},
99 /* year wrap */
100 {{ 59, 59, 23, 31, 12, 112, 0, 0, 0, 0, 0}, 1359676799},
101 /* year wrap */
102 {{ 0, 0, 0, 1, 0, 113, 0, 0, 0, 0, 0}, 1356998400},
103 /* month wrap */
104 {{ 59, 59, 23, 31, 0, 115, 0, 0, 0, 0, 0}, 1422748799},
105 /* month wrap */
106 {{ 0, 0, 0, 1, 1, 115, 0, 0, 0, 0, 0}, 1422748800},
107 /* month wrap */
108 {{ 59, 59, 23, 28, 1, 115, 0, 0, 0, 0, 0}, 1425167999},
109 /* month wrap */
110 {{ 0, 0, 0, 1, 2, 115, 0, 0, 0, 0, 0}, 1425168000},
111 /* month wrap */
112 {{ 59, 59, 23, 31, 2, 115, 0, 0, 0, 0, 0}, 1427846399},
113 /* month wrap */
114 {{ 0, 0, 0, 1, 3, 115, 0, 0, 0, 0, 0}, 1427846400},
115 /* month wrap */
116 {{ 59, 59, 23, 30, 3, 115, 0, 0, 0, 0, 0}, 1430438399},
117 /* month wrap */
118 {{ 0, 0, 0, 1, 4, 115, 0, 0, 0, 0, 0}, 1430438400},
119 /* month wrap */
120 {{ 59, 59, 23, 31, 4, 115, 0, 0, 0, 0, 0}, 1433116799},
121 /* month wrap */
122 {{ 0, 0, 0, 1, 5, 115, 0, 0, 0, 0, 0}, 1433116800},
123 /* month wrap */
124 {{ 59, 59, 23, 30, 5, 115, 0, 0, 0, 0, 0}, 1435708799},
125 /* month wrap */
126 {{ 0, 0, 0, 1, 6, 115, 0, 0, 0, 0, 0}, 1435708800},
127 /* month wrap */
128 {{ 59, 59, 23, 31, 6, 115, 0, 0, 0, 0, 0}, 1438387199},
129 /* month wrap */
130 {{ 0, 0, 0, 1, 7, 115, 0, 0, 0, 0, 0}, 1438387200},
131 /* month wrap */
132 {{ 59, 59, 23, 31, 7, 115, 0, 0, 0, 0, 0}, 1441065599},
133 /* month wrap */
134 {{ 0, 0, 0, 1, 8, 115, 0, 0, 0, 0, 0}, 1441065600},
135 /* month wrap */
136 {{ 59, 59, 23, 30, 8, 115, 0, 0, 0, 0, 0}, 1443657599},
137 /* month wrap */
138 {{ 0, 0, 0, 1, 9, 115, 0, 0, 0, 0, 0}, 1443657600},
139 /* month wrap */
140 {{ 59, 59, 23, 31, 9, 115, 0, 0, 0, 0, 0}, 1446335999},
141 /* month wrap */
142 {{ 0, 0, 0, 1, 10, 115, 0, 0, 0, 0, 0}, 1446336000},
143 /* month wrap */
144 {{ 59, 59, 23, 30, 10, 115, 0, 0, 0, 0, 0}, 1448927999},
145 /* month wrap */
146 {{ 0, 0, 0, 1, 11, 115, 0, 0, 0, 0, 0}, 1448928000},
147 /* month wrap */
148 {{ 59, 59, 23, 31, 11, 115, 0, 0, 0, 0, 0}, 1451606399},
149 /* month wrap */
150 {{ 0, 0, 0, 1, 0, 116, 0, 0, 0, 0, 0}, 1451606400},
151 /* *INDENT-ON* */
152 };
153
154
155 /* tests for timespec_to_iso8601() */
156 static struct
157 {
158 timespec_t ts_time;
159 char *iso8601; /* iso8601 result */
160 } tests1[] = {
161 /* time zero */
162 {{0, 0}, "1970-01-01T00:00:00.000Z"},
163
164 /* before/after leap second end of 2008, notice no :60! */
165 {{1230767999L, 1000000L}, "2008-12-31T23:59:59.001Z"},
166 {{1230767999L, 10000000L}, "2008-12-31T23:59:59.010Z"},
167 {{1230767999L, 100000000L}, "2008-12-31T23:59:59.100Z"},
168 {{1230768000L, 20000000L}, "2009-01-01T00:00:00.020Z"},
169
170 /* test for rounding at %.3f */
171 {{1541766896L, 999412000L}, "2018-11-09T12:34:56.999Z"},
172 {{1541766896L, 999499000L}, "2018-11-09T12:34:56.999Z"},
173 {{1541766896L, 999500000L}, "2018-11-09T12:34:57.000Z"},
174 {{1541766896L, 999501000L}, "2018-11-09T12:34:57.000Z"},
175
176 /* the end of time: 2038 */
177 {{2147483647L, 123456000L}, "2038-01-19T03:14:07.123Z"},
178
179 #if 4 < SIZEOF_TIME_T
180 /* this next line generates compiler warning if 4 < sizeof(time_t)
181 * if so, the test will fail, and your system will break in 2038 */
182 {{2147483648L, 123456000L}, "2038-01-19T03:14:08.123Z"},
183 #endif
184
185 };
186
main(int argc UNUSED,char * argv[]UNUSED)187 int main(int argc UNUSED, char *argv[] UNUSED)
188 {
189 int i;
190 char tbuf[128];
191 bool failed = false;
192 timespec_t ts_time;
193 char ts_buf[TIMESPEC_LEN];
194
195 (void)setenv("TZ", "GMT", 1);
196
197 /* test mktime() */
198 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
199 time_t ts = mktime(&tests[i].t);
200 if (ts != tests[i].result) {
201 failed = true;
202 (void)strftime(tbuf, sizeof(tbuf), "%F %T", &tests[i].t);
203 (void)printf("test_mktime: mktime() test %2d failed.\n"
204 " Time returned from: %s should be %lu "
205 " (but was: %lu)\n",
206 i, tbuf, (unsigned long)tests[i].result,
207 (unsigned long)ts);
208 }
209 }
210
211 /* test mkgmtime() */
212 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
213 time_t ts = mkgmtime(&tests[i].t);
214 if (ts != tests[i].result) {
215 failed = true;
216 (void)strftime(tbuf, sizeof(tbuf), "%F %T", &tests[i].t);
217 (void)printf("test_mktime: mkgmtime() test %2d failed.\n"
218 " Time returned from: %s should be %lu "
219 " (but was: %lu)\n",
220 i, tbuf, (unsigned long)tests[i].result,
221 (unsigned long)ts);
222 }
223 }
224
225 /* test timespec_to_iso8601() */
226 if ( 4 >= sizeof(time_t)) {
227 (void)printf("WARNING: time_t too small. This gpsd binary "
228 "will fail at the 2038 roll over\n");
229 }
230
231 for (i = 0; i < (int)(sizeof(tests1) / sizeof(tests1[0])); i++) {
232 timespec_to_iso8601(tests1[i].ts_time, tbuf, sizeof(tbuf));
233 if (0 != strcmp(tests1[i].iso8601, tbuf)) {
234 failed = true;
235 (void)printf("test_mktime: timespec_to_iso8601() test %s failed.\n"
236 " Got %s, s/b %s\n",
237 timespec_str(&tests1[i].ts_time, ts_buf,
238 sizeof(ts_buf)),
239 tbuf, tests1[i].iso8601);
240 }
241 }
242
243 /* test iso8601_to_timespec() */
244 for (i = 0; i < (int)(sizeof(tests1) / sizeof(tests1[0])); i++) {
245 timespec_t ts_tmp;
246 ts_time = iso8601_to_timespec(tests1[i].iso8601);
247 TS_SUB(&ts_tmp, &ts_time, &tests1[i].ts_time);
248 if (0.001 <= fabs(TSTONS(&ts_tmp))) {
249 failed = true;
250 (void)printf("test_mktime: iso8601_to_timespec() test %s failed.\n"
251 " Got %.3f, s/b %.3f\n",
252 tests1[i].iso8601, TSTONS(&ts_time),
253 TSTONS(&tests1[i].ts_time));
254 }
255 }
256
257 return (int)failed;
258 }
259
260 /* end */
261
262