blob: 02d063d15d90794f098eeb4029068396ee73017c [file] [log] [blame]
#include <cstdlib>
#include <gtest/gtest.h>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/test/sdbus_mock.hpp>
#include <stdexcept>
#include <string>
#include <system_error>
#include <systemd/sd-bus.h>
#include <utility>
// Needed for constuctor error testing
extern sdbusplus::SdBusImpl sdbus_impl;
namespace
{
using sdbusplus::exception::SdBusError;
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;
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;
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());
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(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));
// Ensure the old object was cleaned up
EXPECT_EQ(nullptr, err.name());
EXPECT_EQ(nullptr, err.description());
EXPECT_EQ(std::string{}, err.what());
// Ensure our new object has the same data but moved
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);
// Ensure the old object was cleaned up
EXPECT_EQ(nullptr, errNew.name());
EXPECT_EQ(nullptr, errNew.description());
EXPECT_EQ(std::string{}, errNew.what());
}
// Ensure our new object has the same data but moved
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);
}
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(name, err.name());
EXPECT_EQ(description, err.description());
EXPECT_EQ(prefix + ": " + name + ": " + description, err.what());
EXPECT_EQ(errnoToErrorCode(errorVal), err.code());
}
} // namespace