diff options
| author | Lang Hames <lhames@gmail.com> | 2016-03-18 00:12:37 +0000 |
|---|---|---|
| committer | Lang Hames <lhames@gmail.com> | 2016-03-18 00:12:37 +0000 |
| commit | 01864a2d01527adcd67000fdba29a4b5a82e1385 (patch) | |
| tree | 220b4fdf402b63cf76fb9c9ed482d7f859b73200 /llvm/unittests/Support | |
| parent | 363d331f992d744c61c1d7b789d2b7f5f091fb79 (diff) | |
| download | bcm5719-llvm-01864a2d01527adcd67000fdba29a4b5a82e1385.tar.gz bcm5719-llvm-01864a2d01527adcd67000fdba29a4b5a82e1385.zip | |
[Support] Refactor Error unit tests to avoid duplicating work.
Suggested by Dave Blaikie in review for r263749. Thanks Dave!
llvm-svn: 263768
Diffstat (limited to 'llvm/unittests/Support')
| -rw-r--r-- | llvm/unittests/Support/ErrorTest.cpp | 523 |
1 files changed, 229 insertions, 294 deletions
diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp index 343a2d240c1..788dcd3c8b8 100644 --- a/llvm/unittests/Support/ErrorTest.cpp +++ b/llvm/unittests/Support/ErrorTest.cpp @@ -16,43 +16,6 @@ using namespace llvm; namespace { -// Test: -// -// Constructing success. -// - Silent acceptance of tested success. -// - Programmatic error on untested success. -// -// Custom error class. -// - Creation of a custom error class with a default base class. -// - Handling of a custom error class with a default base class. -// - Handler type deduction. -// - Failure to handle a custom error class. -// - Isa testing of a custom error class. -// -// - Creation of a custom error class with a custom base class. -// - Handling of a custom error class with a default base class. -// - Correct shadowing of handlers. -// -// Utility functions: -// - join_errors to defer errors. -// - consume_error to consume a "safe" error without any output. -// - handleAllUnhandledErrors to assert that all errors are handled. -// - logAllUnhandledErrors to log errors to a stream. -// - ExitOnError tests. -// -// Expected tests: -// - Expected<T> with T. -// - Expected<T> with Error. -// - Failure to handle an Expected<T> in failure mode. -// - Error extraction (Expected -> Error). -// -// std::error_code: -// - std::error_code to Error in success mode. -// - std::error_code to Error (ECError) in failure mode. -// - Error to std::error_code in success mode. -// - Error (ECError) to std::error_code in failure mode. -// - // Custom error class with a default base class and some random 'info' attached. class CustomError : public ErrorInfo<CustomError> { public: @@ -98,28 +61,6 @@ protected: int ExtraInfo; }; -// Verify that success values that are checked (i.e. cast to 'bool') are -// destructed without error, and that unchecked success values cause an -// abort. -TEST(Error, CheckSuccess) { - // Test checked success. - { - Error E; - EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; - } - -// Test unchecked success. -// Test runs in debug mode only. -#ifndef NDEBUG - { - auto DropUncheckedSuccess = []() { Error E; }; - EXPECT_DEATH(DropUncheckedSuccess(), - "Program aborted due to an unhandled Error:") - << "Unchecked Error Succes value did not cause abort()"; - } -#endif -} - static Error handleCustomError(const CustomError &CE) { return Error(); } static void handleCustomErrorVoid(const CustomError &CE) {} @@ -130,64 +71,78 @@ static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} -// Verify creation and handling of custom error classes. -TEST(Error, CheckCustomErrors) { +// Test that success values implicitly convert to false, and don't cause crashes +// once they've been implicitly converted. +TEST(Error, CheckedSuccess) { + Error E; + EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; +} + +// Test that unchecked succes values cause an abort. +#ifndef NDEBUG +TEST(Error, UncheckedSuccess) { + EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:") + << "Unchecked Error Succes value did not cause abort()"; +} +#endif + // Check that we abort on unhandled failure cases. (Force conversion to bool // to make sure that we don't accidentally treat checked errors as handled). // Test runs in debug mode only. #ifndef NDEBUG - { - auto DropUnhandledError = []() { - Error E = make_error<CustomError>(42); - (void)!E; - }; - EXPECT_DEATH(DropUnhandledError(), - "Program aborted due to an unhandled Error:") - << "Unhandled Error failure value did not cause abort()"; - } +TEST(Error, UncheckedError) { + auto DropUnhandledError = []() { + Error E = make_error<CustomError>(42); + (void)!E; + }; + EXPECT_DEATH(DropUnhandledError(), + "Program aborted due to an unhandled Error:") + << "Unhandled Error failure value did not cause abort()"; +} #endif +// Check 'Error::isA<T>' method handling. +TEST(Error, IsAHandling) { // Check 'isA' handling. - { - Error E = make_error<CustomError>(1); - Error F = make_error<CustomSubError>(1, 2); - Error G = Error::success(); - - EXPECT_TRUE(E.isA<CustomError>()); - EXPECT_FALSE(E.isA<CustomSubError>()); - EXPECT_TRUE(F.isA<CustomError>()); - EXPECT_TRUE(F.isA<CustomSubError>()); - EXPECT_FALSE(G.isA<CustomError>()); - - consumeError(std::move(E)); - consumeError(std::move(F)); - consumeError(std::move(G)); - } + Error E = make_error<CustomError>(1); + Error F = make_error<CustomSubError>(1, 2); + Error G = Error::success(); + + EXPECT_TRUE(E.isA<CustomError>()); + EXPECT_FALSE(E.isA<CustomSubError>()); + EXPECT_TRUE(F.isA<CustomError>()); + EXPECT_TRUE(F.isA<CustomSubError>()); + EXPECT_FALSE(G.isA<CustomError>()); + + consumeError(std::move(E)); + consumeError(std::move(F)); + consumeError(std::move(G)); +} - // Check that we can handle a custom error. - { - int CaughtErrorInfo = 0; - handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { - CaughtErrorInfo = CE.getInfo(); - }); +// Check that we can handle a custom error. +TEST(Error, HandleCustomError) { + int CaughtErrorInfo = 0; + handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { + CaughtErrorInfo = CE.getInfo(); + }); - EXPECT_TRUE(CaughtErrorInfo == 42) - << "Wrong result from CustomError handler"; - } + EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; +} - // Check that handler type deduction also works for handlers - // of the following types: - // void (const Err&) - // Error (const Err&) mutable - // void (const Err&) mutable - // Error (Err&) - // void (Err&) - // Error (Err&) mutable - // void (Err&) mutable - // Error (unique_ptr<Err>) - // void (unique_ptr<Err>) - // Error (unique_ptr<Err>) mutable - // void (unique_ptr<Err>) mutable +// Check that handler type deduction also works for handlers +// of the following types: +// void (const Err&) +// Error (const Err&) mutable +// void (const Err&) mutable +// Error (Err&) +// void (Err&) +// Error (Err&) mutable +// void (Err&) mutable +// Error (unique_ptr<Err>) +// void (unique_ptr<Err>) +// Error (unique_ptr<Err>) mutable +// void (unique_ptr<Err>) mutable +TEST(Error, HandlerTypeDeduction) { handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); @@ -233,246 +188,226 @@ TEST(Error, CheckCustomErrors) { // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); +} - // Check that we can handle a custom error with a custom base class. - { - int CaughtErrorInfo = 0; - int CaughtErrorExtraInfo = 0; - handleAllErrors(make_error<CustomSubError>(42, 7), - [&](const CustomSubError &SE) { - CaughtErrorInfo = SE.getInfo(); - CaughtErrorExtraInfo = SE.getExtraInfo(); - }); +// Test that we can handle errors with custom base classes. +TEST(Error, HandleCustomErrorWithCustomBaseClass) { + int CaughtErrorInfo = 0; + int CaughtErrorExtraInfo = 0; + handleAllErrors(make_error<CustomSubError>(42, 7), + [&](const CustomSubError &SE) { + CaughtErrorInfo = SE.getInfo(); + CaughtErrorExtraInfo = SE.getExtraInfo(); + }); + + EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) + << "Wrong result from CustomSubError handler"; +} - EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) - << "Wrong result from CustomSubError handler"; - } +// Check that we trigger only the first handler that applies. +TEST(Error, FirstHandlerOnly) { + int DummyInfo = 0; + int CaughtErrorInfo = 0; + int CaughtErrorExtraInfo = 0; + + handleAllErrors(make_error<CustomSubError>(42, 7), + [&](const CustomSubError &SE) { + CaughtErrorInfo = SE.getInfo(); + CaughtErrorExtraInfo = SE.getExtraInfo(); + }, + [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); + + EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && + DummyInfo == 0) + << "Activated the wrong Error handler(s)"; +} - // Check that we trigger only the first handler that applies. - { - int DummyInfo = 0; - int CaughtErrorInfo = 0; - int CaughtErrorExtraInfo = 0; - - handleAllErrors(make_error<CustomSubError>(42, 7), - [&](const CustomSubError &SE) { - CaughtErrorInfo = SE.getInfo(); - CaughtErrorExtraInfo = SE.getExtraInfo(); - }, - [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); - - EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && - DummyInfo == 0) - << "Activated the wrong Error handler(s)"; - } +// Check that general handlers shadow specific ones. +TEST(Error, HandlerShadowing) { + int CaughtErrorInfo = 0; + int DummyInfo = 0; + int DummyExtraInfo = 0; - // Check that general handlers shadow specific ones. - { - int CaughtErrorInfo = 0; - int DummyInfo = 0; - int DummyExtraInfo = 0; - - handleAllErrors( - make_error<CustomSubError>(42, 7), - [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, - [&](const CustomSubError &SE) { - DummyInfo = SE.getInfo(); - DummyExtraInfo = SE.getExtraInfo(); - }); - - EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0) - << "General Error handler did not shadow specific handler"; - } + handleAllErrors( + make_error<CustomSubError>(42, 7), + [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, + [&](const CustomSubError &SE) { + DummyInfo = SE.getInfo(); + DummyExtraInfo = SE.getExtraInfo(); + }); + + EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0) + << "General Error handler did not shadow specific handler"; } -// Test utility functions. -TEST(Error, CheckErrorUtilities) { - - // Test joinErrors - { - int CustomErrorInfo1 = 0; - int CustomErrorInfo2 = 0; - int CustomErrorExtraInfo = 0; - Error E = joinErrors(make_error<CustomError>(7), - make_error<CustomSubError>(42, 7)); - - handleAllErrors(std::move(E), - [&](const CustomSubError &SE) { - CustomErrorInfo2 = SE.getInfo(); - CustomErrorExtraInfo = SE.getExtraInfo(); - }, - [&](const CustomError &CE) { - // Assert that the CustomError instance above is handled - // before the - // CustomSubError - joinErrors should preserve error - // ordering. - EXPECT_EQ(CustomErrorInfo2, 0) - << "CustomErrorInfo2 should be 0 here. " - "joinErrors failed to preserve ordering.\n"; - CustomErrorInfo1 = CE.getInfo(); - }); +// Test joinErrors. +TEST(Error, CheckJoinErrors) { + int CustomErrorInfo1 = 0; + int CustomErrorInfo2 = 0; + int CustomErrorExtraInfo = 0; + Error E = + joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); + + handleAllErrors(std::move(E), + [&](const CustomSubError &SE) { + CustomErrorInfo2 = SE.getInfo(); + CustomErrorExtraInfo = SE.getExtraInfo(); + }, + [&](const CustomError &CE) { + // Assert that the CustomError instance above is handled + // before the + // CustomSubError - joinErrors should preserve error + // ordering. + EXPECT_EQ(CustomErrorInfo2, 0) + << "CustomErrorInfo2 should be 0 here. " + "joinErrors failed to preserve ordering.\n"; + CustomErrorInfo1 = CE.getInfo(); + }); + + EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && + CustomErrorExtraInfo == 7) + << "Failed handling compound Error."; +} - EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && - CustomErrorExtraInfo == 7) - << "Failed handling compound Error."; - } +// Test that we can consume success values. +TEST(Error, ConsumeSuccess) { + Error E; + consumeError(std::move(E)); +} - // Test consumeError for both success and error cases. - { - Error E; - consumeError(std::move(E)); - } - { - Error E = make_error<CustomError>(7); - consumeError(std::move(E)); - } +TEST(Error, ConsumeError) { + Error E = make_error<CustomError>(7); + consumeError(std::move(E)); +} // Test that handleAllUnhandledErrors crashes if an error is not caught. // Test runs in debug mode only. #ifndef NDEBUG - { - auto FailToHandle = []() { - handleAllErrors(make_error<CustomError>(7), - [&](const CustomSubError &SE) { - errs() << "This should never be called"; - exit(1); - }); - }; - - EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") - << "Unhandled Error in handleAllErrors call did not cause an " - "abort()"; - } +TEST(Error, FailureToHandle) { + auto FailToHandle = []() { + handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { + errs() << "This should never be called"; + exit(1); + }); + }; + + EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") + << "Unhandled Error in handleAllErrors call did not cause an " + "abort()"; +} #endif // Test that handleAllUnhandledErrors crashes if an error is returned from a // handler. // Test runs in debug mode only. #ifndef NDEBUG - { - auto ReturnErrorFromHandler = []() { - handleAllErrors(make_error<CustomError>(7), - [&](std::unique_ptr<CustomSubError> SE) { - return Error(std::move(SE)); - }); - }; - - EXPECT_DEATH(ReturnErrorFromHandler(), - "Program aborted due to an unhandled Error:") - << " Error returned from handler in handleAllErrors call did not " - "cause abort()"; - } +TEST(Error, FailureFromHandler) { + auto ReturnErrorFromHandler = []() { + handleAllErrors(make_error<CustomError>(7), + [&](std::unique_ptr<CustomSubError> SE) { + return Error(std::move(SE)); + }); + }; + + EXPECT_DEATH(ReturnErrorFromHandler(), + "Program aborted due to an unhandled Error:") + << " Error returned from handler in handleAllErrors call did not " + "cause abort()"; +} #endif - // Test that we can return values from handleErrors. - { - int ErrorInfo = 0; +// Test that we can return values from handleErrors. +TEST(Error, CatchErrorFromHandler) { + int ErrorInfo = 0; - Error E = handleErrors( - make_error<CustomError>(7), - [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); + Error E = handleErrors( + make_error<CustomError>(7), + [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); - handleAllErrors(std::move(E), - [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); + handleAllErrors(std::move(E), + [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); - EXPECT_EQ(ErrorInfo, 7) - << "Failed to handle Error returned from handleErrors."; - } - - // Test ExitOnError - { - ExitOnError ExitOnErr; - ExitOnErr.setBanner("Error in tool:"); - ExitOnErr.setExitCodeMapper( - [](const Error &E) { - if (E.isA<CustomSubError>()) - return 2; - return 1; - }); + EXPECT_EQ(ErrorInfo, 7) + << "Failed to handle Error returned from handleErrors."; +} - // Make sure we don't bail on success. - ExitOnErr(Error::success()); - EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) +// Test that the ExitOnError utility works as expected. +TEST(Error, ExitOnError) { + ExitOnError ExitOnErr; + ExitOnErr.setBanner("Error in tool:"); + ExitOnErr.setExitCodeMapper([](const Error &E) { + if (E.isA<CustomSubError>()) + return 2; + return 1; + }); + + // Make sure we don't bail on success. + ExitOnErr(Error::success()); + EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) << "exitOnError returned an invalid value for Expected"; - // Exit tests. - EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), - ::testing::ExitedWithCode(1), "Error in tool:") + // Exit tests. + EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), + ::testing::ExitedWithCode(1), "Error in tool:") << "exitOnError returned an unexpected error result"; - EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), - ::testing::ExitedWithCode(2), "Error in tool:") + EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), + ::testing::ExitedWithCode(2), "Error in tool:") << "exitOnError returned an unexpected error result"; - } } -// Test Expected behavior. -TEST(Error, CheckExpected) { - - // Check that non-errors convert to 'true'. - { - Expected<int> A = 7; - EXPECT_TRUE(!!A) - << "Expected with non-error value doesn't convert to 'true'"; - } - - // Check that non-error values are accessible via operator*. - { - Expected<int> A = 7; - EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; - } - - // Check that errors convert to 'false'. - { - Expected<int> A = make_error<CustomError>(42); - EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; - consumeError(A.takeError()); - } +// Test Expected<T> in success mode. +TEST(Error, ExpectedInSuccessMode) { + Expected<int> A = 7; + EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; + EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; +} - // Check that error values are accessible via takeError(). - { - Expected<int> A = make_error<CustomError>(42); - Error E = A.takeError(); - EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; - consumeError(std::move(E)); - } +// Test Expected<T> in failure mode. +TEST(Error, ExpectedInFailureMode) { + Expected<int> A = make_error<CustomError>(42); + EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; + Error E = A.takeError(); + EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; + consumeError(std::move(E)); +} // Check that an Expected instance with an error value doesn't allow access to // operator*. // Test runs in debug mode only. #ifndef NDEBUG - { - Expected<int> A = make_error<CustomError>(42); - EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"") - << "Incorrect Expected error value"; - consumeError(A.takeError()); - } +TEST(Error, AccessExpectedInFailureMode) { + Expected<int> A = make_error<CustomError>(42); + EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"") + << "Incorrect Expected error value"; + consumeError(A.takeError()); +} #endif // Check that an Expected instance with an error triggers an abort if // unhandled. // Test runs in debug mode only. #ifndef NDEBUG +TEST(Error, UnhandledExpectedInFailureMode) { EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, "Program aborted due to an unhandled Error:") << "Unchecked Expected<T> failure value did not cause an abort()"; +} #endif - // Test covariance of Expected. - { - class B {}; - class D : public B {}; +// Test covariance of Expected. +TEST(Error, ExpectedCovariance) { + class B {}; + class D : public B {}; - Expected<B *> A1(Expected<D *>(nullptr)); - A1 = Expected<D *>(nullptr); + Expected<B *> A1(Expected<D *>(nullptr)); + A1 = Expected<D *>(nullptr); - Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); - A2 = Expected<std::unique_ptr<D>>(nullptr); - } + Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); + A2 = Expected<std::unique_ptr<D>>(nullptr); } TEST(Error, ECError) { - // Round-trip a success value to check that it converts correctly. EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), std::error_code()) |

