#include "kernel/filesystem/file_descriptor_table.hpp" #include "kernel/filesystem/open_file_description.hpp" #include "kernel/test_support/cpu.hpp" #include "kernel/test_support/filesystem/inode.hpp" #include #include #include #include struct file_descriptor_table_RAII { file_descriptor_table_RAII() { kernel::filesystem::file_descriptor_table::init(); } ~file_descriptor_table_RAII() { kernel::filesystem::file_descriptor_table::reset(); } }; struct file_descriptor_table_reset_only { ~file_descriptor_table_reset_only() { kernel::filesystem::file_descriptor_table::reset(); } }; SCENARIO_METHOD(file_descriptor_table_reset_only, "File descriptor table initialization", "[filesystem][file_descriptor_table]") { THEN("accessing the file descriptor table before initialization panics") { REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::get(), kernel::tests::cpu::halt); } THEN("the file descriptor table can be initialized and accessed") { kernel::filesystem::file_descriptor_table::init(); REQUIRE_NOTHROW(kernel::filesystem::file_descriptor_table::get()); } THEN("initializing the file descriptor table more than once panics") { kernel::filesystem::file_descriptor_table::init(); REQUIRE_THROWS_AS(kernel::filesystem::file_descriptor_table::init(), kernel::tests::cpu::halt); } } SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table add/get file", "[filesystem][file_descriptor_table]") { GIVEN("a file descriptor table and an open file description") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); auto file_description_1 = kstd::make_shared(inode); auto file_description_2 = kstd::make_shared(inode); WHEN("adding the open file description to the file descriptor table") { auto fd_1 = table.add_file(file_description_1); auto fd_2 = table.add_file(file_description_2); auto fd_3 = table.add_file(file_description_2); THEN("a valid file descriptor is returned") { REQUIRE(fd_1 == 0); REQUIRE(fd_2 == 1); REQUIRE(fd_3 == 2); } THEN("the file description can be retrieved using the returned file descriptor") { auto retrieved_description = table.get_file(fd_1); REQUIRE(retrieved_description == file_description_1); } } } GIVEN("a invalid open file description") { auto & table = kernel::filesystem::file_descriptor_table::get(); THEN("adding a null file description returns an error code") { auto fd = table.add_file(nullptr); REQUIRE(fd == -1); } THEN("retrieving a file description with a negative file descriptor returns a null pointer") { auto retrieved_description = table.get_file(-1); REQUIRE(retrieved_description == nullptr); } THEN("retrieving a file description with an out-of-bounds file descriptor returns a null pointer") { auto retrieved_description = table.get_file(1000); REQUIRE(retrieved_description == nullptr); } } } SCENARIO_METHOD(file_descriptor_table_RAII, "File descriptor table remove file", "[filesystem][file_descriptor_table]") { GIVEN("a file descriptor table with an open file description") { auto & table = kernel::filesystem::file_descriptor_table::get(); auto inode = kstd::make_shared(); auto file_description = kstd::make_shared(inode); auto fd = table.add_file(file_description); WHEN("removing the file description using the file descriptor") { table.remove_file(fd); THEN("the file description can no longer be retrieved using the file descriptor") { auto retrieved_description = table.get_file(fd); REQUIRE(retrieved_description == nullptr); } } WHEN("removing a file description the other file descriptor keep the same index") { auto fd2 = table.add_file(file_description); table.remove_file(fd); THEN("the second file description can still be retrieved using its file descriptor") { auto retrieved_description = table.get_file(fd2); REQUIRE(retrieved_description == file_description); } } } GIVEN("an invalid file descriptor") { auto & table = kernel::filesystem::file_descriptor_table::get(); THEN("removing a file with a negative file descriptor does nothing") { REQUIRE_NOTHROW(table.remove_file(-1)); } THEN("removing a file with an out-of-bounds file descriptor does nothing") { REQUIRE_NOTHROW(table.remove_file(1000)); } } }