1f7f6d3e9SLang Hames //===----- unittests/ErrorTest.cpp - Error.h tests ------------------------===// 2f7f6d3e9SLang Hames // 3f7f6d3e9SLang Hames // The LLVM Compiler Infrastructure 4f7f6d3e9SLang Hames // 5f7f6d3e9SLang Hames // This file is distributed under the University of Illinois Open Source 6f7f6d3e9SLang Hames // License. See LICENSE.TXT for details. 7f7f6d3e9SLang Hames // 8f7f6d3e9SLang Hames //===----------------------------------------------------------------------===// 9f7f6d3e9SLang Hames 10f7f6d3e9SLang Hames #include "llvm/Support/Error.h" 11f7f6d3e9SLang Hames #include "llvm/Support/Errc.h" 12e7aad357SLang Hames #include "llvm/Support/ErrorHandling.h" 13f7f6d3e9SLang Hames #include "gtest/gtest.h" 14f7f6d3e9SLang Hames #include <memory> 15f7f6d3e9SLang Hames 16f7f6d3e9SLang Hames using namespace llvm; 17f7f6d3e9SLang Hames 18f7f6d3e9SLang Hames namespace { 19f7f6d3e9SLang Hames 20f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached. 21f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> { 22f7f6d3e9SLang Hames public: 23f7f6d3e9SLang Hames // Create an error with some info attached. 24f7f6d3e9SLang Hames CustomError(int Info) : Info(Info) {} 25f7f6d3e9SLang Hames 26f7f6d3e9SLang Hames // Get the info attached to this error. 27f7f6d3e9SLang Hames int getInfo() const { return Info; } 28f7f6d3e9SLang Hames 29f7f6d3e9SLang Hames // Log this error to a stream. 30f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 31f7f6d3e9SLang Hames OS << "CustomError { " << getInfo() << "}"; 32f7f6d3e9SLang Hames } 33f7f6d3e9SLang Hames 34e7aad357SLang Hames std::error_code convertToErrorCode() const override { 35e7aad357SLang Hames llvm_unreachable("CustomError doesn't support ECError conversion"); 36e7aad357SLang Hames } 37e7aad357SLang Hames 38a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 39a15b76b3SReid Kleckner static char ID; 40a15b76b3SReid Kleckner 41f7f6d3e9SLang Hames protected: 42f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 43f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 44f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 45f7f6d3e9SLang Hames // fields. 46f7f6d3e9SLang Hames CustomError() : Info(0) {} 47f7f6d3e9SLang Hames 48f7f6d3e9SLang Hames int Info; 49f7f6d3e9SLang Hames }; 50f7f6d3e9SLang Hames 51a15b76b3SReid Kleckner char CustomError::ID = 0; 52a15b76b3SReid Kleckner 53f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 54f7f6d3e9SLang Hames // 'info'. 55f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 56f7f6d3e9SLang Hames public: 57f7f6d3e9SLang Hames // Create a sub-error with some info attached. 58f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 59f7f6d3e9SLang Hames this->Info = Info; 60f7f6d3e9SLang Hames } 61f7f6d3e9SLang Hames 62f7f6d3e9SLang Hames // Get the extra info attached to this error. 63f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 64f7f6d3e9SLang Hames 65f7f6d3e9SLang Hames // Log this error to a stream. 66f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 67f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 68f7f6d3e9SLang Hames } 69f7f6d3e9SLang Hames 70e7aad357SLang Hames std::error_code convertToErrorCode() const override { 71e7aad357SLang Hames llvm_unreachable("CustomSubError doesn't support ECError conversion"); 72e7aad357SLang Hames } 73e7aad357SLang Hames 74a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 75a15b76b3SReid Kleckner static char ID; 76a15b76b3SReid Kleckner 77f7f6d3e9SLang Hames protected: 78f7f6d3e9SLang Hames int ExtraInfo; 79f7f6d3e9SLang Hames }; 80f7f6d3e9SLang Hames 81a15b76b3SReid Kleckner char CustomSubError::ID = 0; 82a15b76b3SReid Kleckner 83f7f6d3e9SLang Hames static Error handleCustomError(const CustomError &CE) { return Error(); } 84f7f6d3e9SLang Hames 85f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 86f7f6d3e9SLang Hames 87f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 88f7f6d3e9SLang Hames return Error(); 89f7f6d3e9SLang Hames } 90f7f6d3e9SLang Hames 91f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 92f7f6d3e9SLang Hames 9301864a2dSLang Hames // Test that success values implicitly convert to false, and don't cause crashes 9401864a2dSLang Hames // once they've been implicitly converted. 9501864a2dSLang Hames TEST(Error, CheckedSuccess) { 9601864a2dSLang Hames Error E; 9701864a2dSLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 9801864a2dSLang Hames } 9901864a2dSLang Hames 10001864a2dSLang Hames // Test that unchecked succes values cause an abort. 10101864a2dSLang Hames #ifndef NDEBUG 10201864a2dSLang Hames TEST(Error, UncheckedSuccess) { 10301864a2dSLang Hames EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:") 10401864a2dSLang Hames << "Unchecked Error Succes value did not cause abort()"; 10501864a2dSLang Hames } 10601864a2dSLang Hames #endif 10701864a2dSLang Hames 108d1af8fceSLang Hames // ErrorAsOutParameter tester. 109d1af8fceSLang Hames void errAsOutParamHelper(Error &Err) { 110d1af8fceSLang Hames ErrorAsOutParameter ErrAsOutParam(Err); 111d1af8fceSLang Hames // Verify that checked flag is raised - assignment should not crash. 112d1af8fceSLang Hames Err = Error::success(); 113d1af8fceSLang Hames // Raise the checked bit manually - caller should still have to test the 114d1af8fceSLang Hames // error. 115d1af8fceSLang Hames (void)!!Err; 116d0ac31a7SLang Hames } 117d0ac31a7SLang Hames 118d1af8fceSLang Hames // Test that ErrorAsOutParameter sets the checked flag on construction. 119d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterChecked) { 120d1af8fceSLang Hames Error E; 121d1af8fceSLang Hames errAsOutParamHelper(E); 122d1af8fceSLang Hames (void)!!E; 123d1af8fceSLang Hames } 124d1af8fceSLang Hames 125d1af8fceSLang Hames // Test that ErrorAsOutParameter clears the checked flag on destruction. 126d1af8fceSLang Hames #ifndef NDEBUG 127d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterUnchecked) { 128d1af8fceSLang Hames EXPECT_DEATH({ Error E; errAsOutParamHelper(E); }, 129d1af8fceSLang Hames "Program aborted due to an unhandled Error:") 130d1af8fceSLang Hames << "ErrorAsOutParameter did not clear the checked flag on destruction."; 131d1af8fceSLang Hames } 132d1af8fceSLang Hames #endif 133d1af8fceSLang Hames 134f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 135f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 136f7f6d3e9SLang Hames // Test runs in debug mode only. 137f7f6d3e9SLang Hames #ifndef NDEBUG 13801864a2dSLang Hames TEST(Error, UncheckedError) { 139f7f6d3e9SLang Hames auto DropUnhandledError = []() { 140f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 141f7f6d3e9SLang Hames (void)!E; 142f7f6d3e9SLang Hames }; 143f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 144f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 145f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 146f7f6d3e9SLang Hames } 147f7f6d3e9SLang Hames #endif 148f7f6d3e9SLang Hames 14901864a2dSLang Hames // Check 'Error::isA<T>' method handling. 15001864a2dSLang Hames TEST(Error, IsAHandling) { 151f7f6d3e9SLang Hames // Check 'isA' handling. 152f7f6d3e9SLang Hames Error E = make_error<CustomError>(1); 153f7f6d3e9SLang Hames Error F = make_error<CustomSubError>(1, 2); 15401a3cf4dSLang Hames Error G = Error::success(); 155f7f6d3e9SLang Hames 156f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()); 157f7f6d3e9SLang Hames EXPECT_FALSE(E.isA<CustomSubError>()); 158f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomError>()); 159f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomSubError>()); 16001a3cf4dSLang Hames EXPECT_FALSE(G.isA<CustomError>()); 161f7f6d3e9SLang Hames 162f7f6d3e9SLang Hames consumeError(std::move(E)); 163f7f6d3e9SLang Hames consumeError(std::move(F)); 16401a3cf4dSLang Hames consumeError(std::move(G)); 165f7f6d3e9SLang Hames } 166f7f6d3e9SLang Hames 167f7f6d3e9SLang Hames // Check that we can handle a custom error. 16801864a2dSLang Hames TEST(Error, HandleCustomError) { 169f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 170f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 171f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 172f7f6d3e9SLang Hames }); 173f7f6d3e9SLang Hames 17401864a2dSLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 175f7f6d3e9SLang Hames } 176f7f6d3e9SLang Hames 177f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 178f7f6d3e9SLang Hames // of the following types: 179f7f6d3e9SLang Hames // void (const Err&) 180f7f6d3e9SLang Hames // Error (const Err&) mutable 181f7f6d3e9SLang Hames // void (const Err&) mutable 182f7f6d3e9SLang Hames // Error (Err&) 183f7f6d3e9SLang Hames // void (Err&) 184f7f6d3e9SLang Hames // Error (Err&) mutable 185f7f6d3e9SLang Hames // void (Err&) mutable 186f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 187f7f6d3e9SLang Hames // void (unique_ptr<Err>) 188f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 189f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 19001864a2dSLang Hames TEST(Error, HandlerTypeDeduction) { 191f7f6d3e9SLang Hames 192f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 193f7f6d3e9SLang Hames 194f7f6d3e9SLang Hames handleAllErrors( 195f7f6d3e9SLang Hames make_error<CustomError>(42), 196f7f6d3e9SLang Hames [](const CustomError &CE) mutable { return Error::success(); }); 197f7f6d3e9SLang Hames 198f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 199f7f6d3e9SLang Hames [](const CustomError &CE) mutable {}); 200f7f6d3e9SLang Hames 201f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 202f7f6d3e9SLang Hames [](CustomError &CE) { return Error::success(); }); 203f7f6d3e9SLang Hames 204f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 205f7f6d3e9SLang Hames 206f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 207f7f6d3e9SLang Hames [](CustomError &CE) mutable { return Error::success(); }); 208f7f6d3e9SLang Hames 209f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 210f7f6d3e9SLang Hames 211f7f6d3e9SLang Hames handleAllErrors( 212f7f6d3e9SLang Hames make_error<CustomError>(42), 213f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) { return Error::success(); }); 214f7f6d3e9SLang Hames 215f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 216f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) {}); 217f7f6d3e9SLang Hames 218f7f6d3e9SLang Hames handleAllErrors( 219f7f6d3e9SLang Hames make_error<CustomError>(42), 220f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); }); 221f7f6d3e9SLang Hames 222f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 223f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable {}); 224f7f6d3e9SLang Hames 225f7f6d3e9SLang Hames // Check that named handlers of type 'Error (const Err&)' work. 226f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomError); 227f7f6d3e9SLang Hames 228f7f6d3e9SLang Hames // Check that named handlers of type 'void (const Err&)' work. 229f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 230f7f6d3e9SLang Hames 231f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 232f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 233f7f6d3e9SLang Hames 234f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 235f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 23601864a2dSLang Hames } 237f7f6d3e9SLang Hames 23801864a2dSLang Hames // Test that we can handle errors with custom base classes. 23901864a2dSLang Hames TEST(Error, HandleCustomErrorWithCustomBaseClass) { 240f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 241f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 242f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 243f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 244f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 245f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 246f7f6d3e9SLang Hames }); 247f7f6d3e9SLang Hames 248f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 249f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 250f7f6d3e9SLang Hames } 251f7f6d3e9SLang Hames 252f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 25301864a2dSLang Hames TEST(Error, FirstHandlerOnly) { 254f7f6d3e9SLang Hames int DummyInfo = 0; 255f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 256f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 257f7f6d3e9SLang Hames 258f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 259f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 260f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 261f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 262f7f6d3e9SLang Hames }, 263f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 264f7f6d3e9SLang Hames 265f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 266f7f6d3e9SLang Hames DummyInfo == 0) 267f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 268f7f6d3e9SLang Hames } 269f7f6d3e9SLang Hames 270f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 27101864a2dSLang Hames TEST(Error, HandlerShadowing) { 272f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 273f7f6d3e9SLang Hames int DummyInfo = 0; 274f7f6d3e9SLang Hames int DummyExtraInfo = 0; 275f7f6d3e9SLang Hames 276f7f6d3e9SLang Hames handleAllErrors( 277f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 278f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 279f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 280f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 281f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 282f7f6d3e9SLang Hames }); 283f7f6d3e9SLang Hames 284b2cef64bSNAKAMURA Takumi EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) 285f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 286f7f6d3e9SLang Hames } 287f7f6d3e9SLang Hames 28801864a2dSLang Hames // Test joinErrors. 28901864a2dSLang Hames TEST(Error, CheckJoinErrors) { 290f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 291f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 292f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 29301864a2dSLang Hames Error E = 29401864a2dSLang Hames joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 295f7f6d3e9SLang Hames 296f7f6d3e9SLang Hames handleAllErrors(std::move(E), 297f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 298f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 299f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 300f7f6d3e9SLang Hames }, 301f7f6d3e9SLang Hames [&](const CustomError &CE) { 302f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 303f7f6d3e9SLang Hames // before the 304f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 305f7f6d3e9SLang Hames // ordering. 306f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 307f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 308f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 309f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 310f7f6d3e9SLang Hames }); 311f7f6d3e9SLang Hames 312f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 313f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 314f7f6d3e9SLang Hames << "Failed handling compound Error."; 315f7f6d3e9SLang Hames } 316f7f6d3e9SLang Hames 31701864a2dSLang Hames // Test that we can consume success values. 31801864a2dSLang Hames TEST(Error, ConsumeSuccess) { 319f7f6d3e9SLang Hames Error E; 320f7f6d3e9SLang Hames consumeError(std::move(E)); 321f7f6d3e9SLang Hames } 32201864a2dSLang Hames 32301864a2dSLang Hames TEST(Error, ConsumeError) { 324f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 325f7f6d3e9SLang Hames consumeError(std::move(E)); 326f7f6d3e9SLang Hames } 327f7f6d3e9SLang Hames 328f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 329f7f6d3e9SLang Hames // Test runs in debug mode only. 330f7f6d3e9SLang Hames #ifndef NDEBUG 33101864a2dSLang Hames TEST(Error, FailureToHandle) { 332f7f6d3e9SLang Hames auto FailToHandle = []() { 33301864a2dSLang Hames handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 334f7f6d3e9SLang Hames errs() << "This should never be called"; 335f7f6d3e9SLang Hames exit(1); 336f7f6d3e9SLang Hames }); 337f7f6d3e9SLang Hames }; 338f7f6d3e9SLang Hames 339f7f6d3e9SLang Hames EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") 340f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 341f7f6d3e9SLang Hames "abort()"; 342f7f6d3e9SLang Hames } 343f7f6d3e9SLang Hames #endif 344f7f6d3e9SLang Hames 345f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 346f7f6d3e9SLang Hames // handler. 347f7f6d3e9SLang Hames // Test runs in debug mode only. 348f7f6d3e9SLang Hames #ifndef NDEBUG 34901864a2dSLang Hames TEST(Error, FailureFromHandler) { 350f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 351f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 352f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 353f7f6d3e9SLang Hames return Error(std::move(SE)); 354f7f6d3e9SLang Hames }); 355f7f6d3e9SLang Hames }; 356f7f6d3e9SLang Hames 357f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 358f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 359f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 360f7f6d3e9SLang Hames "cause abort()"; 361f7f6d3e9SLang Hames } 362f7f6d3e9SLang Hames #endif 363f7f6d3e9SLang Hames 364f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 36501864a2dSLang Hames TEST(Error, CatchErrorFromHandler) { 366f7f6d3e9SLang Hames int ErrorInfo = 0; 367f7f6d3e9SLang Hames 368f7f6d3e9SLang Hames Error E = handleErrors( 369f7f6d3e9SLang Hames make_error<CustomError>(7), 370f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 371f7f6d3e9SLang Hames 372f7f6d3e9SLang Hames handleAllErrors(std::move(E), 373f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 374f7f6d3e9SLang Hames 375f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 376f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 377f7f6d3e9SLang Hames } 3786935c2d3SLang Hames 37901864a2dSLang Hames // Test that the ExitOnError utility works as expected. 38001864a2dSLang Hames TEST(Error, ExitOnError) { 3816935c2d3SLang Hames ExitOnError ExitOnErr; 3826935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 38301864a2dSLang Hames ExitOnErr.setExitCodeMapper([](const Error &E) { 3846935c2d3SLang Hames if (E.isA<CustomSubError>()) 3856935c2d3SLang Hames return 2; 3866935c2d3SLang Hames return 1; 3876935c2d3SLang Hames }); 3886935c2d3SLang Hames 3896935c2d3SLang Hames // Make sure we don't bail on success. 3906935c2d3SLang Hames ExitOnErr(Error::success()); 3916935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 3926935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 3936935c2d3SLang Hames 394*285639f8SLang Hames int A = 7; 395*285639f8SLang Hames int &B = ExitOnErr(Expected<int&>(A)); 396*285639f8SLang Hames EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference"; 397*285639f8SLang Hames 3986935c2d3SLang Hames // Exit tests. 3996935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 4006935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 4016935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4026935c2d3SLang Hames 4036935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 4046935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 4056935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4066935c2d3SLang Hames } 407f7f6d3e9SLang Hames 408580ca237SLang Hames // Test Checked Expected<T> in success mode. 409580ca237SLang Hames TEST(Error, CheckedExpectedInSuccessMode) { 410f7f6d3e9SLang Hames Expected<int> A = 7; 41101864a2dSLang Hames EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 412580ca237SLang Hames // Access is safe in second test, since we checked the error in the first. 413f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 414f7f6d3e9SLang Hames } 415f7f6d3e9SLang Hames 416*285639f8SLang Hames // Test Expected with reference type. 417*285639f8SLang Hames TEST(Error, ExpectedWithReferenceType) { 418*285639f8SLang Hames int A = 7; 419*285639f8SLang Hames Expected<int&> B = A; 420*285639f8SLang Hames // 'Check' B. 421*285639f8SLang Hames (void)!!B; 422*285639f8SLang Hames int &C = *B; 423*285639f8SLang Hames EXPECT_EQ(&A, &C) << "Expected failed to propagate reference"; 424*285639f8SLang Hames } 425*285639f8SLang Hames 426580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 427580ca237SLang Hames // We expect this to blow up the same way Error would. 428580ca237SLang Hames // Test runs in debug mode only. 429580ca237SLang Hames #ifndef NDEBUG 430580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeDestruction) { 431580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; }, 432580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 433580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 434580ca237SLang Hames } 435580ca237SLang Hames #endif 436580ca237SLang Hames 437580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 438580ca237SLang Hames // We expect this to blow up the same way Error would. 439580ca237SLang Hames // Test runs in debug mode only. 440580ca237SLang Hames #ifndef NDEBUG 441580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAccess) { 442580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; *A; }, 443580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 444580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 445580ca237SLang Hames } 446580ca237SLang Hames #endif 447580ca237SLang Hames 448580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 449580ca237SLang Hames // We expect this to blow up the same way Error would. 450580ca237SLang Hames // Test runs in debug mode only. 451580ca237SLang Hames #ifndef NDEBUG 452580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAssignment) { 453580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, 454580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 455580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 456580ca237SLang Hames } 457580ca237SLang Hames #endif 458580ca237SLang Hames 45901864a2dSLang Hames // Test Expected<T> in failure mode. 46001864a2dSLang Hames TEST(Error, ExpectedInFailureMode) { 461f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 462f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 463f7f6d3e9SLang Hames Error E = A.takeError(); 464f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 465f7f6d3e9SLang Hames consumeError(std::move(E)); 466f7f6d3e9SLang Hames } 467f7f6d3e9SLang Hames 468f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 469f7f6d3e9SLang Hames // operator*. 470f7f6d3e9SLang Hames // Test runs in debug mode only. 471f7f6d3e9SLang Hames #ifndef NDEBUG 47201864a2dSLang Hames TEST(Error, AccessExpectedInFailureMode) { 473f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 474580ca237SLang Hames EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.") 475f7f6d3e9SLang Hames << "Incorrect Expected error value"; 476f7f6d3e9SLang Hames consumeError(A.takeError()); 477f7f6d3e9SLang Hames } 478f7f6d3e9SLang Hames #endif 479f7f6d3e9SLang Hames 480f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 481f7f6d3e9SLang Hames // unhandled. 482f7f6d3e9SLang Hames // Test runs in debug mode only. 483f7f6d3e9SLang Hames #ifndef NDEBUG 48401864a2dSLang Hames TEST(Error, UnhandledExpectedInFailureMode) { 485f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 486580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 487f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 48801864a2dSLang Hames } 489f7f6d3e9SLang Hames #endif 490f7f6d3e9SLang Hames 491f7f6d3e9SLang Hames // Test covariance of Expected. 49201864a2dSLang Hames TEST(Error, ExpectedCovariance) { 493f7f6d3e9SLang Hames class B {}; 494f7f6d3e9SLang Hames class D : public B {}; 495f7f6d3e9SLang Hames 496f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 497580ca237SLang Hames // Check A1 by converting to bool before assigning to it. 498580ca237SLang Hames (void)!!A1; 499f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 500580ca237SLang Hames // Check A1 again before destruction. 501580ca237SLang Hames (void)!!A1; 502f7f6d3e9SLang Hames 503f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 504580ca237SLang Hames // Check A2 by converting to bool before assigning to it. 505580ca237SLang Hames (void)!!A2; 506f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 507580ca237SLang Hames // Check A2 again before destruction. 508580ca237SLang Hames (void)!!A2; 509f7f6d3e9SLang Hames } 510f7f6d3e9SLang Hames 511d21a535bSLang Hames TEST(Error, ErrorCodeConversions) { 512f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 513f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 514f7f6d3e9SLang Hames std::error_code()) 515f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 516f7f6d3e9SLang Hames 517f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 518f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 519f7f6d3e9SLang Hames errc::invalid_argument) 520f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 521f7f6d3e9SLang Hames "conversions"; 522d21a535bSLang Hames 523d21a535bSLang Hames // Round-trip a success value through ErrorOr/Expected to check that it 524d21a535bSLang Hames // converts correctly. 525d21a535bSLang Hames { 526d21a535bSLang Hames auto Orig = ErrorOr<int>(42); 527d21a535bSLang Hames auto RoundTripped = 528d21a535bSLang Hames expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); 529d21a535bSLang Hames EXPECT_EQ(*Orig, *RoundTripped) 530d21a535bSLang Hames << "ErrorOr<T> success value should round-trip via Expected<T> " 531d21a535bSLang Hames "conversions."; 532d21a535bSLang Hames } 533d21a535bSLang Hames 534d21a535bSLang Hames // Round-trip a failure value through ErrorOr/Expected to check that it 535d21a535bSLang Hames // converts correctly. 536d21a535bSLang Hames { 537d21a535bSLang Hames auto Orig = ErrorOr<int>(errc::invalid_argument); 538d21a535bSLang Hames auto RoundTripped = 539d21a535bSLang Hames expectedToErrorOr( 540d21a535bSLang Hames errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); 541d21a535bSLang Hames EXPECT_EQ(Orig.getError(), RoundTripped.getError()) 542d21a535bSLang Hames << "ErrorOr<T> failure value should round-trip via Expected<T> " 543d21a535bSLang Hames "conversions."; 544d21a535bSLang Hames } 545f7f6d3e9SLang Hames } 546f7f6d3e9SLang Hames 547f7f6d3e9SLang Hames } // end anon namespace 548