1 #include <cstdlib> 2 #include <gtest/gtest.h> 3 #include <sdbusplus/exception.hpp> 4 #include <sdbusplus/test/sdbus_mock.hpp> 5 #include <stdexcept> 6 #include <string> 7 #include <system_error> 8 #include <systemd/sd-bus.h> 9 #include <utility> 10 11 // Needed for constuctor error testing 12 extern sdbusplus::SdBusImpl sdbus_impl; 13 14 namespace 15 { 16 17 using sdbusplus::exception::SdBusError; 18 using testing::Return; 19 using testing::_; 20 21 std::error_code errnoToErrorCode(int error) 22 { 23 return std::error_code(error, std::generic_category()); 24 } 25 26 TEST(SdBusError, BasicErrno) 27 { 28 const int errorVal = EBUSY; 29 const std::string prefix = "BasicErrno"; 30 31 // Build the reference sd_bus_error 32 sd_bus_error error = SD_BUS_ERROR_NULL; 33 EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal)); 34 EXPECT_TRUE(sd_bus_error_is_set(&error)); 35 36 // Build the SdBusError 37 SdBusError err(errorVal, prefix.c_str()); 38 39 // Make sure inheritance is defined correctly 40 sdbusplus::exception::exception& sdbusErr = err; 41 EXPECT_EQ(std::string{error.name}, sdbusErr.name()); 42 EXPECT_EQ(std::string{error.message}, sdbusErr.description()); 43 std::system_error& systemErr = err; 44 EXPECT_EQ(errnoToErrorCode(errorVal), systemErr.code()); 45 std::exception& stdErr = sdbusErr; 46 EXPECT_EQ(prefix + ": " + error.name + ": " + error.message, stdErr.what()); 47 48 sd_bus_error_free(&error); 49 } 50 51 TEST(SdBusError, EnomemErrno) 52 { 53 // Make sure no exception is thrown on construction 54 SdBusError err(ENOMEM, "EnomemErrno"); 55 } 56 57 TEST(SdBusError, NotSetErrno) 58 { 59 const int errorVal = EBUSY; 60 61 sdbusplus::SdBusMock sdbus; 62 EXPECT_CALL(sdbus, sd_bus_error_set_errno(_, errorVal)) 63 .Times(1) 64 .WillOnce(Return(errorVal)); 65 EXPECT_CALL(sdbus, sd_bus_error_is_set(_)).Times(1).WillOnce(Return(false)); 66 EXPECT_THROW(SdBusError(errorVal, "NotSetErrno", &sdbus), 67 std::runtime_error); 68 } 69 70 TEST(SdBusError, Move) 71 { 72 const int errorVal = EIO; 73 const std::string prefix = "Move"; 74 75 // Build the reference sd_bus_error 76 sd_bus_error error = SD_BUS_ERROR_NULL; 77 EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal)); 78 EXPECT_TRUE(sd_bus_error_is_set(&error)); 79 const std::string name{error.name}; 80 const std::string message{error.message}; 81 const std::string what = prefix + ": " + error.name + ": " + error.message; 82 83 SdBusError errFinal(EBUSY, "Move2"); 84 // Nest to make sure RAII works for moves 85 { 86 // Build our first SdBusError 87 SdBusError err(errorVal, prefix.c_str()); 88 89 EXPECT_EQ(name, err.name()); 90 EXPECT_EQ(message, err.description()); 91 EXPECT_EQ(what, err.what()); 92 EXPECT_EQ(errnoToErrorCode(errorVal), err.code()); 93 94 // Move our SdBusError to a new one 95 SdBusError errNew(std::move(err)); 96 97 // Ensure the old object was cleaned up 98 EXPECT_EQ(nullptr, err.name()); 99 EXPECT_EQ(nullptr, err.description()); 100 EXPECT_EQ(std::string{}, err.what()); 101 102 // Ensure our new object has the same data but moved 103 EXPECT_EQ(name, errNew.name()); 104 EXPECT_EQ(message, errNew.description()); 105 EXPECT_EQ(what, errNew.what()); 106 EXPECT_EQ(errnoToErrorCode(errorVal), errNew.code()); 107 108 // Move our SdBusError using the operator=() 109 errFinal = std::move(errNew); 110 111 // Ensure the old object was cleaned up 112 EXPECT_EQ(nullptr, errNew.name()); 113 EXPECT_EQ(nullptr, errNew.description()); 114 EXPECT_EQ(std::string{}, errNew.what()); 115 } 116 117 // Ensure our new object has the same data but moved 118 EXPECT_EQ(name, errFinal.name()); 119 EXPECT_EQ(message, errFinal.description()); 120 EXPECT_EQ(what, errFinal.what()); 121 EXPECT_EQ(errnoToErrorCode(errorVal), errFinal.code()); 122 123 sd_bus_error_free(&error); 124 } 125 126 TEST(SdBusError, BasicError) 127 { 128 const std::string name = "org.freedesktop.DBus.Error.Failed"; 129 const std::string description = "TestCase"; 130 const std::string prefix = "BasicError"; 131 132 sd_bus_error error = SD_BUS_ERROR_NULL; 133 sd_bus_error_set(&error, name.c_str(), description.c_str()); 134 EXPECT_TRUE(sd_bus_error_is_set(&error)); 135 const char* nameBeforeMove = error.name; 136 const int errorVal = sd_bus_error_get_errno(&error); 137 SdBusError err(&error, prefix.c_str()); 138 139 // We expect a move not copy 140 EXPECT_EQ(nameBeforeMove, err.name()); 141 142 // The SdBusError should have moved our error so it should be freeable 143 EXPECT_FALSE(sd_bus_error_is_set(&error)); 144 sd_bus_error_free(&error); 145 sd_bus_error_free(&error); 146 147 EXPECT_EQ(name, err.name()); 148 EXPECT_EQ(description, err.description()); 149 EXPECT_EQ(prefix + ": " + name + ": " + description, err.what()); 150 EXPECT_EQ(errnoToErrorCode(errorVal), err.code()); 151 } 152 153 } // namespace 154