diff options
Diffstat (limited to 'test/unit/leapdb.c')
-rw-r--r-- | test/unit/leapdb.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/test/unit/leapdb.c b/test/unit/leapdb.c new file mode 100644 index 0000000..cb27387 --- /dev/null +++ b/test/unit/leapdb.c @@ -0,0 +1,106 @@ +/* + ********************************************************************** + * Copyright (C) Patrick Oppenlander 2024 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ********************************************************************** + */ + +#include <leapdb.c> +#include "test.h" + +struct test_vector { + time_t when; + int tai_offset; + NTP_Leap leap; + int fake; +} tests[] = { + /* leapdb.list is a cut down version of leap-seconds.list */ + {3439756800, 34, LEAP_InsertSecond, 0}, /* 1 Jan 2009 */ + {3550089600, 35, LEAP_InsertSecond, 0}, /* 1 Jul 2012 */ + {3644697600, 36, LEAP_InsertSecond, 0}, /* 1 Jul 2015 */ + {3692217600, 37, LEAP_InsertSecond, 0}, /* 1 Jan 2017 */ + {3786825600, 36, LEAP_DeleteSecond, 1}, /* 1 Jan 2020 fake in leapdb.list */ +}; + +static void +test_leap_source(NTP_Leap (*fn)(time_t when, int *tai_offset), + int skip_fakes) +{ + int i, prev_tai_offset = 34; + + for (i = 0; i < sizeof tests / sizeof tests[0]; ++i) { + struct test_vector *t = tests + i; + + NTP_Leap leap; + int tai_offset = -1; + + /* Our unit test leapdb.list contains a fake entry removing a leap second. + * Skip this when testing with the right/UTC timezone using mktime(). */ + if (skip_fakes && t->fake) + continue; + + /* One second before leap second */ + leap = fn(t->when - LEAP_SEC_LIST_OFFSET - 1, &tai_offset); + TEST_CHECK(leap == t->leap); + TEST_CHECK(tai_offset = prev_tai_offset); + + /* Exactly on leap second */ + leap = fn(t->when - LEAP_SEC_LIST_OFFSET, &tai_offset); + TEST_CHECK(leap == LEAP_Normal); + TEST_CHECK(tai_offset == t->tai_offset); + + /* One second after leap second */ + leap = fn(t->when - LEAP_SEC_LIST_OFFSET + 1, &tai_offset); + TEST_CHECK(leap == LEAP_Normal); + TEST_CHECK(tai_offset == t->tai_offset); + + prev_tai_offset = t->tai_offset; + } +} + +void +test_unit(void) +{ + char conf[][100] = { + "leapsectz right/UTC", + "leapseclist leapdb.list" + }; + int i; + + CNF_Initialise(0, 0); + for (i = 0; i < sizeof conf / sizeof conf[0]; i++) + CNF_ParseLine(NULL, i + 1, conf[i]); + LDB_Initialise(); + + if (check_leap_source(get_tz_leap)) { + DEBUG_LOG("testing get_tz_leap"); + test_leap_source(get_tz_leap, 1); + } else { + DEBUG_LOG("Skipping get_tz_leap test. Either the right/UTC timezone is " + "missing, or mktime() doesn't support leap seconds."); + } + + DEBUG_LOG("testing get_list_leap"); + TEST_CHECK(check_leap_source(get_list_leap)); + test_leap_source(get_list_leap, 0); + + /* This exercises the twice-per-day logic */ + DEBUG_LOG("testing LDB_GetLeap"); + test_leap_source(LDB_GetLeap, 1); + + LDB_Finalise(); + CNF_Finalise(); +} |