internal/sdref: Remove in favor of stdplus/handle

We no longer need to roll our own managed handle type now that stdplus
implements a generic one.

Tested:
    Built and run through unit tests.

Change-Id: Id34cd8d3ffacf7901d49cac335fa93f744f0e310
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/.gitignore b/.gitignore
index c780660..3508cbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,7 +49,6 @@
 /test/clock
 /test/event
 /test/exception
-/test/internal/sdref
 /test/internal/utils
 /test/source/base
 /test/source/child
diff --git a/Makefile.am b/Makefile.am
index 8c7e40d..e27fbe8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,11 +38,12 @@
 endif
 
 export AM_CPPFLAGS = -I$(abs_builddir)/src -I$(abs_srcdir)/src \
-                     $(SYSTEMD_CFLAGS) $(CODE_COVERAGE_CPPFLAGS)
+                     $(SYSTEMD_CFLAGS) $(STDPLUS_CFLAGS) \
+                     $(CODE_COVERAGE_CPPFLAGS)
 export AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
 export AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
 
-export COMMON_LIBS = $(SYSTEMD_LIBS) $(CODE_COVERAGE_LIBS)
+export COMMON_LIBS = $(SYSTEMD_LIBS) $(STDPLUS_LIBS) $(CODE_COVERAGE_LIBS)
 export SDEVENTPLUS_LIBS = $(abs_builddir)/src/libsdeventplus.la $(COMMON_LIBS)
 
 
diff --git a/configure.ac b/configure.ac
index c725bcf..a933bb2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,6 +39,9 @@
 AX_APPEND_COMPILE_FLAGS([-Wall -Wextra -Wpedantic], [CFLAGS])
 AX_APPEND_COMPILE_FLAGS([-Wall -Wextra -Wpedantic], [CXXFLAGS])
 
+# We require stdplus unconditionally
+AX_PKG_CHECK_MODULES([STDPLUS], [stdplus])
+
 # We require systemd unconditionally
 AX_PKG_CHECK_MODULES([SYSTEMD], [libsystemd >= 218])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 9cd7706..40e3c89 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,9 +16,6 @@
 nobase_include_HEADERS += sdeventplus/internal/sdevent.hpp
 libsdeventplus_la_SOURCES += sdeventplus/internal/sdevent.cpp
 
-nobase_include_HEADERS += sdeventplus/internal/sdref.hpp
-libsdeventplus_la_SOURCES += sdeventplus/internal/sdref.cpp
-
 nobase_include_HEADERS += sdeventplus/internal/utils.hpp
 
 nobase_include_HEADERS += sdeventplus/source/base.hpp
diff --git a/src/meson.build b/src/meson.build
index eec3218..a7d99cb 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,4 +1,5 @@
 libsystemd = dependency('libsystemd')
