aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-23 11:40:44 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-23 11:40:44 +0100
commita2a407efd453635af9ff6d3514114bfee95bcbb9 (patch)
tree64c65df834fe3d20e45d4ebfab4d0f80d78161fd /libs
parentbb7a6bd989b748a29c1a1e68807da2dd3176186a (diff)
downloadteachos-a2a407efd453635af9ff6d3514114bfee95bcbb9.tar.xz
teachos-a2a407efd453635af9ff6d3514114bfee95bcbb9.zip
kstd/vector: add more tests for different types
Diffstat (limited to 'libs')
-rw-r--r--libs/kstd/tests/src/vector.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/libs/kstd/tests/src/vector.cpp b/libs/kstd/tests/src/vector.cpp
index 2440247..1427ce8 100644
--- a/libs/kstd/tests/src/vector.cpp
+++ b/libs/kstd/tests/src/vector.cpp
@@ -6,6 +6,7 @@
#include <catch2/catch_test_macros.hpp>
#include <array>
+#include <cstddef>
#include <ranges>
#include <utility>
@@ -560,4 +561,189 @@ SCENARIO("Vector comparison", "[vector]")
}
}
}
+}
+
+struct non_default_constructible
+{
+ int value;
+ non_default_constructible() = delete;
+ explicit non_default_constructible(int v)
+ : value{v}
+ {}
+
+ bool operator==(non_default_constructible const & other) const noexcept = default;
+};
+
+SCENARIO("Vector with non-default-constructible types", "[vector]")
+{
+ GIVEN("A type without a default constructor")
+ {
+ WHEN("constructing an empty vector")
+ {
+ kstd::vector<non_default_constructible> v;
+
+ THEN("the vector is empty")
+ {
+ REQUIRE(v.empty());
+ }
+ }
+
+ WHEN("using emplace_back")
+ {
+ kstd::vector<non_default_constructible> v;
+ v.emplace_back(42);
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 1);
+ REQUIRE(v.back() == non_default_constructible{42});
+ }
+ }
+ }
+}
+
+template<typename T>
+struct tracking_allocator
+{
+ using value_type = T;
+
+ int * allocation_count;
+
+ tracking_allocator(int * counter)
+ : allocation_count{counter}
+ {}
+
+ template<typename U>
+ tracking_allocator(tracking_allocator<U> const & other) noexcept
+ : allocation_count{other.allocation_count}
+ {}
+
+ T * allocate(std::size_t n)
+ {
+ if (allocation_count)
+ {
+ (*allocation_count)++;
+ }
+ return static_cast<T *>(::operator new(n * sizeof(T)));
+ }
+
+ void deallocate(T * p, std::size_t n) noexcept
+ {
+ ::operator delete(p, n * sizeof(T));
+ }
+
+ bool operator==(tracking_allocator const & other)
+ {
+ return allocation_count == other.allocation_count;
+ }
+};
+
+SCENARIO("Vector with custom allocator", "[vector]")
+{
+ GIVEN("a tracking allocator acting as the vector's memory manager")
+ {
+ auto allocations = 0;
+ tracking_allocator<int> allocator{&allocations};
+
+ WHEN("a vector uses this allocator to allocate memory")
+ {
+ kstd::vector<int, tracking_allocator<int>> v{allocator};
+ REQUIRE(allocations == 0);
+
+ v.reserve(10);
+
+ THEN("the allocator was used to allocate memory")
+ {
+ REQUIRE(allocations > 0);
+ }
+ }
+ }
+}
+
+struct move_tracker
+{
+ int value;
+ bool was_copied{};
+ bool was_moved{};
+
+ move_tracker() = default;
+ explicit move_tracker(int v)
+ : value{v}
+ {}
+
+ move_tracker(move_tracker const & other)
+ : value{other.value}
+ , was_copied{true}
+ , was_moved{false}
+ {}
+
+ move_tracker(move_tracker && other) noexcept
+ : value{other.value}
+ , was_copied{false}
+ , was_moved{true}
+ {
+ other.value = -1;
+ }
+
+ move_tracker & operator=(move_tracker const & other)
+ {
+ value = other.value;
+ was_copied = true;
+ was_moved = false;
+ return *this;
+ }
+
+ move_tracker & operator=(move_tracker && other) noexcept
+ {
+ value = other.value;
+ was_moved = true;
+ was_copied = false;
+ other.value = -1;
+ return *this;
+ }
+};
+
+SCENARIO("Vector modifier move semantics", "[vector]")
+{
+ GIVEN("An empty vector and a move tracker element")
+ {
+ kstd::vector<move_tracker> v;
+ move_tracker tracker{42};
+
+ WHEN("push_back is called with the move tracker")
+ {
+ v.push_back(std::move(tracker));
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 1);
+ REQUIRE(v.back().was_moved);
+ REQUIRE_FALSE(v.back().was_copied);
+ REQUIRE(v.back().value == 42);
+ }
+
+ THEN("the original tracker is left in a valid but unspecified state")
+ {
+ REQUIRE(tracker.value == -1);
+ }
+ }
+ }
+
+ GIVEN("An empty vector")
+ {
+ kstd::vector<move_tracker> v;
+
+ WHEN("emplace_back is called with constructor arguments")
+ {
+ v.emplace_back(42);
+
+ THEN("the element is constructed directly, without moves or copies")
+ {
+ REQUIRE(v.size() == 1);
+ REQUIRE_FALSE(v.back().was_moved);
+ REQUIRE_FALSE(v.back().was_copied);
+ REQUIRE(v.back().value == 42);
+ }
+ }
+ }
} \ No newline at end of file