Added sdbusplus::sdbus Interface and Mock

This is meant to be used as an interface to sd-bus.  It sets up a
singleton to the default interface and a mock for use in testing.

Note: This was originally part of another patchset.
Change-Id: I133770fdeec327e018b6c587a7992cbccc7b3f10
Signed-off-by: Patrick Venture <venture@google.com>
diff --git a/Makefile.am b/Makefile.am
index 8c96b3e..9bcba6d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,6 +5,8 @@
 	mapbox/variant.hpp \
 	sdbusplus/bus.hpp \
 	sdbusplus/bus/match.hpp \
+	sdbusplus/sdbus.hpp \
+	sdbusplus/test/sdbus_mock.hpp \
 	sdbusplus/exception.hpp \
 	sdbusplus/message.hpp \
 	sdbusplus/message/append.hpp \
@@ -23,7 +25,8 @@
 	sdbusplus/vtable.hpp
 
 LIBSDBUSPLUS_FILES = \
-	sdbusplus/exception.cpp
+	sdbusplus/exception.cpp \
+	sdbusplus/sdbus.cpp
 
 if WANT_TRANSACTION
 nobase_include_HEADERS += \
diff --git a/sdbusplus/sdbus.cpp b/sdbusplus/sdbus.cpp
new file mode 100644
index 0000000..45a68ba
--- /dev/null
+++ b/sdbusplus/sdbus.cpp
@@ -0,0 +1,3 @@
+#include <sdbusplus/sdbus.hpp>
+
+sdbusplus::SdBusImpl sdbus_impl;
diff --git a/sdbusplus/sdbus.hpp b/sdbusplus/sdbus.hpp
new file mode 100644
index 0000000..f3db3f3
--- /dev/null
+++ b/sdbusplus/sdbus.hpp
@@ -0,0 +1,205 @@
+#pragma once
+
+#include <systemd/sd-bus.h>
+
+// ABC for sdbus implementation.
+namespace sdbusplus
+{
+
+// A wrapper for interfacing or testing sd-bus.  This will hold methods for
+// buses, messages, etc.
+class SdBusInterface
+{
+  public:
+    virtual ~SdBusInterface() = default;
+
+    // https://github.com/systemd/systemd/blob/master/src/systemd/sd-bus.h
+    virtual sd_bus_message *sd_bus_message_ref(sd_bus_message *m) = 0;
+
+    virtual int sd_bus_message_append_basic(sd_bus_message *message, char type,
+                                            const void *value) = 0;
+
+    virtual int sd_bus_message_at_end(sd_bus_message *m, int complete) = 0;
+
+    virtual int sd_bus_message_close_container(sd_bus_message *m) = 0;
+
+    virtual int sd_bus_message_enter_container(sd_bus_message *m, char type,
+                                               const char *contents) = 0;
+
+    virtual int sd_bus_message_exit_container(sd_bus_message *m) = 0;
+
+    virtual sd_bus *sd_bus_message_get_bus(sd_bus_message *m) = 0;
+    virtual int sd_bus_message_get_cookie(sd_bus_message *m,
+                                          uint64_t *cookie) = 0;
+    virtual const char *sd_bus_message_get_destination(sd_bus_message *m) = 0;
+    virtual const char *sd_bus_message_get_interface(sd_bus_message *m) = 0;
+    virtual const char *sd_bus_message_get_member(sd_bus_message *m) = 0;
+    virtual const char *sd_bus_message_get_path(sd_bus_message *m) = 0;
+    virtual const char *sd_bus_message_get_sender(sd_bus_message *m) = 0;
+    virtual const char *sd_bus_message_get_signature(sd_bus_message *m,
+                                                     int complete) = 0;
+
+    virtual int sd_bus_message_is_method_call(sd_bus_message *m,
+                                              const char *interface,
+                                              const char *member) = 0;
+    virtual int sd_bus_message_is_method_error(sd_bus_message *m,
+                                               const char *name) = 0;
+    virtual int sd_bus_message_is_signal(sd_bus_message *m,
+                                         const char *interface,
+                                         const char *member) = 0;
+
+    virtual int sd_bus_message_new_method_return(sd_bus_message *call,
+                                                 sd_bus_message **m) = 0;
+
+    virtual int sd_bus_message_read_basic(sd_bus_message *m, char type,
+                                          void *p) = 0;
+
+    virtual int sd_bus_message_skip(sd_bus_message *m, const char *types) = 0;
+
+    virtual int sd_bus_message_verify_type(sd_bus_message *m, char type,
+                                           const char *contents) = 0;
+
+    virtual int sd_bus_send(sd_bus *bus, sd_bus_message *m,
+                            uint64_t *cookie) = 0;
+
+    virtual int sd_bus_message_open_container(sd_bus_message *m, char type,
+                                              const char *contents) = 0;
+};
+
+class SdBusImpl : public SdBusInterface
+{
+  public:
+    SdBusImpl() = default;
+    ~SdBusImpl() = default;
+    SdBusImpl(const SdBusImpl &) = default;
+    SdBusImpl &operator=(const SdBusImpl &) = default;
+    SdBusImpl(SdBusImpl &&) = default;
+    SdBusImpl &operator=(SdBusImpl &&) = default;
+
+    sd_bus_message *sd_bus_message_ref(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_ref(m);
+    }
+
+    int sd_bus_message_append_basic(sd_bus_message *message, char type,
+                                    const void *value) override
+    {
+        return ::sd_bus_message_append_basic(message, type, value);
+    }
+
+    int sd_bus_message_at_end(sd_bus_message *m, int complete) override
+    {
+        return ::sd_bus_message_at_end(m, complete);
+    }
+
+    int sd_bus_message_close_container(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_close_container(m);
+    }
+
+    int sd_bus_message_enter_container(sd_bus_message *m, char type,
+                                       const char *contents) override
+    {
+        return ::sd_bus_message_enter_container(m, type, contents);
+    }
+
+    int sd_bus_message_exit_container(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_exit_container(m);
+    }
+
+    sd_bus *sd_bus_message_get_bus(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_bus(m);
+    }
+
+    int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) override
+    {
+        return ::sd_bus_message_get_cookie(m, cookie);
+    }
+
+    const char *sd_bus_message_get_destination(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_destination(m);
+    }
+
+    const char *sd_bus_message_get_interface(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_interface(m);
+    }
+
+    const char *sd_bus_message_get_member(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_member(m);
+    }
+
+    const char *sd_bus_message_get_path(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_path(m);
+    }
+
+    const char *sd_bus_message_get_sender(sd_bus_message *m) override
+    {
+        return ::sd_bus_message_get_sender(m);
+    }
+
+    const char *sd_bus_message_get_signature(sd_bus_message *m,
+                                             int complete) override
+    {
+        return ::sd_bus_message_get_signature(m, complete);
+    }
+
+    int sd_bus_message_is_method_call(sd_bus_message *m, const char *interface,
+                                      const char *member) override
+    {
+        return ::sd_bus_message_is_method_call(m, interface, member);
+    }
+
+    int sd_bus_message_is_method_error(sd_bus_message *m,
+                                       const char *name) override
+    {
+        return ::sd_bus_message_is_method_error(m, name);
+    }
+
+    int sd_bus_message_is_signal(sd_bus_message *m, const char *interface,
+                                 const char *member) override
+    {
+        return ::sd_bus_message_is_signal(m, interface, member);
+    }
+
+    int sd_bus_message_new_method_return(sd_bus_message *call,
+                                         sd_bus_message **m) override
+    {
+        return ::sd_bus_message_new_method_return(call, m);
+    }
+
+    int sd_bus_message_read_basic(sd_bus_message *m, char type,
+                                  void *p) override
+    {
+        return ::sd_bus_message_read_basic(m, type, p);
+    }
+
+    int sd_bus_message_skip(sd_bus_message *m, const char *types) override
+    {
+        return ::sd_bus_message_skip(m, types);
+    }
+
+    int sd_bus_message_verify_type(sd_bus_message *m, char type,
+                                   const char *contents) override
+    {
+        return ::sd_bus_message_verify_type(m, type, contents);
+    }
+
+    int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie) override
+    {
+        return ::sd_bus_send(bus, m, cookie);
+    }
+
+    int sd_bus_message_open_container(sd_bus_message *m, char type,
+                                      const char *contents) override
+    {
+        return ::sd_bus_message_open_container(m, type, contents);
+    }
+};
+
+} // namespace sdbusplus
diff --git a/sdbusplus/test/sdbus_mock.hpp b/sdbusplus/test/sdbus_mock.hpp
new file mode 100644
index 0000000..1c2ae7e
--- /dev/null
+++ b/sdbusplus/test/sdbus_mock.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "gmock/gmock.h"
+
+#include <sdbusplus/sdbus.hpp>
+
+namespace sdbusplus
+{
+
+class SdBusMock : public SdBusInterface
+{
+  public:
+    virtual ~SdBusMock(){};
+
+    MOCK_METHOD1(sd_bus_message_ref, sd_bus_message *(sd_bus_message *));
+    MOCK_METHOD3(sd_bus_message_append_basic,
+                 int(sd_bus_message *, char, const void *));
+    MOCK_METHOD2(sd_bus_message_at_end, int(sd_bus_message *, int));
+    MOCK_METHOD1(sd_bus_message_close_container, int(sd_bus_message *));
+    MOCK_METHOD3(sd_bus_message_enter_container,
+                 int(sd_bus_message *, char, const char *));
+    MOCK_METHOD1(sd_bus_message_exit_container, int(sd_bus_message *));
+
+    MOCK_METHOD1(sd_bus_message_get_bus, sd_bus *(sd_bus_message *));
+    MOCK_METHOD2(sd_bus_message_get_cookie, int(sd_bus_message *, uint64_t *));
+    MOCK_METHOD1(sd_bus_message_get_destination,
+                 const char *(sd_bus_message *));
+    MOCK_METHOD1(sd_bus_message_get_interface, const char *(sd_bus_message *));
+    MOCK_METHOD1(sd_bus_message_get_member, const char *(sd_bus_message *));
+    MOCK_METHOD1(sd_bus_message_get_path, const char *(sd_bus_message *));
+    MOCK_METHOD1(sd_bus_message_get_sender, const char *(sd_bus_message *));
+    MOCK_METHOD2(sd_bus_message_get_signature,
+                 const char *(sd_bus_message *, int));
+
+    MOCK_METHOD3(sd_bus_message_is_method_call,
+                 int(sd_bus_message *, const char *, const char *));
+    MOCK_METHOD2(sd_bus_message_is_method_error,
+                 int(sd_bus_message *, const char *));
+    MOCK_METHOD3(sd_bus_message_is_signal,
+                 int(sd_bus_message *, const char *, const char *));
+
+    MOCK_METHOD2(sd_bus_message_new_method_return,
+                 int(sd_bus_message *, sd_bus_message **));
+    MOCK_METHOD3(sd_bus_message_read_basic,
+                 int(sd_bus_message *, char, void *));
+
+    MOCK_METHOD2(sd_bus_message_skip, int(sd_bus_message *, const char *));
+    MOCK_METHOD3(sd_bus_message_verify_type,
+                 int(sd_bus_message *, char, const char *));
+    MOCK_METHOD3(sd_bus_send, int(sd_bus *, sd_bus_message *, uint64_t *));
+
+    MOCK_METHOD3(sd_bus_message_open_container,
+                 int(sd_bus_message *, char, const char *));
+};
+
+} // namespace sdbusplus