Remove multiple inheritance from SdBusError

SdBusError now has a direct line of inheritance down to std::exception
and will behave better when trying to catch it as a std::exception.

Add test cases to check that SdBusError is actually caught by
std::exception and all its other base classes.

Change-Id: I83e614219a1c47ec874ee0b4f14096a5e69ac17d
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/sdbusplus/exception.cpp b/sdbusplus/exception.cpp
index 2e3b88a..3dea6f9 100644
--- a/sdbusplus/exception.cpp
+++ b/sdbusplus/exception.cpp
@@ -1,6 +1,5 @@
 #include <sdbusplus/exception.hpp>
 #include <stdexcept>
-#include <system_error>
 #include <utility>
 
 namespace sdbusplus
@@ -9,8 +8,7 @@
 {
 
 SdBusError::SdBusError(int error, const char* prefix, SdBusInterface* intf) :
-    std::system_error(error, std::generic_category()), error(SD_BUS_ERROR_NULL),
-    intf(intf)
+    error(SD_BUS_ERROR_NULL), intf(intf)
 {
     // We can't check the output of intf->sd_bus_error_set_errno() because
     // it returns the input errorcode. We don't want to try and guess
@@ -27,9 +25,8 @@
 
 SdBusError::SdBusError(sd_bus_error* error, const char* prefix,
                        SdBusInterface* intf) :
-    std::system_error(intf->sd_bus_error_get_errno(error),
-                      std::generic_category()),
-    error(*error), intf(intf)
+    error(*error),
+    intf(intf)
 {
     // We own the error so remove the caller's reference
     *error = SD_BUS_ERROR_NULL;
@@ -37,8 +34,7 @@
     populateMessage(prefix);
 }
 
-SdBusError::SdBusError(SdBusError&& other) :
-    std::system_error(std::move(other)), error(SD_BUS_ERROR_NULL)
+SdBusError::SdBusError(SdBusError&& other) : error(SD_BUS_ERROR_NULL)
 {
     move(std::move(other));
 }
@@ -47,7 +43,6 @@
 {
     if (this != &other)
     {
-        std::system_error::operator=(std::move(other));
         move(std::move(other));
     }
     return *this;
diff --git a/sdbusplus/exception.hpp b/sdbusplus/exception.hpp
index 9f4caa5..2e170ef 100644
--- a/sdbusplus/exception.hpp
+++ b/sdbusplus/exception.hpp
@@ -3,7 +3,6 @@
 #include <exception>
 #include <sdbusplus/sdbus.hpp>
 #include <string>
-#include <system_error>
 #include <systemd/sd-bus.h>
 
 namespace sdbusplus
@@ -26,7 +25,7 @@
 };
 
 /** Exception for when an underlying sd_bus method call fails. */
-class SdBusError final : public internal_exception, public std::system_error
+class SdBusError final : public internal_exception
 {
   public:
     /** Errno must be positive */
diff --git a/test/exception/sdbus_error.cpp b/test/exception/sdbus_error.cpp
index 02d063d..30a2a64 100644
--- a/test/exception/sdbus_error.cpp
+++ b/test/exception/sdbus_error.cpp
@@ -4,7 +4,6 @@
 #include <sdbusplus/test/sdbus_mock.hpp>
 #include <stdexcept>
 #include <string>
-#include <system_error>
 #include <systemd/sd-bus.h>
 #include <utility>
 
@@ -18,11 +17,6 @@
 using testing::Return;
 using testing::_;
 
-std::error_code errnoToErrorCode(int error)
-{
-    return std::error_code(error, std::generic_category());
-}
-
 TEST(SdBusError, BasicErrno)
 {
     const int errorVal = EBUSY;
@@ -40,8 +34,6 @@
     sdbusplus::exception::exception& sdbusErr = err;
     EXPECT_EQ(std::string{error.name}, sdbusErr.name());
     EXPECT_EQ(std::string{error.message}, sdbusErr.description());
-    std::system_error& systemErr = err;
-    EXPECT_EQ(errnoToErrorCode(errorVal), systemErr.code());
     std::exception& stdErr = sdbusErr;
     EXPECT_EQ(prefix + ": " + error.name + ": " + error.message, stdErr.what());
 
@@ -89,7 +81,6 @@
         EXPECT_EQ(name, err.name());
         EXPECT_EQ(message, err.description());
         EXPECT_EQ(what, err.what());
-        EXPECT_EQ(errnoToErrorCode(errorVal), err.code());
 
         // Move our SdBusError to a new one
         SdBusError errNew(std::move(err));
@@ -103,7 +94,6 @@
         EXPECT_EQ(name, errNew.name());
         EXPECT_EQ(message, errNew.description());
         EXPECT_EQ(what, errNew.what());
-        EXPECT_EQ(errnoToErrorCode(errorVal), errNew.code());
 
         // Move our SdBusError using the operator=()
         errFinal = std::move(errNew);
@@ -118,7 +108,6 @@
     EXPECT_EQ(name, errFinal.name());
     EXPECT_EQ(message, errFinal.description());
     EXPECT_EQ(what, errFinal.what());
-    EXPECT_EQ(errnoToErrorCode(errorVal), errFinal.code());
 
     sd_bus_error_free(&error);
 }
@@ -133,7 +122,6 @@
     sd_bus_error_set(&error, name.c_str(), description.c_str());
     EXPECT_TRUE(sd_bus_error_is_set(&error));
     const char* nameBeforeMove = error.name;
-    const int errorVal = sd_bus_error_get_errno(&error);
     SdBusError err(&error, prefix.c_str());
 
     // We expect a move not copy
@@ -147,7 +135,23 @@
     EXPECT_EQ(name, err.name());
     EXPECT_EQ(description, err.description());
     EXPECT_EQ(prefix + ": " + name + ": " + description, err.what());
-    EXPECT_EQ(errnoToErrorCode(errorVal), err.code());
+}
+
+TEST(SdBusError, CatchBaseClassExceptions)
+{
+    /* test each class in the chain:
+     * std::exception
+     *   -> sdbusplus::exception::exception
+     *     -> sdbusplus::exception::internal_exception
+     *       -> sdbusplus::exception::SdBusError
+     */
+    EXPECT_THROW({ throw SdBusError(-EINVAL, "SdBusError"); }, SdBusError);
+    EXPECT_THROW({ throw SdBusError(-EINVAL, "internal_exception"); },
+                 sdbusplus::exception::internal_exception);
+    EXPECT_THROW({ throw SdBusError(-EINVAL, "exception"); },
+                 sdbusplus::exception::exception);
+    EXPECT_THROW({ throw SdBusError(-EINVAL, "std::exception"); },
+                 std::exception);
 }
 
 } // namespace