diff options
| -rw-r--r-- | kernel/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | kernel/kernel/test_support/string_makers.hpp | 132 | ||||
| -rw-r--r-- | kernel/kernel/test_support/string_makers.tests.cpp | 61 |
3 files changed, 197 insertions, 0 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index ca44e79b..fc25f1ca 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -193,6 +193,10 @@ if(BUILD_TESTING) ${KERNEL_TEST_SUPPORT_SOURCES} ) + target_compile_options("${TEST_TARGET}" PRIVATE + "SHELL:-include ${CMAKE_CURRENT_SOURCE_DIR}/kernel/test_support/string_makers.hpp" + ) + target_compile_definitions("${TEST_TARGET}" PRIVATE KERNEL_TEST_ASSETS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/kernel/test_support/vfs/test_assets" ) diff --git a/kernel/kernel/test_support/string_makers.hpp b/kernel/kernel/test_support/string_makers.hpp new file mode 100644 index 00000000..98eed3e8 --- /dev/null +++ b/kernel/kernel/test_support/string_makers.hpp @@ -0,0 +1,132 @@ +#ifndef TEACHOS_KERNEL_TEST_SUPPORT_STRING_MAKERS_HPP +#define TEACHOS_KERNEL_TEST_SUPPORT_STRING_MAKERS_HPP + +//! Catch2 string conversions for kapi and kernel types. +//! +//! This header is force-included into every kernel test translation unit by the build system and must therefore never +//! be included by kernel code. See kstd/test_support/string_makers.hpp for the conversions of kstd types. + +#include <kstd/test_support/string_makers.hpp> // IWYU pragma: export + +#include <kapi/devices.hpp> +#include <kapi/filesystem.hpp> +#include <kapi/memory.hpp> + +#include <catch2/catch_tostring.hpp> + +#include <string> + +namespace Catch +{ + + template<> + struct StringMaker<kapi::filesystem::device_number> + { + static auto convert(kapi::filesystem::device_number number) -> std::string + { + return std::to_string(number.major) + ':' + std::to_string(number.minor); + } + }; + + template<> + struct StringMaker<kapi::filesystem::directory_cursor> + { + static auto convert(kapi::filesystem::directory_cursor cursor) -> std::string + { + return "directory_cursor{" + std::to_string(cursor.value) + '}'; + } + }; + + template<> + struct StringMaker<kapi::filesystem::file_status> + { + static auto convert(kapi::filesystem::file_status const & status) -> std::string + { + return "file_status{mode: " + Catch::Detail::stringify(status.mode) + + ", size: " + Catch::Detail::stringify(status.size) + + ", raw_device: " + Catch::Detail::stringify(status.raw_device) + + ", inode_number: " + Catch::Detail::stringify(status.inode_number) + + ", link_count: " + Catch::Detail::stringify(status.link_count) + '}'; + } + }; + + template<> + struct StringMaker<kapi::memory::frame> + { + static auto convert(kapi::memory::frame frame) -> std::string + { + return "frame{" + std::to_string(frame.number()) + '}'; + } + }; + + template<> + struct StringMaker<kapi::memory::page> + { + static auto convert(kapi::memory::page page) -> std::string + { + return "page{" + std::to_string(page.number()) + '}'; + } + }; + + template<> + struct StringMaker<kapi::devices::mmio_range> + { + static auto convert(kapi::devices::mmio_range const & range) -> std::string + { + return "mmio{" + Catch::Detail::stringify(range.start) + ", " + Catch::Detail::stringify(range.size) + '}'; + } + }; + + template<> + struct StringMaker<kapi::devices::io_port> + { + static auto convert(kapi::devices::io_port const & port) -> std::string + { + return "port{" + std::to_string(port.start) + ", " + std::to_string(port.count) + '}'; + } + }; + + template<> + struct StringMaker<kapi::devices::interrupt_line> + { + static auto convert(kapi::devices::interrupt_line const & line) -> std::string + { + return "irq{" + std::to_string(line.number) + '}'; + } + }; + + template<> + struct StringMaker<kapi::devices::dma_channel> + { + static auto convert(kapi::devices::dma_channel const & channel) -> std::string + { + return "dma{" + std::to_string(channel.number) + '}'; + } + }; + + template<> + struct StringMaker<kapi::devices::resource> + { + static auto convert(kapi::devices::resource const & resource) -> std::string + { + using kapi::devices::resource_type; + + switch (resource.type) + { + case resource_type::mmio: + return Catch::Detail::stringify(resource.get<resource_type::mmio>()); + case resource_type::port: + return Catch::Detail::stringify(resource.get<resource_type::port>()); + case resource_type::irq: + return Catch::Detail::stringify(resource.get<resource_type::irq>()); + case resource_type::dma: + return Catch::Detail::stringify(resource.get<resource_type::dma>()); + } + + return "resource{<unknown>}"; + } + }; + +} // namespace Catch + +#endif diff --git a/kernel/kernel/test_support/string_makers.tests.cpp b/kernel/kernel/test_support/string_makers.tests.cpp new file mode 100644 index 00000000..1bcb332f --- /dev/null +++ b/kernel/kernel/test_support/string_makers.tests.cpp @@ -0,0 +1,61 @@ +#include <kernel/test_support/string_makers.hpp> + +#include <kapi/devices.hpp> +#include <kapi/filesystem.hpp> +#include <kapi/memory.hpp> + +#include <kstd/units.hpp> + +#include <catch2/catch_test_macros.hpp> +#include <catch2/catch_tostring.hpp> + +using namespace kstd::units_literals; + +SCENARIO("Catch2 string conversion of kapi types", "[test_support][string_makers]") +{ + GIVEN("filesystem types") + { + auto const number = kapi::filesystem::device_number{.major = 1, .minor = 2}; + auto const cursor = kapi::filesystem::directory_cursor{3}; + auto const status = kapi::filesystem::file_status{ + .mode = 4, .size = 5_B, .raw_device = number, .inode_number = 6, .link_count = 7}; + + THEN("they are printed with their fields") + { + REQUIRE(Catch::Detail::stringify(number) == "1:2"); + REQUIRE(Catch::Detail::stringify(cursor) == "directory_cursor{3}"); + REQUIRE(Catch::Detail::stringify(status) == + "file_status{mode: 4, size: 5, raw_device: 1:2, inode_number: 6, link_count: 7}"); + } + } + + GIVEN("memory chunks") + { + THEN("they are printed with their number") + { + REQUIRE(Catch::Detail::stringify(kapi::memory::frame{8}) == "frame{8}"); + REQUIRE(Catch::Detail::stringify(kapi::memory::page{9}) == "page{9}"); + } + } + + GIVEN("device resources") + { + auto const port = kapi::devices::io_port{.start = 0x60, .count = 2}; + auto const line = kapi::devices::interrupt_line{.number = 1}; + auto const channel = kapi::devices::dma_channel{.number = 3}; + + THEN("they are printed with their kind and fields") + { + REQUIRE(Catch::Detail::stringify(port) == "port{96, 2}"); + REQUIRE(Catch::Detail::stringify(line) == "irq{1}"); + REQUIRE(Catch::Detail::stringify(channel) == "dma{3}"); + } + + THEN("a resource is printed like the value it holds") + { + REQUIRE(Catch::Detail::stringify(kapi::devices::resource{port}) == "port{96, 2}"); + REQUIRE(Catch::Detail::stringify(kapi::devices::resource{line}) == "irq{1}"); + REQUIRE(Catch::Detail::stringify(kapi::devices::resource{channel}) == "dma{3}"); + } + } +} |
