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/__support/CPP/limits.h" // INT_MAX
10 #include "src/time/mktime.h"
11 #include "src/time/time_constants.h"
12 #include "test/UnitTest/ErrnoSetterMatcher.h"
13 #include "test/UnitTest/Test.h"
14 #include "test/src/time/TmHelper.h"
15 #include "test/src/time/TmMatcher.h"
17 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails
;
18 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds
;
19 using LIBC_NAMESPACE::time_constants::Month
;
21 static inline constexpr int tm_year(int year
) {
22 return year
- LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE
;
25 TEST(LlvmLibcMkTime
, FailureSetsErrno
) {
26 struct tm tm_data
{.tm_sec
= INT_MAX
,
30 .tm_mon
= INT_MAX
- 1,
31 .tm_year
= tm_year(INT_MAX
),
35 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
38 TEST(LlvmLibcMkTime
, InvalidSeconds
) {
40 // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59.
41 struct tm tm_data
{.tm_sec
= -1,
45 .tm_mon
= Month::JANUARY
,
46 .tm_year
= tm_year(1970),
50 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(-1));
51 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
55 .tm_mon
= Month::DECEMBER
,
56 .tm_year
= tm_year(1969),
64 // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00.
65 struct tm tm_data
{.tm_sec
= 60,
69 .tm_mon
= Month::JANUARY
,
70 .tm_year
= tm_year(1970),
74 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(60));
75 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
79 .tm_mon
= Month::JANUARY
,
80 .tm_year
= tm_year(1970),
88 TEST(LlvmLibcMkTime
, InvalidMinutes
) {
90 // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00.
91 struct tm tm_data
{.tm_sec
= 0,
95 .tm_mon
= Month::JANUARY
,
96 .tm_year
= tm_year(1970),
100 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
101 Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN
));
102 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
106 .tm_mon
= Month::DECEMBER
,
107 .tm_year
= tm_year(1969),
115 // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00.
116 struct tm tm_data
{.tm_sec
= 0,
120 .tm_mon
= Month::JANUARY
,
121 .tm_year
= tm_year(1970),
125 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
126 Succeeds(60 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN
));
127 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
131 .tm_mon
= Month::JANUARY
,
132 .tm_year
= tm_year(1970),
140 TEST(LlvmLibcMkTime
, InvalidHours
) {
142 // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00.
143 struct tm tm_data
{.tm_sec
= 0,
147 .tm_mon
= Month::JANUARY
,
148 .tm_year
= tm_year(1970),
152 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
153 Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR
));
154 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
158 .tm_mon
= Month::DECEMBER
,
159 .tm_year
= tm_year(1969),
167 // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00.
168 struct tm tm_data
{.tm_sec
= 0,
172 .tm_mon
= Month::JANUARY
,
173 .tm_year
= tm_year(1970),
178 LIBC_NAMESPACE::mktime(&tm_data
),
179 Succeeds(24 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR
));
180 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
184 .tm_mon
= Month::JANUARY
,
185 .tm_year
= tm_year(1970),
193 TEST(LlvmLibcMkTime
, InvalidYear
) {
194 // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00.
195 struct tm tm_data
{.tm_sec
= 0,
199 .tm_mon
= Month::JANUARY
,
200 .tm_year
= tm_year(1969),
204 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
205 Succeeds(-LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR
*
206 LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
207 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
211 .tm_mon
= Month::JANUARY
,
212 .tm_year
= tm_year(1969),
219 TEST(LlvmLibcMkTime
, InvalidEndOf32BitEpochYear
) {
220 if (sizeof(time_t) != 4)
223 // 2038-01-19 03:14:08 tests overflow of the second in 2038.
224 struct tm tm_data
{.tm_sec
= 8,
228 .tm_mon
= Month::JANUARY
,
229 .tm_year
= tm_year(2038),
233 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
237 // 2038-01-19 03:15:07 tests overflow of the minute in 2038.
238 struct tm tm_data
{.tm_sec
= 7,
242 .tm_mon
= Month::JANUARY
,
243 .tm_year
= tm_year(2038),
247 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
251 // 2038-01-19 04:14:07 tests overflow of the hour in 2038.
252 struct tm tm_data
{.tm_sec
= 7,
256 .tm_mon
= Month::JANUARY
,
257 .tm_year
= tm_year(2038),
261 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
265 // 2038-01-20 03:14:07 tests overflow of the day in 2038.
266 struct tm tm_data
{.tm_sec
= 7,
270 .tm_mon
= Month::JANUARY
,
271 .tm_year
= tm_year(2038),
275 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
279 // 2038-02-19 03:14:07 tests overflow of the month in 2038.
280 struct tm tm_data
{.tm_sec
= 7,
284 .tm_mon
= Month::FEBRUARY
,
285 .tm_year
= tm_year(2038),
289 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
293 // 2039-01-19 03:14:07 tests overflow of the year.
294 struct tm tm_data
{.tm_sec
= 7,
298 .tm_mon
= Month::JANUARY
,
299 .tm_year
= tm_year(2039),
303 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Fails(EOVERFLOW
));
307 TEST(LlvmLibcMkTime
, InvalidMonths
) {
309 // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00.
310 struct tm tm_data
{.tm_sec
= 0,
315 .tm_year
= tm_year(1970),
320 LIBC_NAMESPACE::mktime(&tm_data
),
321 Succeeds(-32 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
322 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
326 .tm_mon
= Month::DECEMBER
,
327 .tm_year
= tm_year(1969),
335 // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00.
336 struct tm tm_data
{.tm_sec
= 0,
341 .tm_year
= tm_year(1970),
346 LIBC_NAMESPACE::mktime(&tm_data
),
347 Succeeds(LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR
*
348 LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
349 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
353 .tm_mon
= Month::JANUARY
,
354 .tm_year
= tm_year(1971),
362 TEST(LlvmLibcMkTime
, InvalidDays
) {
364 // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00.
365 struct tm tm_data
{.tm_sec
= 0,
369 .tm_mon
= Month::JANUARY
,
370 .tm_year
= tm_year(1970),
374 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
375 Succeeds(-1 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
376 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
380 .tm_mon
= Month::DECEMBER
,
381 .tm_year
= tm_year(1969),
389 // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00.
390 struct tm tm_data
{.tm_sec
= 0,
394 .tm_mon
= Month::JANUARY
,
395 .tm_year
= tm_year(1970),
399 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
400 Succeeds(31 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
401 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
405 .tm_mon
= Month::FEBRUARY
,
406 .tm_year
= tm_year(1970),
414 // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00.
415 struct tm tm_data
{.tm_sec
= 0,
419 .tm_mon
= Month::FEBRUARY
,
420 .tm_year
= tm_year(1970),
424 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
425 Succeeds(59 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
426 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
430 .tm_mon
= Month::MARCH
,
431 .tm_year
= tm_year(1970),
439 // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00.
440 struct tm tm_data
{.tm_sec
= 0,
444 .tm_mon
= Month::FEBRUARY
,
445 .tm_year
= tm_year(1972),
450 LIBC_NAMESPACE::mktime(&tm_data
),
451 Succeeds(((2 * LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR
) +
453 LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
454 EXPECT_TM_EQ((tm
{.tm_sec
= 0,
458 .tm_mon
= Month::MARCH
,
459 .tm_year
= tm_year(1972),
467 TEST(LlvmLibcMkTime
, EndOf32BitEpochYear
) {
468 // Test for maximum value of a signed 32-bit integer.
469 // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC.
471 struct tm tm_data
{.tm_sec
= 7,
475 .tm_mon
= Month::JANUARY
,
476 .tm_year
= tm_year(2038),
480 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(0x7FFFFFFF));
481 EXPECT_TM_EQ((tm
{.tm_sec
= 7,
485 .tm_mon
= Month::JANUARY
,
486 .tm_year
= tm_year(2038),
493 // Now test some times before that, to ensure they are not rejected.
495 // 2038-01-19 03:13:59 tests that even a large seconds field is
496 // accepted if the minutes field is smaller.
497 struct tm tm_data
{.tm_sec
= 59,
501 .tm_mon
= Month::JANUARY
,
502 .tm_year
= tm_year(2038),
506 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(0x7FFFFFFF - 8));
507 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
511 .tm_mon
= Month::JANUARY
,
512 .tm_year
= tm_year(2038),
520 // 2038-01-19 02:59:59 tests that large seconds and minutes are
521 // accepted if the hours field is smaller.
522 struct tm tm_data
{.tm_sec
= 59,
526 .tm_mon
= Month::JANUARY
,
527 .tm_year
= tm_year(2038),
531 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
532 Succeeds(0x7FFFFFFF - 8 -
533 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN
));
534 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
538 .tm_mon
= Month::JANUARY
,
539 .tm_year
= tm_year(2038),
547 // 2038-01-18 23:59:59 tests that large seconds, minutes and hours
548 // are accepted if the days field is smaller.
549 struct tm tm_data
{.tm_sec
= 59,
553 .tm_mon
= Month::JANUARY
,
554 .tm_year
= tm_year(2038),
558 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
559 Succeeds(0x7FFFFFFF - 8 -
560 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN
-
561 3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR
));
562 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
566 .tm_mon
= Month::JANUARY
,
567 .tm_year
= tm_year(2038),
575 // 2038-01-18 23:59:59 tests that the final second of 2037 is
577 struct tm tm_data
{.tm_sec
= 59,
581 .tm_mon
= Month::DECEMBER
,
582 .tm_year
= tm_year(2037),
586 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
),
587 Succeeds(0x7FFFFFFF - 8 -
588 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN
-
589 3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR
-
590 18 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY
));
591 EXPECT_TM_EQ((tm
{.tm_sec
= 59,
595 .tm_mon
= Month::DECEMBER
,
596 .tm_year
= tm_year(2037),
604 TEST(LlvmLibcMkTime
, Max64BitYear
) {
605 if (sizeof(time_t) == 4)
608 // Mon Jan 1 12:50:50 2170 (200 years from 1970),
609 struct tm tm_data
{.tm_sec
= 50,
613 .tm_mon
= Month::JANUARY
,
614 .tm_year
= tm_year(2170),
618 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(6311479850));
619 EXPECT_TM_EQ((tm
{.tm_sec
= 50,
623 .tm_mon
= Month::JANUARY
,
624 .tm_year
= tm_year(2170),
632 // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year.
633 struct tm tm_data
{.tm_sec
= 50,
637 .tm_mon
= Month::JANUARY
,
638 .tm_year
= tm_year(2147483647),
642 EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data
), Succeeds(67767976202043050));
643 EXPECT_TM_EQ((tm
{.tm_sec
= 50,
647 .tm_mon
= Month::JANUARY
,
648 .tm_year
= tm_year(2147483647),