#include "src/__support/CPP/limits.h"
#include "src/time/mktime.h"
#include "src/time/time_constants.h"
#include "test/UnitTest/ErrnoSetterMatcher.h"
#include "test/UnitTest/Test.h"
#include "test/src/time/TmHelper.h"
#include "test/src/time/TmMatcher.h"
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
using LIBC_NAMESPACE::time_constants::Month;
#ifndef EOVERFLOW
#define EOVERFLOW 0
#endif
static inline constexpr int tm_year(int year) {
return year - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE;
}
TEST(LlvmLibcMkTime, FailureSetsErrno) {
struct tm tm_data{.tm_sec = INT_MAX,
.tm_min = INT_MAX,
.tm_hour = INT_MAX,
.tm_mday = INT_MAX,
.tm_mon = INT_MAX - 1,
.tm_year = tm_year(INT_MAX),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
TEST(LlvmLibcMkTime, InvalidSeconds) {
{
struct tm tm_data{.tm_sec = -1,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(-1));
EXPECT_TM_EQ((tm{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(1969),
.tm_wday = 3,
.tm_yday = 364,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 60,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(60));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 1,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 4,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, InvalidMinutes) {
{
struct tm tm_data{.tm_sec = 0,
.tm_min = -1,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(1969),
.tm_wday = 3,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 60,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(60 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 1,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 4,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, InvalidHours) {
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = -1,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 23,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(1969),
.tm_wday = 3,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 24,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(
LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(24 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 2,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 5,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, InvalidYear) {
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1969),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(-LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR *
LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1969),
.tm_wday = 3,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) {
if (sizeof(time_t) != 4)
return;
{
struct tm tm_data{.tm_sec = 8,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 15,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 4,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 20,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::FEBRUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2039),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW));
}
}
TEST(LlvmLibcMkTime, InvalidMonths) {
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 0,
.tm_mon = -1,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(
LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(-32 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(1969),
.tm_wday = 1,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = 12,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(
LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR *
LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1971),
.tm_wday = 5,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, InvalidDays) {
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = (1 - 1),
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(-1 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(1969),
.tm_wday = 3,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 32,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(31 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::FEBRUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 29,
.tm_mon = Month::FEBRUARY,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(59 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::MARCH,
.tm_year = tm_year(1970),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 30,
.tm_mon = Month::FEBRUARY,
.tm_year = tm_year(1972),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(
LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(((2 * LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR) +
60) *
LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = 1,
.tm_mon = Month::MARCH,
.tm_year = tm_year(1972),
.tm_wday = 3,
.tm_yday = 0,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, EndOf32BitEpochYear) {
{
struct tm tm_data{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(0x7FFFFFFF));
EXPECT_TM_EQ((tm{.tm_sec = 7,
.tm_min = 14,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 2,
.tm_yday = 7,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 59,
.tm_min = 13,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(0x7FFFFFFF - 8));
EXPECT_TM_EQ((tm{.tm_sec = 59,
.tm_min = 13,
.tm_hour = 3,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 2,
.tm_yday = 7,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 2,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(0x7FFFFFFF - 8 -
14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN));
EXPECT_TM_EQ((tm{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 2,
.tm_mday = 19,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 2,
.tm_yday = 7,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 18,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(0x7FFFFFFF - 8 -
14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN -
3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR));
EXPECT_TM_EQ((tm{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 18,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2038),
.tm_wday = 2,
.tm_yday = 7,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(2037),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data),
Succeeds(0x7FFFFFFF - 8 -
14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN -
3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR -
18 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY));
EXPECT_TM_EQ((tm{.tm_sec = 59,
.tm_min = 59,
.tm_hour = 23,
.tm_mday = 31,
.tm_mon = Month::DECEMBER,
.tm_year = tm_year(2037),
.tm_wday = 2,
.tm_yday = 7,
.tm_isdst = 0}),
tm_data);
}
}
TEST(LlvmLibcMkTime, Max64BitYear) {
if (sizeof(time_t) == 4)
return;
{
struct tm tm_data{.tm_sec = 50,
.tm_min = 50,
.tm_hour = 12,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2170),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(6311479850));
EXPECT_TM_EQ((tm{.tm_sec = 50,
.tm_min = 50,
.tm_hour = 12,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2170),
.tm_wday = 1,
.tm_yday = 50,
.tm_isdst = 0}),
tm_data);
}
{
struct tm tm_data{.tm_sec = 50,
.tm_min = 50,
.tm_hour = 12,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2147483647),
.tm_wday = 0,
.tm_yday = 0,
.tm_isdst = 0};
EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(67767976202043050));
EXPECT_TM_EQ((tm{.tm_sec = 50,
.tm_min = 50,
.tm_hour = 12,
.tm_mday = 1,
.tm_mon = Month::JANUARY,
.tm_year = tm_year(2147483647),
.tm_wday = 2,
.tm_yday = 50,
.tm_isdst = 0}),
tm_data);
}
}