blob: 02d063d15d90794f098eeb4029068396ee73017c [file] [log] [blame]
William A. Kennington III874e82e2018-06-22 19:23:54 -07001#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
12extern sdbusplus::SdBusImpl sdbus_impl;
13
14namespace
15{
16
17using sdbusplus::exception::SdBusError;
18using testing::Return;
19using testing::_;
20
21std::error_code errnoToErrorCode(int error)
22{
23 return std::error_code(error, std::generic_category());
24}
25
26TEST(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
51TEST(SdBusError, EnomemErrno)
52{
53 // Make sure no exception is thrown on construction
54 SdBusError err(ENOMEM, "EnomemErrno");
55}
56
57TEST(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
70TEST(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
126TEST(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