diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-01 07:19:38 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-02 11:28:08 +0200 |
| commit | 724b9693897642497ca5feee65546dc670bed722 (patch) | |
| tree | f5ff5479b2e08294f3d4f6d45e8f22f8404432ff | |
| parent | 5f084e49a27e73fdf9ca88f46121618d9fae399f (diff) | |
| download | teachos-724b9693897642497ca5feee65546dc670bed722.tar.xz teachos-724b9693897642497ca5feee65546dc670bed722.zip | |
kstd/observer_ptr: extend test suite
| -rw-r--r-- | libs/kstd/include/kstd/observer_ptr | 8 | ||||
| -rw-r--r-- | libs/kstd/tests/src/observer_ptr.cpp | 165 |
2 files changed, 149 insertions, 24 deletions
diff --git a/libs/kstd/include/kstd/observer_ptr b/libs/kstd/include/kstd/observer_ptr index 97c9e5e..a328331 100644 --- a/libs/kstd/include/kstd/observer_ptr +++ b/libs/kstd/include/kstd/observer_ptr @@ -85,7 +85,7 @@ namespace kstd //! Get the currently watched object. //! //! @return A reference to the currently watched object. - [[nodiscard]] constexpr auto operator*() const noexcept -> std::add_lvalue_reference_t<element_type> + [[nodiscard]] constexpr auto operator*() const -> std::add_lvalue_reference_t<element_type> { throw_on_null(); return *m_ptr; @@ -94,7 +94,7 @@ namespace kstd //! Get the currently watched object. //! //! @return A pointer to the currently watched object. - [[nodiscard]] constexpr auto operator->() const noexcept -> element_type * + [[nodiscard]] constexpr auto operator->() const -> element_type * { throw_on_null(); return m_ptr; @@ -109,7 +109,7 @@ namespace kstd } //! Compare the observer pointer with another observer pointer. - //! + //!> //! @param other The other observer pointer to compare with. //! @return The result of the comparison. constexpr auto operator<=>(observer_ptr const & other) const noexcept -> std::strong_ordering = default; @@ -118,7 +118,7 @@ namespace kstd //! Throw an exception if the observer pointer is null. //! //! @throws std::runtime_error if the observer pointer is null. - constexpr auto throw_on_null() const noexcept -> void + constexpr auto throw_on_null() const -> void { if (m_ptr == nullptr) { diff --git a/libs/kstd/tests/src/observer_ptr.cpp b/libs/kstd/tests/src/observer_ptr.cpp index 2fe2226..5d94098 100644 --- a/libs/kstd/tests/src/observer_ptr.cpp +++ b/libs/kstd/tests/src/observer_ptr.cpp @@ -3,8 +3,28 @@ #include <catch2/catch_test_macros.hpp> +#include <compare> +#include <type_traits> #include <utility> +namespace +{ + struct Base + { + }; + + struct Derived : Base + { + }; + + struct Element + { + int value{}; + + constexpr auto operator<=>(Element const &) const noexcept = default; + }; +} // namespace + SCENARIO("Observer Pointer initialization and construction", "[observer_ptr]") { GIVEN("An empty context") @@ -59,17 +79,9 @@ SCENARIO("Observer Pointer initialization and construction", "[observer_ptr]") 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); + auto value = Derived{}; + auto ptr = kstd::observer_ptr<Derived>(&value); + kstd::observer_ptr<Base> copy = ptr; THEN("the new observer pointer points to the same object as the other observer pointer") { @@ -112,6 +124,22 @@ SCENARIO("Observer Pointer initialization and construction", "[observer_ptr]") REQUIRE(&*copy == &value); } } + + WHEN("constructing an observer pointer using make_observer") + { + auto value = 1; + auto ptr = kstd::make_observer(&value); + + THEN("the observer pointer points to the correct object") + { + REQUIRE(&*ptr == &value); + } + + THEN("the observe pointer has the correct element type") + { + STATIC_REQUIRE(std::is_same_v<decltype(ptr), kstd::observer_ptr<int>>); + } + } } } @@ -174,6 +202,24 @@ SCENARIO("Observer pointer modifiers", "[observer_ptr]") REQUIRE(&*other_ptr == &value); } } + + WHEN("using namespace-level swap to swap it with another observer pointer") + { + using std::swap; + auto other_value = 2; + auto other_ptr = kstd::observer_ptr{&other_value}; + swap(ptr, 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); + } + } } } @@ -181,14 +227,7 @@ 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 value = Element{1}; auto ptr = kstd::observer_ptr{&value}; WHEN("getting the raw pointer") @@ -223,12 +262,98 @@ SCENARIO("Observer pointer observers", "[observer_ptr]") WHEN("converting the observer pointer to a raw pointer") { - auto raw_ptr = static_cast<A *>(ptr); + auto raw_ptr = static_cast<Element *>(ptr); THEN("the raw pointer points to the correct object") { REQUIRE(raw_ptr == &value); } } + + WHEN("checking the observer pointer as a boolean") + { + THEN("it returns true") + { + REQUIRE(static_cast<bool>(ptr)); + } + } + } + + GIVEN("A null observer pointer") + { + auto ptr = kstd::observer_ptr<Element>{}; + + WHEN("checking the observer pointer as a boolean") + { + THEN("it returns false") + { + REQUIRE_FALSE(static_cast<bool>(ptr)); + } + } + + WHEN("dereferencing the observer pointer") + { + THEN("the observer pointer panics") + { + REQUIRE_THROWS_AS(*ptr, kstd::tests::os_panic); + } + } + + WHEN("writing through the observer pointer with the arrow operator") + { + THEN("the observer pointer panics") + { + REQUIRE_THROWS_AS(ptr->value = 2, kstd::tests::os_panic); + } + } + } +} + +SCENARIO("Observer pointer comparisons", "[observer_ptr]") +{ + GIVEN("Observer pointers to elements of an array") + { + int arr[] = {1, 2}; + auto ptr1 = kstd::observer_ptr{&arr[0]}; + auto ptr2 = kstd::observer_ptr{&arr[1]}; + + WHEN("comparing the same observer pointer") + { + THEN("they are equal") + { + REQUIRE(ptr1 == ptr1); + REQUIRE((ptr1 <=> ptr1) == std::strong_ordering::equal); + } + } + + WHEN("comparing different observer pointers") + { + THEN("they are ordered correctly") + { + REQUIRE(ptr1 != ptr2); + REQUIRE(ptr1 < ptr2); + REQUIRE(ptr1 <= ptr2); + REQUIRE(ptr2 > ptr1); + REQUIRE(ptr2 >= ptr1); + REQUIRE((ptr1 <=> ptr2) == std::strong_ordering::less); + REQUIRE((ptr2 <=> ptr1) == std::strong_ordering::greater); + } + } + } + + GIVEN("A null observer pointer") + { + auto ptr = kstd::observer_ptr<int>{}; + + WHEN("comparing with another null observer pointer") + { + auto other_ptr = kstd::observer_ptr<int>{}; + + THEN("they are equal") + { + REQUIRE(ptr == other_ptr); + REQUIRE((ptr <=> other_ptr) == std::strong_ordering::equal); + } + } } }
\ No newline at end of file |
