aboutsummaryrefslogtreecommitdiff
path: root/kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp')
-rw-r--r--kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp b/kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp
new file mode 100644
index 00000000..20ef7009
--- /dev/null
+++ b/kernel/kernel/filesystem/ext2/directory_iterator.tests.cpp
@@ -0,0 +1,118 @@
+#include <kernel/filesystem/ext2/directory_iterator.hpp>
+
+#include <kernel/devices/storage.hpp>
+#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/ext2/filesystem.hpp>
+#include <kernel/filesystem/ext2/inode.hpp>
+#include <kernel/filesystem/mount.hpp>
+#include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp>
+
+#include <kstd/memory.hpp>
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <algorithm>
+#include <filesystem>
+#include <string>
+#include <vector>
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
+ "Ext2 directory_iterator walks a real directory and terminates", "[filesystem][ext2][readdir]")
+{
+ auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+
+ GIVEN("a mounted ext2 filesystem and its root directory")
+ {
+ REQUIRE(std::filesystem::exists(image_path));
+ REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path}));
+
+ auto boot_device = kernel::devices::storage::determine_boot_device();
+ REQUIRE(boot_device != nullptr);
+
+ auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(boot_device);
+ auto fs = kstd::make_shared<kernel::filesystem::ext2::filesystem>();
+ auto mount = kernel::filesystem::mount::create(nullptr, fs, nullptr, nullptr, dev_inode);
+ REQUIRE(mount);
+
+ auto root = (*mount)->root_dentry()->inode();
+ auto const & root_ext2_inode = static_cast<kernel::filesystem::ext2::inode const &>(*root);
+
+ WHEN("iterating from begin to the default-constructed end sentinel")
+ {
+ auto names = std::vector<std::string>{};
+ auto guard = 0;
+
+ for (auto it = kernel::filesystem::ext2::directory_iterator{root_ext2_inode};
+ it != kernel::filesystem::ext2::directory_iterator{}; ++it)
+ {
+ REQUIRE(guard++ < 64); // fails loudly on a non-terminating loop rather than hanging the suite
+ names.emplace_back(&it->name_start, it->name_len);
+ }
+
+ THEN("iteration terminates on its own and finds the expected entries")
+ {
+ REQUIRE(guard < 64);
+ REQUIRE(std::ranges::find(names, ".") != names.end());
+ REQUIRE(std::ranges::find(names, "..") != names.end());
+ REQUIRE(std::ranges::find(names, "information") != names.end());
+ }
+ }
+ }
+}
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
+ "Ext2 directory_iterator satisfies the forward-iterator multi-pass guarantee",
+ "[filesystem][ext2][readdir]")
+{
+ auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+
+ GIVEN("an iterator positioned at the first entry of the root directory")
+ {
+ REQUIRE(std::filesystem::exists(image_path));
+ REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path}));
+
+ auto boot_device = kernel::devices::storage::determine_boot_device();
+ REQUIRE(boot_device != nullptr);
+
+ auto dev_inode = kstd::make_shared<kernel::filesystem::device_inode>(boot_device);
+ auto fs = kstd::make_shared<kernel::filesystem::ext2::filesystem>();
+ auto mount = kernel::filesystem::mount::create(nullptr, fs, nullptr, nullptr, dev_inode);
+ REQUIRE(mount);
+
+ auto root = (*mount)->root_dentry()->inode();
+ auto const & root_ext2_inode = static_cast<kernel::filesystem::ext2::inode const &>(*root);
+
+ auto original = kernel::filesystem::ext2::directory_iterator{root_ext2_inode};
+ auto const first_name = std::string{&original->name_start, original->name_len};
+
+ WHEN("the iterator is copied, then only the original is advanced")
+ {
+ auto copy = original;
+ ++original;
+
+ THEN("the copy still refers to the first entry, unaffected by advancing the original")
+ {
+ auto const copy_name = std::string{&copy->name_start, copy->name_len};
+ REQUIRE(copy_name == first_name);
+
+ auto const advanced_name = std::string{&original->name_start, original->name_len};
+ REQUIRE(advanced_name != first_name);
+ }
+ }
+ }
+}
+
+SCENARIO("Ext2 directory_iterator's default-constructed value is a valid, comparable end sentinel",
+ "[filesystem][ext2][readdir]")
+{
+ GIVEN("two independently default-constructed iterators")
+ {
+ auto first = kernel::filesystem::ext2::directory_iterator{};
+ auto second = kernel::filesystem::ext2::directory_iterator{};
+
+ THEN("they compare equal to each other")
+ {
+ REQUIRE(first == second);
+ }
+ }
+} \ No newline at end of file