+stdplus = dependency('stdplus')
 
 sdeventplus = library(
   'sdeventplus',
@@ -7,7 +8,6 @@
     'sdeventplus/event.cpp',
     'sdeventplus/exception.cpp',
     'sdeventplus/internal/sdevent.cpp',
-    'sdeventplus/internal/sdref.cpp',
     'sdeventplus/source/base.cpp',
     'sdeventplus/source/child.cpp',
     'sdeventplus/source/event.cpp',
@@ -19,7 +19,10 @@
   include_directories: includes,
   implicit_include_directories: false,
   version: meson.project_version(),
-  dependencies: libsystemd,
+  dependencies: [
+    libsystemd,
+    stdplus
+  ],
   install: true)
 
 import('pkgconfig').generate(
@@ -37,7 +40,6 @@
 
 install_headers(
   'sdeventplus/internal/sdevent.hpp',
-  'sdeventplus/internal/sdref.hpp',
   'sdeventplus/internal/utils.hpp',
   subdir: 'sdeventplus/internal')
 
diff --git a/src/sdeventplus/event.cpp b/src/sdeventplus/event.cpp
index 946d34c..132dc7f 100644
--- a/src/sdeventplus/event.cpp
+++ b/src/sdeventplus/event.cpp
@@ -9,16 +9,14 @@
 {
 
 Event::Event(sd_event* event, const internal::SdEvent* sdevent) :
-    sdevent(sdevent), event(event, &internal::SdEvent::sd_event_ref,
-                            &internal::SdEvent::sd_event_unref, sdevent)
+    sdevent(sdevent), event(event, sdevent)
 {
 }
 
 Event::Event(sd_event* event, std::false_type,
              const internal::SdEvent* sdevent) :
     sdevent(sdevent),
-    event(event, &internal::SdEvent::sd_event_ref,
-          &internal::SdEvent::sd_event_unref, std::false_type(), sdevent)
+    event(std::move(event), sdevent)
 {
 }
 
@@ -46,7 +44,7 @@
 
 sd_event* Event::get() const
 {
-    return event.get();
+    return event.value();
 }
 
 const internal::SdEvent* Event::getSdEvent() const
@@ -148,4 +146,14 @@
     return r;
 }
 
+sd_event* Event::ref(sd_event* const& event, const internal::SdEvent*& sdevent)
+{
+    return sdevent->sd_event_ref(event);
+}
+
+void Event::drop(sd_event*&& event, const internal::SdEvent*& sdevent)
+{
+    sdevent->sd_event_unref(event);
+}
+
 } // namespace sdeventplus
diff --git a/src/sdeventplus/event.hpp b/src/sdeventplus/event.hpp
index ba7c77d..f234e5c 100644
--- a/src/sdeventplus/event.hpp
+++ b/src/sdeventplus/event.hpp
@@ -2,8 +2,8 @@
 
 #include <optional>
 #include <sdeventplus/internal/sdevent.hpp>
-#include <sdeventplus/internal/sdref.hpp>
 #include <sdeventplus/internal/utils.hpp>
+#include <stdplus/handle/copyable.hpp>
 #include <systemd/sd-event.h>
 
 namespace sdeventplus
@@ -146,8 +146,13 @@
     bool set_watchdog(bool b) const;
 
   private:
+    static sd_event* ref(sd_event* const& event,
+                         const internal::SdEvent*& sdevent);
+    static void drop(sd_event*&& event, const internal::SdEvent*& sdevent);
+
     const internal::SdEvent* sdevent;
-    internal::SdRef<sd_event> event;
+    stdplus::Copyable<sd_event*, const internal::SdEvent*>::Handle<drop, ref>
+        event;
 };
 
 } // namespace sdeventplus
