aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-23 11:19:30 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-23 11:19:30 +0100
commitbb7a6bd989b748a29c1a1e68807da2dd3176186a (patch)
tree26cc7927fc672c6bfd8d8e5011667964679ce1e4
parent730a1b83fe02e6249c20cbdd24b0c097c7c57b49 (diff)
downloadteachos-bb7a6bd989b748a29c1a1e68807da2dd3176186a.tar.xz
teachos-bb7a6bd989b748a29c1a1e68807da2dd3176186a.zip
kstd: fix push/emplace_back bug in vector
-rw-r--r--libs/kstd/include/kstd/vector6
-rw-r--r--libs/kstd/tests/src/vector.cpp168
2 files changed, 174 insertions, 0 deletions
diff --git a/libs/kstd/include/kstd/vector b/libs/kstd/include/kstd/vector
index b2cce0b..1242489 100644
--- a/libs/kstd/include/kstd/vector
+++ b/libs/kstd/include/kstd/vector
@@ -594,12 +594,14 @@ namespace kstd
{
auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
auto new_data = allocate_n(new_capacity);
+ auto old_size = size();
std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, value);
uninitialized_move_with_allocator(begin(), new_data, size());
destroy_n(begin(), size());
deallocate();
m_data = new_data;
m_capacity = new_capacity;
+ m_size = old_size;
}
else
{
@@ -615,12 +617,14 @@ namespace kstd
{
auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
auto new_data = allocate_n(new_capacity);
+ auto old_size = size();
std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, std::move(value));
uninitialized_move_with_allocator(begin(), new_data, size());
destroy_n(begin(), size());
deallocate();
m_data = new_data;
m_capacity = new_capacity;
+ m_size = old_size;
}
else
{
@@ -637,12 +641,14 @@ namespace kstd
{
auto new_capacity = m_capacity == 0 ? 1 : m_capacity * 2;
auto new_data = allocate_n(new_capacity);
+ auto old_size = size();
std::allocator_traits<allocator_type>::construct(m_allocator, new_data + m_size, std::forward<Args>(args)...);
uninitialized_move_with_allocator(begin(), new_data, size());
destroy_n(begin(), size());
deallocate();
m_data = new_data;
m_capacity = new_capacity;
+ m_size = old_size;
}
else
{
diff --git a/libs/kstd/tests/src/vector.cpp b/libs/kstd/tests/src/vector.cpp
index cb1b182..2440247 100644
--- a/libs/kstd/tests/src/vector.cpp
+++ b/libs/kstd/tests/src/vector.cpp
@@ -392,4 +392,172 @@ SCENARIO("Vector capacity management", "[vector]")
}
}
}
+}
+
+SCENARIO("Vector modifiers", "[vector]")
+{
+ GIVEN("An empty vector")
+ {
+ kstd::vector<int> v;
+
+ WHEN("push_back is called with a value")
+ {
+ v.push_back(10);
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 1);
+ REQUIRE(v.capacity() >= 1);
+ REQUIRE(v.back() == 10);
+ }
+ }
+
+ WHEN("emplace_back is called with constructor arguments")
+ {
+ v.emplace_back(20);
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 1);
+ REQUIRE(v.capacity() >= 1);
+ REQUIRE(v.back() == 20);
+ }
+ }
+ }
+
+ GIVEN("A populated vector")
+ {
+ kstd::vector<int> v = {10, 20, 30};
+ auto initial_capacity = v.capacity();
+
+ WHEN("push_back is called")
+ {
+ v.push_back(40);
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 4);
+ REQUIRE(v.capacity() >= initial_capacity);
+ REQUIRE(v[0] == 10);
+ REQUIRE(v[1] == 20);
+ REQUIRE(v[2] == 30);
+ REQUIRE(v[3] == 40);
+ }
+ }
+
+ WHEN("emplace_back is called with constructor arguments")
+ {
+ v.emplace_back(40);
+
+ THEN("the element is added and the size and capacity increase")
+ {
+ REQUIRE(v.size() == 4);
+ REQUIRE(v.capacity() >= initial_capacity);
+ REQUIRE(v[0] == 10);
+ REQUIRE(v[1] == 20);
+ REQUIRE(v[2] == 30);
+ REQUIRE(v[3] == 40);
+ }
+ }
+
+ WHEN("pop_back is called")
+ {
+ v.pop_back();
+
+ THEN("the last element is removed and the size decreases")
+ {
+ REQUIRE(v.size() == 2);
+ REQUIRE(v.capacity() == initial_capacity);
+ REQUIRE(v[0] == 10);
+ REQUIRE(v[1] == 20);
+ }
+ }
+
+ WHEN("clear is called")
+ {
+ v.clear();
+
+ THEN("the vector is empty")
+ {
+ REQUIRE(v.empty());
+ REQUIRE(v.size() == 0);
+ REQUIRE(v.capacity() == initial_capacity);
+ }
+ }
+ }
+}
+
+SCENARIO("Vector comparison", "[vector]")
+{
+ GIVEN("Two identical vectors")
+ {
+ kstd::vector<int> v1 = {1, 2, 3};
+ kstd::vector<int> v2 = {1, 2, 3};
+
+ WHEN("comparing for equality")
+ {
+ THEN("the vectors are equal")
+ {
+ REQUIRE(v1 == v2);
+ }
+
+ THEN("the vectors and not not-equal")
+ {
+ REQUIRE_FALSE(v1 != v2);
+ }
+ }
+
+ WHEN("comparing using the spaceship operator")
+ {
+ THEN("the vectors are equivalent")
+ {
+ REQUIRE((v1 <=> v2) == 0);
+ REQUIRE(v1 <= v2);
+ REQUIRE(v1 >= v2);
+ }
+ }
+ }
+
+ GIVEN("Two vectors of different sizes")
+ {
+ kstd::vector<int> v1 = {1, 2, 3};
+ kstd::vector<int> v2 = {1, 2, 3, 4};
+
+ WHEN("comparing for equality")
+ {
+ THEN("the vectors are not equal")
+ {
+ REQUIRE_FALSE(v1 == v2);
+ }
+
+ THEN("the vectors are not-equal")
+ {
+ REQUIRE(v1 != v2);
+ }
+ }
+
+ WHEN("comparing for ordering")
+ {
+ THEN("the shorter vector evaluates as less than the longer vector")
+ {
+ REQUIRE(v1 < v2);
+ REQUIRE(v2 > v1);
+ }
+ }
+ }
+
+ GIVEN("Two vectors of the same size but different elements")
+ {
+ kstd::vector<int> v1 = {1, 2, 3};
+ kstd::vector<int> v2 = {1, 2, 4};
+
+ WHEN("comparing for ordering")
+ {
+ THEN("they are ordered lexicographically")
+ {
+ REQUIRE(v1 < v2);
+ REQUIRE(v2 > v1);
+ }
+ }
+ }
} \ No newline at end of file