aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Oesch <lukasoesch20@gmail.com>2026-05-30 20:17:17 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-14 20:02:54 +0200
commit0fb3f139253a94bc4ab203729eddffd6d97d4a15 (patch)
tree7ac9ed3831d5aff56ad122fa4a791ce3a3c40fd3
parent64586bb24023d04e39476d007e9121e0102c1b47 (diff)
downloadkernel-0fb3f139253a94bc4ab203729eddffd6d97d4a15.tar.xz
kernel-0fb3f139253a94bc4ab203729eddffd6d97d4a15.zip
fix, improve and extend tests
-rw-r--r--kernel/kernel/filesystem/ext2/inode.hpp3
-rw-r--r--kernel/kernel/filesystem/ext2/inode.tests.cpp165
-rw-r--r--kernel/kernel/test_support/filesystem/ext2.cpp12
-rw-r--r--kernel/kernel/test_support/filesystem/ext2.hpp4
4 files changed, 127 insertions, 57 deletions
diff --git a/kernel/kernel/filesystem/ext2/inode.hpp b/kernel/kernel/filesystem/ext2/inode.hpp
index 6001c813..9c5f9beb 100644
--- a/kernel/kernel/filesystem/ext2/inode.hpp
+++ b/kernel/kernel/filesystem/ext2/inode.hpp
@@ -97,9 +97,10 @@ namespace kernel::filesystem::ext2
*/
[[nodiscard]] auto size() const -> uint64_t;
+ auto set_size(uint64_t new_size) -> void;
+
private:
auto append_blocks(size_t count) -> bool;
- auto set_size(uint64_t new_size) -> void;
filesystem * m_filesystem;
uint32_t m_inode_number{};
diff --git a/kernel/kernel/filesystem/ext2/inode.tests.cpp b/kernel/kernel/filesystem/ext2/inode.tests.cpp
index 6aba8b77..752d17d7 100644
--- a/kernel/kernel/filesystem/ext2/inode.tests.cpp
+++ b/kernel/kernel/filesystem/ext2/inode.tests.cpp
@@ -2,6 +2,7 @@
#include <kernel/devices/storage/management.hpp>
#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/ext2/block_group_descriptor.hpp>
#include <kernel/filesystem/ext2/filesystem.hpp>
#include <kernel/filesystem/ext2/superblock.hpp>
#include <kernel/filesystem/filesystem.hpp>
@@ -17,8 +18,10 @@
#include <algorithm>
#include <cstddef>
+#include <cstdint>
#include <filesystem>
#include <string_view>
+#include <vector>
// NOLINTBEGIN(readability-magic-numbers)
@@ -328,44 +331,84 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 in
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) == kernel::filesystem::filesystem::operation_result::success);
-
- // auto inode_data = kernel::filesystem::ext2::inode_data{};
- // inode_data.size = block_size * 2;
- // inode_data.blocks = 2 * block_size / 512;
- // inode_data.block[0] = 20;
- // inode_data.block[1] = 21;
- // inode_data.mode = kernel::filesystem::ext2::constants::mode_regular;
-
- // auto inode = kernel::filesystem::ext2::inode{&fs, 42, 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!");
- // }
- // }
+ 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);
+
+ 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;
+ superblock.rev_level = 1;
+ superblock.free_blocks_count = 64 - 15;
+
+ auto block_group_descriptor = kernel::filesystem::ext2::block_group_descriptor{};
+ block_group_descriptor.inode_table = 5;
+ block_group_descriptor.free_blocks_count = 64 - 15;
+ block_group_descriptor.block_bitmap = 10;
+
+ kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device, superblock, block_group_descriptor);
+
+ auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(device);
+
+ auto block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00});
+ block_bitmap[0] = std::byte{0b1111'1111};
+ block_bitmap[1] = std::byte{0b1111'1111};
+ block_bitmap[2] = std::byte{0b0001'1000};
+
+ dev_inode->write(block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size);
+
+ 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 = 5;
+ inode_data.blocks = 2 * block_size / 512;
+ inode_data.block[0] = 20;
+ inode_data.block[1] = 21;
+ inode_data.mode = kernel::filesystem::ext2::constants::mode_regular;
+
+ uint32_t inode_number = 3;
+ auto inode = kernel::filesystem::ext2::inode{&fs, inode_number, inode_data};
+ dev_inode->write(&inode, inode_number * block_size, sizeof(kernel::filesystem::ext2::inode_data));
+
+ THEN("writing over block boundaries updates backing device no additional blocks allocated")
+ {
+ 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 offset = block_size - 4;
+ auto const bytes_written = inode.write(buffer.data(), offset, 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!");
+
+ auto read_block_bitmap = std::vector<std::byte>(block_size, std::byte{0x00});
+ dev_inode->read(read_block_bitmap.data(), block_group_descriptor.block_bitmap * block_size, block_size);
+ REQUIRE(block_bitmap == read_block_bitmap);
+
+ auto read_inode = kernel::filesystem::ext2::inode{&fs, inode_number, {}};
+ dev_inode->read(&read_inode, inode_number * block_size, sizeof(kernel::filesystem::ext2::inode));
+ REQUIRE(offset + 12 == inode.size());
+ REQUIRE(inode_data.blocks == read_inode.data().blocks);
+
+ auto const current_blocks = inode_data.block;
+ auto const read_blocks = read_inode.data().block;
+ REQUIRE(current_blocks == read_blocks);
+ }
+ }
}
-SCENARIO("Ext2 inode get_size() correctly returns size depending on revision level", "[filesystem][ext2][inode]")
+SCENARIO("Ext2 inode get_size() and set_size() handles size correctly depending on revision level",
+ "[filesystem][ext2][inode]")
{
auto const block_size = 1024uz;
@@ -394,22 +437,29 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev
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 const verify_size_and_set_size = [&](uint16_t mode, uint64_t expected_initial_size,
+ uint32_t expected_dir_acl_after_set_size) {
+ data.mode = mode;
auto inode = kernel::filesystem::ext2::inode{&fs, 42, data};
- REQUIRE(inode.size() == 256);
+ REQUIRE(inode.size() == expected_initial_size);
+
+ inode.set_size(12);
+
+ REQUIRE(inode.size() == 12);
+ REQUIRE(inode.data().size == 12);
+ REQUIRE(inode.data().dir_acl == expected_dir_acl_after_set_size);
+ };
+
+ THEN("the inode size is 256 if mode = regular")
+ {
+ verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 256, 32);
}
THEN("the inode size is 256 if mode = directory")
{
- data.mode = kernel::filesystem::ext2::constants::mode_directory;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, 42, data};
-
- REQUIRE(inode.size() == 256);
+ verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256, 32);
}
}
@@ -430,22 +480,29 @@ SCENARIO("Ext2 inode get_size() correctly returns size depending on revision lev
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 const verify_size_and_set_size = [&](uint16_t mode, uint64_t expected_initial_size,
+ uint32_t expected_dir_acl_after_set_size) {
+ data.mode = mode;
auto inode = kernel::filesystem::ext2::inode{&fs, 42, data};
- REQUIRE(inode.size() == 0x0000'0020'0000'0100);
+ REQUIRE(inode.size() == expected_initial_size);
+
+ inode.set_size(12);
+
+ REQUIRE(inode.size() == 12);
+ REQUIRE(inode.data().size == 12);
+ REQUIRE(inode.data().dir_acl == expected_dir_acl_after_set_size);
+ };
+
+ THEN("the inode size is 256 if mode = regular")
+ {
+ verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_regular, 0x0000'0020'0000'0100, 0);
}
THEN("the inode size is 256 if mode = directory")
{
- data.mode = kernel::filesystem::ext2::constants::mode_directory;
-
- auto inode = kernel::filesystem::ext2::inode{&fs, 42, data};
-
- REQUIRE(inode.size() == 256);
+ verify_size_and_set_size(kernel::filesystem::ext2::constants::mode_directory, 256, 32);
}
}
}
diff --git a/kernel/kernel/test_support/filesystem/ext2.cpp b/kernel/kernel/test_support/filesystem/ext2.cpp
index 52b6efe7..3a7449ed 100644
--- a/kernel/kernel/test_support/filesystem/ext2.cpp
+++ b/kernel/kernel/test_support/filesystem/ext2.cpp
@@ -8,6 +8,7 @@
#include <cstdint>
#include <cstring>
+#include <vector>
namespace kernel::tests::filesystem::ext2
{
@@ -49,10 +50,17 @@ namespace kernel::tests::filesystem::ext2
auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device,
kernel::filesystem::ext2::superblock const & superblock) -> void
{
- write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock));
-
auto group_descriptor = kernel::filesystem::ext2::block_group_descriptor{};
group_descriptor.inode_table = 5;
+
+ setup_mock_ext2_layout(device, superblock, group_descriptor);
+ }
+
+ auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device,
+ kernel::filesystem::ext2::superblock const & superblock,
+ kernel::filesystem::ext2::block_group_descriptor const & group_descriptor) -> void
+ {
+ write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock));
write_bytes(device, 2048, &group_descriptor, sizeof(group_descriptor));
auto root_inode_data = kernel::filesystem::ext2::inode_data{};
diff --git a/kernel/kernel/test_support/filesystem/ext2.hpp b/kernel/kernel/test_support/filesystem/ext2.hpp
index 18cef1c2..3dd80ea3 100644
--- a/kernel/kernel/test_support/filesystem/ext2.hpp
+++ b/kernel/kernel/test_support/filesystem/ext2.hpp
@@ -1,6 +1,7 @@
#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_EXT2_HPP
#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_EXT2_HPP
+#include <kernel/filesystem/ext2/block_group_descriptor.hpp>
#include <kernel/filesystem/ext2/superblock.hpp>
#include <kernel/test_support/devices/block_device.hpp>
@@ -15,6 +16,9 @@ namespace kernel::tests::filesystem::ext2
auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void;
auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device,
kernel::filesystem::ext2::superblock const & superblock) -> void;
+ auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device,
+ kernel::filesystem::ext2::superblock const & superblock,
+ kernel::filesystem::ext2::block_group_descriptor const & group_descriptor) -> void;
} // namespace kernel::tests::filesystem::ext2