162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * KUnit tests for FAT filesystems. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2020 Google LLC. 662306a36Sopenharmony_ci * Author: David Gow <davidgow@google.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <kunit/test.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "fat.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic void fat_checksum_test(struct kunit *test) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci /* With no extension. */ 1662306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, fat_checksum("VMLINUX "), (u8)44); 1762306a36Sopenharmony_ci /* With 3-letter extension. */ 1862306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, fat_checksum("README TXT"), (u8)115); 1962306a36Sopenharmony_ci /* With short (1-letter) extension. */ 2062306a36Sopenharmony_ci KUNIT_EXPECT_EQ(test, fat_checksum("ABCDEFGHA "), (u8)98); 2162306a36Sopenharmony_ci} 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct fat_timestamp_testcase { 2462306a36Sopenharmony_ci const char *name; 2562306a36Sopenharmony_ci struct timespec64 ts; 2662306a36Sopenharmony_ci __le16 time; 2762306a36Sopenharmony_ci __le16 date; 2862306a36Sopenharmony_ci u8 cs; 2962306a36Sopenharmony_ci int time_offset; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic struct fat_timestamp_testcase time_test_cases[] = { 3362306a36Sopenharmony_ci { 3462306a36Sopenharmony_ci .name = "Earliest possible UTC (1980-01-01 00:00:00)", 3562306a36Sopenharmony_ci .ts = {.tv_sec = 315532800LL, .tv_nsec = 0L}, 3662306a36Sopenharmony_ci .time = cpu_to_le16(0), 3762306a36Sopenharmony_ci .date = cpu_to_le16(33), 3862306a36Sopenharmony_ci .cs = 0, 3962306a36Sopenharmony_ci .time_offset = 0, 4062306a36Sopenharmony_ci }, 4162306a36Sopenharmony_ci { 4262306a36Sopenharmony_ci .name = "Latest possible UTC (2107-12-31 23:59:58)", 4362306a36Sopenharmony_ci .ts = {.tv_sec = 4354819198LL, .tv_nsec = 0L}, 4462306a36Sopenharmony_ci .time = cpu_to_le16(49021), 4562306a36Sopenharmony_ci .date = cpu_to_le16(65439), 4662306a36Sopenharmony_ci .cs = 0, 4762306a36Sopenharmony_ci .time_offset = 0, 4862306a36Sopenharmony_ci }, 4962306a36Sopenharmony_ci { 5062306a36Sopenharmony_ci .name = "Earliest possible (UTC-11) (== 1979-12-31 13:00:00 UTC)", 5162306a36Sopenharmony_ci .ts = {.tv_sec = 315493200LL, .tv_nsec = 0L}, 5262306a36Sopenharmony_ci .time = cpu_to_le16(0), 5362306a36Sopenharmony_ci .date = cpu_to_le16(33), 5462306a36Sopenharmony_ci .cs = 0, 5562306a36Sopenharmony_ci .time_offset = 11 * 60, 5662306a36Sopenharmony_ci }, 5762306a36Sopenharmony_ci { 5862306a36Sopenharmony_ci .name = "Latest possible (UTC+11) (== 2108-01-01 10:59:58 UTC)", 5962306a36Sopenharmony_ci .ts = {.tv_sec = 4354858798LL, .tv_nsec = 0L}, 6062306a36Sopenharmony_ci .time = cpu_to_le16(49021), 6162306a36Sopenharmony_ci .date = cpu_to_le16(65439), 6262306a36Sopenharmony_ci .cs = 0, 6362306a36Sopenharmony_ci .time_offset = -11 * 60, 6462306a36Sopenharmony_ci }, 6562306a36Sopenharmony_ci { 6662306a36Sopenharmony_ci .name = "Leap Day / Year (1996-02-29 00:00:00)", 6762306a36Sopenharmony_ci .ts = {.tv_sec = 825552000LL, .tv_nsec = 0L}, 6862306a36Sopenharmony_ci .time = cpu_to_le16(0), 6962306a36Sopenharmony_ci .date = cpu_to_le16(8285), 7062306a36Sopenharmony_ci .cs = 0, 7162306a36Sopenharmony_ci .time_offset = 0, 7262306a36Sopenharmony_ci }, 7362306a36Sopenharmony_ci { 7462306a36Sopenharmony_ci .name = "Year 2000 is leap year (2000-02-29 00:00:00)", 7562306a36Sopenharmony_ci .ts = {.tv_sec = 951782400LL, .tv_nsec = 0L}, 7662306a36Sopenharmony_ci .time = cpu_to_le16(0), 7762306a36Sopenharmony_ci .date = cpu_to_le16(10333), 7862306a36Sopenharmony_ci .cs = 0, 7962306a36Sopenharmony_ci .time_offset = 0, 8062306a36Sopenharmony_ci }, 8162306a36Sopenharmony_ci { 8262306a36Sopenharmony_ci .name = "Year 2100 not leap year (2100-03-01 00:00:00)", 8362306a36Sopenharmony_ci .ts = {.tv_sec = 4107542400LL, .tv_nsec = 0L}, 8462306a36Sopenharmony_ci .time = cpu_to_le16(0), 8562306a36Sopenharmony_ci .date = cpu_to_le16(61537), 8662306a36Sopenharmony_ci .cs = 0, 8762306a36Sopenharmony_ci .time_offset = 0, 8862306a36Sopenharmony_ci }, 8962306a36Sopenharmony_ci { 9062306a36Sopenharmony_ci .name = "Leap year + timezone UTC+1 (== 2004-02-29 00:30:00 UTC)", 9162306a36Sopenharmony_ci .ts = {.tv_sec = 1078014600LL, .tv_nsec = 0L}, 9262306a36Sopenharmony_ci .time = cpu_to_le16(48064), 9362306a36Sopenharmony_ci .date = cpu_to_le16(12380), 9462306a36Sopenharmony_ci .cs = 0, 9562306a36Sopenharmony_ci .time_offset = -60, 9662306a36Sopenharmony_ci }, 9762306a36Sopenharmony_ci { 9862306a36Sopenharmony_ci .name = "Leap year + timezone UTC-1 (== 2004-02-29 23:30:00 UTC)", 9962306a36Sopenharmony_ci .ts = {.tv_sec = 1078097400LL, .tv_nsec = 0L}, 10062306a36Sopenharmony_ci .time = cpu_to_le16(960), 10162306a36Sopenharmony_ci .date = cpu_to_le16(12385), 10262306a36Sopenharmony_ci .cs = 0, 10362306a36Sopenharmony_ci .time_offset = 60, 10462306a36Sopenharmony_ci }, 10562306a36Sopenharmony_ci { 10662306a36Sopenharmony_ci .name = "VFAT odd-second resolution (1999-12-31 23:59:59)", 10762306a36Sopenharmony_ci .ts = {.tv_sec = 946684799LL, .tv_nsec = 0L}, 10862306a36Sopenharmony_ci .time = cpu_to_le16(49021), 10962306a36Sopenharmony_ci .date = cpu_to_le16(10143), 11062306a36Sopenharmony_ci .cs = 100, 11162306a36Sopenharmony_ci .time_offset = 0, 11262306a36Sopenharmony_ci }, 11362306a36Sopenharmony_ci { 11462306a36Sopenharmony_ci .name = "VFAT 10ms resolution (1980-01-01 00:00:00:0010)", 11562306a36Sopenharmony_ci .ts = {.tv_sec = 315532800LL, .tv_nsec = 10000000L}, 11662306a36Sopenharmony_ci .time = cpu_to_le16(0), 11762306a36Sopenharmony_ci .date = cpu_to_le16(33), 11862306a36Sopenharmony_ci .cs = 1, 11962306a36Sopenharmony_ci .time_offset = 0, 12062306a36Sopenharmony_ci }, 12162306a36Sopenharmony_ci}; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic void time_testcase_desc(struct fat_timestamp_testcase *t, 12462306a36Sopenharmony_ci char *desc) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciKUNIT_ARRAY_PARAM(fat_time, time_test_cases, time_testcase_desc); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void fat_time_fat2unix_test(struct kunit *test) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci static struct msdos_sb_info fake_sb; 13462306a36Sopenharmony_ci struct timespec64 ts; 13562306a36Sopenharmony_ci struct fat_timestamp_testcase *testcase = 13662306a36Sopenharmony_ci (struct fat_timestamp_testcase *)test->param_value; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci fake_sb.options.tz_set = 1; 13962306a36Sopenharmony_ci fake_sb.options.time_offset = testcase->time_offset; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci fat_time_fat2unix(&fake_sb, &ts, 14262306a36Sopenharmony_ci testcase->time, 14362306a36Sopenharmony_ci testcase->date, 14462306a36Sopenharmony_ci testcase->cs); 14562306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, 14662306a36Sopenharmony_ci testcase->ts.tv_sec, 14762306a36Sopenharmony_ci ts.tv_sec, 14862306a36Sopenharmony_ci "Timestamp mismatch (seconds)\n"); 14962306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, 15062306a36Sopenharmony_ci testcase->ts.tv_nsec, 15162306a36Sopenharmony_ci ts.tv_nsec, 15262306a36Sopenharmony_ci "Timestamp mismatch (nanoseconds)\n"); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic void fat_time_unix2fat_test(struct kunit *test) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci static struct msdos_sb_info fake_sb; 15862306a36Sopenharmony_ci __le16 date, time; 15962306a36Sopenharmony_ci u8 cs; 16062306a36Sopenharmony_ci struct fat_timestamp_testcase *testcase = 16162306a36Sopenharmony_ci (struct fat_timestamp_testcase *)test->param_value; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci fake_sb.options.tz_set = 1; 16462306a36Sopenharmony_ci fake_sb.options.time_offset = testcase->time_offset; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci fat_time_unix2fat(&fake_sb, &testcase->ts, 16762306a36Sopenharmony_ci &time, &date, &cs); 16862306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, 16962306a36Sopenharmony_ci le16_to_cpu(testcase->time), 17062306a36Sopenharmony_ci le16_to_cpu(time), 17162306a36Sopenharmony_ci "Time mismatch\n"); 17262306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, 17362306a36Sopenharmony_ci le16_to_cpu(testcase->date), 17462306a36Sopenharmony_ci le16_to_cpu(date), 17562306a36Sopenharmony_ci "Date mismatch\n"); 17662306a36Sopenharmony_ci KUNIT_EXPECT_EQ_MSG(test, 17762306a36Sopenharmony_ci testcase->cs, 17862306a36Sopenharmony_ci cs, 17962306a36Sopenharmony_ci "Centisecond mismatch\n"); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic struct kunit_case fat_test_cases[] = { 18362306a36Sopenharmony_ci KUNIT_CASE(fat_checksum_test), 18462306a36Sopenharmony_ci KUNIT_CASE_PARAM(fat_time_fat2unix_test, fat_time_gen_params), 18562306a36Sopenharmony_ci KUNIT_CASE_PARAM(fat_time_unix2fat_test, fat_time_gen_params), 18662306a36Sopenharmony_ci {}, 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic struct kunit_suite fat_test_suite = { 19062306a36Sopenharmony_ci .name = "fat_test", 19162306a36Sopenharmony_ci .test_cases = fat_test_cases, 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_cikunit_test_suites(&fat_test_suite); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 197