| #include <systemd/sd-bus.h> | 
 |  | 
 | #include <sdbusplus/exception.hpp> | 
 | #include <sdbusplus/test/sdbus_mock.hpp> | 
 |  | 
 | #include <cstdlib> | 
 | #include <stdexcept> | 
 | #include <string> | 
 | #include <utility> | 
 |  | 
 | #include <gtest/gtest.h> | 
 |  | 
 | #ifdef __clang__ | 
 | #pragma clang diagnostic push | 
 | #pragma clang diagnostic ignored "-Wc99-extensions" | 
 | #endif | 
 |  | 
 | // Needed for constructor error testing | 
 | extern sdbusplus::SdBusImpl sdbus_impl; | 
 |  | 
 | namespace | 
 | { | 
 |  | 
 | using sdbusplus::exception::SdBusError; | 
 | using testing::_; | 
 | using testing::Return; | 
 |  | 
 | TEST(SdBusError, BasicErrno) | 
 | { | 
 |     const int errorVal = EBUSY; | 
 |     const std::string prefix = "BasicErrno"; | 
 |  | 
 |     // Build the reference sd_bus_error | 
 |     sd_bus_error error = SD_BUS_ERROR_NULL; | 
 |     EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal)); | 
 |     EXPECT_TRUE(sd_bus_error_is_set(&error)); | 
 |  | 
 |     // Build the SdBusError | 
 |     SdBusError err(errorVal, prefix.c_str()); | 
 |  | 
 |     // Make sure inheritance is defined correctly | 
 |     sdbusplus::exception::exception& sdbusErr = err; | 
 |     SdBusError& errNew = err; | 
 |     EXPECT_EQ(errorVal, errNew.get_errno()); | 
 |     EXPECT_EQ(std::string{error.name}, sdbusErr.name()); | 
 |     EXPECT_EQ(std::string{error.message}, sdbusErr.description()); | 
 |     std::exception& stdErr = sdbusErr; | 
 |     EXPECT_EQ(prefix + ": " + error.name + ": " + error.message, stdErr.what()); | 
 |  | 
 |     sd_bus_error_free(&error); | 
 | } | 
 |  | 
 | TEST(SdBusError, EnomemErrno) | 
 | { | 
 |     // Make sure no exception is thrown on construction | 
 |     SdBusError err(ENOMEM, "EnomemErrno"); | 
 | } | 
 |  | 
 | TEST(SdBusError, NotSetErrno) | 
 | { | 
 |     const int errorVal = EBUSY; | 
 |  | 
 |     sdbusplus::SdBusMock sdbus; | 
 |     EXPECT_CALL(sdbus, sd_bus_error_set_errno(_, errorVal)) | 
 |         .Times(1) | 
 |         .WillOnce(Return(errorVal)); | 
 |     EXPECT_CALL(sdbus, sd_bus_error_is_set(_)).Times(1).WillOnce(Return(false)); | 
 |     EXPECT_THROW(SdBusError(errorVal, "NotSetErrno", &sdbus), | 
 |                  std::runtime_error); | 
 | } | 
 |  | 
 | TEST(SdBusError, Move) | 
 | { | 
 |     const int errorVal = EIO; | 
 |     const std::string prefix = "Move"; | 
 |  | 
 |     // Build the reference sd_bus_error | 
 |     sd_bus_error error = SD_BUS_ERROR_NULL; | 
 |     EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal)); | 
 |     EXPECT_TRUE(sd_bus_error_is_set(&error)); | 
 |     const std::string name{error.name}; | 
 |     const std::string message{error.message}; | 
 |     const std::string what = prefix + ": " + error.name + ": " + error.message; | 
 |  | 
 |     SdBusError errFinal(EBUSY, "Move2"); | 
 |     // Nest to make sure RAII works for moves | 
 |     { | 
 |         // Build our first SdBusError | 
 |         SdBusError err(errorVal, prefix.c_str()); | 
 |  | 
 |         EXPECT_EQ(errorVal, err.get_errno()); | 
 |         EXPECT_EQ(name, err.name()); | 
 |         EXPECT_EQ(message, err.description()); | 
 |         EXPECT_EQ(what, err.what()); | 
 |  | 
 |         // Move our SdBusError to a new one | 
 |         SdBusError errNew(std::move(err)); | 
 |  | 
 |         // We are purposefully calling functions on a moved-from object, | 
 |         // so we need to suppress the clang warnings. | 
 | #ifndef __clang_analyzer__ | 
 |         // Ensure the old object was cleaned up | 
 |         EXPECT_EQ(0, err.get_errno()); | 
 |         EXPECT_EQ(nullptr, err.name()); | 
 |         EXPECT_EQ(nullptr, err.description()); | 
 | #endif | 
 |  | 
 |         // Ensure our new object has the same data but moved | 
 |         EXPECT_EQ(errorVal, errNew.get_errno()); | 
 |         EXPECT_EQ(name, errNew.name()); | 
 |         EXPECT_EQ(message, errNew.description()); | 
 |         EXPECT_EQ(what, errNew.what()); | 
 |  | 
 |         // Move our SdBusError using the operator=() | 
 |         errFinal = std::move(errNew); | 
 |  | 
 |         // We are purposefully calling functions on a moved-from object, | 
 |         // so we need to suppress the clang warnings. | 
 | #ifndef __clang_analyzer__ | 
 |         // Ensure the old object was cleaned up | 
 |         EXPECT_EQ(0, errNew.get_errno()); | 
 |         EXPECT_EQ(nullptr, errNew.name()); | 
 |         EXPECT_EQ(nullptr, errNew.description()); | 
 | #endif | 
 |     } | 
 |  | 
 |     // Ensure our new object has the same data but moved | 
 |     EXPECT_EQ(errorVal, errFinal.get_errno()); | 
 |     EXPECT_EQ(name, errFinal.name()); | 
 |     EXPECT_EQ(message, errFinal.description()); | 
 |     EXPECT_EQ(what, errFinal.what()); | 
 |  | 
 |     sd_bus_error_free(&error); | 
 | } | 
 |  | 
 | TEST(SdBusError, BasicError) | 
 | { | 
 |     const std::string name = "org.freedesktop.DBus.Error.Failed"; | 
 |     const std::string description = "TestCase"; | 
 |     const std::string prefix = "BasicError"; | 
 |  | 
 |     sd_bus_error error = SD_BUS_ERROR_NULL; | 
 |     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 | 
 |     EXPECT_EQ(nameBeforeMove, err.name()); | 
 |  | 
 |     // The SdBusError should have moved our error so it should be freeable | 
 |     EXPECT_FALSE(sd_bus_error_is_set(&error)); | 
 |     sd_bus_error_free(&error); | 
 |     sd_bus_error_free(&error); | 
 |  | 
 |     EXPECT_EQ(errorVal, err.get_errno()); | 
 |     EXPECT_EQ(name, err.name()); | 
 |     EXPECT_EQ(description, err.description()); | 
 |     EXPECT_EQ(prefix + ": " + name + ": " + description, err.what()); | 
 | } | 
 |  | 
 | 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 | 
 |  | 
 | #ifdef __clang__ | 
 | #pragma clang diagnostic pop | 
 | #endif |