1 //===-- Unittests for mktime ----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/time/mktime.h"
10 #include "src/time/time_utils.h"
11 #include "test/ErrnoSetterMatcher.h"
12 #include "test/UnitTest/Test.h"
13 #include "test/src/time/TmHelper.h"
14 #include "test/src/time/TmMatcher.h"
19 using __llvm_libc::testing::ErrnoSetterMatcher::Fails
;
20 using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds
;
21 using __llvm_libc::time_utils::Month
;
23 static inline constexpr int tm_year(int year
) {
24 return year
- TimeConstants::TIME_YEAR_BASE
;
27 TEST(LlvmLibcMkTime
, FailureSetsErrno
) {
29 .tm_sec
= INT_MAX
, .tm_min
= INT_MAX
, .tm_hour
= INT_MAX
,
30 .tm_mday
= INT_MAX
, .tm_mon
= INT_MAX
- 1, .tm_year
= tm_year(INT_MAX
),
31 .tm_wday
= 0, .tm_yday
= 0
33 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Fails(EOVERFLOW
));
36 TEST(LlvmLibcMkTime
, InvalidSeconds
) {
38 // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
40 .tm_sec
= -1, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 1,
41 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
44 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Succeeds(-1));
45 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
49 .tm_mon
= Month::DECEMBER
,
50 .tm_year
= tm_year(1969),
57 // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
59 .tm_sec
= 60, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 1,
60 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
63 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Succeeds(60));
64 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
68 .tm_mon
= Month::JANUARY
,
69 .tm_year
= tm_year(1970),
76 TEST(LlvmLibcMkTime
, InvalidMinutes
) {
78 // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
80 .tm_sec
= 0, .tm_min
= -1, .tm_hour
= 0, .tm_mday
= 1,
81 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
84 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
85 Succeeds(-TimeConstants::SECONDS_PER_MIN
));
86 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
90 .tm_mon
= Month::DECEMBER
,
91 .tm_year
= tm_year(1969),
98 // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
100 .tm_sec
= 0, .tm_min
= 60, .tm_hour
= 0, .tm_mday
= 1,
101 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
104 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
105 Succeeds(60 * TimeConstants::SECONDS_PER_MIN
));
106 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
110 .tm_mon
= Month::JANUARY
,
111 .tm_year
= tm_year(1970),
118 TEST(LlvmLibcMkTime
, InvalidHours
) {
120 // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
122 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= -1, .tm_mday
= 1,
123 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
126 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
127 Succeeds(-TimeConstants::SECONDS_PER_HOUR
));
128 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
132 .tm_mon
= Month::DECEMBER
,
133 .tm_year
= tm_year(1969),
140 // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
142 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 24, .tm_mday
= 1,
143 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
146 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
147 Succeeds(24 * TimeConstants::SECONDS_PER_HOUR
));
148 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
152 .tm_mon
= Month::JANUARY
,
153 .tm_year
= tm_year(1970),
160 TEST(LlvmLibcMkTime
, InvalidYear
) {
161 // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
163 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 1,
164 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1969), .tm_wday
= 0,
167 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
168 Succeeds(-TimeConstants::DAYS_PER_NON_LEAP_YEAR
*
169 TimeConstants::SECONDS_PER_DAY
));
170 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
174 .tm_mon
= Month::JANUARY
,
175 .tm_year
= tm_year(1969),
181 TEST(LlvmLibcMkTime
, InvalidEndOf32BitEpochYear
) {
182 if (sizeof(size_t) != 4)
185 // 2038-01-19 03:14:08 tests overflow of the second in 2038.
187 .tm_sec
= 8, .tm_min
= 14, .tm_hour
= 3, .tm_mday
= 19,
188 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
191 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
192 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
196 // 2038-01-19 03:15:07 tests overflow of the minute in 2038.
198 .tm_sec
= 7, .tm_min
= 15, .tm_hour
= 3, .tm_mday
= 19,
199 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
202 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
203 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
207 // 2038-01-19 04:14:07 tests overflow of the hour in 2038.
209 .tm_sec
= 7, .tm_min
= 14, .tm_hour
= 4, .tm_mday
= 19,
210 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
213 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
214 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
218 // 2038-01-20 03:14:07 tests overflow of the day in 2038.
220 .tm_sec
= 7, .tm_min
= 14, .tm_hour
= 3, .tm_mday
= 20,
221 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
224 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
225 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
229 // 2038-02-19 03:14:07 tests overflow of the month in 2038.
231 .tm_sec
= 7, .tm_min
= 14, .tm_hour
= 3, .tm_mday
= 19,
232 .tm_mon
= Month::FEBRUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
235 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
236 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
240 // 2039-01-19 03:14:07 tests overflow of the year.
242 .tm_sec
= 7, .tm_min
= 14, .tm_hour
= 3, .tm_mday
= 19,
243 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2039), .tm_wday
= 0,
246 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
247 Succeeds(TimeConstants::OUT_OF_RANGE_RETURN_VALUE
));
251 TEST(LlvmLibcMkTime
, InvalidMonths
) {
253 // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
255 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 0, .tm_mon
= -1,
256 .tm_year
= tm_year(1970), .tm_wday
= 0, .tm_yday
= 0
258 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
259 Succeeds(-32 * TimeConstants::SECONDS_PER_DAY
));
260 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
264 .tm_mon
= Month::DECEMBER
,
265 .tm_year
= tm_year(1969),
272 // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
274 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 1, .tm_mon
= 12,
275 .tm_year
= tm_year(1970), .tm_wday
= 0, .tm_yday
= 0
277 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
278 Succeeds(TimeConstants::DAYS_PER_NON_LEAP_YEAR
*
279 TimeConstants::SECONDS_PER_DAY
));
280 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
284 .tm_mon
= Month::JANUARY
,
285 .tm_year
= tm_year(1971),
292 TEST(LlvmLibcMkTime
, InvalidDays
) {
294 // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
296 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= (1 - 1),
297 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
300 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
301 Succeeds(-1 * TimeConstants::SECONDS_PER_DAY
));
302 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
306 .tm_mon
= Month::DECEMBER
,
307 .tm_year
= tm_year(1969),
314 // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
316 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 32,
317 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
320 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
321 Succeeds(31 * TimeConstants::SECONDS_PER_DAY
));
322 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
326 .tm_mon
= Month::FEBRUARY
,
327 .tm_year
= tm_year(1970),
334 // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
336 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 29,
337 .tm_mon
= Month::FEBRUARY
, .tm_year
= tm_year(1970), .tm_wday
= 0,
340 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
341 Succeeds(59 * TimeConstants::SECONDS_PER_DAY
));
342 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
346 .tm_mon
= Month::MARCH
,
347 .tm_year
= tm_year(1970),
354 // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
356 .tm_sec
= 0, .tm_min
= 0, .tm_hour
= 0, .tm_mday
= 30,
357 .tm_mon
= Month::FEBRUARY
, .tm_year
= tm_year(1972), .tm_wday
= 0,
360 EXPECT_THAT(__llvm_libc::mktime(&tm_data
),
361 Succeeds(((2 * TimeConstants::DAYS_PER_NON_LEAP_YEAR
) + 60) *
362 TimeConstants::SECONDS_PER_DAY
));
363 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
367 .tm_mon
= Month::MARCH
,
368 .tm_year
= tm_year(1972),
375 TEST(LlvmLibcMkTime
, EndOf32BitEpochYear
) {
376 // Test for maximum value of a signed 32-bit integer.
377 // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
379 .tm_sec
= 7, .tm_min
= 14, .tm_hour
= 3, .tm_mday
= 19,
380 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2038), .tm_wday
= 0,
383 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Succeeds(0x7FFFFFFF));
384 EXPECT_TM_EQ((tm
{.tm_sec
= 7,
388 .tm_mon
= Month::JANUARY
,
389 .tm_year
= tm_year(2038),
395 TEST(LlvmLibcMkTime
, Max64BitYear
) {
396 if (sizeof(time_t) == 4)
399 // Mon Jan 1 12:50:50 2170 (200 years from 1970),
401 .tm_sec
= 50, .tm_min
= 50, .tm_hour
= 12, .tm_mday
= 1,
402 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2170), .tm_wday
= 0,
405 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Succeeds(6311479850));
406 EXPECT_TM_EQ((tm
{.tm_sec
= 50,
410 .tm_mon
= Month::JANUARY
,
411 .tm_year
= tm_year(2170),
418 // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
420 .tm_sec
= 50, .tm_min
= 50, .tm_hour
= 12, .tm_mday
= 1,
421 .tm_mon
= Month::JANUARY
, .tm_year
= tm_year(2147483647), .tm_wday
= 0,
424 EXPECT_THAT(__llvm_libc::mktime(&tm_data
), Succeeds(67767976202043050));
425 EXPECT_TM_EQ((tm
{.tm_sec
= 50,
429 .tm_mon
= Month::JANUARY
,
430 .tm_year
= tm_year(2147483647),