source/*: Allow copies to be made
Sources are now just reference holders so we can copy them freely.
Change-Id: I263219de83341473c333a29cf651ae82428a208a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 3673e24..43e70ff 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -207,6 +207,37 @@
destroy(userdata);
}
+TEST_F(BaseTest, CopyCorrectness)
+{
+ std::unique_ptr<BaseImpl> base1, base2;
+ std::function<void()> destroy;
+ std::tie(base1, destroy) = make_base(*event, expected_source);
+ set_prepare_placeholder(*base1);
+ EXPECT_TRUE(base1->get_prepare());
+
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ base2 = std::make_unique<BaseImpl>(*base1);
+ EXPECT_EQ(&base1->get_prepare(), &base2->get_prepare());
+
+ empty_base(std::move(*base1));
+ EXPECT_THROW(base1->get_prepare(), std::bad_optional_access);
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *base1 = *base2;
+ EXPECT_EQ(&base1->get_prepare(), &base2->get_prepare());
+
+ expect_base_destruct(*event, expected_source);
+ base2.reset();
+ expect_base_destruct(*event, expected_source);
+ base1.reset();
+ destroy();
+}
+
class BaseMethodTest : public BaseTest
{
protected:
diff --git a/test/source/child.cpp b/test/source/child.cpp
index 5dc06b9..71a8789 100644
--- a/test/source/child.cpp
+++ b/test/source/child.cpp
@@ -162,6 +162,39 @@
}
};
+TEST_F(ChildMethodTest, Copy)
+{
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ auto child2 = std::make_unique<Child>(*child);
+ {
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ Child child3(*child);
+
+ expect_destruct();
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *child2 = child3;
+
+ expect_destruct();
+ }
+
+ // Delete the original child
+ child2.swap(child);
+ expect_destruct();
+ child2.reset();
+
+ // Make sure our new copy can still access data
+ child->set_callback(nullptr);
+}
+
TEST_F(ChildMethodTest, GetPidSuccess)
{
const pid_t pid = 32;
diff --git a/test/source/event.cpp b/test/source/event.cpp
index 1d5a877..0d86617 100644
--- a/test/source/event.cpp
+++ b/test/source/event.cpp
@@ -186,6 +186,63 @@
EXPECT_EQ(0, completions);
}
+TEST_F(EventTest, CopyConstruct)
+{
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ sd_event_destroy_t destroy;
+ 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)));
+ 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))
+ .WillOnce(DoAll(SetArgPointee<1>(expected_source), SaveArg<2>(&handler),
+ Return(0)));
+ auto exit = std::make_unique<Exit>(*event, [](EventBase&) {});
+
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ auto exit2 = std::make_unique<Exit>(*exit);
+ {
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ Exit exit3(*exit);
+
+ expect_destruct();
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *exit2 = exit3;
+
+ expect_destruct();
+ }
+
+ // Delete the original exit
+ expect_destruct();
+ exit.reset();
+
+ // Make sure our new copy can still access data
+ exit2->set_callback(nullptr);
+ expect_destruct();
+ exit2.reset();
+ destroy(userdata);
+}
+
} // namespace
} // namespace source
} // namespace sdeventplus
diff --git a/test/source/io.cpp b/test/source/io.cpp
index bafdeb8..e8abb82 100644
--- a/test/source/io.cpp
+++ b/test/source/io.cpp
@@ -162,6 +162,39 @@
}
};
+TEST_F(IOMethodTest, Copy)
+{
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ auto io2 = std::make_unique<IO>(*io);
+ {
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ IO io3(*io);
+
+ expect_destruct();
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *io2 = io3;
+
+ expect_destruct();
+ }
+
+ // Delete the original IO
+ io2.swap(io);
+ expect_destruct();
+ io2.reset();
+
+ // Make sure our new copy can still access data
+ io->set_callback(nullptr);
+}
+
TEST_F(IOMethodTest, GetFdSuccess)
{
const int fd = 5;
diff --git a/test/source/signal.cpp b/test/source/signal.cpp
index 209f2a7..9ac0f67 100644
--- a/test/source/signal.cpp
+++ b/test/source/signal.cpp
@@ -161,6 +161,39 @@
}
};
+TEST_F(SignalMethodTest, Copy)
+{
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ auto signal2 = std::make_unique<Signal>(*signal);
+ {
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ Signal signal3(*signal);
+
+ expect_destruct();
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *signal2 = signal3;
+
+ expect_destruct();
+ }
+
+ // Delete the original signal
+ signal2.swap(signal);
+ expect_destruct();
+ signal2.reset();
+
+ // Make sure our new copy can still access data
+ signal->set_callback(nullptr);
+}
+
TEST_F(SignalMethodTest, GetSignalSuccess)
{
const int sig = SIGTERM;
diff --git a/test/source/time.cpp b/test/source/time.cpp
index 569d2c0..01d4ae2 100644
--- a/test/source/time.cpp
+++ b/test/source/time.cpp
@@ -164,6 +164,39 @@
}
};
+TEST_F(TimeMethodTest, Copy)
+{
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ auto time2 = std::make_unique<Time<id>>(*time);
+ {
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ Time<id> time3(*time);
+
+ expect_time_destroy(expected_event, expected_source);
+ EXPECT_CALL(mock, sd_event_ref(expected_event))
+ .WillOnce(Return(expected_event));
+ EXPECT_CALL(mock, sd_event_source_ref(expected_source))
+ .WillOnce(Return(expected_source));
+ *time2 = time3;
+
+ expect_time_destroy(expected_event, expected_source);
+ }
+
+ // Delete the original time
+ time2.swap(time);
+ expect_time_destroy(expected_event, expected_source);
+ time2.reset();
+
+ // Make sure our new copy can still access data
+ time->set_callback(nullptr);
+}
+
TEST_F(TimeMethodTest, SetTimeSuccess)
{
EXPECT_CALL(mock, sd_event_source_set_time(expected_source, 1000000))