1 //===-- Unittests for mktime ----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "src/time/mktime.h"
10 #include "src/time/time_utils.h"
11 #include "test/ErrnoSetterMatcher.h"
12 #include "test/src/time/TmHelper.h"
13 #include "test/src/time/TmMatcher.h"
14 #include "utils/UnitTest/Test.h"
15
16 #include <errno.h>
17 #include <limits.h>
18 #include <string.h>
19
20 using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
21 using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
22 using __llvm_libc::time_utils::TimeConstants;
23
call_mktime(struct tm * tm_data,int year,int month,int mday,int hour,int min,int sec,int wday,int yday)24 static inline time_t call_mktime(struct tm *tm_data, int year, int month,
25 int mday, int hour, int min, int sec, int wday,
26 int yday) {
27 __llvm_libc::tmhelper::testing::initialize_tm_data(
28 tm_data, year, month, mday, hour, min, sec, wday, yday);
29 return __llvm_libc::mktime(tm_data);
30 }
31
TEST(LlvmLibcMkTime,FailureSetsErrno)32 TEST(LlvmLibcMkTime, FailureSetsErrno) {
33 struct tm tm_data;
34 __llvm_libc::tmhelper::testing::initialize_tm_data(
35 &tm_data, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, -1, 0, 0);
36 EXPECT_THAT(__llvm_libc::mktime(&tm_data), Fails(EOVERFLOW));
37 }
38
TEST(LlvmLibcMkTime,InvalidSeconds)39 TEST(LlvmLibcMkTime, InvalidSeconds) {
40 struct tm tm_data;
41 // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
42 EXPECT_THAT(call_mktime(&tm_data,
43 1970, // year
44 1, // month
45 1, // day
46 0, // hr
47 0, // min
48 -1, // sec
49 0, // wday
50 0), // yday
51 Succeeds(-1));
52 EXPECT_TM_EQ((tm{59, // sec
53 59, // min
54 23, // hr
55 31, // day
56 12 - 1, // tm_mon starts with 0 for Jan
57 1969 - TimeConstants::TIME_YEAR_BASE, // year
58 3, // wday
59 364, // yday
60 0}),
61 tm_data);
62 // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
63 EXPECT_THAT(call_mktime(&tm_data,
64 1970, // year
65 1, // month
66 1, // day
67 0, // hr
68 0, // min
69 60, // sec
70 0, // wday
71 0), // yday
72 Succeeds(60));
73 EXPECT_TM_EQ((tm{0, // sec
74 1, // min
75 0, // hr
76 1, // day
77 0, // tm_mon starts with 0 for Jan
78 1970 - TimeConstants::TIME_YEAR_BASE, // year
79 4, // wday
80 0, // yday
81 0}),
82 tm_data);
83 }
84
TEST(LlvmLibcMkTime,InvalidMinutes)85 TEST(LlvmLibcMkTime, InvalidMinutes) {
86 struct tm tm_data;
87 // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
88 EXPECT_THAT(call_mktime(&tm_data,
89 1970, // year
90 1, // month
91 1, // day
92 0, // hr
93 -1, // min
94 0, // sec
95 0, // wday
96 0), // yday
97 Succeeds(-TimeConstants::SECONDS_PER_MIN));
98 EXPECT_TM_EQ((tm{0, // sec
99 59, // min
100 23, // hr
101 31, // day
102 11, // tm_mon starts with 0 for Jan
103 1969 - TimeConstants::TIME_YEAR_BASE, // year
104 3, // wday
105 0, // yday
106 0}),
107 tm_data);
108 // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
109 EXPECT_THAT(call_mktime(&tm_data,
110 1970, // year
111 1, // month
112 1, // day
113 0, // hr
114 60, // min
115 0, // sec
116 0, // wday
117 0), // yday
118 Succeeds(60 * TimeConstants::SECONDS_PER_MIN));
119 EXPECT_TM_EQ((tm{0, // sec
120 0, // min
121 1, // hr
122 1, // day
123 0, // tm_mon starts with 0 for Jan
124 1970 - TimeConstants::TIME_YEAR_BASE, // year
125 4, // wday
126 0, // yday
127 0}),
128 tm_data);
129 }
130
TEST(LlvmLibcMkTime,InvalidHours)131 TEST(LlvmLibcMkTime, InvalidHours) {
132 struct tm tm_data;
133 // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
134 EXPECT_THAT(call_mktime(&tm_data,
135 1970, // year
136 1, // month
137 1, // day
138 -1, // hr
139 0, // min
140 0, // sec
141 0, // wday
142 0), // yday
143 Succeeds(-TimeConstants::SECONDS_PER_HOUR));
144 EXPECT_TM_EQ((tm{0, // sec
145 0, // min
146 23, // hr
147 31, // day
148 11, // tm_mon starts with 0 for Jan
149 1969 - TimeConstants::TIME_YEAR_BASE, // year
150 3, // wday
151 0, // yday
152 0}),
153 tm_data);
154 // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
155 EXPECT_THAT(call_mktime(&tm_data,
156 1970, // year
157 1, // month
158 1, // day
159 24, // hr
160 0, // min
161 0, // sec
162 0, // wday
163 0), // yday
164 Succeeds(24 * TimeConstants::SECONDS_PER_HOUR));
165 EXPECT_TM_EQ((tm{0, // sec
166 0, // min
167 0, // hr
168 2, // day
169 0, // tm_mon starts with 0 for Jan
170 1970 - TimeConstants::TIME_YEAR_BASE, // year
171 5, // wday
172 0, // yday
173 0}),
174 tm_data);
175 }
176
TEST(LlvmLibcMkTime,InvalidYear)177 TEST(LlvmLibcMkTime, InvalidYear) {
178 struct tm tm_data;
179 // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
180 EXPECT_THAT(call_mktime(&tm_data,
181 1969, // year
182 1, // month
183 1, // day
184 0, // hr
185 0, // min
186 0, // sec
187 0, // wday
188 0), // yday
189 Succeeds(-TimeConstants::DAYS_PER_NON_LEAP_YEAR *
190 TimeConstants::SECONDS_PER_DAY));
191 EXPECT_TM_EQ((tm{0, // sec
192 0, // min
193 0, // hr
194 1, // day
195 0, // tm_mon starts with 0 for Jan
196 1969 - TimeConstants::TIME_YEAR_BASE, // year
197 3, // wday
198 0, // yday
199 0}),
200 tm_data);
201 }
202
TEST(LlvmLibcMkTime,InvalidEndOf32BitEpochYear)203 TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) {
204 if (sizeof(size_t) != 4)
205 return;
206 struct tm tm_data;
207 // 2038-01-19 03:14:08 tests overflow of the second in 2038.
208 EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 3, 14, 8, 0, 0),
209 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
210 // 2038-01-19 03:15:07 tests overflow of the minute in 2038.
211 EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 3, 15, 7, 0, 0),
212 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
213 // 2038-01-19 04:14:07 tests overflow of the hour in 2038.
214 EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 19, 4, 14, 7, 0, 0),
215 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
216 // 2038-01-20 03:14:07 tests overflow of the day in 2038.
217 EXPECT_THAT(call_mktime(&tm_data, 2038, 1, 20, 3, 14, 7, 0, 0),
218 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
219 // 2038-02-19 03:14:07 tests overflow of the month in 2038.
220 EXPECT_THAT(call_mktime(&tm_data, 2038, 2, 19, 3, 14, 7, 0, 0),
221 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
222 // 2039-01-19 03:14:07 tests overflow of the year.
223 EXPECT_THAT(call_mktime(&tm_data, 2039, 1, 19, 3, 14, 7, 0, 0),
224 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE));
225 }
226
TEST(LlvmLibcMkTime,InvalidMonths)227 TEST(LlvmLibcMkTime, InvalidMonths) {
228 struct tm tm_data;
229 // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
230 EXPECT_THAT(call_mktime(&tm_data,
231 1970, // year
232 0, // month
233 1, // day
234 0, // hr
235 0, // min
236 0, // sec
237 0, // wday
238 0), // yday
239 Succeeds(-31 * TimeConstants::SECONDS_PER_DAY));
240 EXPECT_TM_EQ((tm{0, // sec
241 0, // min
242 0, // hr
243 1, // day
244 12 - 1, // tm_mon starts with 0 for Jan
245 1969 - TimeConstants::TIME_YEAR_BASE, // year
246 1, // wday
247 0, // yday
248 0}),
249 tm_data);
250 // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
251 EXPECT_THAT(call_mktime(&tm_data,
252 1970, // year
253 13, // month
254 1, // day
255 0, // hr
256 0, // min
257 0, // sec
258 0, // wday
259 0), // yday
260 Succeeds(TimeConstants::DAYS_PER_NON_LEAP_YEAR *
261 TimeConstants::SECONDS_PER_DAY));
262 EXPECT_TM_EQ((tm{0, // sec
263 0, // min
264 0, // hr
265 1, // day
266 0, // tm_mon starts with 0 for Jan
267 1971 - TimeConstants::TIME_YEAR_BASE, // year
268 5, // wday
269 0, // yday
270 0}),
271 tm_data);
272 }
273
TEST(LlvmLibcMkTime,InvalidDays)274 TEST(LlvmLibcMkTime, InvalidDays) {
275 struct tm tm_data;
276 // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
277 EXPECT_THAT(call_mktime(&tm_data,
278 1970, // year
279 1, // month
280 0, // day
281 0, // hr
282 0, // min
283 0, // sec
284 0, // wday
285 0), // yday
286 Succeeds(-1 * TimeConstants::SECONDS_PER_DAY));
287 EXPECT_TM_EQ((tm{0, // sec
288 0, // min
289 0, // hr
290 31, // day
291 11, // tm_mon starts with 0 for Jan
292 1969 - TimeConstants::TIME_YEAR_BASE, // year
293 3, // wday
294 0, // yday
295 0}),
296 tm_data);
297
298 // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
299 EXPECT_THAT(call_mktime(&tm_data,
300 1970, // year
301 1, // month
302 32, // day
303 0, // hr
304 0, // min
305 0, // sec
306 0, // wday
307 0), // yday
308 Succeeds(31 * TimeConstants::SECONDS_PER_DAY));
309 EXPECT_TM_EQ((tm{0, // sec
310 0, // min
311 0, // hr
312 1, // day
313 0, // tm_mon starts with 0 for Jan
314 1970 - TimeConstants::TIME_YEAR_BASE, // year
315 0, // wday
316 0, // yday
317 0}),
318 tm_data);
319
320 // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
321 EXPECT_THAT(call_mktime(&tm_data,
322 1970, // year
323 2, // month
324 29, // day
325 0, // hr
326 0, // min
327 0, // sec
328 0, // wday
329 0), // yday
330 Succeeds(59 * TimeConstants::SECONDS_PER_DAY));
331 EXPECT_TM_EQ((tm{0, // sec
332 0, // min
333 0, // hr
334 1, // day
335 2, // tm_mon starts with 0 for Jan
336 1970 - TimeConstants::TIME_YEAR_BASE, // year
337 0, // wday
338 0, // yday
339 0}),
340 tm_data);
341
342 // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
343 EXPECT_THAT(call_mktime(&tm_data,
344 1972, // year
345 2, // month
346 30, // day
347 0, // hr
348 0, // min
349 0, // sec
350 0, // wday
351 0), // yday
352 Succeeds(((2 * TimeConstants::DAYS_PER_NON_LEAP_YEAR) + 60) *
353 TimeConstants::SECONDS_PER_DAY));
354 EXPECT_TM_EQ((tm{0, // sec
355 0, // min
356 0, // hr
357 1, // day
358 2, // tm_mon starts with 0 for Jan
359 1972 - TimeConstants::TIME_YEAR_BASE, // year
360 3, // wday
361 0, // yday
362 0}),
363 tm_data);
364 }
365
TEST(LlvmLibcMkTime,EndOf32BitEpochYear)366 TEST(LlvmLibcMkTime, EndOf32BitEpochYear) {
367 struct tm tm_data;
368 // Test for maximum value of a signed 32-bit integer.
369 // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
370 EXPECT_THAT(call_mktime(&tm_data,
371 2038, // year
372 1, // month
373 19, // day
374 3, // hr
375 14, // min
376 7, // sec
377 0, // wday
378 0), // yday
379 Succeeds(0x7FFFFFFF));
380 EXPECT_TM_EQ((tm{7, // sec
381 14, // min
382 3, // hr
383 19, // day
384 0, // tm_mon starts with 0 for Jan
385 2038 - TimeConstants::TIME_YEAR_BASE, // year
386 2, // wday
387 7, // yday
388 0}),
389 tm_data);
390 }
391
TEST(LlvmLibcMkTime,Max64BitYear)392 TEST(LlvmLibcMkTime, Max64BitYear) {
393 if (sizeof(time_t) == 4)
394 return;
395 // Mon Jan 1 12:50:50 2170 (200 years from 1970),
396 struct tm tm_data;
397 EXPECT_THAT(call_mktime(&tm_data,
398 2170, // year
399 1, // month
400 1, // day
401 12, // hr
402 50, // min
403 50, // sec
404 0, // wday
405 0), // yday
406 Succeeds(6311479850));
407 EXPECT_TM_EQ((tm{50, // sec
408 50, // min
409 12, // hr
410 1, // day
411 0, // tm_mon starts with 0 for Jan
412 2170 - TimeConstants::TIME_YEAR_BASE, // year
413 1, // wday
414 50, // yday
415 0}),
416 tm_data);
417
418 // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
419 EXPECT_THAT(call_mktime(&tm_data, 2147483647, 1, 1, 12, 50, 50, 0, 0),
420 Succeeds(67767976202043050));
421 EXPECT_TM_EQ((tm{50, // sec
422 50, // min
423 12, // hr
424 1, // day
425 0, // tm_mon starts with 0 for Jan
426 2147483647 - TimeConstants::TIME_YEAR_BASE, // year
427 2, // wday
428 50, // yday
429 0}),
430 tm_data);
431 }
432