aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kapi')
-rw-r--r--kernel/kapi/filesystem.tests.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/kernel/kapi/filesystem.tests.cpp b/kernel/kapi/filesystem.tests.cpp
index efcb4fd3..f46c6bb8 100644
--- a/kernel/kapi/filesystem.tests.cpp
+++ b/kernel/kapi/filesystem.tests.cpp
@@ -12,7 +12,9 @@
#include <cstddef>
#include <filesystem>
#include <ranges>
+#include <string>
#include <string_view>
+#include <utility>
#include <vector>
using namespace kstd::units_literals;
@@ -339,4 +341,94 @@ SCENARIO_METHOD(kernel::tests::vfs::storage_boot_module_vfs_fixture,
}
}
+SCENARIO_METHOD(kernel::tests::vfs::storage_boot_module_vfs_fixture, "Kapi filesystem with a mounted fat32 image",
+ "[kapi][filesystem][fat32]")
+{
+ auto const ext2_image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+ auto const fat32_image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "fat32.img";
+
+ GIVEN("an ext2 root filesystem with a fat32 image mounted on /information")
+ {
+ REQUIRE(std::filesystem::exists(ext2_image_path));
+ REQUIRE(std::filesystem::exists(fat32_image_path));
+ REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1", "test_img_module_2"},
+ {ext2_image_path, fat32_image_path}));
+ REQUIRE(kapi::filesystem::mount("/dev/ram1", "/information"));
+
+ auto const read_text = [](std::size_t fd, std::size_t chunk_size) {
+ auto text = std::string{};
+ auto buffer = std::vector<std::byte>(chunk_size);
+ while (true)
+ {
+ auto const bytes_read = kapi::filesystem::read(fd, buffer);
+ REQUIRE(bytes_read);
+ if (*bytes_read == 0_B)
+ {
+ return text;
+ }
+ text.append(std::bit_cast<char *>(buffer.data()), bytes_read->value);
+ }
+ };
+
+ THEN("a file can be opened by its lowercase name, read and closed again")
+ {
+ auto const fd = kapi::filesystem::open("/information/hello.txt");
+ REQUIRE(fd);
+ REQUIRE(read_text(*fd, 64) == "Hello World!");
+ REQUIRE(kapi::filesystem::close(*fd));
+ }
+
+ THEN("a file can be read in small chunks through its file descriptor")
+ {
+ auto const fd = kapi::filesystem::open("/information/hello.txt");
+ REQUIRE(fd);
+ REQUIRE(read_text(*fd, 5) == "Hello World!");
+ REQUIRE(kapi::filesystem::close(*fd));
+ }
+
+ THEN("reading continues at a seeked position")
+ {
+ auto const fd = kapi::filesystem::open("/information/hello.txt");
+ REQUIRE(fd);
+ REQUIRE(kapi::filesystem::seek(*fd, 6_B_off, kapi::filesystem::seek_origin::beginning) == 6_B);
+ REQUIRE(read_text(*fd, 16) == "World!");
+ REQUIRE(kapi::filesystem::close(*fd));
+ }
+
+ THEN("the status of a file reports its type and size")
+ {
+ auto const status = kapi::filesystem::status("/information/hello.txt");
+ REQUIRE(status);
+ REQUIRE(status->mode == std::to_underlying(kapi::filesystem::file_type::regular));
+ REQUIRE(status->size == 12_B);
+ }
+
+ THEN("the mounted root directory can be listed")
+ {
+ auto const directory = kapi::filesystem::open("/information");
+ REQUIRE(directory);
+
+ auto buffer = std::vector<kapi::filesystem::directory_entry>{10};
+ REQUIRE(kapi::filesystem::read_directory(*directory, buffer) == 1);
+ REQUIRE(buffer[0].name == "HELLO.TXT");
+ REQUIRE(kapi::filesystem::read_directory(*directory, buffer) == 0);
+ }
+
+ THEN("writing to a file fails because the filesystem is read only")
+ {
+ auto const fd = kapi::filesystem::open("/information/hello.txt");
+ REQUIRE(fd);
+
+ auto const buffer = std::vector<std::byte>{std::byte{'X'}};
+ REQUIRE(kapi::filesystem::write(*fd, buffer).error() == kstd::errc::read_only_file_system);
+ REQUIRE(kapi::filesystem::close(*fd));
+ }
+
+ THEN("opening a missing file fails")
+ {
+ REQUIRE(kapi::filesystem::open("/information/missing.txt").error() == kstd::errc::no_such_file_or_directory);
+ }
+ }
+}
+
// NOLINTEND (readability-magic-numbers) \ No newline at end of file