Cassio Neri | 2760105 | 2021-06-22 22:36:16 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: LGPL-2.1+ |
| 2 | |
| 3 | #include <kunit/test.h> |
| 4 | #include <linux/time.h> |
| 5 | |
| 6 | /* |
| 7 | * Traditional implementation of leap year evaluation. |
| 8 | */ |
| 9 | static bool is_leap(long year) |
| 10 | { |
| 11 | return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); |
| 12 | } |
| 13 | |
| 14 | /* |
| 15 | * Gets the last day of a month. |
| 16 | */ |
| 17 | static int last_day_of_month(long year, int month) |
| 18 | { |
| 19 | if (month == 2) |
| 20 | return 28 + is_leap(year); |
| 21 | if (month == 4 || month == 6 || month == 9 || month == 11) |
| 22 | return 30; |
| 23 | return 31; |
| 24 | } |
| 25 | |
| 26 | /* |
| 27 | * Advances a date by one day. |
| 28 | */ |
| 29 | static void advance_date(long *year, int *month, int *mday, int *yday) |
| 30 | { |
| 31 | if (*mday != last_day_of_month(*year, *month)) { |
| 32 | ++*mday; |
| 33 | ++*yday; |
| 34 | return; |
| 35 | } |
| 36 | |
| 37 | *mday = 1; |
| 38 | if (*month != 12) { |
| 39 | ++*month; |
| 40 | ++*yday; |
| 41 | return; |
| 42 | } |
| 43 | |
| 44 | *month = 1; |
| 45 | *yday = 0; |
| 46 | ++*year; |
| 47 | } |
| 48 | |
| 49 | /* |
| 50 | * Checks every day in a 160000 years interval centered at 1970-01-01 |
| 51 | * against the expected result. |
| 52 | */ |
| 53 | static void time64_to_tm_test_date_range(struct kunit *test) |
| 54 | { |
| 55 | /* |
| 56 | * 80000 years = (80000 / 400) * 400 years |
| 57 | * = (80000 / 400) * 146097 days |
| 58 | * = (80000 / 400) * 146097 * 86400 seconds |
| 59 | */ |
| 60 | time64_t total_secs = ((time64_t) 80000) / 400 * 146097 * 86400; |
| 61 | long year = 1970 - 80000; |
| 62 | int month = 1; |
| 63 | int mdday = 1; |
| 64 | int yday = 0; |
| 65 | |
| 66 | struct tm result; |
| 67 | time64_t secs; |
| 68 | s64 days; |
| 69 | |
| 70 | for (secs = -total_secs; secs <= total_secs; secs += 86400) { |
| 71 | |
| 72 | time64_to_tm(secs, 0, &result); |
| 73 | |
| 74 | days = div_s64(secs, 86400); |
| 75 | |
| 76 | #define FAIL_MSG "%05ld/%02d/%02d (%2d) : %ld", \ |
| 77 | year, month, mdday, yday, days |
| 78 | |
| 79 | KUNIT_ASSERT_EQ_MSG(test, year - 1900, result.tm_year, FAIL_MSG); |
| 80 | KUNIT_ASSERT_EQ_MSG(test, month - 1, result.tm_mon, FAIL_MSG); |
| 81 | KUNIT_ASSERT_EQ_MSG(test, mdday, result.tm_mday, FAIL_MSG); |
| 82 | KUNIT_ASSERT_EQ_MSG(test, yday, result.tm_yday, FAIL_MSG); |
| 83 | |
| 84 | advance_date(&year, &month, &mdday, &yday); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | static struct kunit_case time_test_cases[] = { |
| 89 | KUNIT_CASE(time64_to_tm_test_date_range), |
| 90 | {} |
| 91 | }; |
| 92 | |
| 93 | static struct kunit_suite time_test_suite = { |
| 94 | .name = "time_test_cases", |
| 95 | .test_cases = time_test_cases, |
| 96 | }; |
| 97 | |
| 98 | kunit_test_suite(time_test_suite); |
Thomas Gleixner | 2d0a9eb | 2021-06-26 22:44:11 +0200 | [diff] [blame] | 99 | MODULE_LICENSE("GPL"); |