1 /**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "exception_utils.hpp"
17 #include "journal.hpp"
18 #include "mock_journal.hpp"
19
20 #include <exception>
21 #include <stdexcept>
22 #include <string>
23 #include <vector>
24
25 #include <gtest/gtest.h>
26
27 using namespace phosphor::power::regulators;
28
TEST(ExceptionUtilsTests,GetExceptions)29 TEST(ExceptionUtilsTests, GetExceptions)
30 {
31 // Test where exception pointer is null
32 {
33 std::exception_ptr eptr;
34 std::vector<std::exception_ptr> exceptions =
35 exception_utils::getExceptions(eptr);
36 EXPECT_EQ(exceptions.size(), 0);
37 }
38
39 // Test where exception pointer is not null
40 {
41 // Create nested exception with two nesting levels
42 std::exception_ptr eptr;
43 try
44 {
45 try
46 {
47 throw std::logic_error{"JSON element is not an array"};
48 }
49 catch (...)
50 {
51 std::throw_with_nested(
52 std::runtime_error{"Unable to parse config file"});
53 }
54 }
55 catch (...)
56 {
57 eptr = std::current_exception();
58 }
59
60 // Get vector containing exceptions
61 std::vector<std::exception_ptr> exceptions =
62 exception_utils::getExceptions(eptr);
63 EXPECT_EQ(exceptions.size(), 2);
64
65 // Verify first exception in vector, which is the innermost exception
66 try
67 {
68 std::rethrow_exception(exceptions[0]);
69 ADD_FAILURE() << "Should not have reached this line.";
70 }
71 catch (const std::logic_error& e)
72 {
73 EXPECT_STREQ(e.what(), "JSON element is not an array");
74 }
75 catch (...)
76 {
77 ADD_FAILURE() << "Unexpected exception type";
78 }
79
80 // Verify second exception in vector, which is the outermost exception
81 try
82 {
83 std::rethrow_exception(exceptions[1]);
84 ADD_FAILURE() << "Should not have reached this line.";
85 }
86 catch (const std::runtime_error& e)
87 {
88 EXPECT_STREQ(e.what(), "Unable to parse config file");
89 }
90 catch (...)
91 {
92 ADD_FAILURE() << "Unexpected exception type";
93 }
94 }
95 }
96
TEST(ExceptionUtilsTests,GetMessages)97 TEST(ExceptionUtilsTests, GetMessages)
98 {
99 try
100 {
101 try
102 {
103 throw std::invalid_argument{"JSON element is not an array"};
104 }
105 catch (...)
106 {
107 std::throw_with_nested(
108 std::logic_error{"Unable to parse config file"});
109 }
110 }
111 catch (const std::exception& e)
112 {
113 std::vector<std::string> messages = exception_utils::getMessages(e);
114 EXPECT_EQ(messages.size(), 2);
115 EXPECT_EQ(messages[0], "JSON element is not an array");
116 EXPECT_EQ(messages[1], "Unable to parse config file");
117 }
118 }
119
TEST(ExceptionUtilsTests,InternalGetExceptions)120 TEST(ExceptionUtilsTests, InternalGetExceptions)
121 {
122 // Test where exception pointer is null
123 {
124 std::exception_ptr eptr;
125 std::vector<std::exception_ptr> exceptions;
126 exception_utils::internal::getExceptions(eptr, exceptions);
127 EXPECT_EQ(exceptions.size(), 0);
128 }
129
130 // Test where exception is not nested
131 {
132 // Create exception
133 std::exception_ptr eptr;
134 try
135 {
136 throw std::logic_error{"JSON element is not an array"};
137 }
138 catch (...)
139 {
140 eptr = std::current_exception();
141 }
142
143 // Build vector of exceptions
144 std::vector<std::exception_ptr> exceptions;
145 exception_utils::internal::getExceptions(eptr, exceptions);
146 EXPECT_EQ(exceptions.size(), 1);
147
148 // Verify exception in vector
149 try
150 {
151 std::rethrow_exception(exceptions[0]);
152 ADD_FAILURE() << "Should not have reached this line.";
153 }
154 catch (const std::logic_error& e)
155 {
156 EXPECT_STREQ(e.what(), "JSON element is not an array");
157 }
158 catch (...)
159 {
160 ADD_FAILURE() << "Unexpected exception type";
161 }
162 }
163
164 // Test where exception is nested
165 {
166 // Throw exception with three levels of nesting
167 std::exception_ptr eptr;
168 try
169 {
170 try
171 {
172 try
173 {
174 throw std::string{"Invalid JSON element"};
175 }
176 catch (...)
177 {
178 std::throw_with_nested(
179 std::logic_error{"JSON element is not an array"});
180 }
181 }
182 catch (...)
183 {
184 std::throw_with_nested(
185 std::runtime_error{"Unable to parse config file"});
186 }
187 }
188 catch (...)
189 {
190 eptr = std::current_exception();
191 }
192
193 // Build vector of exceptions
194 std::vector<std::exception_ptr> exceptions;
195 exception_utils::internal::getExceptions(eptr, exceptions);
196 EXPECT_EQ(exceptions.size(), 3);
197
198 // Verify first exception in vector, which is the innermost exception
199 try
200 {
201 std::rethrow_exception(exceptions[0]);
202 ADD_FAILURE() << "Should not have reached this line.";
203 }
204 catch (const std::string& s)
205 {
206 EXPECT_EQ(s, "Invalid JSON element");
207 }
208 catch (...)
209 {
210 ADD_FAILURE() << "Unexpected exception type";
211 }
212
213 // Verify second exception in vector
214 try
215 {
216 std::rethrow_exception(exceptions[1]);
217 ADD_FAILURE() << "Should not have reached this line.";
218 }
219 catch (const std::logic_error& e)
220 {
221 EXPECT_STREQ(e.what(), "JSON element is not an array");
222 }
223 catch (...)
224 {
225 ADD_FAILURE() << "Unexpected exception type";
226 }
227
228 // Verify third exception in vector, which is the outermost exception
229 try
230 {
231 std::rethrow_exception(exceptions[2]);
232 ADD_FAILURE() << "Should not have reached this line.";
233 }
234 catch (const std::runtime_error& e)
235 {
236 EXPECT_STREQ(e.what(), "Unable to parse config file");
237 }
238 catch (...)
239 {
240 ADD_FAILURE() << "Unexpected exception type";
241 }
242 }
243 }
244
TEST(ExceptionUtilsTests,InternalGetMessages)245 TEST(ExceptionUtilsTests, InternalGetMessages)
246 {
247 // Test where exception is not nested
248 {
249 std::invalid_argument e{"JSON element is not an array"};
250 std::vector<std::string> messages{};
251 exception_utils::internal::getMessages(e, messages);
252 EXPECT_EQ(messages.size(), 1);
253 EXPECT_EQ(messages[0], "JSON element is not an array");
254 }
255
256 // Test where exception is nested
257 try
258 {
259 try
260 {
261 try
262 {
263 throw std::invalid_argument{"JSON element is not an array"};
264 }
265 catch (...)
266 {
267 std::throw_with_nested(
268 std::logic_error{"Unable to parse config file"});
269 }
270 }
271 catch (...)
272 {
273 std::throw_with_nested(
274 std::runtime_error{"Unable to configure regulators"});
275 }
276 }
277 catch (const std::exception& e)
278 {
279 std::vector<std::string> messages{};
280 exception_utils::internal::getMessages(e, messages);
281 EXPECT_EQ(messages.size(), 3);
282 EXPECT_EQ(messages[0], "JSON element is not an array");
283 EXPECT_EQ(messages[1], "Unable to parse config file");
284 EXPECT_EQ(messages[2], "Unable to configure regulators");
285 }
286
287 // Test where nested exception is not a child of std::exception
288 try
289 {
290 try
291 {
292 try
293 {
294 throw "JSON element is not an array";
295 }
296 catch (...)
297 {
298 std::throw_with_nested(
299 std::logic_error{"Unable to parse config file"});
300 }
301 }
302 catch (...)
303 {
304 std::throw_with_nested(
305 std::runtime_error{"Unable to configure regulators"});
306 }
307 }
308 catch (const std::exception& e)
309 {
310 std::vector<std::string> messages{};
311 exception_utils::internal::getMessages(e, messages);
312 EXPECT_EQ(messages.size(), 2);
313 EXPECT_EQ(messages[0], "Unable to parse config file");
314 EXPECT_EQ(messages[1], "Unable to configure regulators");
315 }
316 }
317