source/base: Expose trivial built in methods
diff --git a/src/sdeventplus/internal/sdevent.hpp b/src/sdeventplus/internal/sdevent.hpp
index 7603a3d..e6c420c 100644
--- a/src/sdeventplus/internal/sdevent.hpp
+++ b/src/sdeventplus/internal/sdevent.hpp
@@ -25,6 +25,22 @@
         sd_event_source_ref(sd_event_source* source) const = 0;
     virtual sd_event_source*
         sd_event_source_unref(sd_event_source* source) const = 0;
+
+    virtual int
+        sd_event_source_get_description(sd_event_source* source,
+                                        const char** description) const = 0;
+    virtual int
+        sd_event_source_set_description(sd_event_source* source,
+                                        const char* description) const = 0;
+    virtual int sd_event_source_get_pending(sd_event_source* source) const = 0;
+    virtual int sd_event_source_get_priority(sd_event_source* source,
+                                             int64_t* priority) const = 0;
+    virtual int sd_event_source_set_priority(sd_event_source* source,
+                                             int64_t priority) const = 0;
+    virtual int sd_event_source_get_enabled(sd_event_source* source,
+                                            int* enabled) const = 0;
+    virtual int sd_event_source_set_enabled(sd_event_source* source,
+                                            int enabled) const = 0;
 };
 
 class SdEventImpl : public SdEvent
@@ -74,6 +90,41 @@
     {
         return ::sd_event_source_unref(source);
     }
+
+    int sd_event_source_get_description(sd_event_source* source,
+                                        const char** description) const override
+    {
+        return ::sd_event_source_get_description(source, description);
+    }
+    int sd_event_source_set_description(sd_event_source* source,
+                                        const char* description) const override
+    {
+        return ::sd_event_source_set_description(source, description);
+    }
+    int sd_event_source_get_pending(sd_event_source* source) const override
+    {
+        return ::sd_event_source_get_pending(source);
+    }
+    int sd_event_source_get_priority(sd_event_source* source,
+                                     int64_t* priority) const override
+    {
+        return ::sd_event_source_get_priority(source, priority);
+    }
+    int sd_event_source_set_priority(sd_event_source* source,
+                                     int64_t priority) const override
+    {
+        return ::sd_event_source_set_priority(source, priority);
+    }
+    int sd_event_source_get_enabled(sd_event_source* source,
+                                    int* enabled) const override
+    {
+        return ::sd_event_source_get_enabled(source, enabled);
+    }
+    int sd_event_source_set_enabled(sd_event_source* source,
+                                    int enabled) const override
+    {
+        return ::sd_event_source_set_enabled(source, enabled);
+    }
 };
 
 extern SdEventImpl sdevent_impl;
diff --git a/src/sdeventplus/source/base.cpp b/src/sdeventplus/source/base.cpp
index fd9b45f..d99d562 100644
--- a/src/sdeventplus/source/base.cpp
+++ b/src/sdeventplus/source/base.cpp
@@ -1,12 +1,93 @@
+#include <cerrno>
+#include <exception>
+#include <sdeventplus/exception.hpp>
 #include <sdeventplus/internal/sdevent.hpp>
 #include <sdeventplus/source/base.hpp>
+#include <stdexcept>
 #include <type_traits>
+#include <utility>
 
 namespace sdeventplus
 {
 namespace source
 {
 
+Base::~Base()
+{
+    set_enabled(SD_EVENT_OFF);
+}
+
+const char* Base::get_description()
+{
+    const char* description;
+    int r =
+        sdevent->sd_event_source_get_description(source.get(), &description);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_get_description");
+    }
+    return description;
+}
+
+void Base::set_description(const char* description)
+{
+    int r = sdevent->sd_event_source_set_description(source.get(), description);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_set_description");
+    }
+}
+
+int Base::get_pending()
+{
+    int r = sdevent->sd_event_source_get_pending(source.get());
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_get_pending");
+    }
+    return r;
+}
+
+int64_t Base::get_priority()
+{
+    int64_t priority;
+    int r = sdevent->sd_event_source_get_priority(source.get(), &priority);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_get_priority");
+    }
+    return priority;
+}
+
+void Base::set_priority(int64_t priority)
+{
+    int r = sdevent->sd_event_source_set_priority(source.get(), priority);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_set_priority");
+    }
+}
+
+int Base::get_enabled()
+{
+    int enabled;
+    int r = sdevent->sd_event_source_get_enabled(source.get(), &enabled);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_get_enabled");
+    }
+    return enabled;
+}
+
+void Base::set_enabled(int enabled)
+{
+    int r = sdevent->sd_event_source_set_enabled(source.get(), enabled);
+    if (r < 0)
+    {
+        throw SdEventError(-r, "sd_event_source_set_enabled");
+    }
+}
+
 Base::Base(sd_event_source* source, internal::SdEvent* sdevent) :
     sdevent(sdevent), source(source, &internal::SdEvent::sd_event_source_ref,
                              &internal::SdEvent::sd_event_source_unref, sdevent)
