blob: 94a268d27fc908a96b829a168915b8a0de5acae6 [file] [log] [blame]
Patrick Venture95269db2018-08-31 09:19:17 -07001#include <systemd/sd-bus.h>
2
William A. Kennington III874e82e2018-06-22 19:23:54 -07003#include <sdbusplus/exception.hpp>
4#include <sdbusplus/test/sdbus_mock.hpp>
Patrick Williams127b8ab2020-05-21 15:24:19 -05005
6#include <cstdlib>
William A. Kennington III874e82e2018-06-22 19:23:54 -07007#include <stdexcept>
8#include <string>
William A. Kennington III874e82e2018-06-22 19:23:54 -07009#include <utility>
10
Patrick Venture95269db2018-08-31 09:19:17 -070011#include <gtest/gtest.h>
12
Patrick Williams2f5bebd2023-05-19 15:28:10 -050013#ifdef __clang__
14#pragma clang diagnostic push
15#pragma clang diagnostic ignored "-Wc99-extensions"
16#endif
17
Gunnar Mills31a4b132018-08-14 11:59:13 -050018// Needed for constructor error testing
William A. Kennington III874e82e2018-06-22 19:23:54 -070019extern sdbusplus::SdBusImpl sdbus_impl;
20
21namespace
22{
23
24using sdbusplus::exception::SdBusError;
William A. Kennington III874e82e2018-06-22 19:23:54 -070025using testing::_;
Patrick Venture0b5d1e02018-08-31 09:12:15 -070026using testing::Return;
William A. Kennington III874e82e2018-06-22 19:23:54 -070027
William A. Kennington III874e82e2018-06-22 19:23:54 -070028TEST(SdBusError, BasicErrno)
29{
30 const int errorVal = EBUSY;
31 const std::string prefix = "BasicErrno";
32
33 // Build the reference sd_bus_error
34 sd_bus_error error = SD_BUS_ERROR_NULL;
35 EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal));
36 EXPECT_TRUE(sd_bus_error_is_set(&error));
37
38 // Build the SdBusError
39 SdBusError err(errorVal, prefix.c_str());
40
41 // Make sure inheritance is defined correctly
42 sdbusplus::exception::exception& sdbusErr = err;
Adriana Kobylak33335b32018-09-21 11:50:42 -050043 SdBusError& errNew = err;
44 EXPECT_EQ(errorVal, errNew.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -070045 EXPECT_EQ(std::string{error.name}, sdbusErr.name());
46 EXPECT_EQ(std::string{error.message}, sdbusErr.description());
William A. Kennington III874e82e2018-06-22 19:23:54 -070047 std::exception& stdErr = sdbusErr;
48 EXPECT_EQ(prefix + ": " + error.name + ": " + error.message, stdErr.what());
49
50 sd_bus_error_free(&error);
51}
52
53TEST(SdBusError, EnomemErrno)
54{
55 // Make sure no exception is thrown on construction
56 SdBusError err(ENOMEM, "EnomemErrno");
57}
58
59TEST(SdBusError, NotSetErrno)
60{
61 const int errorVal = EBUSY;
62
63 sdbusplus::SdBusMock sdbus;
64 EXPECT_CALL(sdbus, sd_bus_error_set_errno(_, errorVal))
65 .Times(1)
66 .WillOnce(Return(errorVal));
67 EXPECT_CALL(sdbus, sd_bus_error_is_set(_)).Times(1).WillOnce(Return(false));
68 EXPECT_THROW(SdBusError(errorVal, "NotSetErrno", &sdbus),
69 std::runtime_error);
70}
71
72TEST(SdBusError, Move)
73{
74 const int errorVal = EIO;
75 const std::string prefix = "Move";
76
77 // Build the reference sd_bus_error
78 sd_bus_error error = SD_BUS_ERROR_NULL;
79 EXPECT_EQ(-errorVal, sd_bus_error_set_errno(&error, errorVal));
80 EXPECT_TRUE(sd_bus_error_is_set(&error));
81 const std::string name{error.name};
82 const std::string message{error.message};
83 const std::string what = prefix + ": " + error.name + ": " + error.message;
84
85 SdBusError errFinal(EBUSY, "Move2");
86 // Nest to make sure RAII works for moves
87 {
88 // Build our first SdBusError
89 SdBusError err(errorVal, prefix.c_str());
90
Adriana Kobylak33335b32018-09-21 11:50:42 -050091 EXPECT_EQ(errorVal, err.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -070092 EXPECT_EQ(name, err.name());
93 EXPECT_EQ(message, err.description());
94 EXPECT_EQ(what, err.what());
William A. Kennington III874e82e2018-06-22 19:23:54 -070095
96 // Move our SdBusError to a new one
97 SdBusError errNew(std::move(err));
98
Patrick Williams4991d3b2020-05-21 07:33:24 -050099 // We are purposefully calling functions on a moved-from object,
100 // so we need to suppress the clang warnings.
101#ifndef __clang_analyzer__
William A. Kennington III874e82e2018-06-22 19:23:54 -0700102 // Ensure the old object was cleaned up
Adriana Kobylak33335b32018-09-21 11:50:42 -0500103 EXPECT_EQ(0, err.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700104 EXPECT_EQ(nullptr, err.name());
105 EXPECT_EQ(nullptr, err.description());
Patrick Williams4991d3b2020-05-21 07:33:24 -0500106#endif
William A. Kennington III874e82e2018-06-22 19:23:54 -0700107
108 // Ensure our new object has the same data but moved
Adriana Kobylak33335b32018-09-21 11:50:42 -0500109 EXPECT_EQ(errorVal, errNew.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700110 EXPECT_EQ(name, errNew.name());
111 EXPECT_EQ(message, errNew.description());
112 EXPECT_EQ(what, errNew.what());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700113
114 // Move our SdBusError using the operator=()
115 errFinal = std::move(errNew);
116
Patrick Williams4991d3b2020-05-21 07:33:24 -0500117 // We are purposefully calling functions on a moved-from object,
118 // so we need to suppress the clang warnings.
119#ifndef __clang_analyzer__
William A. Kennington III874e82e2018-06-22 19:23:54 -0700120 // Ensure the old object was cleaned up
Adriana Kobylak33335b32018-09-21 11:50:42 -0500121 EXPECT_EQ(0, errNew.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700122 EXPECT_EQ(nullptr, errNew.name());
123 EXPECT_EQ(nullptr, errNew.description());
Patrick Williams4991d3b2020-05-21 07:33:24 -0500124#endif
William A. Kennington III874e82e2018-06-22 19:23:54 -0700125 }
126
127 // Ensure our new object has the same data but moved
Adriana Kobylak33335b32018-09-21 11:50:42 -0500128 EXPECT_EQ(errorVal, errFinal.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700129 EXPECT_EQ(name, errFinal.name());
130 EXPECT_EQ(message, errFinal.description());
131 EXPECT_EQ(what, errFinal.what());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700132
133 sd_bus_error_free(&error);
134}
135
136TEST(SdBusError, BasicError)
137{
138 const std::string name = "org.freedesktop.DBus.Error.Failed";
139 const std::string description = "TestCase";
140 const std::string prefix = "BasicError";
141
142 sd_bus_error error = SD_BUS_ERROR_NULL;
143 sd_bus_error_set(&error, name.c_str(), description.c_str());
144 EXPECT_TRUE(sd_bus_error_is_set(&error));
145 const char* nameBeforeMove = error.name;
Adriana Kobylak33335b32018-09-21 11:50:42 -0500146 const int errorVal = sd_bus_error_get_errno(&error);
William A. Kennington III874e82e2018-06-22 19:23:54 -0700147 SdBusError err(&error, prefix.c_str());
148
149 // We expect a move not copy
150 EXPECT_EQ(nameBeforeMove, err.name());
151
152 // The SdBusError should have moved our error so it should be freeable
153 EXPECT_FALSE(sd_bus_error_is_set(&error));
154 sd_bus_error_free(&error);
155 sd_bus_error_free(&error);
156
Adriana Kobylak33335b32018-09-21 11:50:42 -0500157 EXPECT_EQ(errorVal, err.get_errno());
William A. Kennington III874e82e2018-06-22 19:23:54 -0700158 EXPECT_EQ(name, err.name());
159 EXPECT_EQ(description, err.description());
160 EXPECT_EQ(prefix + ": " + name + ": " + description, err.what());
Vernon Maueryfac43a62018-08-01 12:29:23 -0700161}
162
163TEST(SdBusError, CatchBaseClassExceptions)
164{
165 /* test each class in the chain:
166 * std::exception
167 * -> sdbusplus::exception::exception
168 * -> sdbusplus::exception::internal_exception
169 * -> sdbusplus::exception::SdBusError
170 */
171 EXPECT_THROW({ throw SdBusError(-EINVAL, "SdBusError"); }, SdBusError);
172 EXPECT_THROW({ throw SdBusError(-EINVAL, "internal_exception"); },
173 sdbusplus::exception::internal_exception);
174 EXPECT_THROW({ throw SdBusError(-EINVAL, "exception"); },
175 sdbusplus::exception::exception);
176 EXPECT_THROW({ throw SdBusError(-EINVAL, "std::exception"); },
177 std::exception);
William A. Kennington III874e82e2018-06-22 19:23:54 -0700178}
179
180} // namespace
Patrick Williams2f5bebd2023-05-19 15:28:10 -0500181
182#ifdef __clang__
183#pragma clang diagnostic pop
184#endif