Initial Commit
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..7efd9b2
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,26 @@
+@VALGRIND_CHECK_RULES@
+@CODE_COVERAGE_RULES@
+
+AM_CPPFLAGS = -I$(top_builddir)/src -I$(top_srcdir)/src \
+              $(GTEST_CFLAGS) $(GMOCK_CFLAGS) $(SYSTEMD_CFLAGS) \
+              $(CODE_COVERAGE_CPPFLAGS)
+AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
+AM_CXXFLAGS = $(CODE_COVERAGE_CXXFLAGS)
+test_ldadd = $(top_builddir)/src/libsdeventplus.la $(SYSTEMD_LIBS) \
+             $(CODE_COVERAGE_LIBS)
+gtest_ldadd = $(test_ldadd) $(GTEST_LIBS) $(GMOCK_LIBS) -lgmock_main
+
+check_PROGRAMS =
+TESTS = $(check_PROGRAMS)
+
+check_PROGRAMS += event
+event_SOURCES = event.cpp
+event_LDADD = $(gtest_ldadd)
+
+check_PROGRAMS += exception
+exception_SOURCES = exception.cpp
+exception_LDADD = $(gtest_ldadd)
+
+check_PROGRAMS += sdref
+sdref_SOURCES = sdref.cpp
+sdref_LDADD = $(gtest_ldadd)
diff --git a/test/event.cpp b/test/event.cpp
new file mode 100644
index 0000000..da935cf
--- /dev/null
+++ b/test/event.cpp
@@ -0,0 +1,96 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sdeventplus/event.hpp>
+#include <sdeventplus/exception.hpp>
+#include <sdeventplus/test/sdevent.hpp>
+#include <type_traits>
+
+namespace sdeventplus
+{
+namespace
+{
+
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgPointee;
+
+class EventTest : public testing::Test
+{
+  protected:
+    testing::StrictMock<SdEventMock> mock;
+    sd_event *const expected_event = reinterpret_cast<sd_event *>(1234);
+};
+
+TEST_F(EventTest, NewEventRef)
+{
+    EXPECT_CALL(mock, sd_event_ref(expected_event))
+        .WillOnce(Return(expected_event));
+    Event event(expected_event, &mock);
+
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+}
+
+TEST_F(EventTest, NewEventNoRef)
+{
+    Event event(expected_event, std::false_type(), &mock);
+
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+}
+
+TEST_F(EventTest, GetNewEvent)
+{
+    EXPECT_CALL(mock, sd_event_new(testing::_))
+        .WillOnce(DoAll(SetArgPointee<0>(expected_event), Return(0)));
+    Event event = Event::get_new(&mock);
+
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+}
+
+TEST_F(EventTest, GetNewEventFail)
+{
+    EXPECT_CALL(mock, sd_event_new(testing::_)).WillOnce(Return(-EINVAL));
+    EXPECT_THROW(Event::get_new(&mock), SdEventError);
+}
+
+TEST_F(EventTest, GetDefaultEvent)
+{
+    EXPECT_CALL(mock, sd_event_default(testing::_))
+        .WillOnce(DoAll(SetArgPointee<0>(expected_event), Return(0)));
+    Event event = Event::get_default(&mock);
+
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+}
+
+TEST_F(EventTest, GetDefaultEventFail)
+{
+    EXPECT_CALL(mock, sd_event_default(testing::_)).WillOnce(Return(-EINVAL));
+    EXPECT_THROW(Event::get_default(&mock), SdEventError);
+}
+
+TEST_F(EventTest, LoopSuccess)
+{
+    EXPECT_CALL(mock, sd_event_loop(expected_event)).WillOnce(Return(0));
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+    EXPECT_EQ(0, Event(expected_event, std::false_type(), &mock).loop());
+}
+
+TEST_F(EventTest, LoopUserError)
+{
+    const int user_error = 10;
+    EXPECT_CALL(mock, sd_event_loop(expected_event))
+        .WillOnce(Return(user_error));
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+    EXPECT_EQ(user_error,
+              Event(expected_event, std::false_type(), &mock).loop());
+}
+
+TEST_F(EventTest, LoopInternalError)
+{
+    EXPECT_CALL(mock, sd_event_loop(expected_event)).WillOnce(Return(-EINVAL));
+    EXPECT_CALL(mock, sd_event_unref(expected_event)).WillOnce(Return(nullptr));
+    EXPECT_THROW(Event(expected_event, std::false_type(), &mock).loop(),
+                 SdEventError);
+}
+
+} // namespace
+} // namespace sdeventplus
diff --git a/test/exception.cpp b/test/exception.cpp
new file mode 100644
index 0000000..050513c
--- /dev/null
+++ b/test/exception.cpp
@@ -0,0 +1,25 @@
+#include <gtest/gtest.h>
+#include <sdeventplus/exception.hpp>
+#include <string>
+#include <system_error>
+
+namespace sdeventplus
+{
+namespace
+{
+
+TEST(ExceptionTest, Construct)
+{
+    const int code = EINTR;
+    const char *const prefix = "construct_test";
+
+    std::system_error expected(code, std::generic_category(), prefix);
+    SdEventError err(code, prefix);
+
+    EXPECT_EQ(std::string{expected.what()}, err.what());
+    EXPECT_EQ(code, err.code().value());
+    EXPECT_EQ(std::generic_category(), err.code().category());
+}
+
+} // namespace
+} // namespace sdeventplus
diff --git a/test/sdref.cpp b/test/sdref.cpp
new file mode 100644
index 0000000..6bb5410
--- /dev/null
+++ b/test/sdref.cpp
@@ -0,0 +1,198 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sdeventplus/sdevent.hpp>
+#include <sdeventplus/sdref.hpp>
+#include <sdeventplus/test/sdevent.hpp>
+#include <systemd/sd-event.h>
+#include <type_traits>
+#include <utility>
+
+namespace sdeventplus
+{
+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<SdEventMock> mock;
+    testing::StrictMock<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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, &mock);
+    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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    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_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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+
+    SdRef<sd_event> event2(std::move(event));
+    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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+    SdRef<sd_event> event2(expected_event2, &SdEventInterface::sd_event_ref,
+                           &SdEventInterface::sd_event_unref, std::false_type(),
+                           &mock2);
+    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_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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+    SdRef<sd_event> event2(expected_event2, &SdEventInterface::sd_event_ref,
+                           &SdEventInterface::sd_event_unref, std::false_type(),
+                           &mock2);
+    EXPECT_EQ(expected_event2, event2.get());
+    {
+        SdRef<sd_event> event_mover(std::move(event2));
+        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_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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+
+    event = event;
+    EXPECT_CALL(mock, sd_event_unref(expected_event))
+        .WillOnce(testing::Return(nullptr));
+}
+
+TEST_F(SdRefTest, MoveAssignOverValid)
+{
+    SdRef<sd_event> event(expected_event, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+    SdRef<sd_event> event2(expected_event2, &SdEventInterface::sd_event_ref,
+                           &SdEventInterface::sd_event_unref, std::false_type(),
+                           &mock2);
+    EXPECT_EQ(expected_event2, event2.get());
+
+    EXPECT_CALL(mock2, sd_event_unref(expected_event2))
+        .WillOnce(testing::Return(nullptr));
+    event2 = std::move(event);
+    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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+    SdRef<sd_event> event2(expected_event2, &SdEventInterface::sd_event_ref,
+                           &SdEventInterface::sd_event_unref, std::false_type(),
+                           &mock2);
+    EXPECT_EQ(expected_event2, event2.get());
+    {
+        SdRef<sd_event> event_mover(std::move(event2));
+        EXPECT_EQ(expected_event2, event_mover.get());
+
+        EXPECT_CALL(mock2, sd_event_unref(expected_event2))
+            .WillOnce(testing::Return(nullptr));
+    }
+
+    event2 = std::move(event);
+    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, &SdEventInterface::sd_event_ref,
+                          &SdEventInterface::sd_event_unref, std::false_type(),
+                          &mock);
+    EXPECT_EQ(expected_event, event.get());
+    event = std::move(event);
+    EXPECT_CALL(mock, sd_event_unref(expected_event))
+        .WillOnce(testing::Return(nullptr));
+}
+
+} // namespace
+} // namespace sdeventplus