diff options
| -rw-r--r-- | kernel/kernel/filesystem/ext2/inode.tests.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/kernel/kernel/filesystem/ext2/inode.tests.cpp b/kernel/kernel/filesystem/ext2/inode.tests.cpp index 7041f886..7448181c 100644 --- a/kernel/kernel/filesystem/ext2/inode.tests.cpp +++ b/kernel/kernel/filesystem/ext2/inode.tests.cpp @@ -277,6 +277,85 @@ SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]") } } +SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 inode writes to real image", + "[filesystem][ext2][inode]") +{ + auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img"; + GIVEN("a mounted ext2 filesystem and a regular file inode") + { + REQUIRE(std::filesystem::exists(image_path)); + REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path})); + + auto boot_device = kernel::devices::storage::management::get().determine_boot_device(); + REQUIRE(boot_device != nullptr); + + auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(boot_device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode)); + + auto information = fs.lookup(fs.root_inode(), "information"); + REQUIRE(information); + auto file = fs.lookup(*information, "info_1.txt"); + REQUIRE(file); + REQUIRE(file.value()->is_regular()); + + THEN("writing to the inode updates backing device") + { + auto write_buffer = kstd::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, + std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, + std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; + + auto const bytes_written = file.value()->write(write_buffer.data(), 0, write_buffer.size()); + REQUIRE(bytes_written == 7); + + auto read_buffer = kstd::vector<std::byte>(42, std::byte{0x00}); + auto const bytes_read = file.value()->read(read_buffer.data(), 0, read_buffer.size()); + REQUIRE(bytes_read == 7); + + auto const text = std::string_view{reinterpret_cast<char const *>(read_buffer.data()), *bytes_read}; + REQUIRE(text == "Hello W"); + } + } +} + +SCENARIO("Ext2 inode write across block boundaries", "[filesystem][ext2][inode]") +{ + auto const block_size = 1024uz; + GIVEN("an ext2 inode with two direct blocks") + { + auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 64 * block_size); + REQUIRE(device != nullptr); + kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device); + + auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device); + + auto fs = kernel::filesystem::ext2::filesystem{}; + REQUIRE(fs.mount(dev_inode)); + + auto inode_data = kernel::filesystem::ext2::inode_data{}; + inode_data.size = block_size * 2; + inode_data.block[0] = 20; + inode_data.block[1] = 21; + + auto inode = kernel::filesystem::ext2::inode{&fs, inode_data}; + + THEN("writing over block boundaries updates backing device") + { + auto buffer = kstd::vector<std::byte>{std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'}, + std::byte{'o'}, std::byte{' '}, std::byte{'W'}, std::byte{'o'}, + std::byte{'r'}, std::byte{'l'}, std::byte{'d'}, std::byte{'!'}}; + + auto const bytes_written = inode.write(buffer.data(), block_size - 4, buffer.size()); + REQUIRE(bytes_written == buffer.size()); + + auto const text = + std::string_view{reinterpret_cast<char const *>(device->data.data() + 21 * block_size - 4), *bytes_written}; + REQUIRE(text == "Hello World!"); + } + } +} + SCENARIO("Ext2 inode get_size() correctly returns size depending on revision level", "[filesystem][ext2][inode]") { auto const block_size = 1024uz; |
