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: *year, month: *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(totalsecs: secs, offset: 0, result: &result); |
73 | |
74 | days = div_s64(dividend: secs, divisor: 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: &year, month: &month, mday: &mdday, yday: &yday); |
85 | } |
86 | } |
87 | |
88 | static struct kunit_case time_test_cases[] = { |
89 | KUNIT_CASE_SLOW(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); |
99 | MODULE_LICENSE("GPL" ); |
100 | |