SimpleKernel 1.17.0
Loading...
Searching...
No Matches
fatfs_system_test.cpp
Go to the documentation of this file.
1
5#include <cstddef>
6#include <cstdint>
7
8#include "device_manager.hpp"
9#include "device_node.hpp"
10#include "fatfs.hpp"
11#include "kstd_cstring"
12#include "mount.hpp"
13#include "system_test.h"
14#include "vfs.hpp"
15
16auto fatfs_system_test() -> bool {
17 klog::Info("fatfs_system_test: start");
18
19 // T1: Get virtio-blk device via DeviceManager
20 DeviceNode* blk_nodes[4]{};
21 const size_t blk_count = DeviceManagerSingleton::instance().FindDevicesByType(
22 DeviceType::kBlock, blk_nodes, 4);
23 if (blk_count == 0 || blk_nodes[0]->block_device == nullptr) {
25 "fatfs_system_test: SKIP — no virtio-blk device "
26 "available");
27 return true; // Graceful skip, not a failure
28 }
29 vfs::BlockDevice* blk = blk_nodes[0]->block_device;
30 klog::Info("fatfs_system_test: virtio-blk device: {}", blk->GetName());
31 EXPECT_GT(blk->GetSectorCount(), static_cast<uint64_t>(0),
32 "fatfs_system_test: virtio-blk has zero sectors");
33
34 // T2: Mount FatFS at /mnt/fat
35 // vfs::Init() and ramfs mount at "/" should already have been done by
36 // ramfs_system_test, but call Init() again (it's idempotent).
37 auto init_result = vfs::Init();
38 EXPECT_TRUE(init_result.has_value(), "fatfs_system_test: vfs init failed");
39
40 // Create /mnt and /mnt/fat directories in the VFS tree (in ramfs at /)
41 // before mounting. MkDir is idempotent-ish — ignore errors if exists.
42 (void)vfs::MkDir("/mnt");
43 (void)vfs::MkDir("/mnt/fat");
44
45 static fatfs::FatFsFileSystem fat_fs(0);
46 auto fat_mount = fat_fs.Mount(blk);
47 EXPECT_TRUE(fat_mount.has_value(),
48 "fatfs_system_test: FatFsFileSystem::Mount failed");
49 klog::Info("fatfs_system_test: FatFsFileSystem::Mount ok");
50
51 auto vfs_mount = vfs::GetMountTable().Mount("/mnt/fat", &fat_fs, blk);
52 EXPECT_TRUE(vfs_mount.has_value(),
53 "fatfs_system_test: vfs mount at /mnt/fat failed");
54 klog::Info("fatfs_system_test: vfs mount at /mnt/fat ok");
55
56 // T3: Write a file on the FAT volume
57 {
58 auto file_result =
59 vfs::Open("/mnt/fat/test.txt",
61 EXPECT_TRUE(file_result.has_value(),
62 "fatfs_system_test: open /mnt/fat/test.txt failed");
63 vfs::File* file = file_result.value();
64
65 const char kMsg[] = "Hello, FatFS!";
66 auto write_result = vfs::Write(file, kMsg, sizeof(kMsg) - 1);
67 EXPECT_TRUE(write_result.has_value(),
68 "fatfs_system_test: write to /mnt/fat/test.txt failed");
69 EXPECT_EQ(write_result.value(), sizeof(kMsg) - 1,
70 "fatfs_system_test: write byte count mismatch");
71 klog::Info("fatfs_system_test: wrote {} bytes to /mnt/fat/test.txt",
72 write_result.value());
73
74 (void)vfs::Close(file);
75 }
76
77 // T4: Read back and verify
78 {
79 auto file_result =
80 vfs::Open("/mnt/fat/test.txt", vfs::OpenFlags::kOReadOnly);
81 EXPECT_TRUE(file_result.has_value(),
82 "fatfs_system_test: re-open /mnt/fat/test.txt failed");
83 vfs::File* file = file_result.value();
84
85 char buf[64] = {};
86 const char kMsg[] = "Hello, FatFS!";
87 auto read_result = vfs::Read(file, buf, sizeof(buf) - 1);
88 EXPECT_TRUE(read_result.has_value(),
89 "fatfs_system_test: read from /mnt/fat/test.txt failed");
90 EXPECT_EQ(read_result.value(), sizeof(kMsg) - 1,
91 "fatfs_system_test: read byte count mismatch");
92 EXPECT_EQ(memcmp(buf, kMsg, sizeof(kMsg) - 1), 0,
93 "fatfs_system_test: read content mismatch");
94 klog::Info("fatfs_system_test: verified read: {}", buf);
95
96 (void)vfs::Close(file);
97 }
98
99 // T5: MkDir on FAT volume
100 {
101 auto mkdir_result = vfs::MkDir("/mnt/fat/subdir");
102 EXPECT_TRUE(mkdir_result.has_value(),
103 "fatfs_system_test: mkdir /mnt/fat/subdir failed");
104 klog::Info("fatfs_system_test: mkdir /mnt/fat/subdir ok");
105
106 // Create a file inside subdir
107 auto inner =
108 vfs::Open("/mnt/fat/subdir/inner.txt",
110 EXPECT_TRUE(inner.has_value(),
111 "fatfs_system_test: create /mnt/fat/subdir/inner.txt failed");
112 if (inner.has_value()) {
113 (void)vfs::Close(inner.value());
114 }
115
116 // ReadDir on root of fat volume to find subdir
117 auto dir_file = vfs::Open(
119 EXPECT_TRUE(dir_file.has_value(),
120 "fatfs_system_test: open /mnt/fat as dir failed");
121 if (dir_file.has_value()) {
122 vfs::DirEntry entries[16] = {};
123 auto readdir_result = vfs::ReadDir(dir_file.value(), entries, 16);
124 EXPECT_TRUE(readdir_result.has_value(),
125 "fatfs_system_test: readdir /mnt/fat failed");
126 // Should see at least test.txt and subdir
127 EXPECT_GT(readdir_result.value(), static_cast<size_t>(1),
128 "fatfs_system_test: readdir /mnt/fat should return > 1 entry");
129 klog::Info("fatfs_system_test: readdir /mnt/fat returned {} entries",
130 readdir_result.value());
131 (void)vfs::Close(dir_file.value());
132 }
133 }
134
135 // T6: Unmount and remount — verify persistence
136 {
137 auto unmount_result = fat_fs.Unmount();
138 EXPECT_TRUE(unmount_result.has_value(),
139 "fatfs_system_test: FatFsFileSystem::Unmount failed");
140 klog::Info("fatfs_system_test: unmounted ok");
141
142 // Remount
143 auto remount_result = fat_fs.Mount(blk);
144 EXPECT_TRUE(remount_result.has_value(),
145 "fatfs_system_test: remount failed");
146 klog::Info("fatfs_system_test: remounted ok");
147
148 // Re-wire VFS mount
149 auto vfs_remount = vfs::GetMountTable().Mount("/mnt/fat", &fat_fs, blk);
150 EXPECT_TRUE(vfs_remount.has_value(),
151 "fatfs_system_test: vfs remount failed");
152
153 // Verify test.txt persisted
154 auto file_result =
155 vfs::Open("/mnt/fat/test.txt", vfs::OpenFlags::kOReadOnly);
156 EXPECT_TRUE(file_result.has_value(),
157 "fatfs_system_test: test.txt not found after remount");
158 if (file_result.has_value()) {
159 char buf[64] = {};
160 const char kMsg[] = "Hello, FatFS!";
161 auto read_result = vfs::Read(file_result.value(), buf, sizeof(buf) - 1);
162 EXPECT_TRUE(read_result.has_value(),
163 "fatfs_system_test: read after remount failed");
164 EXPECT_EQ(memcmp(buf, kMsg, sizeof(kMsg) - 1), 0,
165 "fatfs_system_test: data corrupted after remount");
166 klog::Info("fatfs_system_test: persistence verified: {}", buf);
167 (void)vfs::Close(file_result.value());
168 }
169 }
170
171 klog::Info("fatfs_system_test: all tests passed");
172 return true;
173}
FatFS VFS 适配器
Definition fatfs.hpp:25
auto Unmount() -> Expected< void > override
卸载 FatFS 卷
Definition fatfs.cpp:155
auto Mount(vfs::BlockDevice *device) -> Expected< vfs::Inode * > override
挂载 FatFS 卷
Definition fatfs.cpp:109
块设备抽象基类
virtual auto GetName() const -> const char *=0
获取设备名称(如 "virtio-blk0")
virtual auto GetSectorCount() const -> uint64_t=0
获取设备总扇区数
@ kBlock
块设备(磁盘等)
auto fatfs_system_test() -> bool
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
@ kODirectory
必须是目录
auto Read(File *file, void *buf, size_t count) -> Expected< size_t >
从文件读取数据
Definition read.cpp:13
auto Write(File *file, const void *buf, size_t count) -> Expected< size_t >
向文件写入数据
Definition write.cpp:13
auto Open(const char *path, OpenFlags flags) -> Expected< File * >
打开文件
Definition open.cpp:14
auto ReadDir(File *file, DirEntry *dirent, size_t count) -> Expected< size_t >
读取目录内容
Definition readdir.cpp:13
auto MkDir(const char *path) -> Expected< void >
创建目录
Definition mkdir.cpp:14
auto Close(File *file) -> Expected< void >
关闭文件
Definition close.cpp:15
auto GetMountTable() -> MountTable &
获取全局挂载表实例
Definition mount.cpp:234
auto Init() -> Expected< void >
VFS 全局初始化
Definition vfs.cpp:80
#define memcmp
单个设备的硬件资源描述。
目录项结构(用于 readdir)
File — 打开的文件实例(每次 open 产生一个)
Definition vfs.hpp:65
#define EXPECT_TRUE(cond, msg)
#define EXPECT_GT(val1, val2, msg)
#define EXPECT_EQ(val1, val2, msg)