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"); 197