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" 12*e7aad357SLang 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 34*e7aad357SLang Hames std::error_code convertToErrorCode() const override { 35*e7aad357SLang Hames llvm_unreachable("CustomError doesn't support ECError conversion"); 36*e7aad357SLang Hames } 37*e7aad357SLang Hames 38f7f6d3e9SLang Hames protected: 39f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 40f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 41f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 42f7f6d3e9SLang Hames // fields. 43f7f6d3e9SLang Hames CustomError() : Info(0) {} 44f7f6d3e9SLang Hames 45f7f6d3e9SLang Hames int Info; 46f7f6d3e9SLang Hames }; 47f7f6d3e9SLang Hames 48f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 49f7f6d3e9SLang Hames // 'info'. 50f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 51f7f6d3e9SLang Hames public: 52f7f6d3e9SLang Hames // Create a sub-error with some info attached. 53f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 54f7f6d3e9SLang Hames this->Info = Info; 55f7f6d3e9SLang Hames } 56f7f6d3e9SLang Hames 57f7f6d3e9SLang Hames // Get the extra info attached to this error. 58f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 59f7f6d3e9SLang Hames 60f7f6d3e9SLang Hames // Log this error to a stream. 61f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 62f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 63f7f6d3e9SLang Hames } 64f7f6d3e9SLang Hames 65*e7aad357SLang Hames std::error_code convertToErrorCode() const override { 66*e7aad357SLang Hames llvm_unreachable("CustomSubError doesn't support ECError conversion"); 67*e7aad357SLang Hames } 68*e7aad357SLang Hames 69f7f6d3e9SLang Hames protected: 70f7f6d3e9SLang Hames int ExtraInfo; 71f7f6d3e9SLang Hames }; 72f7f6d3e9SLang Hames 73f7f6d3e9SLang Hames static Error handleCustomError(const CustomError &CE) { return Error(); } 74f7f6d3e9SLang Hames 75f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 76f7f6d3e9SLang Hames 77f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 78f7f6d3e9SLang Hames return Error(); 79f7f6d3e9SLang Hames } 80f7f6d3e9SLang Hames 81f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 82f7f6d3e9SLang Hames 8301864a2dSLang Hames // Test that success values implicitly convert to false, and don't cause crashes 8401864a2dSLang Hames // once they've been implicitly converted. 8501864a2dSLang Hames TEST(Error, CheckedSuccess) { 8601864a2dSLang Hames Error E; 8701864a2dSLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 8801864a2dSLang Hames } 8901864a2dSLang Hames 9001864a2dSLang Hames // Test that unchecked succes values cause an abort. 9101864a2dSLang Hames #ifndef NDEBUG 9201864a2dSLang Hames TEST(Error, UncheckedSuccess) { 9301864a2dSLang Hames EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:") 9401864a2dSLang Hames << "Unchecked Error Succes value did not cause abort()"; 9501864a2dSLang Hames } 9601864a2dSLang Hames #endif 9701864a2dSLang Hames 98f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 99f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 100f7f6d3e9SLang Hames // Test runs in debug mode only. 101f7f6d3e9SLang Hames #ifndef NDEBUG 10201864a2dSLang Hames TEST(Error, UncheckedError) { 103f7f6d3e9SLang Hames auto DropUnhandledError = []() { 104f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 105f7f6d3e9SLang Hames (void)!E; 106f7f6d3e9SLang Hames }; 107f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 108f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 109f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 110f7f6d3e9SLang Hames } 111f7f6d3e9SLang Hames #endif 112f7f6d3e9SLang Hames 11301864a2dSLang Hames // Check 'Error::isA<T>' method handling. 11401864a2dSLang Hames TEST(Error, IsAHandling) { 115f7f6d3e9SLang Hames // Check 'isA' handling. 116f7f6d3e9SLang Hames Error E = make_error<CustomError>(1); 117f7f6d3e9SLang Hames Error F = make_error<CustomSubError>(1, 2); 11801a3cf4dSLang Hames Error G = Error::success(); 119f7f6d3e9SLang Hames 120f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()); 121f7f6d3e9SLang Hames EXPECT_FALSE(E.isA<CustomSubError>()); 122f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomError>()); 123f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomSubError>()); 12401a3cf4dSLang Hames EXPECT_FALSE(G.isA<CustomError>()); 125f7f6d3e9SLang Hames 126f7f6d3e9SLang Hames consumeError(std::move(E)); 127f7f6d3e9SLang Hames consumeError(std::move(F)); 12801a3cf4dSLang Hames consumeError(std::move(G)); 129f7f6d3e9SLang Hames } 130f7f6d3e9SLang Hames 131f7f6d3e9SLang Hames // Check that we can handle a custom error. 13201864a2dSLang Hames TEST(Error, HandleCustomError) { 133f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 134f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 135f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 136f7f6d3e9SLang Hames }); 137f7f6d3e9SLang Hames 13801864a2dSLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 139f7f6d3e9SLang Hames } 140f7f6d3e9SLang Hames 141f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 142f7f6d3e9SLang Hames // of the following types: 143f7f6d3e9SLang Hames // void (const Err&) 144f7f6d3e9SLang Hames // Error (const Err&) mutable 145f7f6d3e9SLang Hames // void (const Err&) mutable 146f7f6d3e9SLang Hames // Error (Err&) 147f7f6d3e9SLang Hames // void (Err&) 148f7f6d3e9SLang Hames // Error (Err&) mutable 149f7f6d3e9SLang Hames // void (Err&) mutable 150f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 151f7f6d3e9SLang Hames // void (unique_ptr<Err>) 152f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 153f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 15401864a2dSLang Hames TEST(Error, HandlerTypeDeduction) { 155f7f6d3e9SLang Hames 156f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 157f7f6d3e9SLang Hames 158f7f6d3e9SLang Hames handleAllErrors( 159f7f6d3e9SLang Hames make_error<CustomError>(42), 160f7f6d3e9SLang Hames [](const CustomError &CE) mutable { return Error::success(); }); 161f7f6d3e9SLang Hames 162f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 163f7f6d3e9SLang Hames [](const CustomError &CE) mutable {}); 164f7f6d3e9SLang Hames 165f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 166f7f6d3e9SLang Hames [](CustomError &CE) { return Error::success(); }); 167f7f6d3e9SLang Hames 168f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 169f7f6d3e9SLang Hames 170f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 171f7f6d3e9SLang Hames [](CustomError &CE) mutable { return Error::success(); }); 172f7f6d3e9SLang Hames 173f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 174f7f6d3e9SLang Hames 175f7f6d3e9SLang Hames handleAllErrors( 176f7f6d3e9SLang Hames make_error<CustomError>(42), 177f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) { return Error::success(); }); 178f7f6d3e9SLang Hames 179f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 180f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) {}); 181f7f6d3e9SLang Hames 182f7f6d3e9SLang Hames handleAllErrors( 183f7f6d3e9SLang Hames make_error<CustomError>(42), 184f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); }); 185f7f6d3e9SLang Hames 186f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 187f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable {}); 188f7f6d3e9SLang Hames 189f7f6d3e9SLang Hames // Check that named handlers of type 'Error (const Err&)' work. 190f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomError); 191f7f6d3e9SLang Hames 192f7f6d3e9SLang Hames // Check that named handlers of type 'void (const Err&)' work. 193f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 194f7f6d3e9SLang Hames 195f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 196f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 197f7f6d3e9SLang Hames 198f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 199f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 20001864a2dSLang Hames } 201f7f6d3e9SLang Hames 20201864a2dSLang Hames // Test that we can handle errors with custom base classes. 20301864a2dSLang Hames TEST(Error, HandleCustomErrorWithCustomBaseClass) { 204f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 205f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 206f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 207f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 208f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 209f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 210f7f6d3e9SLang Hames }); 211f7f6d3e9SLang Hames 212f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 213f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 214f7f6d3e9SLang Hames } 215f7f6d3e9SLang Hames 216f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 21701864a2dSLang Hames TEST(Error, FirstHandlerOnly) { 218f7f6d3e9SLang Hames int DummyInfo = 0; 219f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 220f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 221f7f6d3e9SLang Hames 222f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 223f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 224f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 225f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 226f7f6d3e9SLang Hames }, 227f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 228f7f6d3e9SLang Hames 229f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 230f7f6d3e9SLang Hames DummyInfo == 0) 231f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 232f7f6d3e9SLang Hames } 233f7f6d3e9SLang Hames 234f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 23501864a2dSLang Hames TEST(Error, HandlerShadowing) { 236f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 237f7f6d3e9SLang Hames int DummyInfo = 0; 238f7f6d3e9SLang Hames int DummyExtraInfo = 0; 239f7f6d3e9SLang Hames 240f7f6d3e9SLang Hames handleAllErrors( 241f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 242f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 243f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 244f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 245f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 246f7f6d3e9SLang Hames }); 247f7f6d3e9SLang Hames 248f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0) 249f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 250f7f6d3e9SLang Hames } 251f7f6d3e9SLang Hames 25201864a2dSLang Hames // Test joinErrors. 25301864a2dSLang Hames TEST(Error, CheckJoinErrors) { 254f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 255f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 256f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 25701864a2dSLang Hames Error E = 25801864a2dSLang Hames joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 259f7f6d3e9SLang Hames 260f7f6d3e9SLang Hames handleAllErrors(std::move(E), 261f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 262f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 263f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 264f7f6d3e9SLang Hames }, 265f7f6d3e9SLang Hames [&](const CustomError &CE) { 266f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 267f7f6d3e9SLang Hames // before the 268f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 269f7f6d3e9SLang Hames // ordering. 270f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 271f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 272f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 273f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 274f7f6d3e9SLang Hames }); 275f7f6d3e9SLang Hames 276f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 277f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 278f7f6d3e9SLang Hames << "Failed handling compound Error."; 279f7f6d3e9SLang Hames } 280f7f6d3e9SLang Hames 28101864a2dSLang Hames // Test that we can consume success values. 28201864a2dSLang Hames TEST(Error, ConsumeSuccess) { 283f7f6d3e9SLang Hames Error E; 284f7f6d3e9SLang Hames consumeError(std::move(E)); 285f7f6d3e9SLang Hames } 28601864a2dSLang Hames 28701864a2dSLang Hames TEST(Error, ConsumeError) { 288f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 289f7f6d3e9SLang Hames consumeError(std::move(E)); 290f7f6d3e9SLang Hames } 291f7f6d3e9SLang Hames 292f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 293f7f6d3e9SLang Hames // Test runs in debug mode only. 294f7f6d3e9SLang Hames #ifndef NDEBUG 29501864a2dSLang Hames TEST(Error, FailureToHandle) { 296f7f6d3e9SLang Hames auto FailToHandle = []() { 29701864a2dSLang Hames handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 298f7f6d3e9SLang Hames errs() << "This should never be called"; 299f7f6d3e9SLang Hames exit(1); 300f7f6d3e9SLang Hames }); 301f7f6d3e9SLang Hames }; 302f7f6d3e9SLang Hames 303f7f6d3e9SLang Hames EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") 304f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 305f7f6d3e9SLang Hames "abort()"; 306f7f6d3e9SLang Hames } 307f7f6d3e9SLang Hames #endif 308f7f6d3e9SLang Hames 309f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 310f7f6d3e9SLang Hames // handler. 311f7f6d3e9SLang Hames // Test runs in debug mode only. 312f7f6d3e9SLang Hames #ifndef NDEBUG 31301864a2dSLang Hames TEST(Error, FailureFromHandler) { 314f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 315f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 316f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 317f7f6d3e9SLang Hames return Error(std::move(SE)); 318f7f6d3e9SLang Hames }); 319f7f6d3e9SLang Hames }; 320f7f6d3e9SLang Hames 321f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 322f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 323f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 324f7f6d3e9SLang Hames "cause abort()"; 325f7f6d3e9SLang Hames } 326f7f6d3e9SLang Hames #endif 327f7f6d3e9SLang Hames 328f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 32901864a2dSLang Hames TEST(Error, CatchErrorFromHandler) { 330f7f6d3e9SLang Hames int ErrorInfo = 0; 331f7f6d3e9SLang Hames 332f7f6d3e9SLang Hames Error E = handleErrors( 333f7f6d3e9SLang Hames make_error<CustomError>(7), 334f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 335f7f6d3e9SLang Hames 336f7f6d3e9SLang Hames handleAllErrors(std::move(E), 337f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 338f7f6d3e9SLang Hames 339f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 340f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 341f7f6d3e9SLang Hames } 3426935c2d3SLang Hames 34301864a2dSLang Hames // Test that the ExitOnError utility works as expected. 34401864a2dSLang Hames TEST(Error, ExitOnError) { 3456935c2d3SLang Hames ExitOnError ExitOnErr; 3466935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 34701864a2dSLang Hames ExitOnErr.setExitCodeMapper([](const Error &E) { 3486935c2d3SLang Hames if (E.isA<CustomSubError>()) 3496935c2d3SLang Hames return 2; 3506935c2d3SLang Hames return 1; 3516935c2d3SLang Hames }); 3526935c2d3SLang Hames 3536935c2d3SLang Hames // Make sure we don't bail on success. 3546935c2d3SLang Hames ExitOnErr(Error::success()); 3556935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 3566935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 3576935c2d3SLang Hames 3586935c2d3SLang Hames // Exit tests. 3596935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 3606935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 3616935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 3626935c2d3SLang Hames 3636935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 3646935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 3656935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 3666935c2d3SLang Hames } 367f7f6d3e9SLang Hames 36801864a2dSLang Hames // Test Expected<T> in success mode. 36901864a2dSLang Hames TEST(Error, ExpectedInSuccessMode) { 370f7f6d3e9SLang Hames Expected<int> A = 7; 37101864a2dSLang Hames EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 372f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 373f7f6d3e9SLang Hames } 374f7f6d3e9SLang Hames 37501864a2dSLang Hames // Test Expected<T> in failure mode. 37601864a2dSLang Hames TEST(Error, ExpectedInFailureMode) { 377f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 378f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 379f7f6d3e9SLang Hames Error E = A.takeError(); 380f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 381f7f6d3e9SLang Hames consumeError(std::move(E)); 382f7f6d3e9SLang Hames } 383f7f6d3e9SLang Hames 384f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 385f7f6d3e9SLang Hames // operator*. 386f7f6d3e9SLang Hames // Test runs in debug mode only. 387f7f6d3e9SLang Hames #ifndef NDEBUG 38801864a2dSLang Hames TEST(Error, AccessExpectedInFailureMode) { 389f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 3909fb8e1b2SLang Hames EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"") 391f7f6d3e9SLang Hames << "Incorrect Expected error value"; 392f7f6d3e9SLang Hames consumeError(A.takeError()); 393f7f6d3e9SLang Hames } 394f7f6d3e9SLang Hames #endif 395f7f6d3e9SLang Hames 396f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 397f7f6d3e9SLang Hames // unhandled. 398f7f6d3e9SLang Hames // Test runs in debug mode only. 399f7f6d3e9SLang Hames #ifndef NDEBUG 40001864a2dSLang Hames TEST(Error, UnhandledExpectedInFailureMode) { 401f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 402f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 403f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 40401864a2dSLang Hames } 405f7f6d3e9SLang Hames #endif 406f7f6d3e9SLang Hames 407f7f6d3e9SLang Hames // Test covariance of Expected. 40801864a2dSLang Hames TEST(Error, ExpectedCovariance) { 409f7f6d3e9SLang Hames class B {}; 410f7f6d3e9SLang Hames class D : public B {}; 411f7f6d3e9SLang Hames 412f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 413f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 414f7f6d3e9SLang Hames 415f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 416f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 417f7f6d3e9SLang Hames } 418f7f6d3e9SLang Hames 419f7f6d3e9SLang Hames TEST(Error, ECError) { 420f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 421f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 422f7f6d3e9SLang Hames std::error_code()) 423f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 424f7f6d3e9SLang Hames 425f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 426f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 427f7f6d3e9SLang Hames errc::invalid_argument) 428f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 429f7f6d3e9SLang Hames "conversions"; 430f7f6d3e9SLang Hames } 431f7f6d3e9SLang Hames 432f7f6d3e9SLang Hames } // end anon namespace 433