aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-09-10 09:42:12 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-09-10 09:42:12 +0200
commita89e51ccca32a0535471d3cc2e1171ca65f6c97f (patch)
tree18a0470add68105aa0ba18f6b449178fe50d271a /libs
parentc20011f985ef60855f99dc515b4d407aed0e1eab (diff)
downloadkernel-a89e51ccca32a0535471d3cc2e1171ca65f6c97f.tar.xz
kernel-a89e51ccca32a0535471d3cc2e1171ca65f6c97f.zip
kstd/vector: fix UB in test suite
Diffstat (limited to 'libs')
-rw-r--r--libs/kstd/kstd/test_support/test_types.hpp56
-rw-r--r--libs/kstd/kstd/vector.tests.cpp34
2 files changed, 79 insertions, 11 deletions
diff --git a/libs/kstd/kstd/test_support/test_types.hpp b/libs/kstd/kstd/test_support/test_types.hpp
index 8231fd3b..baf5e853 100644
--- a/libs/kstd/kstd/test_support/test_types.hpp
+++ b/libs/kstd/kstd/test_support/test_types.hpp
@@ -13,6 +13,28 @@ namespace kstd::tests
//! This type is designed to test move and copy semantics of standard library containers implemented in kstd.
struct special_member_tracker
{
+ struct counters
+ {
+ //! A counter to track how many times an instance of this type was default constructed.
+ std::size_t default_constructed{0};
+ //! A counter to track how many times an instance of this type was copy constructed.
+ std::size_t copy_constructed{0};
+ //! A counter to track how many times an instance of this type was move constructed.
+ std::size_t move_constructed{0};
+ //! A counter to track how many times an instance of this type was value constructed.
+ std::size_t value_constructed{0};
+ //! A counter to track how many times an instance of this type was copy assigned.
+ std::size_t copy_assigned{0};
+ //! A counter to track how many times an instance of this type was move assigned.
+ std::size_t move_assigned{0};
+ //! A counter to track how many times an instance of this type was destroyed.
+ std::size_t destroyed{0};
+ //! A counter to track how many times an instance of this type was copied from another instance.
+ std::size_t copied_from{0};
+ //! A counter to track how many times an instance of this type was moved from another instance.
+ std::size_t moved_from{0};
+ } * external = nullptr;
+
//! A value indicating that the object was moved from.
constexpr auto static moved_from_v = -1;
@@ -47,7 +69,15 @@ namespace kstd::tests
{
value = other.value;
++copy_assigned_count;
+ if (external)
+ {
+ ++external->copy_assigned;
+ }
++other.copied_from_count;
+ if (other.external)
+ {
+ ++other.external->copied_from;
+ }
}
return *this;
}
@@ -61,8 +91,16 @@ namespace kstd::tests
{
value = other.value;
++move_assigned_count;
+ if (external)
+ {
+ ++external->move_assigned;
+ }
other.value = moved_from_v;
++other.moved_from_count;
+ if (other.external)
+ {
+ ++other.external->moved_from;
+ }
}
return *this;
}
@@ -70,6 +108,24 @@ namespace kstd::tests
~special_member_tracker()
{
++destroyed_count;
+ if (external)
+ {
+ ++external->destroyed;
+ }
+ }
+
+ auto set_external_counters(counters & counters) noexcept
+ {
+ external = &counters;
+ external->default_constructed = default_constructed_count;
+ external->copy_constructed = copy_constructed_count;
+ external->move_constructed = move_constructed_count;
+ external->value_constructed = value_constructed_count;
+ external->copy_assigned = copy_assigned_count;
+ external->move_assigned = move_assigned_count;
+ external->destroyed = destroyed_count;
+ external->copied_from = copied_from_count;
+ external->moved_from = moved_from_count;
}
auto reset_counts() -> void
diff --git a/libs/kstd/kstd/vector.tests.cpp b/libs/kstd/kstd/vector.tests.cpp
index 24598bf9..ed0695fb 100644
--- a/libs/kstd/kstd/vector.tests.cpp
+++ b/libs/kstd/kstd/vector.tests.cpp
@@ -1628,6 +1628,9 @@ SCENARIO("Vector modifier move semantics", "[vector]")
elem.reset_counts();
}
+ auto counters = kstd::tests::special_member_tracker::counters{};
+ v[2].set_external_counters(counters);
+
auto it = v.erase(v.cbegin() + 1);
THEN("the subsequent elements are move-assigned leftwards")
@@ -1642,8 +1645,8 @@ SCENARIO("Vector modifier move semantics", "[vector]")
REQUIRE(v[1].move_assigned_count == 1);
REQUIRE(v[1].copy_assigned_count == 0);
- REQUIRE(v.data()[2].destroyed_count == 1);
- REQUIRE(v.data()[2].moved_from_count == 1);
+ REQUIRE(counters.destroyed == 1);
+ REQUIRE(counters.moved_from == 1);
REQUIRE(it == v.begin() + 1);
}
@@ -1656,6 +1659,9 @@ SCENARIO("Vector modifier move semantics", "[vector]")
elem.reset_counts();
}
+ auto counters = kstd::tests::special_member_tracker::counters{};
+ v[2].set_external_counters(counters);
+
auto it = v.erase(v.cend() - 1);
THEN("no elements are moved, just the last element destroyed")
@@ -1674,9 +1680,9 @@ SCENARIO("Vector modifier move semantics", "[vector]")
REQUIRE(v[1].move_assigned_count == 0);
REQUIRE(v[1].copy_assigned_count == 0);
- REQUIRE(v.data()[2].destroyed_count == 1);
- REQUIRE(v.data()[2].moved_from_count == 0);
- REQUIRE(v.data()[2].copied_from_count == 0);
+ REQUIRE(counters.destroyed == 1);
+ REQUIRE(counters.moved_from == 0);
+ REQUIRE(counters.copied_from == 0);
REQUIRE(it == v.end());
}
@@ -1692,6 +1698,12 @@ SCENARIO("Vector modifier move semantics", "[vector]")
elem.reset_counts();
}
+ auto counters3 = kstd::tests::special_member_tracker::counters{};
+ v[3].set_external_counters(counters3);
+
+ auto counters4 = kstd::tests::special_member_tracker::counters{};
+ v[4].set_external_counters(counters4);
+
auto it = v.erase(v.cbegin() + 1, v.cbegin() + 3);
THEN("the specified elements are destroyed and subsequent elements are move-assigned leftwards")
@@ -1716,13 +1728,13 @@ SCENARIO("Vector modifier move semantics", "[vector]")
REQUIRE(v[2].move_assigned_count == 1);
REQUIRE(v[2].copy_assigned_count == 0);
- REQUIRE(v.data()[3].destroyed_count == 1);
- REQUIRE(v.data()[3].moved_from_count == 1);
- REQUIRE(v.data()[3].copied_from_count == 0);
+ REQUIRE(counters3.destroyed == 1);
+ REQUIRE(counters3.moved_from == 1);
+ REQUIRE(counters3.copied_from == 0);
- REQUIRE(v.data()[4].destroyed_count == 1);
- REQUIRE(v.data()[4].moved_from_count == 1);
- REQUIRE(v.data()[4].copied_from_count == 0);
+ REQUIRE(counters4.destroyed == 1);
+ REQUIRE(counters4.moved_from == 1);
+ REQUIRE(counters4.copied_from == 0);
REQUIRE(it == v.begin() + 1);
}