diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-23 10:32:15 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-23 10:32:15 +0100 |
| commit | 48a2c33d205397adeaad385aebc1d1e008915b3e (patch) | |
| tree | 379265414d551747585a1f86b9f390539ef2dfeb /libs | |
| parent | 754012dd458985a6a4953c99204c6651318892b2 (diff) | |
| download | teachos-48a2c33d205397adeaad385aebc1d1e008915b3e.tar.xz teachos-48a2c33d205397adeaad385aebc1d1e008915b3e.zip | |
ci: enable test builds
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/kstd/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | libs/kstd/tests/include/kstd/tests/os_panic.hpp | 23 | ||||
| -rw-r--r-- | libs/kstd/tests/os_mock.cpp | 15 | ||||
| -rw-r--r-- | libs/kstd/tests/src/os_panic.cpp | 15 | ||||
| -rw-r--r-- | libs/kstd/tests/src/vector.cpp | 395 | ||||
| -rw-r--r-- | libs/kstd/tests/vector.cpp | 11 |
6 files changed, 442 insertions, 28 deletions
diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index 2f360cd..06543ab 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -44,8 +44,12 @@ endif() if(NOT CMAKE_CROSSCOMPILING) add_executable("kstd_tests" - "tests/vector.cpp" - "tests/os_mock.cpp" + "tests/src/vector.cpp" + "tests/src/os_panic.cpp" + ) + + target_include_directories("kstd_tests" PRIVATE + "tests/include" ) target_link_libraries("kstd_tests" PRIVATE @@ -59,5 +63,8 @@ if(NOT CMAKE_CROSSCOMPILING) EXCLUDE_FROM_ALL NO ) + enable_coverage("kstd") + enable_coverage("kstd_tests") + catch_discover_tests("kstd_tests") endif()
\ No newline at end of file diff --git a/libs/kstd/tests/include/kstd/tests/os_panic.hpp b/libs/kstd/tests/include/kstd/tests/os_panic.hpp new file mode 100644 index 0000000..4396a9f --- /dev/null +++ b/libs/kstd/tests/include/kstd/tests/os_panic.hpp @@ -0,0 +1,23 @@ +#ifndef KSTD_TESTS_OS_PANIC_HPP +#define KSTD_TESTS_OS_PANIC_HPP + +#include <source_location> +#include <stdexcept> +#include <string> + +namespace kstd::tests +{ + + struct os_panic : std::runtime_error + { + os_panic(std::string message, std::source_location location) + : std::runtime_error{message} + , location(location) + {} + + std::source_location location; + }; + +} // namespace kstd::tests + +#endif
\ No newline at end of file diff --git a/libs/kstd/tests/os_mock.cpp b/libs/kstd/tests/os_mock.cpp deleted file mode 100644 index 39b7f0d..0000000 --- a/libs/kstd/tests/os_mock.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include <exception> -#include <format> -#include <source_location> -#include <stdexcept> -#include <string_view> - -namespace kstd::os -{ - auto panic(std::string_view message, std::source_location location) - { - auto full_message = - std::format("OS Panic Handler called '{}' at {}:{}", message, location.file_name(), location.line()); - throw std::runtime_error{full_message}; - } -} // namespace kstd::os
\ No newline at end of file diff --git a/libs/kstd/tests/src/os_panic.cpp b/libs/kstd/tests/src/os_panic.cpp new file mode 100644 index 0000000..3eae6ff --- /dev/null +++ b/libs/kstd/tests/src/os_panic.cpp @@ -0,0 +1,15 @@ +#include "kstd/tests/os_panic.hpp" + +#include <source_location> +#include <string> +#include <string_view> + +namespace kstd::os +{ + + auto panic(std::string_view message, std::source_location location) + { + throw kstd::tests::os_panic{std::string{message}, location}; + } + +} // namespace kstd::os
\ No newline at end of file diff --git a/libs/kstd/tests/src/vector.cpp b/libs/kstd/tests/src/vector.cpp new file mode 100644 index 0000000..cb1b182 --- /dev/null +++ b/libs/kstd/tests/src/vector.cpp @@ -0,0 +1,395 @@ +#include "kstd/tests/os_panic.hpp" + +#include <kstd/ranges> +#include <kstd/vector> + +#include <catch2/catch_test_macros.hpp> + +#include <array> +#include <ranges> +#include <utility> + +SCENARIO("Vector initialization and construction", "[vector]") +{ + GIVEN("An empty context") + { + WHEN("constructing by default") + { + kstd::vector<int> v; + + THEN("the vector is empty") + { + REQUIRE(v.empty()); + } + + THEN("the size and capacity are zero") + { + REQUIRE(v.size() == 0); + REQUIRE(v.capacity() == 0); + } + } + + WHEN("constructing with a specific size") + { + kstd::vector<int> v(10); + + THEN("the vector is not empty") + { + REQUIRE_FALSE(v.empty()); + } + + THEN("the size is and capacity match the specified value") + { + REQUIRE(v.size() == 10); + REQUIRE(v.capacity() == 10); + } + } + + WHEN("constructing from an initializer list") + { + kstd::vector<int> v = {1, 2, 3, 4, 5}; + + THEN("the vector is not empty") + { + REQUIRE_FALSE(v.empty()); + } + + THEN("the size is and capacity match the specified value") + { + REQUIRE(v.size() == 5); + REQUIRE(v.capacity() == 5); + } + + THEN("the elements are correctly initialized") + { + REQUIRE(v[0] == 1); + REQUIRE(v[1] == 2); + REQUIRE(v[2] == 3); + REQUIRE(v[3] == 4); + REQUIRE(v[4] == 5); + } + } + } + + GIVEN("A non-empty range") + { + auto range = std::array<int, 3>{1, 2, 3}; + + WHEN("constructing from a random-access iterator range") + { + auto v = kstd::vector<int>{std::begin(range), std::end(range)}; + + THEN("the vector is not empty") + { + REQUIRE_FALSE(v.empty()); + } + + THEN("the size and capacity match the range size") + { + REQUIRE(v.size() == std::size(range)); + REQUIRE(v.capacity() == std::size(range)); + } + + THEN("the elements are correctly initialized") + { + REQUIRE(v[0] == 1); + REQUIRE(v[1] == 2); + REQUIRE(v[2] == 3); + } + } + + WHEN("constructing from a range") + { + auto v = kstd::vector<int>{kstd::from_range, range}; + + THEN("the vector is not empty") + { + REQUIRE_FALSE(v.empty()); + } + + THEN("the size and capacity match the range size") + { + REQUIRE(v.size() == std::ranges::size(range)); + REQUIRE(v.capacity() == std::ranges::size(range)); + } + + THEN("the elements are correctly initialized") + { + REQUIRE(v[0] == 1); + REQUIRE(v[1] == 2); + REQUIRE(v[2] == 3); + } + } + } + + GIVEN("A populated vector") + { + kstd::vector<int> source = {1, 2, 3, 4, 5}; + + WHEN("copy constructing a new vector") + { + kstd::vector<int> copy(source); + + THEN("the copy matches the original") + { + REQUIRE(copy.size() == source.size()); + REQUIRE(copy.capacity() == source.capacity()); + REQUIRE(copy[0] == 1); + REQUIRE(copy[1] == 2); + REQUIRE(copy[2] == 3); + REQUIRE(copy[3] == 4); + REQUIRE(copy[4] == 5); + } + + THEN("the original is left unchanged") + { + REQUIRE(source.size() == 5); + REQUIRE(source.capacity() == 5); + REQUIRE(source[0] == 1); + REQUIRE(source[1] == 2); + REQUIRE(source[2] == 3); + REQUIRE(source[3] == 4); + REQUIRE(source[4] == 5); + } + } + + WHEN("move constructing a new vector") + { + kstd::vector<int> moved(std::move(source)); + + THEN("The new vector has the original elements") + { + REQUIRE(moved.size() == 5); + REQUIRE(moved.capacity() == 5); + REQUIRE(moved[0] == 1); + REQUIRE(moved[1] == 2); + REQUIRE(moved[2] == 3); + REQUIRE(moved[3] == 4); + REQUIRE(moved[4] == 5); + } + + THEN("The original vector is left in a valid but unspecified state") + { + REQUIRE(source.empty()); + REQUIRE(source.size() == 0); + REQUIRE(source.capacity() == 0); + } + } + } +} + +SCENARIO("Vector element access", "[vector]") +{ + GIVEN("A populated vector") + { + kstd::vector<int> v = {10, 20, 30}; + + WHEN("accessing elements for reading") + { + THEN("operator[] and at() return the correct elements") + { + REQUIRE(v[0] == 10); + REQUIRE(v[1] == 20); + REQUIRE(v[2] == 30); + + REQUIRE(v.at(0) == 10); + REQUIRE(v.at(1) == 20); + REQUIRE(v.at(2) == 30); + } + + THEN("front() and back() return the first and last elements") + { + REQUIRE(v.front() == 10); + REQUIRE(v.back() == 30); + } + + THEN("data() return a pointer to the contiguous storage") + { + auto ptr = v.data(); + REQUIRE(ptr); + REQUIRE(ptr[0] == 10); + REQUIRE(ptr[1] == 20); + REQUIRE(ptr[2] == 30); + } + + THEN("accessing out of bounds elements panics") + { + REQUIRE_THROWS_AS(v.at(3), kstd::tests::os_panic); + } + } + + WHEN("accessing elements for writing") + { + v[0] = 100; + v.at(1) = 200; + v.back() = 300; + + THEN("the elements are correctly modified") + { + REQUIRE(v[0] == 100); + REQUIRE(v[1] == 200); + REQUIRE(v[2] == 300); + } + } + } +} + +SCENARIO("Vector iterators", "[vector]") +{ + GIVEN("A populated vector") + { + kstd::vector<int> v = {1, 2, 3}; + + WHEN("using forward iterators") + { + THEN("they navigate the elements in the correct forward order") + { + auto it = v.begin(); + REQUIRE(it != v.end()); + REQUIRE(*it == 1); + + ++it; + REQUIRE(it != v.end()); + REQUIRE(*it == 2); + + ++it; + REQUIRE(it != v.end()); + REQUIRE(*it == 3); + + ++it; + REQUIRE(it == v.end()); + } + + THEN("const forward iterators provide correct access") + { + auto it = v.cbegin(); + REQUIRE(it != v.cend()); + REQUIRE(*it == 1); + + ++it; + REQUIRE(it != v.cend()); + REQUIRE(*it == 2); + + ++it; + REQUIRE(it != v.cend()); + REQUIRE(*it == 3); + + ++it; + REQUIRE(it == v.cend()); + } + } + + WHEN("using reverse iterators") + { + THEN("they navigate the elements in the correct reverse order") + { + auto it = v.rbegin(); + REQUIRE(it != v.rend()); + REQUIRE(*it == 3); + + ++it; + REQUIRE(it != v.rend()); + REQUIRE(*it == 2); + + ++it; + REQUIRE(it != v.rend()); + REQUIRE(*it == 1); + + ++it; + REQUIRE(it == v.rend()); + } + + THEN("const reverse iterators provide correct access") + { + auto it = v.crbegin(); + REQUIRE(it != v.crend()); + REQUIRE(*it == 3); + + ++it; + REQUIRE(it != v.crend()); + REQUIRE(*it == 2); + + ++it; + REQUIRE(it != v.crend()); + REQUIRE(*it == 1); + + ++it; + REQUIRE(it == v.crend()); + } + } + } + + GIVEN("an empty vector") + { + kstd::vector<int> v; + + WHEN("getting iterators") + { + THEN("begin() equals end() and cbegin() equals cend()") + { + REQUIRE(v.begin() == v.end()); + REQUIRE(v.cbegin() == v.cend()); + } + + THEN("rbegin() equals rend() and crbegin() equals crend()") + { + REQUIRE(v.rbegin() == v.rend()); + REQUIRE(v.crbegin() == v.crend()); + } + } + } +} + +SCENARIO("Vector capacity management", "[vector]") +{ + GIVEN("An empty vector") + { + kstd::vector<int> v; + + WHEN("reserving space") + { + v.reserve(10); + + THEN("the capacity is at least the reserved amount") + { + REQUIRE(v.capacity() >= 10); + } + + THEN("the size is still zero") + { + REQUIRE(v.size() == 0); + } + + THEN("the vector is still empty") + { + REQUIRE(v.empty()); + } + } + } + + GIVEN("A populated vector with excess capacity") + { + kstd::vector<int> v{1, 2, 3}; + v.reserve(10); + + REQUIRE(v.capacity() == 10); + + WHEN("calling shrink_to_fit") + { + v.shrink_to_fit(); + + THEN("the capacity is reduced to match the size") + { + REQUIRE(v.capacity() == 3); + REQUIRE(v.size() == 3); + } + + THEN("the elements remain unchanged") + { + REQUIRE(v[0] == 1); + REQUIRE(v[1] == 2); + REQUIRE(v[2] == 3); + } + } + } +}
\ No newline at end of file diff --git a/libs/kstd/tests/vector.cpp b/libs/kstd/tests/vector.cpp deleted file mode 100644 index 3a45008..0000000 --- a/libs/kstd/tests/vector.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include <kstd/vector> - -#include <catch2/catch_test_macros.hpp> - -TEST_CASE("Creating an empty vector") -{ - kstd::vector<int> v; - REQUIRE(v.empty()); - REQUIRE(v.size() == 0); - REQUIRE(v.capacity() == 0); -} |
