Commit | Line | Data |
---|---|---|
b0d4adaf DG |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * KUnit tests for FAT filesystems. | |
4 | * | |
5 | * Copyright (C) 2020 Google LLC. | |
6 | * Author: David Gow <davidgow@google.com> | |
7 | */ | |
8 | ||
9 | #include <kunit/test.h> | |
10 | ||
11 | #include "fat.h" | |
12 | ||
13 | static void fat_checksum_test(struct kunit *test) | |
14 | { | |
15 | /* With no extension. */ | |
16 | KUNIT_EXPECT_EQ(test, fat_checksum("VMLINUX "), (u8)44); | |
17 | /* With 3-letter extension. */ | |
18 | KUNIT_EXPECT_EQ(test, fat_checksum("README TXT"), (u8)115); | |
19 | /* With short (1-letter) extension. */ | |
20 | KUNIT_EXPECT_EQ(test, fat_checksum("ABCDEFGHA "), (u8)98); | |
21 | } | |
22 | ||
23 | struct fat_timestamp_testcase { | |
24 | const char *name; | |
25 | struct timespec64 ts; | |
26 | __le16 time; | |
27 | __le16 date; | |
28 | u8 cs; | |
29 | int time_offset; | |
30 | }; | |
31 | ||
32 | static struct fat_timestamp_testcase time_test_cases[] = { | |
33 | { | |
34 | .name = "Earliest possible UTC (1980-01-01 00:00:00)", | |
35 | .ts = {.tv_sec = 315532800LL, .tv_nsec = 0L}, | |
36 | .time = cpu_to_le16(0), | |
37 | .date = cpu_to_le16(33), | |
38 | .cs = 0, | |
39 | .time_offset = 0, | |
40 | }, | |
41 | { | |
42 | .name = "Latest possible UTC (2107-12-31 23:59:58)", | |
43 | .ts = {.tv_sec = 4354819198LL, .tv_nsec = 0L}, | |
44 | .time = cpu_to_le16(49021), | |
45 | .date = cpu_to_le16(65439), | |
46 | .cs = 0, | |
47 | .time_offset = 0, | |
48 | }, | |
49 | { | |
50 | .name = "Earliest possible (UTC-11) (== 1979-12-31 13:00:00 UTC)", | |
51 | .ts = {.tv_sec = 315493200LL, .tv_nsec = 0L}, | |
52 | .time = cpu_to_le16(0), | |
53 | .date = cpu_to_le16(33), | |
54 | .cs = 0, | |
55 | .time_offset = 11 * 60, | |
56 | }, | |
57 | { | |
58 | .name = "Latest possible (UTC+11) (== 2108-01-01 10:59:58 UTC)", | |
59 | .ts = {.tv_sec = 4354858798LL, .tv_nsec = 0L}, | |
60 | .time = cpu_to_le16(49021), | |
61 | .date = cpu_to_le16(65439), | |
62 | .cs = 0, | |
63 | .time_offset = -11 * 60, | |
64 | }, | |
65 | { | |
66 | .name = "Leap Day / Year (1996-02-29 00:00:00)", | |
67 | .ts = {.tv_sec = 825552000LL, .tv_nsec = 0L}, | |
68 | .time = cpu_to_le16(0), | |
69 | .date = cpu_to_le16(8285), | |
70 | .cs = 0, | |
71 | .time_offset = 0, | |
72 | }, | |
73 | { | |
74 | .name = "Year 2000 is leap year (2000-02-29 00:00:00)", | |
75 | .ts = {.tv_sec = 951782400LL, .tv_nsec = 0L}, | |
76 | .time = cpu_to_le16(0), | |
77 | .date = cpu_to_le16(10333), | |
78 | .cs = 0, | |
79 | .time_offset = 0, | |
80 | }, | |
81 | { | |
82 | .name = "Year 2100 not leap year (2100-03-01 00:00:00)", | |
83 | .ts = {.tv_sec = 4107542400LL, .tv_nsec = 0L}, | |
84 | .time = cpu_to_le16(0), | |
85 | .date = cpu_to_le16(61537), | |
86 | .cs = 0, | |
87 | .time_offset = 0, | |
88 | }, | |
89 | { | |
90 | .name = "Leap year + timezone UTC+1 (== 2004-02-29 00:30:00 UTC)", | |
91 | .ts = {.tv_sec = 1078014600LL, .tv_nsec = 0L}, | |
92 | .time = cpu_to_le16(48064), | |
93 | .date = cpu_to_le16(12380), | |
94 | .cs = 0, | |
95 | .time_offset = -60, | |
96 | }, | |
97 | { | |
98 | .name = "Leap year + timezone UTC-1 (== 2004-02-29 23:30:00 UTC)", | |
99 | .ts = {.tv_sec = 1078097400LL, .tv_nsec = 0L}, | |
100 | .time = cpu_to_le16(960), | |
101 | .date = cpu_to_le16(12385), | |
102 | .cs = 0, | |
103 | .time_offset = 60, | |
104 | }, | |
105 | { | |
106 | .name = "VFAT odd-second resolution (1999-12-31 23:59:59)", | |
107 | .ts = {.tv_sec = 946684799LL, .tv_nsec = 0L}, | |
108 | .time = cpu_to_le16(49021), | |
109 | .date = cpu_to_le16(10143), | |
110 | .cs = 100, | |
111 | .time_offset = 0, | |
112 | }, | |
113 | { | |
114 | .name = "VFAT 10ms resolution (1980-01-01 00:00:00:0010)", | |
115 | .ts = {.tv_sec = 315532800LL, .tv_nsec = 10000000L}, | |
116 | .time = cpu_to_le16(0), | |
117 | .date = cpu_to_le16(33), | |
118 | .cs = 1, | |
119 | .time_offset = 0, | |
120 | }, | |
121 | }; | |
122 | ||
123 | static void time_testcase_desc(struct fat_timestamp_testcase *t, | |
124 | char *desc) | |
125 | { | |
126 | strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); | |
127 | } | |
128 | ||
129 | KUNIT_ARRAY_PARAM(fat_time, time_test_cases, time_testcase_desc); | |
130 | ||
131 | static void fat_time_fat2unix_test(struct kunit *test) | |
132 | { | |
133 | static struct msdos_sb_info fake_sb; | |
134 | struct timespec64 ts; | |
135 | struct fat_timestamp_testcase *testcase = | |
136 | (struct fat_timestamp_testcase *)test->param_value; | |
137 | ||
138 | fake_sb.options.tz_set = 1; | |
139 | fake_sb.options.time_offset = testcase->time_offset; | |
140 | ||
141 | fat_time_fat2unix(&fake_sb, &ts, | |
142 | testcase->time, | |
143 | testcase->date, | |
144 | testcase->cs); | |
145 | KUNIT_EXPECT_EQ_MSG(test, | |
146 | testcase->ts.tv_sec, | |
147 | ts.tv_sec, | |
148 | "Timestamp mismatch (seconds)\n"); | |
149 | KUNIT_EXPECT_EQ_MSG(test, | |
150 | testcase->ts.tv_nsec, | |
151 | ts.tv_nsec, | |
152 | "Timestamp mismatch (nanoseconds)\n"); | |
153 | } | |
154 | ||
155 | static void fat_time_unix2fat_test(struct kunit *test) | |
156 | { | |
157 | static struct msdos_sb_info fake_sb; | |
158 | __le16 date, time; | |
159 | u8 cs; | |
160 | struct fat_timestamp_testcase *testcase = | |
161 | (struct fat_timestamp_testcase *)test->param_value; | |
162 | ||
163 | fake_sb.options.tz_set = 1; | |
164 | fake_sb.options.time_offset = testcase->time_offset; | |
165 | ||
166 | fat_time_unix2fat(&fake_sb, &testcase->ts, | |
167 | &time, &date, &cs); | |
168 | KUNIT_EXPECT_EQ_MSG(test, | |
169 | le16_to_cpu(testcase->time), | |
170 | le16_to_cpu(time), | |
171 | "Time mismatch\n"); | |
172 | KUNIT_EXPECT_EQ_MSG(test, | |
173 | le16_to_cpu(testcase->date), | |
174 | le16_to_cpu(date), | |
175 | "Date mismatch\n"); | |
176 | KUNIT_EXPECT_EQ_MSG(test, | |
177 | testcase->cs, | |
178 | cs, | |
179 | "Centisecond mismatch\n"); | |
180 | } | |
181 | ||
182 | static struct kunit_case fat_test_cases[] = { | |
183 | KUNIT_CASE(fat_checksum_test), | |
184 | KUNIT_CASE_PARAM(fat_time_fat2unix_test, fat_time_gen_params), | |
185 | KUNIT_CASE_PARAM(fat_time_unix2fat_test, fat_time_gen_params), | |
186 | {}, | |
187 | }; | |
188 | ||
189 | static struct kunit_suite fat_test_suite = { | |
190 | .name = "fat_test", | |
191 | .test_cases = fat_test_cases, | |
192 | }; | |
193 | ||
194 | kunit_test_suites(&fat_test_suite); | |
195 | ||
196 | MODULE_LICENSE("GPL v2"); |