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 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 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 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 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