#include "kernel/filesystem/open_file_description.hpp" #include "kernel/filesystem/vfs.hpp" #include "kernel/test_support/filesystem/inode.hpp" #include "kernel/test_support/filesystem/storage_boot_module_vfs_fixture.hpp" #include #include #include #include #include #include #include SCENARIO("Open file description construction", "[filesystem][open_file_description]") { GIVEN("an inode and an open file description for that inode") { auto inode = kstd::make_shared(); auto file_description = kernel::filesystem::open_file_description{inode}; THEN("the initial offset is zero") { REQUIRE(file_description.offset() == 0); } } } SCENARIO("Open file description read/write offset management", "[filesystem][open_file_description]") { GIVEN("an inode that tracks read/write calls and an open file description for that inode") { auto inode = kstd::make_shared(); auto file_description = kernel::filesystem::open_file_description{inode}; THEN("the offset is updated correctly after reads") { REQUIRE(file_description.read(nullptr, 100) == 100); REQUIRE(file_description.offset() == 100); REQUIRE(file_description.read(nullptr, 50) == 50); REQUIRE(file_description.offset() == 150); } THEN("the offset is updated correctly after writes") { REQUIRE(file_description.write(nullptr, 200) == 200); REQUIRE(file_description.offset() == 200); REQUIRE(file_description.write(nullptr, 25) == 25); REQUIRE(file_description.offset() == 225); } THEN("reads and writes both update the same offset") { REQUIRE(file_description.read(nullptr, 10) == 10); REQUIRE(file_description.offset() == 10); REQUIRE(file_description.write(nullptr, 20) == 20); REQUIRE(file_description.offset() == 30); REQUIRE(file_description.read(nullptr, 5) == 5); REQUIRE(file_description.offset() == 35); REQUIRE(file_description.write(nullptr, 15) == 15); REQUIRE(file_description.offset() == 50); } } } SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "Open file description read with real image", "[filesystem][open_file_description][img]") { auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; GIVEN("an open file description for a file in a real image") { REQUIRE(std::filesystem::exists(image_path)); REQUIRE_NOTHROW(setup_modules_from_img_and_init_vfs({"test_img_module"}, {image_path})); auto & vfs = kernel::filesystem::vfs::get(); auto ofd = vfs.open("/information/info_1.txt"); REQUIRE(ofd != nullptr); THEN("the file can be read and the offset is updated") { kstd::vector buffer(32); auto bytes_read = ofd->read(buffer.data(), buffer.size()); REQUIRE(bytes_read == 32); REQUIRE(ofd->offset() == 32); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), static_cast(bytes_read)}; auto const content_end = buffer_as_str.find('\0'); REQUIRE(buffer_as_str.substr(0, content_end) == "info_1\n"); for (auto i = content_end; i < buffer_as_str.size(); ++i) { REQUIRE(buffer_as_str[i] == '\0'); } } THEN("the file can be read multiple times") { kstd::vector buffer(4); auto bytes_read_1 = ofd->read(buffer.data(), buffer.size() / 2); REQUIRE(bytes_read_1 == buffer.size() / 2); REQUIRE(ofd->offset() == buffer.size() / 2); auto bytes_read_2 = ofd->read(buffer.data() + buffer.size() / 2, buffer.size() / 2); REQUIRE(bytes_read_2 == buffer.size() / 2); REQUIRE(ofd->offset() == buffer.size()); std::string_view buffer_as_str{reinterpret_cast(buffer.data()), bytes_read_1 + bytes_read_2}; REQUIRE(buffer_as_str == "info"); } } }