1 //===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Support/Error.h" 11 #include "llvm/Support/Errc.h" 12 #include "llvm/Support/ErrorHandling.h" 13 #include "gtest/gtest.h" 14 #include <memory> 15 16 using namespace llvm; 17 18 namespace { 19 20 // Custom error class with a default base class and some random 'info' attached. 21 class CustomError : public ErrorInfo<CustomError> { 22 public: 23 // Create an error with some info attached. 24 CustomError(int Info) : Info(Info) {} 25 26 // Get the info attached to this error. 27 int getInfo() const { return Info; } 28 29 // Log this error to a stream. 30 void log(raw_ostream &OS) const override { 31 OS << "CustomError { " << getInfo() << "}"; 32 } 33 34 std::error_code convertToErrorCode() const override { 35 llvm_unreachable("CustomError doesn't support ECError conversion"); 36 } 37 38 // Used by ErrorInfo::classID. 39 static char ID; 40 41 protected: 42 // This error is subclassed below, but we can't use inheriting constructors 43 // yet, so we can't propagate the constructors through ErrorInfo. Instead 44 // we have to have a default constructor and have the subclass initialize all 45 // fields. 46 CustomError() : Info(0) {} 47 48 int Info; 49 }; 50 51 char CustomError::ID = 0; 52 53 // Custom error class with a custom base class and some additional random 54 // 'info'. 55 class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 56 public: 57 // Create a sub-error with some info attached. 58 CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 59 this->Info = Info; 60 } 61 62 // Get the extra info attached to this error. 63 int getExtraInfo() const { return ExtraInfo; } 64 65 // Log this error to a stream. 66 void log(raw_ostream &OS) const override { 67 OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 68 } 69 70 std::error_code convertToErrorCode() const override { 71 llvm_unreachable("CustomSubError doesn't support ECError conversion"); 72 } 73 74 // Used by ErrorInfo::classID. 75 static char ID; 76 77 protected: 78 int ExtraInfo; 79 }; 80 81 char CustomSubError::ID = 0; 82 83 static Error handleCustomError(const CustomError &CE) { return Error(); } 84 85 static void handleCustomErrorVoid(const CustomError &CE) {} 86 87 static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 88 return Error(); 89 } 90 91 static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 92 93 // Test that success values implicitly convert to false, and don't cause crashes 94 // once they've been implicitly converted. 95 TEST(Error, CheckedSuccess) { 96 Error E; 97 EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 98 } 99 100 // Test that unchecked succes values cause an abort. 101 #ifndef NDEBUG 102 TEST(Error, UncheckedSuccess) { 103 EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:") 104 << "Unchecked Error Succes value did not cause abort()"; 105 } 106 #endif 107 108 // ErrorAsOutParameter tester. 109 void errAsOutParamHelper(Error &Err) { 110 ErrorAsOutParameter ErrAsOutParam(Err); 111 // Verify that checked flag is raised - assignment should not crash. 112 Err = Error::success(); 113 // Raise the checked bit manually - caller should still have to test the 114 // error. 115 (void)!!Err; 116 } 117 118 // Test that ErrorAsOutParameter sets the checked flag on construction. 119 TEST(Error, ErrorAsOutParameterChecked) { 120 Error E; 121 errAsOutParamHelper(E); 122 (void)!!E; 123 } 124 125 // Test that ErrorAsOutParameter clears the checked flag on destruction. 126 #ifndef NDEBUG 127 TEST(Error, ErrorAsOutParameterUnchecked) { 128 EXPECT_DEATH({ Error E; errAsOutParamHelper(E); }, 129 "Program aborted due to an unhandled Error:") 130 << "ErrorAsOutParameter did not clear the checked flag on destruction."; 131 } 132 #endif 133 134 // Check that we abort on unhandled failure cases. (Force conversion to bool 135 // to make sure that we don't accidentally treat checked errors as handled). 136 // Test runs in debug mode only. 137 #ifndef NDEBUG 138 TEST(Error, UncheckedError) { 139 auto DropUnhandledError = []() { 140 Error E = make_error<CustomError>(42); 141 (void)!E; 142 }; 143 EXPECT_DEATH(DropUnhandledError(), 144 "Program aborted due to an unhandled Error:") 145 << "Unhandled Error failure value did not cause abort()"; 146 } 147 #endif 148 149 // Check 'Error::isA<T>' method handling. 150 TEST(Error, IsAHandling) { 151 // Check 'isA' handling. 152 Error E = make_error<CustomError>(1); 153 Error F = make_error<CustomSubError>(1, 2); 154 Error G = Error::success(); 155 156 EXPECT_TRUE(E.isA<CustomError>()); 157 EXPECT_FALSE(E.isA<CustomSubError>()); 158 EXPECT_TRUE(F.isA<CustomError>()); 159 EXPECT_TRUE(F.isA<CustomSubError>()); 160 EXPECT_FALSE(G.isA<CustomError>()); 161 162 consumeError(std::move(E)); 163 consumeError(std::move(F)); 164 consumeError(std::move(G)); 165 } 166 167 // Check that we can handle a custom error. 168 TEST(Error, HandleCustomError) { 169 int CaughtErrorInfo = 0; 170 handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 171 CaughtErrorInfo = CE.getInfo(); 172 }); 173 174 EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 175 } 176 177 // Check that handler type deduction also works for handlers 178 // of the following types: 179 // void (const Err&) 180 // Error (const Err&) mutable 181 // void (const Err&) mutable 182 // Error (Err&) 183 // void (Err&) 184 // Error (Err&) mutable 185 // void (Err&) mutable 186 // Error (unique_ptr<Err>) 187 // void (unique_ptr<Err>) 188 // Error (unique_ptr<Err>) mutable 189 // void (unique_ptr<Err>) mutable 190 TEST(Error, HandlerTypeDeduction) { 191 192 handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 193 194 handleAllErrors( 195 make_error<CustomError>(42), 196 [](const CustomError &CE) mutable { return Error::success(); }); 197 198 handleAllErrors(make_error<CustomError>(42), 199 [](const CustomError &CE) mutable {}); 200 201 handleAllErrors(make_error<CustomError>(42), 202 [](CustomError &CE) { return Error::success(); }); 203 204 handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 205 206 handleAllErrors(make_error<CustomError>(42), 207 [](CustomError &CE) mutable { return Error::success(); }); 208 209 handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 210 211 handleAllErrors( 212 make_error<CustomError>(42), 213 [](std::unique_ptr<CustomError> CE) { return Error::success(); }); 214 215 handleAllErrors(make_error<CustomError>(42), 216 [](std::unique_ptr<CustomError> CE) {}); 217 218 handleAllErrors( 219 make_error<CustomError>(42), 220 [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); }); 221 222 handleAllErrors(make_error<CustomError>(42), 223 [](std::unique_ptr<CustomError> CE) mutable {}); 224 225 // Check that named handlers of type 'Error (const Err&)' work. 226 handleAllErrors(make_error<CustomError>(42), handleCustomError); 227 228 // Check that named handlers of type 'void (const Err&)' work. 229 handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 230 231 // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 232 handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 233 234 // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 235 handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 236 } 237 238 // Test that we can handle errors with custom base classes. 239 TEST(Error, HandleCustomErrorWithCustomBaseClass) { 240 int CaughtErrorInfo = 0; 241 int CaughtErrorExtraInfo = 0; 242 handleAllErrors(make_error<CustomSubError>(42, 7), 243 [&](const CustomSubError &SE) { 244 CaughtErrorInfo = SE.getInfo(); 245 CaughtErrorExtraInfo = SE.getExtraInfo(); 246 }); 247 248 EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 249 << "Wrong result from CustomSubError handler"; 250 } 251 252 // Check that we trigger only the first handler that applies. 253 TEST(Error, FirstHandlerOnly) { 254 int DummyInfo = 0; 255 int CaughtErrorInfo = 0; 256 int CaughtErrorExtraInfo = 0; 257 258 handleAllErrors(make_error<CustomSubError>(42, 7), 259 [&](const CustomSubError &SE) { 260 CaughtErrorInfo = SE.getInfo(); 261 CaughtErrorExtraInfo = SE.getExtraInfo(); 262 }, 263 [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 264 265 EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 266 DummyInfo == 0) 267 << "Activated the wrong Error handler(s)"; 268 } 269 270 // Check that general handlers shadow specific ones. 271 TEST(Error, HandlerShadowing) { 272 int CaughtErrorInfo = 0; 273 int DummyInfo = 0; 274 int DummyExtraInfo = 0; 275 276 handleAllErrors( 277 make_error<CustomSubError>(42, 7), 278 [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 279 [&](const CustomSubError &SE) { 280 DummyInfo = SE.getInfo(); 281 DummyExtraInfo = SE.getExtraInfo(); 282 }); 283 284 EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) 285 << "General Error handler did not shadow specific handler"; 286 } 287 288 // Test joinErrors. 289 TEST(Error, CheckJoinErrors) { 290 int CustomErrorInfo1 = 0; 291 int CustomErrorInfo2 = 0; 292 int CustomErrorExtraInfo = 0; 293 Error E = 294 joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 295 296 handleAllErrors(std::move(E), 297 [&](const CustomSubError &SE) { 298 CustomErrorInfo2 = SE.getInfo(); 299 CustomErrorExtraInfo = SE.getExtraInfo(); 300 }, 301 [&](const CustomError &CE) { 302 // Assert that the CustomError instance above is handled 303 // before the 304 // CustomSubError - joinErrors should preserve error 305 // ordering. 306 EXPECT_EQ(CustomErrorInfo2, 0) 307 << "CustomErrorInfo2 should be 0 here. " 308 "joinErrors failed to preserve ordering.\n"; 309 CustomErrorInfo1 = CE.getInfo(); 310 }); 311 312 EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 313 CustomErrorExtraInfo == 7) 314 << "Failed handling compound Error."; 315 } 316 317 // Test that we can consume success values. 318 TEST(Error, ConsumeSuccess) { 319 Error E; 320 consumeError(std::move(E)); 321 } 322 323 TEST(Error, ConsumeError) { 324 Error E = make_error<CustomError>(7); 325 consumeError(std::move(E)); 326 } 327 328 // Test that handleAllUnhandledErrors crashes if an error is not caught. 329 // Test runs in debug mode only. 330 #ifndef NDEBUG 331 TEST(Error, FailureToHandle) { 332 auto FailToHandle = []() { 333 handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 334 errs() << "This should never be called"; 335 exit(1); 336 }); 337 }; 338 339 EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") 340 << "Unhandled Error in handleAllErrors call did not cause an " 341 "abort()"; 342 } 343 #endif 344 345 // Test that handleAllUnhandledErrors crashes if an error is returned from a 346 // handler. 347 // Test runs in debug mode only. 348 #ifndef NDEBUG 349 TEST(Error, FailureFromHandler) { 350 auto ReturnErrorFromHandler = []() { 351 handleAllErrors(make_error<CustomError>(7), 352 [&](std::unique_ptr<CustomSubError> SE) { 353 return Error(std::move(SE)); 354 }); 355 }; 356 357 EXPECT_DEATH(ReturnErrorFromHandler(), 358 "Program aborted due to an unhandled Error:") 359 << " Error returned from handler in handleAllErrors call did not " 360 "cause abort()"; 361 } 362 #endif 363 364 // Test that we can return values from handleErrors. 365 TEST(Error, CatchErrorFromHandler) { 366 int ErrorInfo = 0; 367 368 Error E = handleErrors( 369 make_error<CustomError>(7), 370 [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 371 372 handleAllErrors(std::move(E), 373 [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 374 375 EXPECT_EQ(ErrorInfo, 7) 376 << "Failed to handle Error returned from handleErrors."; 377 } 378 379 // Test that the ExitOnError utility works as expected. 380 TEST(Error, ExitOnError) { 381 ExitOnError ExitOnErr; 382 ExitOnErr.setBanner("Error in tool:"); 383 ExitOnErr.setExitCodeMapper([](const Error &E) { 384 if (E.isA<CustomSubError>()) 385 return 2; 386 return 1; 387 }); 388 389 // Make sure we don't bail on success. 390 ExitOnErr(Error::success()); 391 EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 392 << "exitOnError returned an invalid value for Expected"; 393 394 // Exit tests. 395 EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 396 ::testing::ExitedWithCode(1), "Error in tool:") 397 << "exitOnError returned an unexpected error result"; 398 399 EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 400 ::testing::ExitedWithCode(2), "Error in tool:") 401 << "exitOnError returned an unexpected error result"; 402 } 403 404 // Test Checked Expected<T> in success mode. 405 TEST(Error, CheckedExpectedInSuccessMode) { 406 Expected<int> A = 7; 407 EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 408 // Access is safe in second test, since we checked the error in the first. 409 EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 410 } 411 412 // Test Unchecked Expected<T> in success mode. 413 // We expect this to blow up the same way Error would. 414 // Test runs in debug mode only. 415 #ifndef NDEBUG 416 TEST(Error, UncheckedExpectedInSuccessModeDestruction) { 417 EXPECT_DEATH({ Expected<int> A = 7; }, 418 "Expected<T> must be checked before access or destruction.") 419 << "Unchecekd Expected<T> success value did not cause an abort()."; 420 } 421 #endif 422 423 // Test Unchecked Expected<T> in success mode. 424 // We expect this to blow up the same way Error would. 425 // Test runs in debug mode only. 426 #ifndef NDEBUG 427 TEST(Error, UncheckedExpectedInSuccessModeAccess) { 428 EXPECT_DEATH({ Expected<int> A = 7; *A; }, 429 "Expected<T> must be checked before access or destruction.") 430 << "Unchecekd Expected<T> success value did not cause an abort()."; 431 } 432 #endif 433 434 // Test Unchecked Expected<T> in success mode. 435 // We expect this to blow up the same way Error would. 436 // Test runs in debug mode only. 437 #ifndef NDEBUG 438 TEST(Error, UncheckedExpectedInSuccessModeAssignment) { 439 EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, 440 "Expected<T> must be checked before access or destruction.") 441 << "Unchecekd Expected<T> success value did not cause an abort()."; 442 } 443 #endif 444 445 // Test Expected<T> in failure mode. 446 TEST(Error, ExpectedInFailureMode) { 447 Expected<int> A = make_error<CustomError>(42); 448 EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 449 Error E = A.takeError(); 450 EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 451 consumeError(std::move(E)); 452 } 453 454 // Check that an Expected instance with an error value doesn't allow access to 455 // operator*. 456 // Test runs in debug mode only. 457 #ifndef NDEBUG 458 TEST(Error, AccessExpectedInFailureMode) { 459 Expected<int> A = make_error<CustomError>(42); 460 EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.") 461 << "Incorrect Expected error value"; 462 consumeError(A.takeError()); 463 } 464 #endif 465 466 // Check that an Expected instance with an error triggers an abort if 467 // unhandled. 468 // Test runs in debug mode only. 469 #ifndef NDEBUG 470 TEST(Error, UnhandledExpectedInFailureMode) { 471 EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 472 "Expected<T> must be checked before access or destruction.") 473 << "Unchecked Expected<T> failure value did not cause an abort()"; 474 } 475 #endif 476 477 // Test covariance of Expected. 478 TEST(Error, ExpectedCovariance) { 479 class B {}; 480 class D : public B {}; 481 482 Expected<B *> A1(Expected<D *>(nullptr)); 483 // Check A1 by converting to bool before assigning to it. 484 (void)!!A1; 485 A1 = Expected<D *>(nullptr); 486 // Check A1 again before destruction. 487 (void)!!A1; 488 489 Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 490 // Check A2 by converting to bool before assigning to it. 491 (void)!!A2; 492 A2 = Expected<std::unique_ptr<D>>(nullptr); 493 // Check A2 again before destruction. 494 (void)!!A2; 495 } 496 497 TEST(Error, ErrorCodeConversions) { 498 // Round-trip a success value to check that it converts correctly. 499 EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 500 std::error_code()) 501 << "std::error_code() should round-trip via Error conversions"; 502 503 // Round-trip an error value to check that it converts correctly. 504 EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 505 errc::invalid_argument) 506 << "std::error_code error value should round-trip via Error " 507 "conversions"; 508 509 // Round-trip a success value through ErrorOr/Expected to check that it 510 // converts correctly. 511 { 512 auto Orig = ErrorOr<int>(42); 513 auto RoundTripped = 514 expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); 515 EXPECT_EQ(*Orig, *RoundTripped) 516 << "ErrorOr<T> success value should round-trip via Expected<T> " 517 "conversions."; 518 } 519 520 // Round-trip a failure value through ErrorOr/Expected to check that it 521 // converts correctly. 522 { 523 auto Orig = ErrorOr<int>(errc::invalid_argument); 524 auto RoundTripped = 525 expectedToErrorOr( 526 errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); 527 EXPECT_EQ(Orig.getError(), RoundTripped.getError()) 528 << "ErrorOr<T> failure value should round-trip via Expected<T> " 529 "conversions."; 530 } 531 } 532 533 } // end anon namespace 534