aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/ext2/inode.tests.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-03 09:32:30 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-03 09:32:30 +0200
commit3012fa5dfe5dfed5e83baf9b40934ed8e8317627 (patch)
tree00d1c60a3d5d1cdfa55e0ff1691cd3362b6064ee /kernel/src/filesystem/ext2/inode.tests.cpp
parent5d8a58d538515ffc57ddf82ba40ba763990a8696 (diff)
downloadkernel-3012fa5dfe5dfed5e83baf9b40934ed8e8317627.tar.xz
kernel-3012fa5dfe5dfed5e83baf9b40934ed8e8317627.zip
kernel: rearrange sources according to p1204
Diffstat (limited to 'kernel/src/filesystem/ext2/inode.tests.cpp')
-rw-r--r--kernel/src/filesystem/ext2/inode.tests.cpp376
1 files changed, 0 insertions, 376 deletions
diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp
deleted file mode 100644
index 4aecc04a..00000000
--- a/kernel/src/filesystem/ext2/inode.tests.cpp
+++ /dev/null
@@ -1,376 +0,0 @@
-#include <kernel/filesystem/ext2/inode.hpp>
-
-#include <kernel/devices/storage/management.hpp>
-#include <kernel/filesystem/device_inode.hpp>
-#include <kernel/filesystem/ext2/filesystem.hpp>
-#include <kernel/filesystem/ext2/superblock.hpp>
-#include <kernel/filesystem/filesystem.hpp>
-#include <kernel/test_support/cpu.hpp>
-#include <kernel/test_support/devices/block_device.hpp>
-#include <kernel/test_support/filesystem/ext2.hpp>
-#include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp>
-
-#include <kstd/memory>
-#include <kstd/vector>
-
-#include <catch2/catch_test_macros.hpp>
-
-#include <algorithm>
-#include <cstddef>
-#include <filesystem>
-#include <string_view>
-
-SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]")
-{
- GIVEN("an ext2 filesystem")
- {
- auto fs = kernel::filesystem::ext2::filesystem{};
- auto data = kernel::filesystem::ext2::inode_data{};
-
- THEN("the inode is initialized with regular file mode in data and has the kind regular")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_regular;
- auto inode = kernel::filesystem::ext2::inode(&fs, data);
-
- REQUIRE(inode.is_regular());
- REQUIRE_FALSE(inode.is_directory());
- REQUIRE_FALSE(inode.is_device());
- REQUIRE_FALSE(inode.is_symbolic_link());
- }
-
- THEN("the inode is initialized with directory mode in data and has the kind directory")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_directory;
- auto inode = kernel::filesystem::ext2::inode(&fs, data);
-
- REQUIRE_FALSE(inode.is_regular());
- REQUIRE(inode.is_directory());
- REQUIRE_FALSE(inode.is_device());
- REQUIRE_FALSE(inode.is_symbolic_link());
- }
-
- THEN("the inode is initialized with symbolic link mode in data and has the kind symbolic link")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_symbolic_link;
- auto inode = kernel::filesystem::ext2::inode(&fs, data);
-
- REQUIRE_FALSE(inode.is_regular());
- REQUIRE_FALSE(inode.is_directory());
- REQUIRE_FALSE(inode.is_device());
- REQUIRE(inode.is_symbolic_link());
- }
-
- THEN("the inode is initialized with zero mode in data and has no specific kind")
- {
- data.mode = 0;
- auto inode = kernel::filesystem::ext2::inode(&fs, data);
-
- REQUIRE_FALSE(inode.is_regular());
- REQUIRE_FALSE(inode.is_directory());
- REQUIRE_FALSE(inode.is_device());
- REQUIRE_FALSE(inode.is_symbolic_link());
- }
- }
-
- GIVEN("no filesystem (null pointer)")
- {
- THEN("constructing an inode with a null filesystem pointer panics")
- {
- REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode(nullptr, {}), kernel::tests::cpu::halt);
- }
- }
-}
-
-SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 inode reads from real image",
- "[filesystem][ext2][inode][img]")
-{
- 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) == kernel::filesystem::filesystem::operation_result::success);
-
- auto information = fs.lookup(fs.root_inode(), "information");
- REQUIRE(information != nullptr);
- auto file = fs.lookup(information, "info_1.txt");
- REQUIRE(file != nullptr);
- REQUIRE(file->is_regular());
-
- THEN("reading from offset zero returns expected file prefix")
- {
- auto buffer = kstd::vector<std::byte>(6);
- auto const bytes_read = file->read(buffer.data(), 0, buffer.size());
-
- REQUIRE(bytes_read == 6);
-
- auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
- REQUIRE(text == "info_1");
- }
-
- THEN("reading with an offset returns the expected byte")
- {
- auto buffer = kstd::vector<std::byte>(1);
- auto const bytes_read = file->read(buffer.data(), 5, buffer.size());
-
- REQUIRE(bytes_read == 1);
- REQUIRE(static_cast<char>(buffer[0]) == '1');
- }
- }
-}
-
-SCENARIO("Ext2 inode handles zeros in block mappings as file holes", "[filesystem][ext2][inode]")
-{
- auto const block_size = 1024uz;
- GIVEN("an ext2 inode with only direct mapped data 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) == kernel::filesystem::filesystem::operation_result::success);
-
- auto data = kernel::filesystem::ext2::inode_data{};
- data.block[0] = 30;
- data.block[1] = 0;
- data.block[2] = 31;
- data.size = block_size * 3;
-
- kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5);
- kernel::tests::filesystem::ext2::write_bytes(*device, 31 * block_size, "World!", 6);
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- auto buffer = kstd::vector<std::byte>(data.size, std::byte{0xAB});
-
- THEN("correct number of bytes are read and holes are returned as zeros")
- {
- auto const bytes_read = inode.read(buffer.data(), 0, buffer.size());
- REQUIRE(bytes_read == data.size);
-
- auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
- REQUIRE(text.substr(0, 5) == "Hello");
- REQUIRE(std::ranges::all_of(text.substr(5, block_size - 5), [](char c) { return c == '\0'; }));
- REQUIRE(text.substr(2 * block_size, 6) == "World!");
- REQUIRE(std::ranges::all_of(text.substr(2 * block_size + 6, 3 * block_size), [](char c) { return c == '\0'; }));
- }
- }
-
- GIVEN("an ext2 indode with file holes in singly indirect 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) == kernel::filesystem::filesystem::operation_result::success);
-
- auto data = kernel::filesystem::ext2::inode_data{};
- data.block[0] = 30;
- data.block[12] = 31;
- data.size = block_size * 15;
-
- kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size, 50);
- kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 4, 0);
- kernel::tests::filesystem::ext2::write_u32(*device, 31 * block_size + 8, 51);
-
- kernel::tests::filesystem::ext2::write_bytes(*device, 30 * block_size, "Hello", 5);
- kernel::tests::filesystem::ext2::write_bytes(*device, 50 * block_size, "Blub", 4);
- kernel::tests::filesystem::ext2::write_bytes(*device, 51 * block_size, "World!", 6);
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- auto buffer = kstd::vector<std::byte>(data.size, std::byte{0xAB});
-
- THEN("correct number of bytes are read and holes are returned as zeros")
- {
- auto const bytes_read = inode.read(buffer.data(), 0, buffer.size());
- REQUIRE(bytes_read == data.size);
-
- auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
- REQUIRE(text.substr(0, 5) == "Hello");
- REQUIRE(std::ranges::all_of(text.substr(5, 12 * block_size - 5), [](char c) { return c == '\0'; }));
- REQUIRE(text.substr(12 * block_size, 4) == "Blub");
- REQUIRE(
- std::ranges::all_of(text.substr(12 * block_size + 4, 2 * block_size - 4), [](char c) { return c == '\0'; }));
- REQUIRE(text.substr(14 * block_size, 6) == "World!");
- REQUIRE(
- std::ranges::all_of(text.substr(14 * block_size + 6, 1 * block_size - 6), [](char c) { return c == '\0'; }));
- }
- }
-
- GIVEN("an ext2 inode with zero singly indirect block pointer")
- {
- 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) == kernel::filesystem::filesystem::operation_result::success);
-
- auto data = kernel::filesystem::ext2::inode_data{};
- data.block[12] = 0;
- data.size = block_size * 15;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- auto buffer = kstd::vector<std::byte>(block_size * 15, std::byte{0xAB});
-
- THEN("all direct blocks are zero when singly indirect block pointer is zero")
- {
- auto const bytes_read = inode.read(buffer.data(), 0, buffer.size());
- REQUIRE(bytes_read == buffer.size());
- REQUIRE(std::ranges::all_of(buffer, [](std::byte c) { return c == std::byte{0x00}; }));
- }
- }
-}
-
-SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]")
-{
- auto const block_size = 1024uz;
- GIVEN("an ext2 inode with two direct blocks and a block size of 1024 bytes")
- {
- 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) == kernel::filesystem::filesystem::operation_result::success);
-
- auto inode_data = kernel::filesystem::ext2::inode_data{};
- inode_data.size = block_size * 2;
- inode_data.block[0] = 20;
- kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6);
- inode_data.block[1] = 21;
- kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6);
- auto inode = kernel::filesystem::ext2::inode{&fs, inode_data};
-
- auto buffer = kstd::vector<std::byte>(12, std::byte{0x00});
-
- THEN("reading across the block boundary returns the combined content")
- {
- auto const bytes_read = inode.read(buffer.data(), block_size - 6, buffer.size());
- REQUIRE(bytes_read == 12);
-
- auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
- REQUIRE(text == "Hello World!");
- }
- }
-}
-
-SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]")
-{
- GIVEN("an ext2 inode")
- {
- auto fs = kernel::filesystem::ext2::filesystem{};
- auto inode = kernel::filesystem::ext2::inode{&fs, kernel::filesystem::ext2::inode_data{}};
-
- THEN("writing to the inode panics")
- {
- auto buffer = kstd::vector<std::byte>(32, std::byte{0x00});
- REQUIRE_THROWS_AS(inode.write(buffer.data(), 0, buffer.size()), kernel::tests::cpu::halt);
- }
- }
-}
-
-SCENARIO("Ext2 inode get_size() correctly returns size depending on revision level", "[filesystem][ext2][inode]")
-{
- auto const block_size = 1024uz;
-
- auto superblock = kernel::filesystem::ext2::superblock{};
- superblock.magic = kernel::filesystem::ext2::constants::magic_number;
- superblock.log_block_size = 0;
- superblock.blocks_count = 64;
- superblock.blocks_per_group = 64;
- superblock.inodes_per_group = 32;
- superblock.inode_size = 128;
-
- GIVEN("an ext2 inode with good old revision and inode_data.size = 256, inode_data.dir_acl = 32")
- {
- superblock.rev_level = 0;
-
- 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, superblock);
-
- auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
-
- auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
-
- auto data = kernel::filesystem::ext2::inode_data{};
- data.size = 256;
- data.dir_acl = 32;
-
- THEN("the inode size is 256 if mode = regular")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_regular;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- REQUIRE(inode.size() == 256);
- }
-
- THEN("the inode size is 256 if mode = directory")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_directory;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- REQUIRE(inode.size() == 256);
- }
- }
-
- GIVEN("an ext2 inode with good dynamic revision and inode_data.size = 256, inode_data.dir_acl = 32")
- {
- superblock.rev_level = 1;
-
- 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, superblock);
-
- auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
-
- auto fs = kernel::filesystem::ext2::filesystem{};
- REQUIRE(fs.mount(dev_inode) == kernel::filesystem::filesystem::operation_result::success);
-
- auto data = kernel::filesystem::ext2::inode_data{};
- data.size = 256;
- data.dir_acl = 32;
-
- THEN("the inode size is 256 if mode = regular")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_regular;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- REQUIRE(inode.size() == 0x0000'0020'0000'0100);
- }
-
- THEN("the inode size is 256 if mode = directory")
- {
- data.mode = kernel::filesystem::ext2::constants::mode_directory;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, data};
-
- REQUIRE(inode.size() == 256);
- }
- }
-} \ No newline at end of file