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