aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/CMakeLists.txt9
-rw-r--r--kernel/include/kernel/test_support/filesystem/storage_boot_module_fixture.hpp19
-rw-r--r--kernel/include/kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp24
-rw-r--r--kernel/src/filesystem/vfs.tests.cpp166
-rw-r--r--kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp90
-rw-r--r--kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp32
-rw-r--r--kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img3
-rw-r--r--kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img3
-rw-r--r--kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img3
9 files changed, 330 insertions, 19 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index 6a2e4b5..88d420b 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -106,7 +106,7 @@ else()
"src/test_support/filesystem/inode.cpp"
"src/test_support/filesystem/filesystem.cpp"
"src/test_support/filesystem/storage_boot_module_fixture.cpp"
- "src/test_support/log_buffer.cpp"
+ "src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp" "src/test_support/log_buffer.cpp"
"src/test_support/output_device.cpp"
"src/test_support/page_mapper.cpp"
"src/test_support/simulated_memory.cpp"
@@ -142,7 +142,8 @@ else()
"src/filesystem/mount_table.tests.cpp"
"src/filesystem/mount.tests.cpp"
"src/filesystem/open_file_description.tests.cpp"
-
+ "src/filesystem/vfs.tests.cpp"
+
# Storage Subsystem Tests
"src/devices/block_device_utils.tests.cpp"
"src/devices/block_device.tests.cpp"
@@ -155,6 +156,10 @@ else()
"os::kernel_test_support"
)
+ target_compile_definitions("kernel_tests" PRIVATE
+ KERNEL_TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/test_support/filesystem/test_assets"
+ )
+
set_target_properties("kernel_tests" PROPERTIES
C_CLANG_TIDY ""
CXX_CLANG_TIDY ""
diff --git a/kernel/include/kernel/test_support/filesystem/storage_boot_module_fixture.hpp b/kernel/include/kernel/test_support/filesystem/storage_boot_module_fixture.hpp
index a57659b..ee658e2 100644
--- a/kernel/include/kernel/test_support/filesystem/storage_boot_module_fixture.hpp
+++ b/kernel/include/kernel/test_support/filesystem/storage_boot_module_fixture.hpp
@@ -3,20 +3,29 @@
#include "kapi/boot_module/boot_module_registry.hpp"
+#include <kstd/string>
+#include <kstd/vector>
+
#include <cstddef>
-#include <string>
-#include <vector>
+#include <filesystem>
namespace kernel::tests::filesystem
{
struct storage_boot_module_fixture
{
+ ~storage_boot_module_fixture();
+
auto setup_modules(std::size_t module_count, std::size_t module_size = 4096) -> void;
+ auto setup_modules_from_img(kstd::vector<kstd::string> const & module_names,
+ kstd::vector<std::filesystem::path> const & img_paths) -> void;
protected:
- kapi::boot_modules::boot_module_registry registry{};
- std::vector<std::string> module_names{};
- std::vector<std::vector<std::byte>> module_data{};
+ kapi::boot_modules::boot_module_registry m_registry{};
+ kstd::vector<kstd::string> m_module_names{};
+ kstd::vector<kstd::vector<std::byte>> m_module_data{};
+
+ private:
+ auto setup_module_from_img(kstd::string const & module_name, std::filesystem::path const & img_path) -> void;
};
} // namespace kernel::tests::filesystem
diff --git a/kernel/include/kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp b/kernel/include/kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp
new file mode 100644
index 0000000..98012b0
--- /dev/null
+++ b/kernel/include/kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp
@@ -0,0 +1,24 @@
+#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_STORAGE_BOOT_MODULE_VFS_FIXTURE_HPP
+#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_STORAGE_BOOT_MODULE_VFS_FIXTURE_HPP
+
+#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp"
+
+#include <kstd/string>
+#include <kstd/vector>
+
+#include <cstddef>
+#include <filesystem>
+
+namespace kernel::tests::filesystem
+{
+ struct storage_boot_module_vfs_fixture : storage_boot_module_fixture
+ {
+ ~storage_boot_module_vfs_fixture();
+
+ auto setup_modules_and_init_vfs(std::size_t module_count, std::size_t module_size = 4096) -> void;
+ auto setup_modules_from_img_and_init_vfs(kstd::vector<kstd::string> const & module_names,
+ kstd::vector<std::filesystem::path> const & img_paths) -> void;
+ };
+} // namespace kernel::tests::filesystem
+
+#endif \ No newline at end of file
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);
+ }
+ }
+}
diff --git a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp
index 8bbf194..a139f63 100644
--- a/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp
+++ b/kernel/src/test_support/filesystem/storage_boot_module_fixture.cpp
@@ -8,36 +8,102 @@
#include "kernel/test_support/boot_modules.hpp"
#include "kernel/test_support/devices/storage/management.hpp"
+#include <kstd/string>
+#include <kstd/vector>
+
#include <cstddef>
-#include <string>
+#include <filesystem>
+#include <fstream>
+#include <ios>
+#include <stdexcept>
namespace kernel::tests::filesystem
{
- auto storage_boot_module_fixture::setup_modules(std::size_t module_count, std::size_t module_size) -> void
+ storage_boot_module_fixture::~storage_boot_module_fixture()
{
kernel::tests::devices::storage::management::deinit();
kernel::tests::boot_modules::deinit();
+ }
- module_names.clear();
- module_data.clear();
- registry = {};
+ auto storage_boot_module_fixture::setup_modules(std::size_t module_count, std::size_t module_size) -> void
+ {
+ m_module_names.clear();
+ m_module_data.clear();
+ m_registry = {};
- module_names.reserve(module_count);
- module_data.reserve(module_count);
+ m_module_names.reserve(module_count);
+ m_module_data.reserve(module_count);
for (std::size_t i = 0; i < module_count; ++i)
{
- module_names.push_back("test_mod" + std::to_string(i));
- module_data.emplace_back(module_size, std::byte{static_cast<unsigned char>(0x40 + (i % 16))});
+ m_module_names.push_back("test_mod" + kstd::to_string(i));
+ m_module_data.emplace_back(module_size, std::byte{static_cast<unsigned char>(0x40 + (i % 16))});
}
for (std::size_t i = 0; i < module_count; ++i)
{
- registry.add_boot_module(kapi::boot_modules::boot_module{
- module_names[i], kapi::memory::linear_address{module_data[i].data()}, module_data[i].size()});
+ m_registry.add_boot_module(kapi::boot_modules::boot_module{
+ m_module_names[i].view(), kapi::memory::linear_address{m_module_data[i].data()}, m_module_data[i].size()});
+ }
+
+ kapi::boot_modules::set_boot_module_registry(m_registry);
+ kernel::devices::storage::management::init();
+ }
+
+ auto storage_boot_module_fixture::setup_modules_from_img(kstd::vector<kstd::string> const & module_names,
+ kstd::vector<std::filesystem::path> const & img_paths)
+ -> void
+ {
+ m_module_names.clear();
+ m_module_data.clear();
+ m_registry = {};
+
+ if (module_names.size() != img_paths.size())
+ {
+ throw std::invalid_argument{"Module names and image paths vectors must have the same size."};
+ }
+
+ for (size_t i = 0; i < module_names.size(); ++i)
+ {
+ setup_module_from_img(module_names[i], img_paths[i]);
}
- kapi::boot_modules::set_boot_module_registry(registry);
+ kapi::boot_modules::set_boot_module_registry(m_registry);
kernel::devices::storage::management::init();
}
+
+ auto storage_boot_module_fixture::setup_module_from_img(kstd::string const & module_name,
+ std::filesystem::path const & img_path) -> void
+ {
+ auto file = std::ifstream{img_path, std::ios::binary | std::ios::ate};
+ if (!file)
+ {
+ throw std::runtime_error{"Failed to open image file for test boot module: " + img_path.string()};
+ }
+
+ auto const end_pos = file.tellg();
+ if (end_pos < 0)
+ {
+ throw std::runtime_error{"Failed to determine image file size for test boot module: " + img_path.string()};
+ }
+
+ auto const size = static_cast<std::size_t>(end_pos);
+ file.seekg(0, std::ios::beg);
+
+ m_module_names.push_back(module_name);
+ m_module_data.emplace_back(size);
+
+ if (size > 0)
+ {
+ file.read(reinterpret_cast<char *>(m_module_data.back().data()), static_cast<std::streamsize>(size));
+ if (!file)
+ {
+ throw std::runtime_error{"Failed to read image file content for test boot module: " + img_path.string()};
+ }
+ }
+
+ m_registry.add_boot_module(kapi::boot_modules::boot_module{
+ m_module_names.back().view(), kapi::memory::linear_address{m_module_data.back().data()},
+ m_module_data.back().size()});
+ }
} // namespace kernel::tests::filesystem \ No newline at end of file
diff --git a/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp
new file mode 100644
index 0000000..cba7278
--- /dev/null
+++ b/kernel/src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp
@@ -0,0 +1,32 @@
+#include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp"
+
+#include "kernel/filesystem/vfs.hpp"
+#include "kernel/test_support/filesystem/vfs.hpp"
+
+#include <kstd/string>
+#include <kstd/vector>
+
+#include <cstddef>
+#include <filesystem>
+
+namespace kernel::tests::filesystem
+{
+ storage_boot_module_vfs_fixture::~storage_boot_module_vfs_fixture()
+ {
+ kernel::tests::filesystem::vfs::deinit();
+ }
+
+ auto storage_boot_module_vfs_fixture::setup_modules_and_init_vfs(std::size_t module_count, std::size_t module_size)
+ -> void
+ {
+ setup_modules(module_count, module_size);
+ kernel::filesystem::vfs::init();
+ }
+
+ auto storage_boot_module_vfs_fixture::setup_modules_from_img_and_init_vfs(
+ kstd::vector<kstd::string> const & module_names, kstd::vector<std::filesystem::path> const & img_paths) -> void
+ {
+ setup_modules_from_img(module_names, img_paths);
+ kernel::filesystem::vfs::init();
+ }
+} // namespace kernel::tests::filesystem \ No newline at end of file
diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img
new file mode 100644
index 0000000..9f1ee4a
--- /dev/null
+++ b/kernel/src/test_support/filesystem/test_assets/ext2_1KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:94d3988bc309eb9e81f06042c72bf4c4fb5991cd7fdd597eb00c518a96c792d8
+size 10485760
diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img
new file mode 100644
index 0000000..1880911
--- /dev/null
+++ b/kernel/src/test_support/filesystem/test_assets/ext2_2KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9a13da5abb9c65c737105b1da0d4344c7cd7604c7952c762c4f4e3d3f96fd42d
+size 5242880
diff --git a/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img
new file mode 100644
index 0000000..3aaceb8
--- /dev/null
+++ b/kernel/src/test_support/filesystem/test_assets/ext2_4KB_fs.img
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4ce6a1aea277906e1af6de223c017ff900b96569f076b4d99fc04eaa1ee986f4
+size 10485760