diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-31 22:52:52 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-02 11:28:08 +0200 |
| commit | 15b882d0416bb83a18e5437480c08419b2035e1f (patch) | |
| tree | 39da51bdd18a3203c519d36b458400f6c58c0c47 /libs | |
| parent | 77473afe9d5acb9450443b07b56d3dbc2f0639a6 (diff) | |
| download | teachos-15b882d0416bb83a18e5437480c08419b2035e1f.tar.xz teachos-15b882d0416bb83a18e5437480c08419b2035e1f.zip | |
kstd: add some basic observer_ptr tests
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/kstd/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | libs/kstd/include/kstd/observer_ptr | 7 | ||||
| -rw-r--r-- | libs/kstd/tests/src/observer_ptr.cpp | 234 |
3 files changed, 239 insertions, 3 deletions
diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt index ec0f441..240118e 100644 --- a/libs/kstd/CMakeLists.txt +++ b/libs/kstd/CMakeLists.txt @@ -44,6 +44,7 @@ else() add_executable("kstd_tests" "tests/src/flat_map.cpp" "tests/src/vector.cpp" + "tests/src/observer_ptr.cpp" "tests/src/os_panic.cpp" "tests/src/string.cpp" ) diff --git a/libs/kstd/include/kstd/observer_ptr b/libs/kstd/include/kstd/observer_ptr index d3d24b4..97c9e5e 100644 --- a/libs/kstd/include/kstd/observer_ptr +++ b/libs/kstd/include/kstd/observer_ptr @@ -6,6 +6,7 @@ #include <compare> #include <concepts> #include <cstddef> +#include <type_traits> #include <utility> namespace kstd @@ -52,7 +53,7 @@ namespace kstd //! Reset the observer pointer. //! //! @param pointer The new object to watch. - constexpr auto reset(element_type * pointer) noexcept -> void + constexpr auto reset(element_type * pointer = nullptr) noexcept -> void { m_ptr = pointer; } @@ -84,7 +85,7 @@ namespace kstd //! Get the currently watched object. //! //! @return A reference to the currently watched object. - [[nodiscard]] constexpr auto operator*() const noexcept -> element_type & + [[nodiscard]] constexpr auto operator*() const noexcept -> std::add_lvalue_reference_t<element_type> { throw_on_null(); return *m_ptr; @@ -126,7 +127,7 @@ namespace kstd } //! The raw pointer to the watched object. - ElementType * m_ptr; + ElementType * m_ptr{}; }; //! Swap two observer pointers. diff --git a/libs/kstd/tests/src/observer_ptr.cpp b/libs/kstd/tests/src/observer_ptr.cpp new file mode 100644 index 0000000..2fe2226 --- /dev/null +++ b/libs/kstd/tests/src/observer_ptr.cpp @@ -0,0 +1,234 @@ +#include <kstd/observer_ptr> +#include <kstd/tests/os_panic.hpp> + +#include <catch2/catch_test_macros.hpp> + +#include <utility> + +SCENARIO("Observer Pointer initialization and construction", "[observer_ptr]") +{ + GIVEN("An empty context") + { + WHEN("constructing by default") + { + auto ptr = kstd::observer_ptr<int>{}; + + THEN("the observer pointer is null") + { + REQUIRE_FALSE(ptr); + } + } + + WHEN("constructing from a nullptr") + { + auto ptr = kstd::observer_ptr<int>{nullptr}; + + THEN("the observer pointer is null") + { + REQUIRE_FALSE(ptr); + } + } + + WHEN("constructing from a raw pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + + THEN("the observer pointer is not null") + { + REQUIRE(ptr); + } + + THEN("the observer pointer points to the correct object") + { + REQUIRE(&*ptr == &value); + } + } + + WHEN("copy constructing from an existing observer pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + auto copy = ptr; + + THEN("the new observer pointer points to the same object as the other observer pointer") + { + REQUIRE(&*copy == &value); + } + } + + WHEN("copy constructing from an existing observer pointer with a compatible type") + { + struct A + { + }; + + struct B : A + { + }; + + auto value = B{}; + auto ptr = kstd::observer_ptr<B>(&value); + auto copy = kstd::observer_ptr<A>(ptr); + + THEN("the new observer pointer points to the same object as the other observer pointer") + { + REQUIRE(&*copy == &value); + } + } + + WHEN("copy assigning from an existing observer pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + auto copy = ptr; + + THEN("the new observer pointer points to the same object as the other observer pointer") + { + REQUIRE(&*copy == &value); + } + } + + WHEN("move constructing from an existing observer pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + auto copy = std::move(ptr); + + THEN("the new observer pointer points to the same object as the other observer pointer") + { + REQUIRE(&*copy == &value); + } + } + + WHEN("move assigning from an existing observer pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + auto copy = std::move(ptr); + + THEN("the new observer pointer points to the same object as the other observer pointer") + { + REQUIRE(&*copy == &value); + } + } + } +} + +SCENARIO("Observer pointer modifiers", "[observer_ptr]") +{ + GIVEN("A non-null observer pointer") + { + auto value = 1; + auto ptr = kstd::observer_ptr{&value}; + + WHEN("releasing the observer pointer") + { + auto raw_ptr = ptr.release(); + + THEN("the observer pointer is null") + { + REQUIRE_FALSE(ptr); + } + + THEN("the returned pointer points to the correct object") + { + REQUIRE(raw_ptr == &value); + } + } + + WHEN("resetting the observer pointer to nullptr") + { + ptr.reset(); + + THEN("the observer pointer is null") + { + REQUIRE_FALSE(ptr); + } + } + + WHEN("resetting the observer pointer to a new object") + { + auto other_value = 2; + ptr.reset(&other_value); + + THEN("the observer pointer points to the new object") + { + REQUIRE(&*ptr == &other_value); + } + } + + WHEN("swapping it with another observer pointer") + { + auto other_value = 2; + auto other_ptr = kstd::observer_ptr{&other_value}; + ptr.swap(other_ptr); + + THEN("the observer pointer points to the other object") + { + REQUIRE(&*ptr == &other_value); + } + + THEN("the other observer pointer points to the original object") + { + REQUIRE(&*other_ptr == &value); + } + } + } +} + +SCENARIO("Observer pointer observers", "[observer_ptr]") +{ + GIVEN("A non-null observer pointer") + { + struct A + { + int value{}; + + constexpr auto operator<=>(A const & other) const noexcept = default; + }; + + auto value = A{1}; + auto ptr = kstd::observer_ptr{&value}; + + WHEN("getting the raw pointer") + { + auto raw_ptr = ptr.get(); + + THEN("the raw pointer points to the correct object") + { + REQUIRE(raw_ptr == &value); + } + } + + WHEN("dereferencing the observer pointer") + { + auto dereferenced = *ptr; + + THEN("the dereferenced value is the correct value") + { + REQUIRE(dereferenced == value); + } + } + + WHEN("writing through the observer pointer with the arrow operator") + { + ptr->value = 2; + + THEN("the value is updated") + { + REQUIRE(value.value == 2); + } + } + + WHEN("converting the observer pointer to a raw pointer") + { + auto raw_ptr = static_cast<A *>(ptr); + + THEN("the raw pointer points to the correct object") + { + REQUIRE(raw_ptr == &value); + } + } + } +}
\ No newline at end of file |