diff --git a/src/sdeventplus/source/base.hpp b/src/sdeventplus/source/base.hpp
index 88a17f0..20ab820 100644
--- a/src/sdeventplus/source/base.hpp
+++ b/src/sdeventplus/source/base.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include <cstdint>
 #include <sdeventplus/internal/sdevent.hpp>
 #include <sdeventplus/internal/sdref.hpp>
 #include <systemd/sd-bus.h>
@@ -13,15 +14,25 @@
 class Base
 {
   public:
+    virtual ~Base();
+
     // We don't want to allow any kind of slicing.
     Base(const Base& source) = delete;
     Base& operator=(const Base& source) = delete;
     Base(Base&& source) = delete;
     Base& operator=(Base&& source) = delete;
 
+    const char* get_description();
+    void set_description(const char* description);
+    int get_pending();
+    int64_t get_priority();
+    void set_priority(int64_t priority);
+    int get_enabled();
+    void set_enabled(int enabled);
+
   protected:
-    internal::SdEvent* sdevent;
-    internal::SdRef<sd_event_source> source;
+    const internal::SdEvent* const sdevent;
+    const internal::SdRef<sd_event_source> source;
 
     // Base sources cannot be directly constructed.
     Base(sd_event_source* source,
diff --git a/src/sdeventplus/test/sdevent.hpp b/src/sdeventplus/test/sdevent.hpp
index 982e4e7..1cb723f 100644
--- a/src/sdeventplus/test/sdevent.hpp
+++ b/src/sdeventplus/test/sdevent.hpp
@@ -24,6 +24,21 @@
     MOCK_CONST_METHOD1(sd_event_source_ref, sd_event_source*(sd_event_source*));
     MOCK_CONST_METHOD1(sd_event_source_unref,
                        sd_event_source*(sd_event_source*));
+
+    MOCK_CONST_METHOD2(sd_event_source_get_description,
+                       int(sd_event_source*, const char**));
+    MOCK_CONST_METHOD2(sd_event_source_set_description,
+                       int(sd_event_source*, const char*));
+    MOCK_CONST_METHOD2(sd_event_source_set_prepare,
+                       int(sd_event_source*, sd_event_handler_t));
+    MOCK_CONST_METHOD1(sd_event_source_get_pending, int(sd_event_source*));
+    MOCK_CONST_METHOD2(sd_event_source_get_priority,
+                       int(sd_event_source*, int64_t*));
+    MOCK_CONST_METHOD2(sd_event_source_set_priority,
+                       int(sd_event_source*, int64_t));
+    MOCK_CONST_METHOD2(sd_event_source_get_enabled,
+                       int(sd_event_source*, int*));
+    MOCK_CONST_METHOD2(sd_event_source_set_enabled, int(sd_event_source*, int));
 };
 
 } // namespace test
diff --git a/test/source/base.cpp b/test/source/base.cpp
index 3bf76c0..ce95f12 100644
--- a/test/source/base.cpp
+++ b/test/source/base.cpp
@@ -1,8 +1,10 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <sdeventplus/exception.hpp>
 #include <sdeventplus/internal/sdevent.hpp>
 #include <sdeventplus/source/base.hpp>
 #include <sdeventplus/test/sdevent.hpp>
+#include <string>
 #include <type_traits>
 
 namespace sdeventplus
