1201 lines · cpp
1//===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Support/Error.h"10#include "llvm-c/Error.h"11 12#include "llvm/ADT/Twine.h"13#include "llvm/Support/Errc.h"14#include "llvm/Support/ErrorHandling.h"15#include "llvm/Testing/Support/Error.h"16#include "gmock/gmock.h"17#include "gtest/gtest-spi.h"18#include "gtest/gtest.h"19#include <memory>20 21using namespace llvm;22 23namespace {24 25// Custom error class with a default base class and some random 'info' attached.26class CustomError : public ErrorInfo<CustomError> {27public:28 // Create an error with some info attached.29 CustomError(int Info) : Info(Info) {}30 31 // Get the info attached to this error.32 int getInfo() const { return Info; }33 34 // Log this error to a stream.35 void log(raw_ostream &OS) const override {36 OS << "CustomError {" << getInfo() << "}";37 }38 39 std::error_code convertToErrorCode() const override {40 llvm_unreachable("CustomError doesn't support ECError conversion");41 }42 43 // Used by ErrorInfo::classID.44 static char ID;45 46protected:47 // This error is subclassed below, but we can't use inheriting constructors48 // yet, so we can't propagate the constructors through ErrorInfo. Instead49 // we have to have a default constructor and have the subclass initialize all50 // fields.51 CustomError() : Info(0) {}52 53 int Info;54};55 56char CustomError::ID = 0;57 58// Custom error class with a custom base class and some additional random59// 'info'.60class CustomSubError : public ErrorInfo<CustomSubError, CustomError> {61public:62 // Create a sub-error with some info attached.63 CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) {64 this->Info = Info;65 }66 67 // Get the extra info attached to this error.68 int getExtraInfo() const { return ExtraInfo; }69 70 // Log this error to a stream.71 void log(raw_ostream &OS) const override {72 OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}";73 }74 75 std::error_code convertToErrorCode() const override {76 llvm_unreachable("CustomSubError doesn't support ECError conversion");77 }78 79 // Used by ErrorInfo::classID.80 static char ID;81 82protected:83 int ExtraInfo;84};85 86char CustomSubError::ID = 0;87 88static Error handleCustomError(const CustomError &CE) {89 return Error::success();90}91 92static void handleCustomErrorVoid(const CustomError &CE) {}93 94static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) {95 return Error::success();96}97 98static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {}99 100// Test that success values implicitly convert to false, and don't cause crashes101// once they've been implicitly converted.102TEST(Error, CheckedSuccess) {103 Error E = Error::success();104 EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";105}106 107// Test that unchecked success values cause an abort.108#if LLVM_ENABLE_ABI_BREAKING_CHECKS109TEST(Error, UncheckedSuccess) {110 EXPECT_DEATH({ Error E = Error::success(); },111 "Program aborted due to an unhandled Error:")112 << "Unchecked Error Succes value did not cause abort()";113}114#endif115 116// ErrorAsOutParameter tester.117void errAsOutParamHelper(Error &Err) {118 ErrorAsOutParameter ErrAsOutParam(&Err);119 // Verify that checked flag is raised - assignment should not crash.120 Err = Error::success();121 // Raise the checked bit manually - caller should still have to test the122 // error.123 (void)!!Err;124}125 126// Test that ErrorAsOutParameter sets the checked flag on construction.127TEST(Error, ErrorAsOutParameterChecked) {128 Error E = Error::success();129 errAsOutParamHelper(E);130 (void)!!E;131}132 133// Test that ErrorAsOutParameter clears the checked flag on destruction.134#if LLVM_ENABLE_ABI_BREAKING_CHECKS135TEST(Error, ErrorAsOutParameterUnchecked) {136 EXPECT_DEATH({ Error E = Error::success(); errAsOutParamHelper(E); },137 "Program aborted due to an unhandled Error:")138 << "ErrorAsOutParameter did not clear the checked flag on destruction.";139}140#endif141 142// Check that we abort on unhandled failure cases. (Force conversion to bool143// to make sure that we don't accidentally treat checked errors as handled).144// Test runs in debug mode only.145#if LLVM_ENABLE_ABI_BREAKING_CHECKS146TEST(Error, UncheckedError) {147 auto DropUnhandledError = []() {148 Error E = make_error<CustomError>(42);149 (void)!E;150 };151 EXPECT_DEATH(DropUnhandledError(),152 "Program aborted due to an unhandled Error:")153 << "Unhandled Error failure value did not cause abort()";154}155#endif156 157// Check 'Error::isA<T>' method handling.158TEST(Error, IsAHandling) {159 // Check 'isA' handling.160 Error E = make_error<CustomError>(1);161 Error F = make_error<CustomSubError>(1, 2);162 Error G = Error::success();163 164 EXPECT_TRUE(E.isA<CustomError>());165 EXPECT_FALSE(E.isA<CustomSubError>());166 EXPECT_TRUE(F.isA<CustomError>());167 EXPECT_TRUE(F.isA<CustomSubError>());168 EXPECT_FALSE(G.isA<CustomError>());169 170 consumeError(std::move(E));171 consumeError(std::move(F));172 consumeError(std::move(G));173}174 175// Check that we can handle a custom error.176TEST(Error, HandleCustomError) {177 int CaughtErrorInfo = 0;178 handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {179 CaughtErrorInfo = CE.getInfo();180 });181 182 EXPECT_EQ(CaughtErrorInfo, 42) << "Wrong result from CustomError handler";183}184 185// Check that handler type deduction also works for handlers186// of the following types:187// void (const Err&)188// Error (const Err&) mutable189// void (const Err&) mutable190// Error (Err&)191// void (Err&)192// Error (Err&) mutable193// void (Err&) mutable194// Error (unique_ptr<Err>)195// void (unique_ptr<Err>)196// Error (unique_ptr<Err>) mutable197// void (unique_ptr<Err>) mutable198TEST(Error, HandlerTypeDeduction) {199 200 handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {});201 202 handleAllErrors(203 make_error<CustomError>(42),204 [](const CustomError &CE) mutable -> Error { return Error::success(); });205 206 handleAllErrors(make_error<CustomError>(42),207 [](const CustomError &CE) mutable {});208 209 handleAllErrors(make_error<CustomError>(42),210 [](CustomError &CE) -> Error { return Error::success(); });211 212 handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {});213 214 handleAllErrors(make_error<CustomError>(42),215 [](CustomError &CE) mutable -> Error { return Error::success(); });216 217 handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {});218 219 handleAllErrors(220 make_error<CustomError>(42),221 [](std::unique_ptr<CustomError> CE) -> Error { return Error::success(); });222 223 handleAllErrors(make_error<CustomError>(42),224 [](std::unique_ptr<CustomError> CE) {});225 226 handleAllErrors(227 make_error<CustomError>(42),228 [](std::unique_ptr<CustomError> CE) mutable -> Error { return Error::success(); });229 230 handleAllErrors(make_error<CustomError>(42),231 [](std::unique_ptr<CustomError> CE) mutable {});232 233 // Check that named handlers of type 'Error (const Err&)' work.234 handleAllErrors(make_error<CustomError>(42), handleCustomError);235 236 // Check that named handlers of type 'void (const Err&)' work.237 handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid);238 239 // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.240 handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP);241 242 // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.243 handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid);244}245 246// Test that we can handle errors with custom base classes.247TEST(Error, HandleCustomErrorWithCustomBaseClass) {248 int CaughtErrorInfo = 0;249 int CaughtErrorExtraInfo = 0;250 handleAllErrors(make_error<CustomSubError>(42, 7),251 [&](const CustomSubError &SE) {252 CaughtErrorInfo = SE.getInfo();253 CaughtErrorExtraInfo = SE.getExtraInfo();254 });255 256 EXPECT_EQ(CaughtErrorInfo, 42) << "Wrong result from CustomSubError handler";257 EXPECT_EQ(CaughtErrorExtraInfo, 7)258 << "Wrong result from CustomSubError handler";259}260 261// Check that we trigger only the first handler that applies.262TEST(Error, FirstHandlerOnly) {263 int DummyInfo = 0;264 int CaughtErrorInfo = 0;265 int CaughtErrorExtraInfo = 0;266 267 handleAllErrors(make_error<CustomSubError>(42, 7),268 [&](const CustomSubError &SE) {269 CaughtErrorInfo = SE.getInfo();270 CaughtErrorExtraInfo = SE.getExtraInfo();271 },272 [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });273 274 EXPECT_EQ(CaughtErrorInfo, 42) << "Activated the wrong Error handler(s)";275 EXPECT_EQ(CaughtErrorExtraInfo, 7) << "Activated the wrong Error handler(s)";276 EXPECT_EQ(DummyInfo, 0) << "Activated the wrong Error handler(s)";277}278 279// Check that general handlers shadow specific ones.280TEST(Error, HandlerShadowing) {281 int CaughtErrorInfo = 0;282 int DummyInfo = 0;283 int DummyExtraInfo = 0;284 285 handleAllErrors(286 make_error<CustomSubError>(42, 7),287 [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },288 [&](const CustomSubError &SE) {289 DummyInfo = SE.getInfo();290 DummyExtraInfo = SE.getExtraInfo();291 });292 293 EXPECT_EQ(CaughtErrorInfo, 42)294 << "General Error handler did not shadow specific handler";295 EXPECT_EQ(DummyInfo, 0)296 << "General Error handler did not shadow specific handler";297 EXPECT_EQ(DummyExtraInfo, 0)298 << "General Error handler did not shadow specific handler";299}300 301// Test joinErrors.302TEST(Error, CheckJoinErrors) {303 int CustomErrorInfo1 = 0;304 int CustomErrorInfo2 = 0;305 int CustomErrorExtraInfo = 0;306 Error E =307 joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7));308 309 handleAllErrors(std::move(E),310 [&](const CustomSubError &SE) {311 CustomErrorInfo2 = SE.getInfo();312 CustomErrorExtraInfo = SE.getExtraInfo();313 },314 [&](const CustomError &CE) {315 // Assert that the CustomError instance above is handled316 // before the317 // CustomSubError - joinErrors should preserve error318 // ordering.319 EXPECT_EQ(CustomErrorInfo2, 0)320 << "CustomErrorInfo2 should be 0 here. "321 "joinErrors failed to preserve ordering.\n";322 CustomErrorInfo1 = CE.getInfo();323 });324 325 EXPECT_EQ(CustomErrorInfo1, 7) << "Failed handling compound Error.";326 EXPECT_EQ(CustomErrorInfo2, 42) << "Failed handling compound Error.";327 EXPECT_EQ(CustomErrorExtraInfo, 7) << "Failed handling compound Error.";328 329 // Test appending a single item to a list.330 {331 int Sum = 0;332 handleAllErrors(333 joinErrors(334 joinErrors(make_error<CustomError>(7),335 make_error<CustomError>(7)),336 make_error<CustomError>(7)),337 [&](const CustomError &CE) {338 Sum += CE.getInfo();339 });340 EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list.";341 }342 343 // Test prepending a single item to a list.344 {345 int Sum = 0;346 handleAllErrors(347 joinErrors(348 make_error<CustomError>(7),349 joinErrors(make_error<CustomError>(7),350 make_error<CustomError>(7))),351 [&](const CustomError &CE) {352 Sum += CE.getInfo();353 });354 EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list.";355 }356 357 // Test concatenating two error lists.358 {359 int Sum = 0;360 handleAllErrors(361 joinErrors(362 joinErrors(363 make_error<CustomError>(7),364 make_error<CustomError>(7)),365 joinErrors(366 make_error<CustomError>(7),367 make_error<CustomError>(7))),368 [&](const CustomError &CE) {369 Sum += CE.getInfo();370 });371 EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate error lists.";372 }373}374 375// Test that we can consume success values.376TEST(Error, ConsumeSuccess) {377 Error E = Error::success();378 consumeError(std::move(E));379}380 381TEST(Error, ConsumeError) {382 Error E = make_error<CustomError>(7);383 consumeError(std::move(E));384}385 386// Test that handleAllUnhandledErrors crashes if an error is not caught.387// Test runs in debug mode only.388#if LLVM_ENABLE_ABI_BREAKING_CHECKS389TEST(Error, FailureToHandle) {390 auto FailToHandle = []() {391 handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) {392 errs() << "This should never be called";393 exit(1);394 });395 };396 397 EXPECT_DEATH(FailToHandle(),398 "Failure value returned from cantFail wrapped call\n"399 "CustomError \\{7\\}")400 << "Unhandled Error in handleAllErrors call did not cause an "401 "abort()";402}403#endif404 405// Test that handleAllUnhandledErrors crashes if an error is returned from a406// handler.407// Test runs in debug mode only.408#if LLVM_ENABLE_ABI_BREAKING_CHECKS409TEST(Error, FailureFromHandler) {410 auto ReturnErrorFromHandler = []() {411 handleAllErrors(make_error<CustomError>(7),412 [&](std::unique_ptr<CustomSubError> SE) {413 return Error(std::move(SE));414 });415 };416 417 EXPECT_DEATH(ReturnErrorFromHandler(),418 "Failure value returned from cantFail wrapped call\n"419 "CustomError \\{7\\}")420 << " Error returned from handler in handleAllErrors call did not "421 "cause abort()";422}423#endif424 425// Test that we can return values from handleErrors.426TEST(Error, CatchErrorFromHandler) {427 int ErrorInfo = 0;428 429 Error E = handleErrors(430 make_error<CustomError>(7),431 [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });432 433 handleAllErrors(std::move(E),434 [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });435 436 EXPECT_EQ(ErrorInfo, 7)437 << "Failed to handle Error returned from handleErrors.";438}439 440TEST(Error, StringError) {441 std::string Msg;442 raw_string_ostream S(Msg);443 logAllUnhandledErrors(444 make_error<StringError>("foo" + Twine(42), inconvertibleErrorCode()), S);445 EXPECT_EQ(Msg, "foo42\n") << "Unexpected StringError log result";446 447 auto EC =448 errorToErrorCode(make_error<StringError>("", errc::invalid_argument));449 EXPECT_EQ(EC, errc::invalid_argument)450 << "Failed to convert StringError to error_code.";451}452 453TEST(Error, createStringError) {454 static const char *Bar = "bar";455 static const std::error_code EC = errc::invalid_argument;456 std::string Msg;457 raw_string_ostream S(Msg);458 logAllUnhandledErrors(createStringError(EC, "foo%s%d0x%" PRIx8, Bar, 1, 0xff),459 S);460 EXPECT_EQ(Msg, "foobar10xff\n")461 << "Unexpected createStringError() log result";462 463 Msg.clear();464 logAllUnhandledErrors(createStringError(EC, Bar), S);465 EXPECT_EQ(Msg, "bar\n")466 << "Unexpected createStringError() (overloaded) log result";467 468 Msg.clear();469 auto Res = errorToErrorCode(createStringError(EC, "foo%s", Bar));470 EXPECT_EQ(Res, EC)471 << "Failed to convert createStringError() result to error_code.";472}473 474// Test that the ExitOnError utility works as expected.475TEST(ErrorDeathTest, ExitOnError) {476 ExitOnError ExitOnErr;477 ExitOnErr.setBanner("Error in tool:");478 ExitOnErr.setExitCodeMapper([](const Error &E) {479 if (E.isA<CustomSubError>())480 return 2;481 return 1;482 });483 484 // Make sure we don't bail on success.485 ExitOnErr(Error::success());486 EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7)487 << "exitOnError returned an invalid value for Expected";488 489 int A = 7;490 int &B = ExitOnErr(Expected<int&>(A));491 EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference";492 493 // Exit tests.494 EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)),495 ::testing::ExitedWithCode(1), "Error in tool:")496 << "exitOnError returned an unexpected error result";497 498 EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))),499 ::testing::ExitedWithCode(2), "Error in tool:")500 << "exitOnError returned an unexpected error result";501}502 503// Test that the ExitOnError utility works as expected.504TEST(Error, CantFailSuccess) {505 cantFail(Error::success());506 507 int X = cantFail(Expected<int>(42));508 EXPECT_EQ(X, 42) << "Expected value modified by cantFail";509 510 int Dummy = 42;511 int &Y = cantFail(Expected<int&>(Dummy));512 EXPECT_EQ(&Dummy, &Y) << "Reference mangled by cantFail";513}514 515// Test that cantFail results in a crash if you pass it a failure value.516#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)517TEST(Error, CantFailDeath) {518 EXPECT_DEATH(cantFail(make_error<StringError>("Original error message",519 inconvertibleErrorCode()),520 "Cantfail call failed"),521 "Cantfail call failed\n"522 "Original error message")523 << "cantFail(Error) did not cause an abort for failure value";524 525 EXPECT_DEATH(526 {527 auto IEC = inconvertibleErrorCode();528 int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC)));529 (void)X;530 },531 "Failure value returned from cantFail wrapped call")532 << "cantFail(Expected<int>) did not cause an abort for failure value";533}534#endif535 536 537// Test Checked Expected<T> in success mode.538TEST(Error, CheckedExpectedInSuccessMode) {539 Expected<int> A = 7;540 EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'";541 // Access is safe in second test, since we checked the error in the first.542 EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";543}544 545// Test Expected with reference type.546TEST(Error, ExpectedWithReferenceType) {547 int A = 7;548 Expected<int&> B = A;549 // 'Check' B.550 (void)!!B;551 int &C = *B;552 EXPECT_EQ(&A, &C) << "Expected failed to propagate reference";553}554 555// Test Unchecked Expected<T> in success mode.556// We expect this to blow up the same way Error would.557// Test runs in debug mode only.558#if LLVM_ENABLE_ABI_BREAKING_CHECKS559TEST(Error, UncheckedExpectedInSuccessModeDestruction) {560 EXPECT_DEATH({ Expected<int> A = 7; },561 "Expected<T> must be checked before access or destruction.")562 << "Unchecked Expected<T> success value did not cause an abort().";563}564#endif565 566// Test Unchecked Expected<T> in success mode.567// We expect this to blow up the same way Error would.568// Test runs in debug mode only.569#if LLVM_ENABLE_ABI_BREAKING_CHECKS570TEST(Error, UncheckedExpectedInSuccessModeAccess) {571 EXPECT_DEATH(572 {573 const Expected<int> A = 7;574 *A;575 },576 "Expected<T> must be checked before access or destruction.")577 << "Unchecked Expected<T> success value did not cause an abort().";578}579#endif580 581// Test Unchecked Expected<T> in success mode.582// We expect this to blow up the same way Error would.583// Test runs in debug mode only.584#if LLVM_ENABLE_ABI_BREAKING_CHECKS585TEST(Error, UncheckedExpectedInSuccessModeAssignment) {586 EXPECT_DEATH(587 {588 Expected<int> A = 7;589 A = 7;590 },591 "Expected<T> must be checked before access or destruction.")592 << "Unchecked Expected<T> success value did not cause an abort().";593}594#endif595 596// Test Expected<T> in failure mode.597TEST(Error, ExpectedInFailureMode) {598 Expected<int> A = make_error<CustomError>(42);599 EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";600 Error E = A.takeError();601 EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";602 consumeError(std::move(E));603}604 605// Check that an Expected instance with an error value doesn't allow access to606// operator*.607// Test runs in debug mode only.608#if LLVM_ENABLE_ABI_BREAKING_CHECKS609TEST(Error, AccessExpectedInFailureMode) {610 Expected<int> A = make_error<CustomError>(42);611 EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.")612 << "Incorrect Expected error value";613 consumeError(A.takeError());614}615#endif616 617// Check that an Expected instance with an error triggers an abort if618// unhandled.619// Test runs in debug mode only.620#if LLVM_ENABLE_ABI_BREAKING_CHECKS621TEST(Error, UnhandledExpectedInFailureMode) {622 EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },623 "Expected<T> must be checked before access or destruction.")624 << "Unchecked Expected<T> failure value did not cause an abort()";625}626#endif627 628// Test covariance of Expected.629TEST(Error, ExpectedCovariance) {630 class B {};631 class D : public B {};632 633 Expected<B *> A1(Expected<D *>(nullptr));634 // Check A1 by converting to bool before assigning to it.635 (void)!!A1;636 A1 = Expected<D *>(nullptr);637 // Check A1 again before destruction.638 (void)!!A1;639 640 Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));641 // Check A2 by converting to bool before assigning to it.642 (void)!!A2;643 A2 = Expected<std::unique_ptr<D>>(nullptr);644 // Check A2 again before destruction.645 (void)!!A2;646}647 648// Test that handleExpected just returns success values.649TEST(Error, HandleExpectedSuccess) {650 auto ValOrErr =651 handleExpected(Expected<int>(42),652 []() { return Expected<int>(43); });653 EXPECT_TRUE(!!ValOrErr)654 << "handleExpected should have returned a success value here";655 EXPECT_EQ(*ValOrErr, 42)656 << "handleExpected should have returned the original success value here";657}658 659enum FooStrategy { Aggressive, Conservative };660 661static Expected<int> foo(FooStrategy S) {662 if (S == Aggressive)663 return make_error<CustomError>(7);664 return 42;665}666 667// Test that handleExpected invokes the error path if errors are not handled.668TEST(Error, HandleExpectedUnhandledError) {669 // foo(Aggressive) should return a CustomError which should pass through as670 // there is no handler for CustomError.671 auto ValOrErr =672 handleExpected(673 foo(Aggressive),674 []() { return foo(Conservative); });675 676 EXPECT_FALSE(!!ValOrErr)677 << "handleExpected should have returned an error here";678 auto Err = ValOrErr.takeError();679 EXPECT_TRUE(Err.isA<CustomError>())680 << "handleExpected should have returned the CustomError generated by "681 "foo(Aggressive) here";682 consumeError(std::move(Err));683}684 685// Test that handleExpected invokes the fallback path if errors are handled.686TEST(Error, HandleExpectedHandledError) {687 // foo(Aggressive) should return a CustomError which should handle triggering688 // the fallback path.689 auto ValOrErr =690 handleExpected(691 foo(Aggressive),692 []() { return foo(Conservative); },693 [](const CustomError&) { /* do nothing */ });694 695 EXPECT_TRUE(!!ValOrErr)696 << "handleExpected should have returned a success value here";697 EXPECT_EQ(*ValOrErr, 42)698 << "handleExpected returned the wrong success value";699}700 701TEST(Error, ErrorCodeConversions) {702 // Round-trip a success value to check that it converts correctly.703 EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),704 std::error_code())705 << "std::error_code() should round-trip via Error conversions";706 707 // Round-trip an error value to check that it converts correctly.708 EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)),709 errc::invalid_argument)710 << "std::error_code error value should round-trip via Error "711 "conversions";712 713 // Round-trip a success value through ErrorOr/Expected to check that it714 // converts correctly.715 {716 auto Orig = ErrorOr<int>(42);717 auto RoundTripped =718 expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42)));719 EXPECT_EQ(*Orig, *RoundTripped)720 << "ErrorOr<T> success value should round-trip via Expected<T> "721 "conversions.";722 }723 724 // Round-trip a failure value through ErrorOr/Expected to check that it725 // converts correctly.726 {727 auto Orig = ErrorOr<int>(errc::invalid_argument);728 auto RoundTripped =729 expectedToErrorOr(730 errorOrToExpected(ErrorOr<int>(errc::invalid_argument)));731 EXPECT_EQ(Orig.getError(), RoundTripped.getError())732 << "ErrorOr<T> failure value should round-trip via Expected<T> "733 "conversions.";734 }735}736 737// Test that error messages work.738TEST(Error, ErrorMessage) {739 EXPECT_EQ(toString(Error::success()), "");740 741 Error E0 = Error::success();742 EXPECT_EQ(toStringWithoutConsuming(E0), "");743 EXPECT_EQ(toString(std::move(E0)), "");744 745 Error E1 = make_error<CustomError>(0);746 EXPECT_EQ(toStringWithoutConsuming(E1), "CustomError {0}");747 EXPECT_EQ(toString(std::move(E1)), "CustomError {0}");748 749 Error E2 = make_error<CustomError>(0);750 visitErrors(E2, [](const ErrorInfoBase &EI) {751 EXPECT_EQ(EI.message(), "CustomError {0}");752 });753 handleAllErrors(std::move(E2), [](const CustomError &CE) {754 EXPECT_EQ(CE.message(), "CustomError {0}");755 });756 757 Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1));758 EXPECT_EQ(toStringWithoutConsuming(E3), "CustomError {0}\n"759 "CustomError {1}");760 EXPECT_EQ(toString(std::move(E3)), "CustomError {0}\n"761 "CustomError {1}");762}763 764TEST(Error, Stream) {765 {766 Error OK = Error::success();767 std::string Buf;768 llvm::raw_string_ostream S(Buf);769 S << OK;770 EXPECT_EQ("success", Buf);771 consumeError(std::move(OK));772 }773 {774 Error E1 = make_error<CustomError>(0);775 std::string Buf;776 llvm::raw_string_ostream S(Buf);777 S << E1;778 EXPECT_EQ("CustomError {0}", Buf);779 consumeError(std::move(E1));780 }781}782 783TEST(Error, SucceededMatcher) {784 EXPECT_THAT_ERROR(Error::success(), Succeeded());785 EXPECT_NONFATAL_FAILURE(786 EXPECT_THAT_ERROR(make_error<CustomError>(0), Succeeded()),787 "Expected: succeeded\n Actual: failed (CustomError {0})");788 789 EXPECT_THAT_EXPECTED(Expected<int>(0), Succeeded());790 EXPECT_NONFATAL_FAILURE(791 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),792 Succeeded()),793 "Expected: succeeded\n Actual: failed (CustomError {0})");794 int a = 1;795 EXPECT_THAT_EXPECTED(Expected<int &>(a), Succeeded());796}797 798TEST(Error, FailedMatcher) {799 EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed());800 EXPECT_NONFATAL_FAILURE(EXPECT_THAT_ERROR(Error::success(), Failed()),801 "Expected: failed\n Actual: succeeded");802 803 EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomError>());804 EXPECT_NONFATAL_FAILURE(805 EXPECT_THAT_ERROR(Error::success(), Failed<CustomError>()),806 "Expected: failed with Error of given type\n Actual: succeeded");807 EXPECT_NONFATAL_FAILURE(808 EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomSubError>()),809 "Error was not of given type");810 EXPECT_NONFATAL_FAILURE(811 EXPECT_THAT_ERROR(812 joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)),813 Failed<CustomError>()),814 "multiple errors");815 816 EXPECT_THAT_ERROR(817 make_error<CustomError>(0),818 Failed<CustomError>(testing::Property(&CustomError::getInfo, 0)));819 EXPECT_NONFATAL_FAILURE(820 EXPECT_THAT_ERROR(821 make_error<CustomError>(0),822 Failed<CustomError>(testing::Property(&CustomError::getInfo, 1))),823 "Expected: failed with Error of given type and the error is an object "824 "whose given property is equal to 1\n"825 " Actual: failed (CustomError {0})");826 EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<ErrorInfoBase>());827 828 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), Failed());829 EXPECT_NONFATAL_FAILURE(830 EXPECT_THAT_EXPECTED(Expected<int>(0), Failed()),831 "Expected: failed\n Actual: succeeded with value 0");832 EXPECT_THAT_EXPECTED(Expected<int &>(make_error<CustomError>(0)), Failed());833}834 835TEST(Error, HasValueMatcher) {836 EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(0));837 EXPECT_NONFATAL_FAILURE(838 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),839 HasValue(0)),840 "Expected: succeeded with value (is equal to 0)\n"841 " Actual: failed (CustomError {0})");842 EXPECT_NONFATAL_FAILURE(843 EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(0)),844 "Expected: succeeded with value (is equal to 0)\n"845 " Actual: succeeded with value 1, (isn't equal to 0)");846 847 int a = 1;848 EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(testing::Eq(1)));849 850 EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(testing::Gt(0)));851 EXPECT_NONFATAL_FAILURE(852 EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(testing::Gt(1))),853 "Expected: succeeded with value (is > 1)\n"854 " Actual: succeeded with value 0, (isn't > 1)");855 EXPECT_NONFATAL_FAILURE(856 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),857 HasValue(testing::Gt(1))),858 "Expected: succeeded with value (is > 1)\n"859 " Actual: failed (CustomError {0})");860}861 862TEST(Error, FailedWithMessageMatcher) {863 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),864 FailedWithMessage("CustomError {0}"));865 866 EXPECT_NONFATAL_FAILURE(867 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(1)),868 FailedWithMessage("CustomError {0}")),869 "Expected: failed with Error whose message has 1 element that is equal "870 "to \"CustomError {0}\"\n"871 " Actual: failed (CustomError {1})");872 873 EXPECT_NONFATAL_FAILURE(874 EXPECT_THAT_EXPECTED(Expected<int>(0),875 FailedWithMessage("CustomError {0}")),876 "Expected: failed with Error whose message has 1 element that is equal "877 "to \"CustomError {0}\"\n"878 " Actual: succeeded with value 0");879 880 EXPECT_NONFATAL_FAILURE(881 EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)),882 FailedWithMessage("CustomError {0}", "CustomError {0}")),883 "Expected: failed with Error whose message has 2 elements where\n"884 "element #0 is equal to \"CustomError {0}\",\n"885 "element #1 is equal to \"CustomError {0}\"\n"886 " Actual: failed (CustomError {0}), which has 1 element");887 888 EXPECT_NONFATAL_FAILURE(889 EXPECT_THAT_EXPECTED(890 Expected<int>(joinErrors(make_error<CustomError>(0),891 make_error<CustomError>(0))),892 FailedWithMessage("CustomError {0}")),893 "Expected: failed with Error whose message has 1 element that is equal "894 "to \"CustomError {0}\"\n"895 " Actual: failed (CustomError {0}; CustomError {0}), which has 2 elements");896 897 EXPECT_THAT_ERROR(898 joinErrors(make_error<CustomError>(0), make_error<CustomError>(0)),899 FailedWithMessageArray(testing::SizeIs(2)));900}901 902TEST(Error, C_API) {903 EXPECT_THAT_ERROR(unwrap(wrap(Error::success())), Succeeded())904 << "Failed to round-trip Error success value via C API";905 EXPECT_THAT_ERROR(unwrap(wrap(make_error<CustomError>(0))),906 Failed<CustomError>())907 << "Failed to round-trip Error failure value via C API";908 909 auto Err =910 wrap(make_error<StringError>("test message", inconvertibleErrorCode()));911 EXPECT_EQ(LLVMGetErrorTypeId(Err), LLVMGetStringErrorTypeId())912 << "Failed to match error type ids via C API";913 char *ErrMsg = LLVMGetErrorMessage(Err);914 EXPECT_STREQ(ErrMsg, "test message")915 << "Failed to roundtrip StringError error message via C API";916 LLVMDisposeErrorMessage(ErrMsg);917 918 bool GotCSE = false;919 bool GotCE = false;920 handleAllErrors(921 unwrap(wrap(joinErrors(make_error<CustomSubError>(42, 7),922 make_error<CustomError>(42)))),923 [&](CustomSubError &CSE) {924 GotCSE = true;925 },926 [&](CustomError &CE) {927 GotCE = true;928 });929 EXPECT_TRUE(GotCSE) << "Failed to round-trip ErrorList via C API";930 EXPECT_TRUE(GotCE) << "Failed to round-trip ErrorList via C API";931 932 LLVMCantFail(wrap(Error::success()));933}934 935TEST(Error, FileErrorTest) {936#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST937 EXPECT_DEATH(938 {939 Error S = Error::success();940 consumeError(createFileError("file.bin", std::move(S)));941 },942 "");943#endif944 // Not allowed, would fail at compile-time945 //consumeError(createFileError("file.bin", ErrorSuccess()));946 947 Error E1 = make_error<CustomError>(1);948 Error FE1 = createFileError("file.bin", std::move(E1));949 EXPECT_EQ(toString(std::move(FE1)), "'file.bin': CustomError {1}");950 951 Error E2 = make_error<CustomError>(2);952 Error FE2 = createFileError("file.bin", std::move(E2));953 handleAllErrors(std::move(FE2), [](const FileError &F) {954 EXPECT_EQ(F.message(), "'file.bin': CustomError {2}");955 });956 957 Error E3 = make_error<CustomError>(3);958 Error FE3 = createFileError("file.bin", std::move(E3));959 auto E31 = handleErrors(std::move(FE3), [](std::unique_ptr<FileError> F) {960 return F->takeError();961 });962 handleAllErrors(std::move(E31), [](const CustomError &C) {963 EXPECT_EQ(C.message(), "CustomError {3}");964 });965 966 Error FE4 =967 joinErrors(createFileError("file.bin", make_error<CustomError>(41)),968 createFileError("file2.bin", make_error<CustomError>(42)));969 EXPECT_EQ(toString(std::move(FE4)), "'file.bin': CustomError {41}\n"970 "'file2.bin': CustomError {42}");971 972 Error FE5 = createFileError("", make_error<CustomError>(5));973 EXPECT_EQ(toString(std::move(FE5)), "'': CustomError {5}");974 975 Error FE6 = createFileError("unused", make_error<CustomError>(6));976 handleAllErrors(std::move(FE6), [](std::unique_ptr<FileError> F) {977 EXPECT_EQ(F->messageWithoutFileInfo(), "CustomError {6}");978 });979 980 Error FE7 =981 createFileError("file.bin", make_error_code(std::errc::invalid_argument),982 "invalid argument");983 EXPECT_EQ(toString(std::move(FE7)), "'file.bin': invalid argument");984 985 StringRef Argument = "arg";986 Error FE8 =987 createFileError("file.bin", make_error_code(std::errc::invalid_argument),988 "invalid argument '%s'", Argument.str().c_str());989 EXPECT_EQ(toString(std::move(FE8)), "'file.bin': invalid argument 'arg'");990}991 992TEST(Error, FileErrorErrorCode) {993 for (std::error_code EC : {994 make_error_code(std::errc::not_supported),995 make_error_code(std::errc::invalid_argument),996 make_error_code(std::errc::no_such_file_or_directory),997 }) {998 EXPECT_EQ(EC, errorToErrorCode(999 createFileError("file.bin", EC)));1000 EXPECT_EQ(EC, errorToErrorCode(1001 createFileError("file.bin", /*Line=*/5, EC)));1002 EXPECT_EQ(EC, errorToErrorCode(1003 createFileError("file.bin", errorCodeToError(EC))));1004 EXPECT_EQ(EC, errorToErrorCode(1005 createFileError("file.bin", /*Line=*/5, errorCodeToError(EC))));1006 }1007 1008 // inconvertibleErrorCode() should be wrapped to avoid a fatal error.1009 EXPECT_EQ(1010 "A file error occurred.",1011 errorToErrorCode(createFileError("file.bin", inconvertibleErrorCode()))1012 .message());1013 EXPECT_EQ(1014 "A file error occurred.",1015 errorToErrorCode(createFileError("file.bin", /*Line=*/5, inconvertibleErrorCode()))1016 .message());1017}1018 1019enum class test_error_code {1020 unspecified = 1,1021 error_1,1022 error_2,1023};1024 1025} // end anon namespace1026 1027namespace std {1028 template <>1029 struct is_error_code_enum<test_error_code> : std::true_type {};1030} // namespace std1031 1032namespace {1033 1034const std::error_category &TErrorCategory();1035 1036inline std::error_code make_error_code(test_error_code E) {1037 return std::error_code(static_cast<int>(E), TErrorCategory());1038}1039 1040class TestDebugError : public ErrorInfo<TestDebugError, StringError> {1041public:1042 using ErrorInfo<TestDebugError, StringError >::ErrorInfo; // inherit constructors1043 TestDebugError(const Twine &S) : ErrorInfo(S, test_error_code::unspecified) {}1044 static char ID;1045};1046 1047class TestErrorCategory : public std::error_category {1048public:1049 const char *name() const noexcept override { return "error"; }1050 std::string message(int Condition) const override {1051 switch (static_cast<test_error_code>(Condition)) {1052 case test_error_code::unspecified:1053 return "An unknown error has occurred.";1054 case test_error_code::error_1:1055 return "Error 1.";1056 case test_error_code::error_2:1057 return "Error 2.";1058 }1059 llvm_unreachable("Unrecognized test_error_code");1060 }1061};1062 1063const std::error_category &TErrorCategory() {1064 static TestErrorCategory TestErrCategory;1065 return TestErrCategory;1066}1067 1068char TestDebugError::ID;1069 1070TEST(Error, SubtypeStringErrorTest) {1071 auto E1 = make_error<TestDebugError>(test_error_code::error_1);1072 EXPECT_EQ(toString(std::move(E1)), "Error 1.");1073 1074 auto E2 = make_error<TestDebugError>(test_error_code::error_1,1075 "Detailed information");1076 EXPECT_EQ(toString(std::move(E2)), "Error 1. Detailed information");1077 1078 auto E3 = make_error<TestDebugError>(test_error_code::error_2);1079 handleAllErrors(std::move(E3), [](const TestDebugError &F) {1080 EXPECT_EQ(F.message(), "Error 2.");1081 });1082 1083 auto E4 = joinErrors(make_error<TestDebugError>(test_error_code::error_1,1084 "Detailed information"),1085 make_error<TestDebugError>(test_error_code::error_2));1086 EXPECT_EQ(toString(std::move(E4)), "Error 1. Detailed information\n"1087 "Error 2.");1088}1089 1090static Error createAnyError() {1091 return errorCodeToError(test_error_code::unspecified);1092}1093 1094struct MoveOnlyBox {1095 std::optional<int> Box;1096 1097 explicit MoveOnlyBox(int I) : Box(I) {}1098 MoveOnlyBox() = default;1099 MoveOnlyBox(MoveOnlyBox &&) = default;1100 MoveOnlyBox &operator=(MoveOnlyBox &&) = default;1101 1102 MoveOnlyBox(const MoveOnlyBox &) = delete;1103 MoveOnlyBox &operator=(const MoveOnlyBox &) = delete;1104 1105 bool operator==(const MoveOnlyBox &RHS) const {1106 if (bool(Box) != bool(RHS.Box))1107 return false;1108 return Box ? *Box == *RHS.Box : false;1109 }1110};1111 1112TEST(Error, moveInto) {1113 // Use MoveOnlyBox as the T in Expected<T>.1114 auto make = [](int I) -> Expected<MoveOnlyBox> { return MoveOnlyBox(I); };1115 auto makeFailure = []() -> Expected<MoveOnlyBox> { return createAnyError(); };1116 1117 {1118 MoveOnlyBox V;1119 1120 // Failure with no prior value.1121 EXPECT_THAT_ERROR(makeFailure().moveInto(V), Failed());1122 EXPECT_EQ(std::nullopt, V.Box);1123 1124 // Success with no prior value.1125 EXPECT_THAT_ERROR(make(5).moveInto(V), Succeeded());1126 EXPECT_EQ(5, V.Box);1127 1128 // Success with an existing value.1129 EXPECT_THAT_ERROR(make(7).moveInto(V), Succeeded());1130 EXPECT_EQ(7, V.Box);1131 1132 // Failure with an existing value. Might be nice to assign a1133 // default-constructed value in this case, but for now it's being left1134 // alone.1135 EXPECT_THAT_ERROR(makeFailure().moveInto(V), Failed());1136 EXPECT_EQ(7, V.Box);1137 }1138 1139 // Check that this works with optionals too.1140 {1141 // Same cases as above.1142 std::optional<MoveOnlyBox> MaybeV;1143 EXPECT_THAT_ERROR(makeFailure().moveInto(MaybeV), Failed());1144 EXPECT_EQ(std::nullopt, MaybeV);1145 1146 EXPECT_THAT_ERROR(make(5).moveInto(MaybeV), Succeeded());1147 EXPECT_EQ(MoveOnlyBox(5), MaybeV);1148 1149 EXPECT_THAT_ERROR(make(7).moveInto(MaybeV), Succeeded());1150 EXPECT_EQ(MoveOnlyBox(7), MaybeV);1151 1152 EXPECT_THAT_ERROR(makeFailure().moveInto(MaybeV), Failed());1153 EXPECT_EQ(MoveOnlyBox(7), MaybeV);1154 }1155}1156 1157TEST(Error, FatalBadAllocErrorHandlersInteraction) {1158 auto ErrorHandler = [](void *Data, const char *, bool) {};1159 install_fatal_error_handler(ErrorHandler, nullptr);1160 // The following call should not crash; previously, a bug in1161 // install_bad_alloc_error_handler asserted that no fatal-error handler is1162 // installed already.1163 install_bad_alloc_error_handler(ErrorHandler, nullptr);1164 1165 // Don't interfere with other tests.1166 remove_fatal_error_handler();1167 remove_bad_alloc_error_handler();1168}1169 1170TEST(Error, BadAllocFatalErrorHandlersInteraction) {1171 auto ErrorHandler = [](void *Data, const char *, bool) {};1172 install_bad_alloc_error_handler(ErrorHandler, nullptr);1173 // The following call should not crash; related to1174 // FatalBadAllocErrorHandlersInteraction: Ensure that the error does not occur1175 // in the other direction.1176 install_fatal_error_handler(ErrorHandler, nullptr);1177 1178 // Don't interfere with other tests.1179 remove_fatal_error_handler();1180 remove_bad_alloc_error_handler();1181}1182 1183TEST(Error, ForwardToExpected) {1184 auto ErrorReturningFct = [](bool Fail) {1185 return Fail ? make_error<StringError>(llvm::errc::invalid_argument,1186 "Some Error")1187 : Error::success();1188 };1189 auto ExpectedReturningFct = [&](bool Fail) -> Expected<int> {1190 auto Err = ErrorReturningFct(Fail);1191 if (Err)1192 return Err;1193 return 42;1194 };1195 std::optional<int> MaybeV;1196 EXPECT_THAT_ERROR(ExpectedReturningFct(true).moveInto(MaybeV), Failed());1197 EXPECT_THAT_ERROR(ExpectedReturningFct(false).moveInto(MaybeV), Succeeded());1198 EXPECT_EQ(*MaybeV, 42);1199}1200} // namespace1201