diff --git a/src/sdeventplus/internal/sdref.cpp b/src/sdeventplus/internal/sdref.cpp
deleted file mode 100644
index add6b90..0000000
--- a/src/sdeventplus/internal/sdref.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <sdeventplus/internal/sdref.hpp>
-#include <type_traits>
-#include <utility>
-
-namespace sdeventplus
-{
-namespace internal
-{
-
-template <typename T>
-SdRef<T>::SdRef(T* ref, Func take_ref, Func release_ref,
-                const SdEvent* sdevent) :
-    SdRef(take_ref(sdevent, ref), take_ref, release_ref, std::false_type(),
-          sdevent)
-{
-}
-
-template <typename T>
-SdRef<T>::SdRef(T* ref, Func take_ref, Func release_ref, std::false_type,
-                const SdEvent* sdevent) :
-    sdevent(sdevent),
-    take_ref(take_ref), release_ref(release_ref), ref(ref)
-{
-}
-
-template <typename T>
-SdRef<T>::SdRef(const SdRef& other) :
-    SdRef(other.ref, other.take_ref, other.release_ref, other.sdevent)
-{
-}
-
-template <typename T>
-SdRef<T>& SdRef<T>::operator=(const SdRef& other)
-{
-    if (this != &other)
-    {
-        // release_ref will be invalid if moved
-        if (release_ref)
-        {
-            release_ref(sdevent, ref);
-        }
-
-        sdevent = other.sdevent;
-        take_ref = other.take_ref;
-        release_ref = other.release_ref;
-        ref = take_ref(sdevent, other.ref);
-    }
-    return *this;
-}
-
-template <typename T>
-SdRef<T>::SdRef(SdRef&& other) :
-    sdevent(std::move(other.sdevent)), take_ref(std::move(other.take_ref)),
-    release_ref(std::move(other.release_ref)), ref(std::move(other.ref))
-{
-    other.ref = nullptr;
-}
-
-template <typename T>
-SdRef<T>& SdRef<T>::operator=(SdRef&& other)
-{
-    if (this != &other)
-    {
-        // release_ref will be invalid if move
-        if (release_ref)
-        {
-            release_ref(sdevent, ref);
-        }
-
-        sdevent = std::move(other.sdevent);
-        take_ref = std::move(other.take_ref);
-        release_ref = std::move(other.release_ref);
-        ref = std::move(other.ref);
-        other.ref = nullptr;
-    }
-    return *this;
-}
-
-template <typename T>
-SdRef<T>::~SdRef()
-{
-    // release_ref will be invalid after a move
-    if (release_ref)
-        release_ref(sdevent, ref);
-}
-
-template <typename T>
-SdRef<T>::operator bool() const
-{
-    return ref != nullptr;
-}
-
-template <typename T>
-T* SdRef<T>::get() const
-{
-    return ref;
-}
-
-template class SdRef<sd_event>;
-template class SdRef<sd_event_source>;
-
-} // namespace internal
-} // namespace sdeventplus
diff --git a/src/sdeventplus/internal/sdref.hpp b/src/sdeventplus/internal/sdref.hpp
deleted file mode 100644
index a05eca2..0000000
--- a/src/sdeventplus/internal/sdref.hpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#pragma once
-
-#include <functional>
-#include <sdeventplus/internal/sdevent.hpp>
-#include <type_traits>
-
-namespace sdeventplus
-{
-namespace internal
-{
-
-/** @class SdRef
- *  @brief Takes and releases references to T objects
- *  @details Used primarily as an RAII wrapper around sd_event
- *           and sd_event_source object references.
- */
-template <typename T>
-class SdRef
-{
-  public:
-    /** @brief The type signature of ref / deref functions
-     */
-    using Func = std::function<T*(const SdEvent*, T*)>;
-
-    /** @brief Constructs a new reference holder
-     *         This constructor calls take_ref on ref
-     *
-     *  @param[in] ref         - Object which is referenced
-     *  @param[in] take_ref    - Function used to take references
-     *  @param[im] release_ref - Function used to release references
-     *  @param[in] sdevent     - Optional underlying sd_event implementation
-     */
-    SdRef(T* ref, Func take_ref, Func release_ref,
-          const SdEvent* sdevent = &sdevent_impl);
-
-    /** @brief Constructs a new reference holder
-     *         Does not take a new reference on the passed ref
-     *         NOTE: This will still take a reference during future copies
-     *         Useful for first creation of an object reference
-     *
-     *  @param[in] ref         - Object which is referenced
-     *  @param[in] take_ref    - Function used to take references
-     *  @param[im] release_ref - Function used to release references
-     *  @param[in]             - Denotes no reference taken during construction
-     *  @param[in] sdevent     - Optional underlying sd_event implementation
-     */
-    SdRef(T* ref, Func take_ref, Func release_ref, std::false_type,
-          const SdEvent* sdevent = &sdevent_impl);
-
-    virtual ~SdRef();
-    SdRef(const SdRef& other);
-    SdRef& operator=(const SdRef& other);
-    SdRef(SdRef&& other);
-    SdRef& operator=(SdRef&& other);
-
-    /** @brief Determines if a reference is currently being held
-     *
-     *  @return 'true' if a reference is held
-     *          'false' if empty
-     */
-    explicit operator bool() const;
-
-    /** @brief Get a pointer to the object being referenced
-     *
-     * @return The object pointer
-     */
-    T* get() const;
-
-  private:
-    const SdEvent* sdevent;
-    Func take_ref;
-    Func release_ref;
-    T* ref;
-};
-
-} // namespace internal
-} // namespace sdeventplus
diff --git a/src/sdeventplus/source/base.cpp b/src/sdeventplus/source/base.cpp
index 81ea591..55c2d10 100644
--- a/src/sdeventplus/source/base.cpp
+++ b/src/sdeventplus/source/base.cpp
@@ -20,7 +20,7 @@
 
 sd_event_source* Base::get() const
 {
-    return source.get();
+    return source.value();
 }
 
 const Event& Base::get_event() const
@@ -119,17 +119,13 @@
 }
 
 Base::Base(const Event& event, sd_event_source* source) :
-    event(event),
-    source(source, &internal::SdEvent::sd_event_source_ref,
-           &internal::SdEvent::sd_event_source_unref, event.getSdEvent())
+    event(event), source(source, event.getSdEvent())
 {
     set_userdata();
 }
 
 Base::Base(const Event& event, sd_event_source* source, std::false_type) :
-    event(event), source(source, &internal::SdEvent::sd_event_source_ref,
-                         &internal::SdEvent::sd_event_source_unref,
-                         std::false_type(), event.getSdEvent())
+    event(event), source(std::move(source), event.getSdEvent())
 {
     set_userdata();
 }
@@ -161,6 +157,17 @@
     return *this;
 }
 
+sd_event_source* Base::ref(sd_event_source* const& source,
+                           const internal::SdEvent*& sdevent)
+{
+    return sdevent->sd_event_source_ref(source);
+}
+
+void Base::drop(sd_event_source*&& source, const internal::SdEvent*& sdevent)
+{
+    sdevent->sd_event_source_unref(source);
+}
+
 int Base::prepareCallback(sd_event_source* source, void* userdata)
 {
     return sourceCallback<Callback, Base, &Base::get_prepare>("prepareCallback",
diff --git a/src/sdeventplus/source/base.hpp b/src/sdeventplus/source/base.hpp
index 33b37d7..c14ad7f 100644
--- a/src/sdeventplus/source/base.hpp
+++ b/src/sdeventplus/source/base.hpp
@@ -5,8 +5,8 @@
 #include <cstdio>
 #include <functional>
 #include <sdeventplus/event.hpp>
-#include <sdeventplus/internal/sdref.hpp>
 #include <sdeventplus/internal/utils.hpp>
+#include <stdplus/handle/copyable.hpp>
 #include <systemd/sd-bus.h>
 #include <type_traits>
 
@@ -112,7 +112,6 @@
 
   protected:
     Event event;
-    internal::SdRef<sd_event_source> source;
 
     /** @brief Constructs a basic event source wrapper
      *         Adds a reference to the source
@@ -175,6 +174,14 @@
     }
 
   private:
+    static sd_event_source* ref(sd_event_source* const& source,
+                                const internal::SdEvent*& sdevent);
+    static void drop(sd_event_source*&& source,
+                     const internal::SdEvent*& sdevent);
+
+    stdplus::Copyable<sd_event_source*, const internal::SdEvent*>::Handle<drop,
+                                                                          ref>
+        source;
     Callback prepare;
 
     /** @brief A helper used to make sure the userdata for the sd-event
diff --git a/test/Makefile.am b/test/Makefile.am
index e45b11f..76a82b8 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -21,11 +21,6 @@
 exception_CPPFLAGS = $(gtest_cppflags)
 exception_LDADD = $(gtest_ldadd)
 
-check_PROGRAMS += internal/sdref
-internal_sdref_SOURCES = internal/sdref.cpp
-internal_sdref_CPPFLAGS = $(gtest_cppflags)
-internal_sdref_LDADD = $(gtest_ldadd)
-
 check_PROGRAMS += internal/utils
 internal_utils_SOURCES = internal/utils.cpp
 internal_utils_CPPFLAGS = $(gtest_cppflags)
diff --git a/test/internal/sdref.cpp b/test/internal/sdref.cpp
deleted file mode 100644
index e8effa9..0000000
--- a/test/internal/sdref.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <sdeventplus/internal/sdref.hpp>
-#include <sdeventplus/test/sdevent.hpp>
-#include <systemd/sd-event.h>
-#include <type_traits>
-#include <utility>
-
-namespace sdeventplus
-{
-namespace internal
-{
-namespace
-{
-
-class SdRefTest : public testing::Test
-{
-  protected:
-    sd_event* const expected_event = reinterpret_cast<sd_event*>(1234);
-    sd_event* const expected_event2 = reinterpret_cast<sd_event*>(2345);
-    testing::StrictMock<test::SdEventMock> mock;
-    testing::StrictMock<test::SdEventMock> mock2;
-};
-
-TEST_F(SdRefTest, ConstructRef)
-{
-    EXPECT_CALL(mock, sd_event_ref(expected_event))
-        .WillOnce(testing::Return(expected_event));
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, ConstructNoRef)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, CopyConstruct)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-    EXPECT_CALL(mock, sd_event_ref(expected_event))
-        .WillOnce(testing::Return(expected_event));
-    SdRef<sd_event> event2(event);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .Times(2)
-        .WillRepeatedly(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, MoveConstruct)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-    SdRef<sd_event> event2(std::move(event));
-    EXPECT_FALSE(event);
-    EXPECT_EQ(nullptr, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, CopyAssignOverValid)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    SdRef<sd_event> event2(expected_event2, &SdEvent::sd_event_ref,
-                           &SdEvent::sd_event_unref, std::false_type(), &mock2);
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event2, event2.get());
-
-    EXPECT_CALL(mock2, sd_event_unref(expected_event2))
-        .WillOnce(testing::Return(nullptr));
-    EXPECT_CALL(mock, sd_event_ref(expected_event))
-        .WillOnce(testing::Return(expected_event));
-    event2 = event;
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .Times(2)
-        .WillRepeatedly(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, CopyAssignOverMoved)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    SdRef<sd_event> event2(expected_event2, &SdEvent::sd_event_ref,
-                           &SdEvent::sd_event_unref, std::false_type(), &mock2);
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event2, event2.get());
-    {
-        SdRef<sd_event> event_mover(std::move(event2));
-        EXPECT_FALSE(event2);
-        EXPECT_EQ(nullptr, event2.get());
-        EXPECT_TRUE(event_mover);
-        EXPECT_EQ(expected_event2, event_mover.get());
-
-        EXPECT_CALL(mock2, sd_event_unref(expected_event2))
-            .WillOnce(testing::Return(nullptr));
-    }
-
-    EXPECT_CALL(mock, sd_event_ref(expected_event))
-        .WillOnce(testing::Return(expected_event));
-    event2 = event;
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .Times(2)
-        .WillRepeatedly(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, CopySelf)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-    event = event;
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, MoveAssignOverValid)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    SdRef<sd_event> event2(expected_event2, &SdEvent::sd_event_ref,
-                           &SdEvent::sd_event_unref, std::false_type(), &mock2);
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event2, event2.get());
-
-    EXPECT_CALL(mock2, sd_event_unref(expected_event2))
-        .WillOnce(testing::Return(nullptr));
-    event2 = std::move(event);
-    EXPECT_FALSE(event);
-    EXPECT_EQ(nullptr, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, MoveAssignOverMoved)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_EQ(expected_event, event.get());
-    SdRef<sd_event> event2(expected_event2, &SdEvent::sd_event_ref,
-                           &SdEvent::sd_event_unref, std::false_type(), &mock2);
-    EXPECT_EQ(expected_event2, event2.get());
-    {
-        SdRef<sd_event> event_mover(std::move(event2));
-        EXPECT_FALSE(event2);
-        EXPECT_EQ(nullptr, event2.get());
-        EXPECT_TRUE(event_mover);
-        EXPECT_EQ(expected_event2, event_mover.get());
-
-        EXPECT_CALL(mock2, sd_event_unref(expected_event2))
-            .WillOnce(testing::Return(nullptr));
-    }
-
-    event2 = std::move(event);
-    EXPECT_FALSE(event);
-    EXPECT_EQ(nullptr, event.get());
-    EXPECT_TRUE(event2);
-    EXPECT_EQ(expected_event, event2.get());
-
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-TEST_F(SdRefTest, MoveSelf)
-{
-    SdRef<sd_event> event(expected_event, &SdEvent::sd_event_ref,
-                          &SdEvent::sd_event_unref, std::false_type(), &mock);
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wself-move"
-#endif
-    event = std::move(event);
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-    EXPECT_TRUE(event);
-    EXPECT_EQ(expected_event, event.get());
-    EXPECT_CALL(mock, sd_event_unref(expected_event))
-        .WillOnce(testing::Return(nullptr));
-}
-
-} // namespace
-} // namespace internal
-} // namespace sdeventplus
diff --git a/test/meson.build b/test/meson.build
index d894a3f..8fa22a7 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -5,7 +5,6 @@
   'clock',
   'event',
   'exception',
-  'internal/sdref',
   'internal/utils',
   'source/base',
   'source/child',
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 75a6dde..2139dd0 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -2,6 +2,7 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <memory>
+#include <optional>
 #include <sdeventplus/event.hpp>
 #include <sdeventplus/exception.hpp>
 #include <sdeventplus/internal/sdevent.hpp>
@@ -93,8 +94,8 @@
             .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
         BaseImpl mover(std::move(other));
         EXPECT_EQ(&mover, userdata);
-        EXPECT_EQ(nullptr, other.get());
-        EXPECT_EQ(nullptr, other.get_event().get());
+        EXPECT_THROW(other.get(), std::bad_optional_access);
+        EXPECT_THROW(other.get_event().get(), std::bad_optional_access);
         EXPECT_FALSE(other.get_prepare());
 
         expect_base_destruct(mover.get_event(), mover.get());
@@ -160,8 +161,8 @@
         .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
     BaseImpl source2(std::move(*source1));
     EXPECT_EQ(&source2, userdata);
-    EXPECT_EQ(nullptr, source1->get());
-    EXPECT_EQ(nullptr, source1->get_event().get());
+    EXPECT_THROW(source1->get(), std::bad_optional_access);
+    EXPECT_THROW(source1->get_event().get(), std::bad_optional_access);
     EXPECT_FALSE(source1->get_prepare());
     EXPECT_EQ(expected_source, source2.get());
     EXPECT_EQ(expected_event, source2.get_event().get());
@@ -199,8 +200,8 @@
         *source2 = std::move(*source1);
         EXPECT_EQ(source2.get(), userdata);
     }
-    EXPECT_EQ(nullptr, source1->get());
-    EXPECT_EQ(nullptr, source1->get_event().get());
+    EXPECT_THROW(source1->get(), std::bad_optional_access);
+    EXPECT_THROW(source1->get_event().get(), std::bad_optional_access);
     EXPECT_FALSE(source1->get_prepare());
     EXPECT_EQ(expected_source, source2->get());
     EXPECT_EQ(expected_event, source2->get_event().get());
@@ -232,8 +233,8 @@
         *source2 = std::move(*source1);
         EXPECT_EQ(source2.get(), userdata);
     }
-    EXPECT_EQ(nullptr, source1->get());
-    EXPECT_EQ(nullptr, source1->get_event().get());
+    EXPECT_THROW(source1->get(), std::bad_optional_access);
+    EXPECT_THROW(source1->get_event().get(), std::bad_optional_access);
     EXPECT_FALSE(source1->get_prepare());
     EXPECT_EQ(expected_source, source2->get());
     EXPECT_EQ(expected_event, source2->get_event().get());