aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/vfs.tests.cpp
diff options
context:
space:
mode:
authorLukas Oesch <lukasoesch20@gmail.com>2026-04-09 10:33:38 +0200
committerLukas Oesch <lukasoesch20@gmail.com>2026-04-11 08:05:53 +0200
commit787671aac288590e40c5cabfc9f82a31f21629fe (patch)
tree94793077278d65b9661ee342bed02959ddba51df /kernel/src/filesystem/vfs.tests.cpp
parent186bc5c9a08c5d6e0d306ce8b4fe3d75f4782cd2 (diff)
downloadteachos-787671aac288590e40c5cabfc9f82a31f21629fe.tar.xz
teachos-787671aac288590e40c5cabfc9f82a31f21629fe.zip
add vfs tests with real ext2 images
Diffstat (limited to 'kernel/src/filesystem/vfs.tests.cpp')
-rw-r--r--kernel/src/filesystem/vfs.tests.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp
new file mode 100644
index 0000000..fec32e1
--- /dev/null
+++ b/kernel/src/filesystem/vfs.tests.cpp
@@ -0,0 +1,166 @@
+#include "kernel/filesystem/vfs.hpp"
+
+#include "kernel/devices/storage/management.hpp"
+#include "kernel/filesystem/filesystem.hpp"
+#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp"
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <filesystem>
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with dummy modules",
+ "[filesystem][vfs]")
+{
+ GIVEN("an initialized boot module registry with multiple modules")
+ {
+ REQUIRE_NOTHROW(setup_modules_and_init_vfs(5));
+
+ THEN("vfs initializes and provides /dev mount")
+ {
+ auto & vfs = kernel::filesystem::vfs::get();
+ auto dev = vfs.open("/dev");
+
+ REQUIRE(dev != nullptr);
+ }
+
+ THEN("vfs initializes root filesystem with boot device if boot module is present")
+ {
+ auto & vfs = kernel::filesystem::vfs::get();
+ auto root_file = vfs.open("/");
+
+ REQUIRE(root_file != nullptr);
+ }
+ }
+}
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS with file backed image",
+ "[filesystem][vfs][img]")
+{
+ auto const image_path_1 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+ auto const image_path_2 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_2KB_fs.img";
+ auto const image_path_3 = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_4KB_fs.img";
+
+ GIVEN("a real image file")
+ {
+ REQUIRE(std::filesystem::exists(image_path_1));
+ REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path_1}));
+
+ THEN("vfs initializes and provides expected mount points")
+ {
+ auto & volatilefs = kernel::filesystem::vfs::get();
+ auto root = volatilefs.open("/");
+ auto dev = volatilefs.open("/dev");
+ auto information = volatilefs.open("/information/info_1.txt");
+
+ REQUIRE(root != nullptr);
+ REQUIRE(dev != nullptr);
+ REQUIRE(information != nullptr);
+ }
+ }
+
+ GIVEN("three real image files")
+ {
+ REQUIRE(std::filesystem::exists(image_path_1));
+ REQUIRE(std::filesystem::exists(image_path_2));
+ REQUIRE(std::filesystem::exists(image_path_3));
+ REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module_1", "test_img_module_2", "test_img_module_3"},
+ {image_path_1, image_path_2, image_path_3}));
+
+ auto & vfs = kernel::filesystem::vfs::get();
+ auto storage_mgmt = kernel::devices::storage::management::get();
+ auto device_1 = storage_mgmt.device_by_major_minor(1, 16);
+ auto fs_1 = kernel::filesystem::filesystem::probe_and_mount(device_1);
+ auto device_2 = storage_mgmt.device_by_major_minor(1, 32);
+ auto fs_2 = kernel::filesystem::filesystem::probe_and_mount(device_2);
+
+ THEN("vfs initializes first module as root")
+ {
+ auto & vfs = kernel::filesystem::vfs::get();
+ auto info1 = vfs.open("/information/info_1.txt");
+ auto info2 = vfs.open("/information/info_2.txt");
+
+ REQUIRE(info1 != nullptr);
+ REQUIRE(info2 != nullptr);
+ }
+
+ THEN("second image can be mounted, data retrieved and unmounted again")
+ {
+ REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success);
+
+ auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt");
+ REQUIRE(mounted_monkey_1 != nullptr);
+
+ REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
+ auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt");
+ REQUIRE(unmounted_monkey_1 == nullptr);
+
+ auto info_1 = vfs.open("/information/info_1.txt");
+ REQUIRE(info_1 != nullptr);
+ }
+
+ THEN("third image can be mounted in a mounted file system, unmount only if no child mount exists")
+ {
+ REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.do_mount("/information/monkey_house/infrastructure", fs_2) ==
+ kernel::filesystem::vfs::operation_result::success);
+
+ auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt");
+ auto mounted_fish1 = vfs.open("/information/monkey_house/infrastructure/enclosures/aquarium/tank_1/fish_1.txt");
+
+ REQUIRE(mounted_monkey_1 != nullptr);
+ REQUIRE(mounted_fish1 != nullptr);
+
+ REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed);
+ REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") ==
+ kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
+ }
+
+ THEN("images can be stacked mounted and correct file system is unmounted again")
+ {
+ REQUIRE(vfs.do_mount("/information", fs_1) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.do_mount("/information", fs_2) == kernel::filesystem::vfs::operation_result::success);
+
+ auto mounted_tickets = vfs.open("/information/entrance/tickets.txt");
+ REQUIRE(mounted_tickets != nullptr);
+
+ REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
+ mounted_tickets = vfs.open("/information/entrance/tickets.txt");
+ REQUIRE(mounted_tickets == nullptr);
+
+ auto mounted_monkey = vfs.open("/information/monkey_house/monkey_1.txt");
+ REQUIRE(mounted_monkey != nullptr);
+ }
+
+ THEN("mount with null file system fails")
+ {
+ REQUIRE(vfs.do_mount("/information", nullptr) == kernel::filesystem::vfs::operation_result::filesystem_null);
+ }
+
+ THEN("mount with invalid path fails")
+ {
+ REQUIRE(vfs.do_mount("", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path);
+ REQUIRE(vfs.do_mount("information", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path);
+ REQUIRE(vfs.do_mount("/information/", fs_1) == kernel::filesystem::vfs::operation_result::invalid_path);
+ }
+
+ THEN("mount with non-existent mount point fails")
+ {
+ REQUIRE(vfs.do_mount("/information/nonexistent", fs_1) ==
+ kernel::filesystem::vfs::operation_result::mount_point_not_found);
+ }
+
+ THEN("unmount with invalid path fails")
+ {
+ REQUIRE(vfs.unmount("") == kernel::filesystem::vfs::operation_result::invalid_path);
+ REQUIRE(vfs.unmount("information") == kernel::filesystem::vfs::operation_result::invalid_path);
+ REQUIRE(vfs.unmount("/information/") == kernel::filesystem::vfs::operation_result::invalid_path);
+ }
+
+ THEN("unmounting non-existent mount point returns expected error code")
+ {
+ REQUIRE(vfs.unmount("/information/nonexistent") ==
+ kernel::filesystem::vfs::operation_result::mount_point_not_found);
+ }
+ }
+}