1 /*
2 * Copyright (c) 2019 Peter Bigot Consulting
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* Tests where time_t requires a 64-bit value */
8
9 #include <errno.h>
10 #include <zephyr/ztest.h>
11 #include "timeutil_test.h"
12
13 static const struct timeutil_test_data tests[] = {
14 /* 32-bit, but algorithm subtraction underflows */
15 { .ux = -2147483648,
16 .civil = "1901-12-13 20:45:52 Fri 347",
17 .tm = {
18 .tm_sec = 52,
19 .tm_min = 45,
20 .tm_hour = 20,
21 .tm_mday = 13,
22 .tm_mon = 11,
23 .tm_year = 1,
24 .tm_wday = 5,
25 .tm_yday = 346,
26 } },
27 { .ux = (time_t)-2147483649,
28 .civil = "1901-12-13 20:45:51 Fri 347",
29 .tm = {
30 .tm_sec = 51,
31 .tm_min = 45,
32 .tm_hour = 20,
33 .tm_mday = 13,
34 .tm_mon = 11,
35 .tm_year = 1,
36 .tm_wday = 5,
37 .tm_yday = 346,
38 } },
39 { .ux = (time_t)2147483648,
40 .civil = "2038-01-19 03:14:08 Tue 019",
41 .tm = {
42 .tm_sec = 8,
43 .tm_min = 14,
44 .tm_hour = 3,
45 .tm_mday = 19,
46 .tm_mon = 0,
47 .tm_year = 138,
48 .tm_wday = 2,
49 .tm_yday = 18,
50 } },
51 { .ux = (time_t)64060588799,
52 .civil = "3999-12-31 23:59:59 Fri 365",
53 .tm = {
54 .tm_sec = 59,
55 .tm_min = 59,
56 .tm_hour = 23,
57 .tm_mday = 31,
58 .tm_mon = 11,
59 .tm_year = 2099,
60 .tm_wday = 5,
61 .tm_yday = 364,
62 } },
63 { .ux = (time_t)64060588800,
64 .civil = "4000-01-01 00:00:00 Sat 001",
65 .tm = {
66 .tm_sec = 0,
67 .tm_min = 0,
68 .tm_hour = 0,
69 .tm_mday = 1,
70 .tm_mon = 0,
71 .tm_year = 2100,
72 .tm_wday = 6,
73 .tm_yday = 0,
74 } },
75 /* Normal century is a common year */
76 { .ux = (time_t)-2208988801,
77 .civil = "1899-12-31 23:59:59 Sun 365",
78 .tm = {
79 .tm_sec = 59,
80 .tm_min = 59,
81 .tm_hour = 23,
82 .tm_mday = 31,
83 .tm_mon = 11,
84 .tm_year = -1,
85 .tm_wday = 0,
86 .tm_yday = 364,
87 } },
88 { .ux = (time_t)-2208988800,
89 .civil = "1900-01-01 00:00:00 Mon 001",
90 .tm = {
91 .tm_sec = 0,
92 .tm_min = 0,
93 .tm_hour = 0,
94 .tm_mday = 1,
95 .tm_mon = 0,
96 .tm_year = 0,
97 .tm_wday = 1,
98 .tm_yday = 0,
99 } },
100 { .ux = (time_t)-2203977600,
101 .civil = "1900-02-28 00:00:00 Wed 059",
102 .tm = {
103 .tm_sec = 0,
104 .tm_min = 0,
105 .tm_hour = 0,
106 .tm_mday = 28,
107 .tm_mon = 1,
108 .tm_year = 0,
109 .tm_wday = 3,
110 .tm_yday = 58,
111 } },
112 { .ux = (time_t)-2203891200,
113 .civil = "1900-03-01 00:00:00 Thu 060",
114 .tm = {
115 .tm_sec = 0,
116 .tm_min = 0,
117 .tm_hour = 0,
118 .tm_mday = 1,
119 .tm_mon = 2,
120 .tm_year = 0,
121 .tm_wday = 4,
122 .tm_yday = 59,
123 } },
124 { .ux = (time_t)-2177539200,
125 .civil = "1900-12-31 00:00:00 Mon 365",
126 .tm = {
127 .tm_sec = 0,
128 .tm_min = 0,
129 .tm_hour = 0,
130 .tm_mday = 31,
131 .tm_mon = 11,
132 .tm_year = 0,
133 .tm_wday = 1,
134 .tm_yday = 364,
135 } },
136 { .ux = (time_t)-2177452800,
137 .civil = "1901-01-01 00:00:00 Tue 001",
138 .tm = {
139 .tm_sec = 0,
140 .tm_min = 0,
141 .tm_hour = 0,
142 .tm_mday = 1,
143 .tm_mon = 0,
144 .tm_year = 1,
145 .tm_wday = 2,
146 .tm_yday = 0,
147 } },
148
149 /* Extrema, check against proleptic Gregorian calendar data:
150 * https://www.timeanddate.com/calendar/?year=1&country=22
151 */
152 { .ux = (time_t)-62167305600,
153 .civil = "-1-12-31 00:00:00 Fri 365",
154 .tm = {
155 .tm_sec = 0,
156 .tm_min = 0,
157 .tm_hour = 0,
158 .tm_mday = 31,
159 .tm_mon = 11,
160 .tm_year = -1901,
161 .tm_wday = 5,
162 .tm_yday = 364,
163 } },
164 { .ux = (time_t)-62167219200,
165 .civil = "0-01-01 00:00:00 Sat 001",
166 .tm = {
167 .tm_sec = 0,
168 .tm_min = 0,
169 .tm_hour = 0,
170 .tm_mday = 1,
171 .tm_mon = 0,
172 .tm_year = -1900,
173 .tm_wday = 6,
174 .tm_yday = 0,
175 } },
176 { .ux = (time_t)-62135596801,
177 .civil = "0-12-31 23:59:59 Sun 366",
178 .tm = {
179 .tm_sec = 59,
180 .tm_min = 59,
181 .tm_hour = 23,
182 .tm_mday = 31,
183 .tm_mon = 11,
184 .tm_year = -1900,
185 .tm_wday = 0,
186 .tm_yday = 365,
187 } },
188 { .ux = (time_t)-62135596800,
189 .civil = "1-01-01 00:00:00 Mon 001",
190 .tm = {
191 .tm_sec = 0,
192 .tm_min = 0,
193 .tm_hour = 0,
194 .tm_mday = 1,
195 .tm_mon = 0,
196 .tm_year = -1899,
197 .tm_wday = 1,
198 .tm_yday = 0,
199 } },
200 { .ux = (time_t)-62135596800,
201 .civil = "1-01-01 00:00:00 Mon 001",
202 .tm = {
203 .tm_sec = 0,
204 .tm_min = 0,
205 .tm_hour = 0,
206 .tm_mday = 1,
207 .tm_mon = 0,
208 .tm_year = -1899,
209 .tm_wday = 1,
210 .tm_yday = 0,
211 } },
212 };
213
test_time32_errno_clear(void)214 static void test_time32_errno_clear(void)
215 {
216 const struct timeutil_test_data *tp = &(const struct timeutil_test_data){
217 .ux = 0,
218 .civil = "1970-01-01 00:00:00 Thu 001",
219 .tm = {
220 .tm_sec = 0,
221 .tm_min = 0,
222 .tm_hour = 0,
223 .tm_mday = 1,
224 .tm_mon = 0,
225 .tm_year = 70,
226 .tm_wday = 4,
227 .tm_yday = 0,
228 },
229 };
230
231 errno = EINVAL;
232
233 time_t ux = timeutil_timegm(&tp->tm);
234
235 zassert_equal(ux, tp->ux,
236 "conversion incorrect");
237 zassert_equal(errno, 0,
238 "errno was not cleared");
239 }
240
test_time32_epochm1(void)241 static void test_time32_epochm1(void)
242 {
243 const struct timeutil_test_data *tp = &(const struct timeutil_test_data){
244 .ux = -1,
245 .civil = "1969-12-31 23:59:59 Wed 365",
246 .tm = {
247 .tm_sec = 59,
248 .tm_min = 59,
249 .tm_hour = 23,
250 .tm_mday = 31,
251 .tm_mon = 11,
252 .tm_year = 69,
253 .tm_wday = 3,
254 .tm_yday = 364,
255 },
256 };
257
258 errno = EINVAL;
259
260 time_t ux = timeutil_timegm(&tp->tm);
261
262 zassert_equal(ux, tp->ux,
263 "conversion incorrect");
264 zassert_equal(errno, 0,
265 "final errno state bad");
266 }
267
test_time32_underflow(void)268 static void test_time32_underflow(void)
269 {
270 const int64_t unix64 = -2147483649;
271 const struct timeutil_test_data *tp = &(const struct timeutil_test_data){
272 .civil = "1901-12-13 20:45:51 Fri 347",
273 .tm = {
274 .tm_sec = 51,
275 .tm_min = 45,
276 .tm_hour = 20,
277 .tm_mday = 13,
278 .tm_mon = 11,
279 .tm_year = 1,
280 .tm_wday = 5,
281 .tm_yday = 346,
282 },
283 };
284
285 zassert_equal(timeutil_timegm64(&tp->tm), unix64,
286 "fullscale failed");
287 errno = 0;
288
289 time_t ux = timeutil_timegm(&tp->tm);
290
291 zassert_equal(ux, -1,
292 "underflow undetected");
293 zassert_equal(errno, ERANGE,
294 "final errno state bad");
295 }
296
test_time32_overflow(void)297 static void test_time32_overflow(void)
298 {
299 const int64_t unix64 = 2147483648;
300 const struct timeutil_test_data *tp = &(const struct timeutil_test_data){
301 .civil = "2038-01-19 03:14:08 Tue 019",
302 .tm = {
303 .tm_sec = 8,
304 .tm_min = 14,
305 .tm_hour = 3,
306 .tm_mday = 19,
307 .tm_mon = 0,
308 .tm_year = 138,
309 .tm_wday = 2,
310 .tm_yday = 18,
311 },
312 };
313
314 zassert_equal(timeutil_timegm64(&tp->tm), unix64,
315 "fullscale failed");
316 errno = 0;
317
318 time_t ux = timeutil_timegm(&tp->tm);
319
320 zassert_equal(ux, -1,
321 "overflow undetected");
322 zassert_equal(errno, ERANGE,
323 "final errno state bad");
324 }
325
ZTEST(timeutil_api,test_s64)326 ZTEST(timeutil_api, test_s64)
327 {
328 if (sizeof(time_t) < 8U) {
329 test_time32_errno_clear();
330 test_time32_epochm1();
331 test_time32_underflow();
332 test_time32_overflow();
333 return;
334 }
335 timeutil_check(tests, sizeof(tests) / sizeof(*tests));
336 }
337