@@ -12,7 +14,9 @@
 namespace
 {
 
+using testing::DoAll;
 using testing::Return;
+using testing::SetArgPointee;
 
 class BaseImpl : public Base
 {
@@ -42,16 +46,163 @@
         .WillOnce(Return(expected_source));
     BaseImpl source(expected_source, &mock);
 
-    EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-        .WillOnce(Return(nullptr));
+    {
+        testing::InSequence seq;
+        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));
+    }
 }
 
 TEST_F(BaseTest, NewBaseNoRef)
 {
     BaseImpl source(expected_source, std::false_type(), &mock);
 
-    EXPECT_CALL(mock, sd_event_source_unref(expected_source))
-        .WillOnce(Return(nullptr));
+    {
+        testing::InSequence seq;
+        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));
+    }
+}
+
+class BaseMethodTest : public BaseTest
+{
+  protected:
+    std::unique_ptr<BaseImpl> base;
+
+    void SetUp()
+    {
+        base = std::make_unique<BaseImpl>(expected_source, std::false_type(),
+                                          &mock);
+    }
+
+    void TearDown()
+    {
+        {
+            testing::InSequence seq;
+            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));
+        }
+    }
+};
+
+TEST_F(BaseMethodTest, GetDescriptionSuccess)
+{
+    const char* expected = "test_desc";
+    EXPECT_CALL(mock,
+                sd_event_source_get_description(expected_source, testing::_))
+        .WillOnce(DoAll(SetArgPointee<1>(expected), Return(0)));
+    // Intentionally comparing pointers to make sure no copying is happening
+    EXPECT_EQ(expected, base->get_description());
+}
+
+TEST_F(BaseMethodTest, GetDescriptionError)
+{
+    EXPECT_CALL(mock,
+                sd_event_source_get_description(expected_source, testing::_))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->get_description(), SdEventError);
+}
+
+TEST_F(BaseMethodTest, SetDescriptionSuccess)
+{
+    const char* expected = "test desc";
+    // Intentionally comparing pointers to make sure no copying is happening
+    EXPECT_CALL(mock,
+                sd_event_source_set_description(expected_source, expected))
+        .WillOnce(Return(0));
+    base->set_description(expected);
+}
+
+TEST_F(BaseMethodTest, SetDescriptionError)
+{
+    const char* expected = "test desc";
+    // Intentionally comparing pointers to make sure no copying is happening
+    EXPECT_CALL(mock,
+                sd_event_source_set_description(expected_source, expected))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->set_description(expected), SdEventError);
+}
+
+TEST_F(BaseMethodTest, GetPendingSuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
+        .WillOnce(Return(0));
+    EXPECT_EQ(0, base->get_pending());
+    EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
+        .WillOnce(Return(4));
+    EXPECT_EQ(4, base->get_pending());
+}
+
+TEST_F(BaseMethodTest, GetPendingError)
+{
+    EXPECT_CALL(mock, sd_event_source_get_pending(expected_source))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->get_pending(), SdEventError);
+}
+
+TEST_F(BaseMethodTest, GetPrioritySuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
+        .WillOnce(DoAll(SetArgPointee<1>(1024), Return(0)));
+    EXPECT_EQ(1024, base->get_priority());
+}
+
+TEST_F(BaseMethodTest, GetPriorityError)
+{
+    EXPECT_CALL(mock, sd_event_source_get_priority(expected_source, testing::_))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->get_priority(), SdEventError);
+}
+
+TEST_F(BaseMethodTest, SetPrioritySuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
+        .WillOnce(Return(0));
+    base->set_priority(1024);
+}
+
+TEST_F(BaseMethodTest, SetPriorityError)
+{
+    EXPECT_CALL(mock, sd_event_source_set_priority(expected_source, 1024))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->set_priority(1024), SdEventError);
+}
+
+TEST_F(BaseMethodTest, GetEnabledSuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
+        .WillOnce(DoAll(SetArgPointee<1>(SD_EVENT_ON), Return(0)));
+    EXPECT_EQ(SD_EVENT_ON, base->get_enabled());
+}
+
+TEST_F(BaseMethodTest, GetEnabledError)
+{
+    EXPECT_CALL(mock, sd_event_source_get_enabled(expected_source, testing::_))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->get_enabled(), SdEventError);
+}
+
+TEST_F(BaseMethodTest, SetEnabledSuccess)
+{
+    EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
+        .WillOnce(Return(0));
+    base->set_enabled(SD_EVENT_ON);
+}
+
+TEST_F(BaseMethodTest, SetEnabledError)
+{
+    EXPECT_CALL(mock, sd_event_source_set_enabled(expected_source, SD_EVENT_ON))
+        .WillOnce(Return(-EINVAL));
+    EXPECT_THROW(base->set_enabled(SD_EVENT_ON), SdEventError);
 }
 
 } // namespace