From a37c8021a6963d3ea8bf89e33323ed6acadb23f9 Mon Sep 17 00:00:00 2001 From: Jakub Czapiga Date: Thu, 15 Apr 2021 11:39:13 +0200 Subject: [PATCH] tests: Add lib/rtc-test test case Signed-off-by: Jakub Czapiga Change-Id: I2062e0d9dc2018bd6d8a210c8d26f2091e8c03fe Reviewed-on: https://review.coreboot.org/c/coreboot/+/52414 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg --- tests/lib/Makefile.inc | 5 + tests/lib/rtc-test.c | 312 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 317 insertions(+) create mode 100644 tests/lib/rtc-test.c diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc index 4943e06849..c76870bec0 100644 --- a/tests/lib/Makefile.inc +++ b/tests/lib/Makefile.inc @@ -27,6 +27,7 @@ tests-y += uuid-test tests-y += bootmem-test tests-y += dimm_info_util-test tests-y += coreboot_table-test +tests-y += rtc-test string-test-srcs += tests/lib/string-test.c string-test-srcs += src/lib/string.c @@ -139,3 +140,7 @@ coreboot_table-test-srcs += src/lib/imd.c coreboot_table-test-cflags += -I src -I 3rdparty/vboot/firmware/include coreboot_table-test-cflags += -I tests/include/tests/lib/fmap coreboot_table-test-mocks += cbmem_top_chipset + +rtc-test-srcs += tests/lib/rtc-test.c +rtc-test-srcs += src/lib/rtc.c + diff --git a/tests/lib/rtc-test.c b/tests/lib/rtc-test.c new file mode 100644 index 0000000000..d58011d128 --- /dev/null +++ b/tests/lib/rtc-test.c @@ -0,0 +1,312 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +static void test_rtc_to_tm_from_unix_time(void **state) +{ + struct rtc_time tm; + int tim; + + /* Zero-day */ + tim = 0; + assert_int_equal(0, rtc_to_tm(tim, &tm)); + assert_int_equal(1970, tm.year); + assert_int_equal(1, tm.mon); + assert_int_equal(1, tm.mday); + assert_int_equal(0, tm.hour); + assert_int_equal(0, tm.min); + assert_int_equal(0, tm.sec); + assert_int_equal(4, tm.wday); /* Thursday */ + + /* One second from time base */ + tim = 1; + assert_int_equal(0, rtc_to_tm(tim, &tm)); + assert_int_equal(1970, tm.year); + assert_int_equal(1, tm.mon); + assert_int_equal(1, tm.mday); + assert_int_equal(0, tm.hour); + assert_int_equal(0, tm.min); + assert_int_equal(1, tm.sec); + assert_int_equal(4, tm.wday); /* Thursday */ + + /* Full time value */ + tim = INT32_MAX; + assert_int_equal(0, rtc_to_tm(tim, &tm)); + assert_int_equal(2038, tm.year); + assert_int_equal(1, tm.mon); + assert_int_equal(19, tm.mday); + assert_int_equal(3, tm.hour); + assert_int_equal(14, tm.min); + assert_int_equal(7, tm.sec); + assert_int_equal(2, tm.wday); /* Tuesday */ + + /* Other common value */ + tim = 1618484725; + assert_int_equal(0, rtc_to_tm(tim, &tm)); + assert_int_equal(2021, tm.year); + assert_int_equal(4, tm.mon); + assert_int_equal(15, tm.mday); + assert_int_equal(11, tm.hour); + assert_int_equal(5, tm.min); + assert_int_equal(25, tm.sec); + assert_int_equal(4, tm.wday); /* Thursday */ + + /* Negative value - expect incorrect output */ + tim = -1; + assert_int_equal(0, rtc_to_tm(tim, &tm)); + assert_int_equal(1970, tm.year); + assert_int_equal(1, tm.mon); + assert_int_equal(1, tm.mday); + assert_int_equal(0, tm.hour); + assert_int_equal(0, tm.min); + assert_int_equal(-1, tm.sec); + assert_int_equal(4, tm.wday); /* Thursday */ +} + +static void test_mktime(void **state) +{ + struct rtc_time tm; + struct rtc_time tm2; + memset(&tm, 0, sizeof(tm)); + memset(&tm2, 0, sizeof(tm2)); + + /* Epoch start */ + tm = (struct rtc_time){ + .year = 1970, .mon = 1, .mday = 1, .hour = 0, .min = 0, .sec = 0, + }; + assert_int_equal(0, rtc_mktime(&tm)); + + /* Last correct value */ + tm = (struct rtc_time){ + .year = 2038, .mon = 1, .mday = 19, .hour = 3, .min = 14, .sec = 7, + }; + assert_int_equal(INT32_MAX, rtc_mktime(&tm)); + + /* Common non-leap year */ + tm = (struct rtc_time){ + .year = 1999, .mon = 12, .mday = 6, .hour = 16, .min = 13, .sec = 59, + }; + assert_int_equal(944496839, rtc_mktime(&tm)); + + /* Ensure that February 29 gives the same result as March 1 in non-leap year */ + tm = (struct rtc_time){ + .year = 2017, .mon = 2, .mday = 29, .hour = 1, .min = 2, .sec = 3, + }; + tm2 = (struct rtc_time){ + .year = 2017, .mon = 3, .mday = 1, .hour = 1, .min = 2, .sec = 3, + }; + assert_int_equal(rtc_mktime(&tm), rtc_mktime(&tm2)); + + /* Leap year (only division by 4 rule applies) */ + tm = (struct rtc_time){ + .year = 2004, .mon = 8, .mday = 30, .hour = 13, .min = 45, .sec = 33, + }; + assert_int_equal(1093873533, rtc_mktime(&tm)); + /* Last day of February in leap year */ + tm.mon = 2; + tm.mday = 29; + assert_int_equal(1078062333, rtc_mktime(&tm)); + /* Ensure that February 29 and March 1 have different different and correct values + in leap year */ + tm = (struct rtc_time){ + .year = 2004, .mon = 3, .mday = 1, .hour = 7, .min = 7, .sec = 17, + }; + tm2 = (struct rtc_time){ + .year = 2004, .mon = 2, .mday = 29, .hour = 7, .min = 7, .sec = 17, + }; + /* There should be exactly one day of difference */ + assert_int_equal(24 * 60 * 60, rtc_mktime(&tm) - rtc_mktime(&tm2)); + + /* Leap year (division by 400 rule applies and division by 100 is excluded) */ + tm = (struct rtc_time){ + .year = 2000, .mon = 6, .mday = 11, .hour = 21, .min = 3, .sec = 6, + }; + assert_int_equal(960757386, rtc_mktime(&tm)); + tm.mon = 2; + tm.mday = 29; + assert_int_equal(951858186, rtc_mktime(&tm)); + + tm = (struct rtc_time){ + .year = 2000, .mon = 3, .mday = 1, .hour = 10, .min = 55, .sec = 21, + }; + tm2 = (struct rtc_time){ + .year = 2000, .mon = 2, .mday = 29, .hour = 10, .min = 55, .sec = 21, + }; + assert_int_equal(24 * 60 * 60, rtc_mktime(&tm) - rtc_mktime(&tm2)); +} + +static void assert_rtc_time_equal(struct rtc_time *tm1, struct rtc_time *tm2) +{ + assert_int_equal(tm1->sec, tm2->sec); + assert_int_equal(tm1->min, tm2->min); + assert_int_equal(tm1->hour, tm2->hour); + assert_int_equal(tm1->mday, tm2->mday); + assert_int_equal(tm1->mon, tm2->mon); + assert_int_equal(tm1->year, tm2->year); + assert_int_equal(tm1->wday, tm2->wday); +} + +/* This test check if combination of rtc_to_tm and rtc_mktime gives result equal to input. + Week day is ignored by rtc_mktime, but is calculated by rtc_to_tm, so it is included + in input. */ +static void test_rtc_mktime_with_rtc_to_tm(void **state) +{ + struct rtc_time tm_in; + struct rtc_time tm_out; + int tim; + + memset(&tm_in, 0, sizeof(tm_in)); + memset(&tm_out, 0, sizeof(tm_out)); + + /* Conversion from rtc_time to timestamp and back to rtc_time */ + tm_in = (struct rtc_time){ + .year = 1970, .mon = 1, .mday = 1, .hour = 0, .min = 0, .sec = 0, .wday = 4 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + tm_in = (struct rtc_time){ + .year = 2000, .mon = 2, .mday = 29, .hour = 13, .min = 4, .sec = 15, .wday = 2 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + tm_in = (struct rtc_time){ + .year = 2000, .mon = 3, .mday = 1, .hour = 13, .min = 8, .sec = 37, .wday = 3 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + tm_in = (struct rtc_time){ + .year = 2017, .mon = 12, .mday = 7, .hour = 8, .min = 18, .sec = 9, .wday = 4 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + tm_in = (struct rtc_time){ + .year = 2020, .mon = 2, .mday = 29, .hour = 18, .min = 50, .sec = 0, .wday = 6 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + tm_in = (struct rtc_time){ + .year = 2020, .mon = 3, .mday = 1, .hour = 1, .min = 20, .sec = 23, .wday = 0 + }; + assert_int_equal(0, rtc_to_tm(rtc_mktime(&tm_in), &tm_out)); + assert_rtc_time_equal(&tm_in, &tm_out); + + + /* Conversion from timestamp to rtc_time and back to timestamp */ + tim = 0; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + tim = INT32_MAX; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + /* 2000-02-29 1:23:34 */ + tim = 951787414; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + /* 2000-03-01 1:23:34 */ + tim = 951873814; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + /* 1999-09-09 9:09:09 */ + tim = 936868149; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + /* 2020-02-29 2:29:02 */ + tim = 1582943342; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); + + /* 2020-03-01 3:01:03 */ + tim = 1583031663; + rtc_to_tm(tim, &tm_out); + assert_int_equal(tim, rtc_mktime(&tm_out)); +} + +static void test_leap_day_secday(void **state) +{ + const int secday = 60 * 60 * 24; + struct rtc_time tm_in; + struct rtc_time tm_out; + struct rtc_time tm_expected; + int tim; + + memset(&tm_in, 0, sizeof(tm_in)); + memset(&tm_out, 0, sizeof(tm_out)); + + /* Non-leap year */ + tm_in = (struct rtc_time) { + .year = 1999, .mon = 2, .mday = 28, .hour = 5, .min = 37, .sec = 15, .wday = 0 + }; + tim = rtc_mktime(&tm_in) + secday; + tm_expected = (struct rtc_time) { + .year = 1999, .mon = 3, .mday = 1, .hour = 5, .min = 37, .sec = 15, .wday = 1 + }; + assert_int_equal(0, rtc_to_tm(tim, &tm_out)); + assert_rtc_time_equal(&tm_out, &tm_expected); + + /* Leap-year February 28 to February 29 */ + tm_in = (struct rtc_time) { + .year = 2000, .mon = 2, .mday = 28, .hour = 0, .min = 33, .sec = 11, .wday = 1, + }; + tim = rtc_mktime(&tm_in) + secday; + tm_expected = (struct rtc_time) { + .year = 2000, .mon = 2, .mday = 29, .hour = 0, .min = 33, .sec = 11, .wday = 2, + }; + assert_int_equal(0, rtc_to_tm(tim, &tm_out)); + assert_rtc_time_equal(&tm_out, &tm_expected); + + tm_in = (struct rtc_time) { + .year = 2004, .mon = 2, .mday = 28, .hour = 9, .min = 13, .sec = 45, .wday = 6, + }; + tim = rtc_mktime(&tm_in) + secday; + tm_expected = (struct rtc_time) { + .year = 2004, .mon = 2, .mday = 29, .hour = 9, .min = 13, .sec = 45, .wday = 0, + }; + assert_int_equal(0, rtc_to_tm(tim, &tm_out)); + assert_rtc_time_equal(&tm_out, &tm_expected); + + /* Leap-year February 29 to March 1 */ + tm_in = (struct rtc_time) { + .year = 2000, .mon = 2, .mday = 29, .hour = 22, .min = 50, .sec = 25, .wday = 2, + }; + tim = rtc_mktime(&tm_in) + secday; + tm_expected = (struct rtc_time) { + .year = 2000, .mon = 3, .mday = 1, .hour = 22, .min = 50, .sec = 25, .wday = 3, + }; + assert_int_equal(0, rtc_to_tm(tim, &tm_out)); + assert_rtc_time_equal(&tm_out, &tm_expected); + + tm_in = (struct rtc_time) { + .year = 2004, .mon = 2, .mday = 29, .hour = 17, .min = 56, .sec = 27, .wday = 0, + }; + tim = rtc_mktime(&tm_in) + secday; + tm_expected = (struct rtc_time) { + .year = 2004, .mon = 3, .mday = 1, .hour = 17, .min = 56, .sec = 27, .wday = 1, + }; + assert_int_equal(0, rtc_to_tm(tim, &tm_out)); + assert_rtc_time_equal(&tm_out, &tm_expected); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_rtc_to_tm_from_unix_time), + cmocka_unit_test(test_mktime), + cmocka_unit_test(test_rtc_mktime_with_rtc_to_tm), + cmocka_unit_test(test_leap_day_secday), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +}