source/*: Implement heap based userdata

This makes no immediate change to the external interface, but it will
enable us to do things like making copies of the event sources and
support for floating event source types.

Change-Id: Ida73e773eb0869f6f6f21c1e03c61e9ce2b5625c
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 27e5bc3..3673e24 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -1,4 +1,5 @@
 #include <cerrno>
+#include <functional>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <memory>
@@ -8,8 +9,10 @@
 #include <sdeventplus/internal/sdevent.hpp>
 #include <sdeventplus/source/base.hpp>
 #include <sdeventplus/test/sdevent.hpp>
+#include <sdeventplus/types.hpp>
 #include <string>
 #include <systemd/sd-event.h>
+#include <tuple>
 #include <type_traits>
 #include <utility>
 
@@ -27,24 +30,48 @@
 
 using UniqueEvent = std::unique_ptr<Event, std::function<void(Event*)>>;
 
+class BaseImplData;
+
 class BaseImpl : public Base
 {
   public:
-    BaseImpl(const Event& event, sd_event_source* source, std::false_type) :
-        Base(event, source, std::false_type())
+    BaseImpl(const Event& event, sd_event_source* source, std::false_type);
+
+    BaseImpl(const BaseImpl& other, sdeventplus::internal::NoOwn) :
+        Base(other, sdeventplus::internal::NoOwn())
     {
     }
 
     using Base::get_prepare;
 };
 
+class BaseImplData : public BaseImpl, public detail::BaseData
+{
+  public:
+    BaseImplData(const BaseImpl& base) :
+        BaseImpl(base, sdeventplus::internal::NoOwn()), BaseData(base)
+    {
+    }
+};
+
+BaseImpl::BaseImpl(const Event& event, sd_event_source* source,
+                   std::false_type) :
+    Base(event, source, std::false_type())
+{
+    set_userdata(std::make_unique<BaseImplData>(*this));
+}
+
 class BaseTest : public testing::Test
 {
   protected:
     testing::StrictMock<test::SdEventMock> mock;
     sd_event_source* const expected_source =
         reinterpret_cast<sd_event_source*>(1234);
+    sd_event_source* const expected_source2 =
+        reinterpret_cast<sd_event_source*>(3456);
     sd_event* const expected_event = reinterpret_cast<sd_event*>(2345);
+    sd_event* const expected_event2 = reinterpret_cast<sd_event*>(4567);
+
     UniqueEvent event = make_event(expected_event);
 
     UniqueEvent make_event(sd_event* event)
@@ -59,21 +86,30 @@
 
     // Using a unique_ptr to make sure we don't get any superfluous moves or
     // copies.
-    std::unique_ptr<BaseImpl> make_base(const Event& event,
-                                        sd_event_source* source)
+    std::tuple<std::unique_ptr<BaseImpl>, std::function<void()>>
+        make_base(const Event& event, sd_event_source* source)
     {
         EXPECT_CALL(mock, sd_event_ref(event.get()))
             .WillOnce(Return(event.get()));
+        sd_event_destroy_t destroy;
         void* userdata;
-        EXPECT_CALL(mock, sd_event_source_set_userdata(source, testing::_))
-            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        {
+            testing::InSequence seq;
+            EXPECT_CALL(
+                mock, sd_event_source_set_destroy_callback(source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+            EXPECT_CALL(mock, sd_event_source_set_userdata(source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        }
         auto ret = std::make_unique<BaseImpl>(event, source, std::false_type());
-        EXPECT_EQ(ret.get(), userdata);
+        EXPECT_CALL(mock, sd_event_source_get_userdata(source))
+            .WillRepeatedly(Return(userdata));
+        EXPECT_NE(ret.get(), userdata);
         EXPECT_EQ(source, ret->get());
         EXPECT_NE(&event, &ret->get_event());
         EXPECT_EQ(event.get(), ret->get_event().get());
         EXPECT_FALSE(ret->get_prepare());
-        return ret;
+        return {std::move(ret), std::bind(destroy, userdata)};
     }
 
     void set_prepare_placeholder(BaseImpl& base)
@@ -86,152 +122,107 @@
 
     void empty_base(BaseImpl&& other)
     {
-        void* userdata;
-        EXPECT_CALL(mock, sd_event_source_set_userdata(other.get(), testing::_))
-            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
         BaseImpl mover(std::move(other));
-        EXPECT_EQ(&mover, userdata);
         EXPECT_THROW(other.get(), std::bad_optional_access);
         EXPECT_THROW(other.get_event().get(), std::bad_optional_access);
-        EXPECT_FALSE(other.get_prepare());
+        EXPECT_THROW(other.get_prepare(), std::bad_optional_access);
 
         expect_base_destruct(mover.get_event(), mover.get());
     }
 
     void expect_base_destruct(const Event& event, sd_event_source* source)
     {
-        {
-            testing::InSequence seq;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(source, SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(event.get()))
             .WillOnce(Return(nullptr));
     }
 };
 
+TEST_F(BaseTest, NewBaseFail)
+{
+    EXPECT_CALL(mock, sd_event_ref(expected_event))
+        .WillOnce(Return(expected_event));
+    EXPECT_CALL(
+        mock, sd_event_source_set_destroy_callback(expected_source, testing::_))
+        .WillOnce(Return(-EINVAL));
+    expect_base_destruct(*event, expected_source);
+    EXPECT_THROW(BaseImpl(*event, expected_source, std::false_type()),
+                 SdEventError);
+}
+
 TEST_F(BaseTest, NewBaseNoRef)
 {
     EXPECT_CALL(mock, sd_event_ref(expected_event))
         .WillOnce(Return(expected_event));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    }
     BaseImpl source(*event, expected_source, std::false_type());
-    EXPECT_EQ(&source, userdata);
+    EXPECT_NE(&source, userdata);
     EXPECT_EQ(expected_source, source.get());
     EXPECT_NE(event.get(), &source.get_event());
     EXPECT_EQ(expected_event, source.get_event().get());
+
+    EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+        .WillOnce(Return(userdata));
     EXPECT_FALSE(source.get_prepare());
 
     expect_base_destruct(*event, expected_source);
+    destroy(userdata);
 }
 
-TEST_F(BaseTest, MoveConstruct)
+TEST_F(BaseTest, UserdataOutlives)
 {
-    std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
-    set_prepare_placeholder(*source1);
-
+    EXPECT_CALL(mock, sd_event_ref(expected_event))
+        .WillOnce(Return(expected_event));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
-    BaseImpl source2(std::move(*source1));
-    EXPECT_EQ(&source2, userdata);
-    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());
-    EXPECT_TRUE(source2.get_prepare());
-
-    expect_base_destruct(*event, expected_source);
-}
-
-TEST_F(BaseTest, MoveAssignSelf)
-{
-    std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
-    set_prepare_placeholder(*source1);
-
-    *source1 = std::move(*source1);
-    EXPECT_EQ(expected_source, source1->get());
-    EXPECT_EQ(expected_event, source1->get_event().get());
-    EXPECT_TRUE(source1->get_prepare());
-
-    expect_base_destruct(*event, expected_source);
-}
-
-TEST_F(BaseTest, MoveAssignEmpty)
-{
-    std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
-    set_prepare_placeholder(*source1);
-
-    std::unique_ptr<BaseImpl> source2 = make_base(*event, expected_source);
-    empty_base(std::move(*source2));
-
     {
-        void* userdata;
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
         EXPECT_CALL(mock,
                     sd_event_source_set_userdata(expected_source, testing::_))
             .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
-        *source2 = std::move(*source1);
-        EXPECT_EQ(source2.get(), userdata);
     }
-    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());
-    EXPECT_TRUE(source2->get_prepare());
+    auto source =
+        std::make_unique<BaseImpl>(*event, expected_source, std::false_type());
+    EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+        .WillRepeatedly(Return(userdata));
+    EXPECT_FALSE(source->get_prepare());
 
-    // Make sure source1 is deleted to ensure it isn't holding a reference
-    source1.reset();
     expect_base_destruct(*event, expected_source);
-}
-
-TEST_F(BaseTest, MoveAssignExisting)
-{
-    sd_event_source* const expected_source2 =
-        reinterpret_cast<sd_event_source*>(3456);
-    sd_event* const expected_event2 = reinterpret_cast<sd_event*>(4567);
-
-    std::unique_ptr<BaseImpl> source1 = make_base(*event, expected_source);
-    set_prepare_placeholder(*source1);
-
-    UniqueEvent event2 = make_event(expected_event2);
-    std::unique_ptr<BaseImpl> source2 = make_base(*event2, expected_source2);
-
-    {
-        expect_base_destruct(*event2, expected_source2);
-        void* userdata;
-        EXPECT_CALL(mock,
-                    sd_event_source_set_userdata(expected_source, testing::_))
-            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
-        *source2 = std::move(*source1);
-        EXPECT_EQ(source2.get(), userdata);
-    }
-    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());
-    EXPECT_TRUE(source2->get_prepare());
-
-    // Make sure source1 is deleted to ensure it isn't holding a reference
-    source1.reset();
-    expect_base_destruct(*event, expected_source);
+    source.reset();
+    EXPECT_FALSE(reinterpret_cast<BaseImpl*>(userdata)->get_prepare());
+    destroy(userdata);
 }
 
 class BaseMethodTest : public BaseTest
 {
   protected:
-    std::unique_ptr<BaseImpl> base = make_base(*event, expected_source);
+    std::unique_ptr<BaseImpl> base;
+    std::function<void()> destroy;
+
+    void SetUp()
+    {
+        std::tie(base, destroy) = make_base(*event, expected_source);
+    }
 
     void TearDown()
     {
         expect_base_destruct(base->get_event(), base->get());
         base.reset();
+        destroy();
     }
 };
 
diff --git a/test/source/child.cpp b/test/source/child.cpp
index ab173b1..5dc06b9 100644
--- a/test/source/child.cpp
+++ b/test/source/child.cpp
@@ -21,6 +21,7 @@
 
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 
@@ -47,14 +48,8 @@
 
     void expect_destruct()
     {
-        {
-            testing::InSequence sequence;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
-                                                          SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(expected_event))
             .WillOnce(Return(nullptr));
     }
@@ -72,9 +67,19 @@
                                          options, testing::_, nullptr))
         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
                         Return(0)));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     int completions = 0;
     const siginfo_t* return_si;
     Child::Callback callback = [&](Child&, const siginfo_t* si) {
@@ -83,19 +88,20 @@
     };
     Child child(*event, pid, options, std::move(callback));
     EXPECT_FALSE(callback);
-    EXPECT_EQ(&child, userdata);
+    EXPECT_NE(&child, userdata);
     EXPECT_EQ(0, completions);
 
     const siginfo_t* expected_si = reinterpret_cast<siginfo_t*>(865);
-    EXPECT_EQ(0, handler(nullptr, expected_si, &child));
+    EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
     EXPECT_EQ(1, completions);
     EXPECT_EQ(expected_si, return_si);
 
     child.set_callback(std::bind([]() {}));
-    EXPECT_EQ(0, handler(nullptr, expected_si, &child));
+    EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(ChildTest, ConstructError)
@@ -120,6 +126,8 @@
 {
   protected:
     std::unique_ptr<Child> child;
+    sd_event_destroy_t destroy;
+    void* userdata;
 
     void SetUp()
     {
@@ -131,9 +139,17 @@
         EXPECT_CALL(mock, sd_event_add_child(expected_event, testing::_, pid,
                                              options, testing::_, nullptr))
             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
-        EXPECT_CALL(mock,
-                    sd_event_source_set_userdata(expected_source, testing::_))
-            .WillOnce(Return(nullptr));
+        {
+            testing::InSequence seq;
+            EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
+                                  expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+            EXPECT_CALL(
+                mock, sd_event_source_set_userdata(expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+            EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+                .WillRepeatedly(ReturnPointee(&userdata));
+        }
         child = std::make_unique<Child>(*event, pid, options,
                                         [](Child&, const siginfo_t*) {});
     }
@@ -142,6 +158,7 @@
     {
         expect_destruct();
         child.reset();
+        destroy(userdata);
     }
 };
 
diff --git a/test/source/event.cpp b/test/source/event.cpp
index e4d7b2a..1d5a877 100644
--- a/test/source/event.cpp
+++ b/test/source/event.cpp
@@ -20,6 +20,7 @@
 
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 
@@ -46,14 +47,8 @@
 
     void expect_destruct()
     {
-        {
-            testing::InSequence sequence;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
-                                                          SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(expected_event))
             .WillOnce(Return(nullptr));
     }
@@ -63,9 +58,19 @@
 {
     EXPECT_CALL(mock, sd_event_ref(expected_event))
         .WillOnce(Return(expected_event));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     sd_event_handler_t handler;
     EXPECT_CALL(mock, sd_event_add_defer(expected_event, testing::_, testing::_,
                                          nullptr))
@@ -76,27 +81,38 @@
         completions++;
     };
     Defer defer(*event, std::move(callback));
-    EXPECT_EQ(&defer, userdata);
+    EXPECT_NE(&defer, userdata);
     EXPECT_FALSE(callback);
     EXPECT_EQ(0, completions);
 
-    EXPECT_EQ(0, handler(nullptr, &defer));
+    EXPECT_EQ(0, handler(nullptr, userdata));
     EXPECT_EQ(1, completions);
 
     defer.set_callback(std::bind([]() {}));
-    EXPECT_EQ(0, handler(nullptr, &defer));
+    EXPECT_EQ(0, handler(nullptr, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(EventTest, PostConstruct)
 {
     EXPECT_CALL(mock, sd_event_ref(expected_event))
         .WillOnce(Return(expected_event));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     sd_event_handler_t handler;
     EXPECT_CALL(mock, sd_event_add_post(expected_event, testing::_, testing::_,
                                         nullptr))
@@ -107,23 +123,34 @@
         completions++;
     };
     Post post(*event, std::move(callback));
-    EXPECT_EQ(&post, userdata);
+    EXPECT_NE(&post, userdata);
     EXPECT_FALSE(callback);
     EXPECT_EQ(0, completions);
 
-    EXPECT_EQ(0, handler(nullptr, &post));
+    EXPECT_EQ(0, handler(nullptr, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(EventTest, ExitConstruct)
 {
     EXPECT_CALL(mock, sd_event_ref(expected_event))
         .WillOnce(Return(expected_event));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     sd_event_handler_t handler;
     EXPECT_CALL(mock, sd_event_add_exit(expected_event, testing::_, testing::_,
                                         nullptr))
@@ -134,14 +161,15 @@
         completions++;
     };
     Exit exit(*event, std::move(callback));
-    EXPECT_EQ(&exit, userdata);
+    EXPECT_NE(&exit, userdata);
     EXPECT_FALSE(callback);
     EXPECT_EQ(0, completions);
 
-    EXPECT_EQ(0, handler(nullptr, &exit));
+    EXPECT_EQ(0, handler(nullptr, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(EventTest, ConstructFailure)
diff --git a/test/source/io.cpp b/test/source/io.cpp
index 89506b1..bafdeb8 100644
--- a/test/source/io.cpp
+++ b/test/source/io.cpp
@@ -20,6 +20,7 @@
 
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 
@@ -46,14 +47,8 @@
 
     void expect_destruct()
     {
-        {
-            testing::InSequence sequence;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
-                                                          SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(expected_event))
             .WillOnce(Return(nullptr));
     }
@@ -71,9 +66,19 @@
                                       testing::_, nullptr))
         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<4>(&handler),
                         Return(0)));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     int completions = 0;
     int return_fd;
     uint32_t return_revents;
@@ -84,19 +89,20 @@
     };
     IO io(*event, fd, events, std::move(callback));
     EXPECT_FALSE(callback);
-    EXPECT_EQ(&io, userdata);
+    EXPECT_NE(&io, userdata);
     EXPECT_EQ(0, completions);
 
-    EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, &io));
+    EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, userdata));
     EXPECT_EQ(1, completions);
     EXPECT_EQ(5, return_fd);
     EXPECT_EQ(EPOLLIN, return_revents);
 
     io.set_callback(std::bind([]() {}));
-    EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, &io));
+    EXPECT_EQ(0, handler(nullptr, 5, EPOLLIN, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(IOTest, ConstructError)
@@ -120,6 +126,8 @@
 {
   protected:
     std::unique_ptr<IO> io;
+    sd_event_destroy_t destroy;
+    void* userdata;
 
     void SetUp()
     {
@@ -131,9 +139,17 @@
         EXPECT_CALL(mock, sd_event_add_io(expected_event, testing::_, fd,
                                           events, testing::_, nullptr))
             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
-        EXPECT_CALL(mock,
-                    sd_event_source_set_userdata(expected_source, testing::_))
-            .WillOnce(Return(nullptr));
+        {
+            testing::InSequence seq;
+            EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
+                                  expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+            EXPECT_CALL(
+                mock, sd_event_source_set_userdata(expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+            EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+                .WillRepeatedly(ReturnPointee(&userdata));
+        }
         io =
             std::make_unique<IO>(*event, fd, events, [](IO&, int, uint32_t) {});
     }
@@ -142,6 +158,7 @@
     {
         expect_destruct();
         io.reset();
+        destroy(userdata);
     }
 };
 
diff --git a/test/source/signal.cpp b/test/source/signal.cpp
index d3b53a7..209f2a7 100644
--- a/test/source/signal.cpp
+++ b/test/source/signal.cpp
@@ -21,6 +21,7 @@
 
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 
@@ -47,14 +48,8 @@
 
     void expect_destruct()
     {
-        {
-            testing::InSequence sequence;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source,
-                                                          SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(expected_source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(expected_event))
             .WillOnce(Return(nullptr));
     }
@@ -71,9 +66,19 @@
                                           testing::_, nullptr))
         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<3>(&handler),
                         Return(0)));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     int completions = 0;
     const struct signalfd_siginfo* return_si;
     Signal::Callback callback = [&](Signal&,
@@ -83,20 +88,21 @@
     };
     Signal signal(*event, sig, std::move(callback));
     EXPECT_FALSE(callback);
-    EXPECT_EQ(&signal, userdata);
+    EXPECT_NE(&signal, userdata);
     EXPECT_EQ(0, completions);
 
     const struct signalfd_siginfo* expected_si =
         reinterpret_cast<struct signalfd_siginfo*>(865);
-    EXPECT_EQ(0, handler(nullptr, expected_si, &signal));
+    EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
     EXPECT_EQ(1, completions);
     EXPECT_EQ(expected_si, return_si);
 
     signal.set_callback(std::bind([]() {}));
-    EXPECT_EQ(0, handler(nullptr, expected_si, &signal));
+    EXPECT_EQ(0, handler(nullptr, expected_si, userdata));
     EXPECT_EQ(1, completions);
 
     expect_destruct();
+    destroy(userdata);
 }
 
 TEST_F(SignalTest, ConstructError)
@@ -120,6 +126,8 @@
 {
   protected:
     std::unique_ptr<Signal> signal;
+    sd_event_destroy_t destroy;
+    void* userdata;
 
     void SetUp()
     {
@@ -130,9 +138,17 @@
         EXPECT_CALL(mock, sd_event_add_signal(expected_event, testing::_, sig,
                                               testing::_, nullptr))
             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
-        EXPECT_CALL(mock,
-                    sd_event_source_set_userdata(expected_source, testing::_))
-            .WillOnce(Return(nullptr));
+        {
+            testing::InSequence seq;
+            EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
+                                  expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+            EXPECT_CALL(
+                mock, sd_event_source_set_userdata(expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+            EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+                .WillRepeatedly(ReturnPointee(&userdata));
+        }
         signal = std::make_unique<Signal>(
             *event, sig, [](Signal&, const struct signalfd_siginfo*) {});
     }
@@ -141,6 +157,7 @@
     {
         expect_destruct();
         signal.reset();
+        destroy(userdata);
     }
 };
 
diff --git a/test/source/time.cpp b/test/source/time.cpp
index 96a920e..569d2c0 100644
--- a/test/source/time.cpp
+++ b/test/source/time.cpp
@@ -21,6 +21,7 @@
 
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 
@@ -47,13 +48,8 @@
 
     void expect_time_destroy(sd_event* event, sd_event_source* source)
     {
-        {
-            testing::InSequence sequence;
-            EXPECT_CALL(mock, sd_event_source_set_enabled(source, SD_EVENT_OFF))
-                .WillOnce(Return(0));
-            EXPECT_CALL(mock, sd_event_source_unref(source))
-                .WillOnce(Return(nullptr));
-        }
+        EXPECT_CALL(mock, sd_event_source_unref(source))
+            .WillOnce(Return(nullptr));
         EXPECT_CALL(mock, sd_event_unref(event)).WillOnce(Return(nullptr));
     }
 };
@@ -77,12 +73,23 @@
                                   2000000, 50000, testing::_, nullptr))
         .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<5>(&handler),
                         Return(0)));
+    sd_event_destroy_t destroy;
     void* userdata;
-    EXPECT_CALL(mock, sd_event_source_set_userdata(expected_source, testing::_))
-        .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+    {
+        testing::InSequence seq;
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+        EXPECT_CALL(mock,
+                    sd_event_source_set_userdata(expected_source, testing::_))
+            .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&userdata));
+    }
     Time<id> time(*event, expected_time, expected_accuracy,
                   std::move(callback));
     EXPECT_FALSE(callback);
+    EXPECT_NE(&time, userdata);
     EXPECT_EQ(expected_event, time.get_event().get());
     EXPECT_EQ(expected_source, time.get());
 
@@ -96,6 +103,7 @@
               saved_time);
 
     expect_time_destroy(expected_event, expected_source);
+    destroy(userdata);
 }
 
 TEST_F(TimeTest, ConstructError)
@@ -120,6 +128,8 @@
   protected:
     static constexpr ClockId id = ClockId::BootTime;
     std::unique_ptr<Time<id>> time;
+    sd_event_destroy_t destroy;
+    void* userdata;
 
     void SetUp()
     {
@@ -129,9 +139,17 @@
                                             CLOCK_BOOTTIME, 2000000, 50000,
                                             testing::_, nullptr))
             .WillOnce(DoAll(SetArgPointee<1>(expected_source), Return(0)));
-        EXPECT_CALL(mock,
-                    sd_event_source_set_userdata(expected_source, testing::_))
-            .WillOnce(Return(nullptr));
+        {
+            testing::InSequence seq;
+            EXPECT_CALL(mock, sd_event_source_set_destroy_callback(
+                                  expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&destroy), Return(0)));
+            EXPECT_CALL(
+                mock, sd_event_source_set_userdata(expected_source, testing::_))
+                .WillOnce(DoAll(SaveArg<1>(&userdata), Return(nullptr)));
+            EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+                .WillRepeatedly(ReturnPointee(&userdata));
+        }
         time = std::make_unique<Time<id>>(
             *event, Time<id>::TimePoint(std::chrono::seconds{2}),
             std::chrono::milliseconds{50},
@@ -142,6 +160,7 @@
     {
         expect_time_destroy(expected_event, expected_source);
         time.reset();
+        destroy(userdata);
     }
 };
 
diff --git a/test/utility/timer.cpp b/test/utility/timer.cpp
index f35a0c4..70fda1b 100644
--- a/test/utility/timer.cpp
+++ b/test/utility/timer.cpp
@@ -23,6 +23,7 @@
 using std::chrono::milliseconds;
 using testing::DoAll;
 using testing::Return;
+using testing::ReturnPointee;
 using testing::SaveArg;
 using testing::SetArgPointee;
 using TestTimer = Timer<testClock>;
@@ -54,6 +55,7 @@
     const milliseconds starting_time2{30};
     sd_event_time_handler_t handler = nullptr;
     void* handler_userdata;
+    sd_event_destroy_t handler_destroy;
     std::unique_ptr<Event> event;
     std::unique_ptr<TestTimer> timer;
     std::function<void()> callback;
@@ -94,6 +96,7 @@
         {
             expectSetEnabled(source::Enabled::Off);
             timer.reset();
+            handler_destroy(handler_userdata);
         }
     }
 
@@ -116,10 +119,15 @@
         event = std::make_unique<Event>(expected_event, &mock);
         EXPECT_CALL(mock, sd_event_source_unref(expected_source))
             .WillRepeatedly(Return(nullptr));
+        EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source,
+                                                               testing::_))
+            .WillRepeatedly(DoAll(SaveArg<1>(&handler_destroy), Return(0)));
         EXPECT_CALL(mock,
                     sd_event_source_set_userdata(expected_source, testing::_))
             .WillRepeatedly(
                 DoAll(SaveArg<1>(&handler_userdata), Return(nullptr)));
+        EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source))
+            .WillRepeatedly(ReturnPointee(&handler_userdata));
 
         // Having a callback proxy allows us to update the test callback
         // dynamically, without changing it inside the timer
@@ -349,9 +357,16 @@
     callback = [&]() { ++called; };
 
     expectNow(starting_time2);
+    sd_event_destroy_t local_destroy;
+    EXPECT_CALL(mock, sd_event_source_set_destroy_callback(expected_source2,
+                                                           testing::_))
+        .WillOnce(DoAll(SaveArg<1>(&local_destroy), Return(0)));
+    void* local_userdata;
     EXPECT_CALL(mock,
                 sd_event_source_set_userdata(expected_source2, testing::_))
-        .WillOnce(Return(nullptr));
+        .WillOnce(DoAll(SaveArg<1>(&local_userdata), Return(nullptr)));
+    EXPECT_CALL(mock, sd_event_source_get_userdata(expected_source2))
+        .WillRepeatedly(ReturnPointee(&local_userdata));
     EXPECT_CALL(mock, sd_event_add_time(expected_event, testing::_,
                                         static_cast<clockid_t>(testClock),
                                         microseconds(starting_time2).count(),
@@ -368,6 +383,7 @@
 
     // Move assign
     local_timer = std::move(*timer);
+    local_destroy(local_userdata);
     timer.reset();
 
     // Move construct