/* * Copyright (c) 2019 Peter Bigot Consulting * * SPDX-License-Identifier: Apache-2.0 */ /* Tests where time_t requires a 64-bit value */ #include #include #include "timeutil_test.h" static const struct timeutil_test_data tests[] = { /* 32-bit, but algorithm subtraction underflows */ { .ux = -2147483648, .civil = "1901-12-13 20:45:52 Fri 347", .tm = { .tm_sec = 52, .tm_min = 45, .tm_hour = 20, .tm_mday = 13, .tm_mon = 11, .tm_year = 1, .tm_wday = 5, .tm_yday = 346, } }, { .ux = (time_t)-2147483649, .civil = "1901-12-13 20:45:51 Fri 347", .tm = { .tm_sec = 51, .tm_min = 45, .tm_hour = 20, .tm_mday = 13, .tm_mon = 11, .tm_year = 1, .tm_wday = 5, .tm_yday = 346, } }, { .ux = (time_t)2147483648, .civil = "2038-01-19 03:14:08 Tue 019", .tm = { .tm_sec = 8, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, .tm_mon = 0, .tm_year = 138, .tm_wday = 2, .tm_yday = 18, } }, { .ux = (time_t)64060588799, .civil = "3999-12-31 23:59:59 Fri 365", .tm = { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, .tm_mon = 11, .tm_year = 2099, .tm_wday = 5, .tm_yday = 364, } }, { .ux = (time_t)64060588800, .civil = "4000-01-01 00:00:00 Sat 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = 2100, .tm_wday = 6, .tm_yday = 0, } }, /* Normal century is a common year */ { .ux = (time_t)-2208988801, .civil = "1899-12-31 23:59:59 Sun 365", .tm = { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, .tm_mon = 11, .tm_year = -1, .tm_wday = 0, .tm_yday = 364, } }, { .ux = (time_t)-2208988800, .civil = "1900-01-01 00:00:00 Mon 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = 0, .tm_wday = 1, .tm_yday = 0, } }, { .ux = (time_t)-2203977600, .civil = "1900-02-28 00:00:00 Wed 059", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 28, .tm_mon = 1, .tm_year = 0, .tm_wday = 3, .tm_yday = 58, } }, { .ux = (time_t)-2203891200, .civil = "1900-03-01 00:00:00 Thu 060", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 2, .tm_year = 0, .tm_wday = 4, .tm_yday = 59, } }, { .ux = (time_t)-2177539200, .civil = "1900-12-31 00:00:00 Mon 365", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 31, .tm_mon = 11, .tm_year = 0, .tm_wday = 1, .tm_yday = 364, } }, { .ux = (time_t)-2177452800, .civil = "1901-01-01 00:00:00 Tue 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = 1, .tm_wday = 2, .tm_yday = 0, } }, /* Extrema, check against proleptic Gregorian calendar data: * https://www.timeanddate.com/calendar/?year=1&country=22 */ { .ux = (time_t)-62167305600, .civil = "-1-12-31 00:00:00 Fri 365", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 31, .tm_mon = 11, .tm_year = -1901, .tm_wday = 5, .tm_yday = 364, } }, { .ux = (time_t)-62167219200, .civil = "0-01-01 00:00:00 Sat 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = -1900, .tm_wday = 6, .tm_yday = 0, } }, { .ux = (time_t)-62135596801, .civil = "0-12-31 23:59:59 Sun 366", .tm = { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, .tm_mon = 11, .tm_year = -1900, .tm_wday = 0, .tm_yday = 365, } }, { .ux = (time_t)-62135596800, .civil = "1-01-01 00:00:00 Mon 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = -1899, .tm_wday = 1, .tm_yday = 0, } }, { .ux = (time_t)-62135596800, .civil = "1-01-01 00:00:00 Mon 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = -1899, .tm_wday = 1, .tm_yday = 0, } }, }; static void test_time32_errno_clear(void) { const struct timeutil_test_data *tp = &(const struct timeutil_test_data){ .ux = 0, .civil = "1970-01-01 00:00:00 Thu 001", .tm = { .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 0, .tm_year = 70, .tm_wday = 4, .tm_yday = 0, }, }; errno = EINVAL; time_t ux = timeutil_timegm(&tp->tm); zassert_equal(ux, tp->ux, "conversion incorrect"); zassert_equal(errno, 0, "errno was not cleared"); } static void test_time32_epochm1(void) { const struct timeutil_test_data *tp = &(const struct timeutil_test_data){ .ux = -1, .civil = "1969-12-31 23:59:59 Wed 365", .tm = { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, .tm_mon = 11, .tm_year = 69, .tm_wday = 3, .tm_yday = 364, }, }; errno = EINVAL; time_t ux = timeutil_timegm(&tp->tm); zassert_equal(ux, tp->ux, "conversion incorrect"); zassert_equal(errno, 0, "final errno state bad"); } static void test_time32_underflow(void) { const int64_t unix64 = -2147483649; const struct timeutil_test_data *tp = &(const struct timeutil_test_data){ .civil = "1901-12-13 20:45:51 Fri 347", .tm = { .tm_sec = 51, .tm_min = 45, .tm_hour = 20, .tm_mday = 13, .tm_mon = 11, .tm_year = 1, .tm_wday = 5, .tm_yday = 346, }, }; zassert_equal(timeutil_timegm64(&tp->tm), unix64, "fullscale failed"); errno = 0; time_t ux = timeutil_timegm(&tp->tm); zassert_equal(ux, -1, "underflow undetected"); zassert_equal(errno, ERANGE, "final errno state bad"); } static void test_time32_overflow(void) { const int64_t unix64 = 2147483648; const struct timeutil_test_data *tp = &(const struct timeutil_test_data){ .civil = "2038-01-19 03:14:08 Tue 019", .tm = { .tm_sec = 8, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, .tm_mon = 0, .tm_year = 138, .tm_wday = 2, .tm_yday = 18, }, }; zassert_equal(timeutil_timegm64(&tp->tm), unix64, "fullscale failed"); errno = 0; time_t ux = timeutil_timegm(&tp->tm); zassert_equal(ux, -1, "overflow undetected"); zassert_equal(errno, ERANGE, "final errno state bad"); } void test_s64(void) { if (sizeof(time_t) < 8U) { test_time32_errno_clear(); test_time32_epochm1(); test_time32_underflow(); test_time32_overflow(); return; } timeutil_check(tests, sizeof(tests) / sizeof(*tests)); }