aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/kernel/filesystem/ext2/inode.tests.cpp79
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;