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" 12f7f6d3e9SLang Hames #include "gtest/gtest.h" 13f7f6d3e9SLang Hames #include <memory> 14f7f6d3e9SLang Hames 15f7f6d3e9SLang Hames using namespace llvm; 16f7f6d3e9SLang Hames 17f7f6d3e9SLang Hames namespace { 18f7f6d3e9SLang Hames 19f7f6d3e9SLang Hames // Test: 20f7f6d3e9SLang Hames // 21f7f6d3e9SLang Hames // Constructing success. 22f7f6d3e9SLang Hames // - Silent acceptance of tested success. 23f7f6d3e9SLang Hames // - Programmatic error on untested success. 24f7f6d3e9SLang Hames // 25f7f6d3e9SLang Hames // Custom error class. 26f7f6d3e9SLang Hames // - Creation of a custom error class with a default base class. 27f7f6d3e9SLang Hames // - Handling of a custom error class with a default base class. 28f7f6d3e9SLang Hames // - Handler type deduction. 29f7f6d3e9SLang Hames // - Failure to handle a custom error class. 30f7f6d3e9SLang Hames // - Isa testing of a custom error class. 31f7f6d3e9SLang Hames // 32f7f6d3e9SLang Hames // - Creation of a custom error class with a custom base class. 33f7f6d3e9SLang Hames // - Handling of a custom error class with a default base class. 34f7f6d3e9SLang Hames // - Correct shadowing of handlers. 35f7f6d3e9SLang Hames // 36f7f6d3e9SLang Hames // Utility functions: 37f7f6d3e9SLang Hames // - join_errors to defer errors. 38f7f6d3e9SLang Hames // - consume_error to consume a "safe" error without any output. 39f7f6d3e9SLang Hames // - handleAllUnhandledErrors to assert that all errors are handled. 40f7f6d3e9SLang Hames // - logAllUnhandledErrors to log errors to a stream. 41*6935c2d3SLang Hames // - ExitOnError tests. 42f7f6d3e9SLang Hames // 43f7f6d3e9SLang Hames // Expected tests: 44f7f6d3e9SLang Hames // - Expected<T> with T. 45f7f6d3e9SLang Hames // - Expected<T> with Error. 46f7f6d3e9SLang Hames // - Failure to handle an Expected<T> in failure mode. 47f7f6d3e9SLang Hames // - Error extraction (Expected -> Error). 48f7f6d3e9SLang Hames // 49f7f6d3e9SLang Hames // std::error_code: 50f7f6d3e9SLang Hames // - std::error_code to Error in success mode. 51f7f6d3e9SLang Hames // - std::error_code to Error (ECError) in failure mode. 52f7f6d3e9SLang Hames // - Error to std::error_code in success mode. 53f7f6d3e9SLang Hames // - Error (ECError) to std::error_code in failure mode. 54*6935c2d3SLang Hames // 55f7f6d3e9SLang Hames 56f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached. 57f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> { 58f7f6d3e9SLang Hames public: 59f7f6d3e9SLang Hames // Create an error with some info attached. 60f7f6d3e9SLang Hames CustomError(int Info) : Info(Info) {} 61f7f6d3e9SLang Hames 62f7f6d3e9SLang Hames // Get the info attached to this error. 63f7f6d3e9SLang Hames int getInfo() const { return Info; } 64f7f6d3e9SLang Hames 65f7f6d3e9SLang Hames // Log this error to a stream. 66f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 67f7f6d3e9SLang Hames OS << "CustomError { " << getInfo() << "}"; 68f7f6d3e9SLang Hames } 69f7f6d3e9SLang Hames 70f7f6d3e9SLang Hames protected: 71f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 72f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 73f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 74f7f6d3e9SLang Hames // fields. 75f7f6d3e9SLang Hames CustomError() : Info(0) {} 76f7f6d3e9SLang Hames 77f7f6d3e9SLang Hames int Info; 78f7f6d3e9SLang Hames }; 79f7f6d3e9SLang Hames 80f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 81f7f6d3e9SLang Hames // 'info'. 82f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 83f7f6d3e9SLang Hames public: 84f7f6d3e9SLang Hames // Create a sub-error with some info attached. 85f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 86f7f6d3e9SLang Hames this->Info = Info; 87f7f6d3e9SLang Hames } 88f7f6d3e9SLang Hames 89f7f6d3e9SLang Hames // Get the extra info attached to this error. 90f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 91f7f6d3e9SLang Hames 92f7f6d3e9SLang Hames // Log this error to a stream. 93f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 94f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 95f7f6d3e9SLang Hames } 96f7f6d3e9SLang Hames 97f7f6d3e9SLang Hames protected: 98f7f6d3e9SLang Hames int ExtraInfo; 99f7f6d3e9SLang Hames }; 100f7f6d3e9SLang Hames 101f7f6d3e9SLang Hames // Verify that success values that are checked (i.e. cast to 'bool') are 102f7f6d3e9SLang Hames // destructed without error, and that unchecked success values cause an 103f7f6d3e9SLang Hames // abort. 104f7f6d3e9SLang Hames TEST(Error, CheckSuccess) { 105f7f6d3e9SLang Hames // Test checked success. 106f7f6d3e9SLang Hames { 107f7f6d3e9SLang Hames Error E; 108f7f6d3e9SLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 109f7f6d3e9SLang Hames } 110f7f6d3e9SLang Hames 111f7f6d3e9SLang Hames // Test unchecked success. 112f7f6d3e9SLang Hames // Test runs in debug mode only. 113f7f6d3e9SLang Hames #ifndef NDEBUG 114f7f6d3e9SLang Hames { 115f7f6d3e9SLang Hames auto DropUncheckedSuccess = []() { Error E; }; 116f7f6d3e9SLang Hames EXPECT_DEATH(DropUncheckedSuccess(), 117f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 118f7f6d3e9SLang Hames << "Unchecked Error Succes value did not cause abort()"; 119f7f6d3e9SLang Hames } 120f7f6d3e9SLang Hames #endif 121f7f6d3e9SLang Hames } 122f7f6d3e9SLang Hames 123f7f6d3e9SLang Hames static Error handleCustomError(const CustomError &CE) { return Error(); } 124f7f6d3e9SLang Hames 125f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 126f7f6d3e9SLang Hames 127f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 128f7f6d3e9SLang Hames return Error(); 129f7f6d3e9SLang Hames } 130f7f6d3e9SLang Hames 131f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 132f7f6d3e9SLang Hames 133f7f6d3e9SLang Hames // Verify creation and handling of custom error classes. 134f7f6d3e9SLang Hames TEST(Error, CheckCustomErrors) { 135f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 136f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 137f7f6d3e9SLang Hames // Test runs in debug mode only. 138f7f6d3e9SLang Hames #ifndef NDEBUG 139f7f6d3e9SLang Hames { 140f7f6d3e9SLang Hames auto DropUnhandledError = []() { 141f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 142f7f6d3e9SLang Hames (void)!E; 143f7f6d3e9SLang Hames }; 144f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 145f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 146f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 147f7f6d3e9SLang Hames } 148f7f6d3e9SLang Hames #endif 149f7f6d3e9SLang Hames 150f7f6d3e9SLang Hames // Check 'isA' handling. 151f7f6d3e9SLang Hames { 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. 168f7f6d3e9SLang Hames { 169f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 170f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 171f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 172f7f6d3e9SLang Hames }); 173f7f6d3e9SLang Hames 174f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) 175f7f6d3e9SLang Hames << "Wrong result from CustomError handler"; 176f7f6d3e9SLang Hames } 177f7f6d3e9SLang Hames 178f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 179f7f6d3e9SLang Hames // of the following types: 180f7f6d3e9SLang Hames // void (const Err&) 181f7f6d3e9SLang Hames // Error (const Err&) mutable 182f7f6d3e9SLang Hames // void (const Err&) mutable 183f7f6d3e9SLang Hames // Error (Err&) 184f7f6d3e9SLang Hames // void (Err&) 185f7f6d3e9SLang Hames // Error (Err&) mutable 186f7f6d3e9SLang Hames // void (Err&) mutable 187f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 188f7f6d3e9SLang Hames // void (unique_ptr<Err>) 189f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 190f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 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); 236f7f6d3e9SLang Hames 237f7f6d3e9SLang Hames // Check that we can handle a custom error with a custom base class. 238f7f6d3e9SLang Hames { 239f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 240f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 241f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 242f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 243f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 244f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 245f7f6d3e9SLang Hames }); 246f7f6d3e9SLang Hames 247f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 248f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 249f7f6d3e9SLang Hames } 250f7f6d3e9SLang Hames 251f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 252f7f6d3e9SLang Hames { 253f7f6d3e9SLang Hames int DummyInfo = 0; 254f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 255f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 256f7f6d3e9SLang Hames 257f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 258f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 259f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 260f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 261f7f6d3e9SLang Hames }, 262f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 263f7f6d3e9SLang Hames 264f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 265f7f6d3e9SLang Hames DummyInfo == 0) 266f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 267f7f6d3e9SLang Hames } 268f7f6d3e9SLang Hames 269f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 270f7f6d3e9SLang Hames { 271f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 272f7f6d3e9SLang Hames int DummyInfo = 0; 273f7f6d3e9SLang Hames int DummyExtraInfo = 0; 274f7f6d3e9SLang Hames 275f7f6d3e9SLang Hames handleAllErrors( 276f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 277f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 278f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 279f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 280f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 281f7f6d3e9SLang Hames }); 282f7f6d3e9SLang Hames 283f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo = 42 && DummyInfo == 0 && DummyExtraInfo == 0) 284f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 285f7f6d3e9SLang Hames } 286f7f6d3e9SLang Hames } 287f7f6d3e9SLang Hames 288f7f6d3e9SLang Hames // Test utility functions. 289f7f6d3e9SLang Hames TEST(Error, CheckErrorUtilities) { 290f7f6d3e9SLang Hames 291f7f6d3e9SLang Hames // Test joinErrors 292f7f6d3e9SLang Hames { 293f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 294f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 295f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 296f7f6d3e9SLang Hames Error E = joinErrors(make_error<CustomError>(7), 297f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7)); 298f7f6d3e9SLang Hames 299f7f6d3e9SLang Hames handleAllErrors(std::move(E), 300f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 301f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 302f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 303f7f6d3e9SLang Hames }, 304f7f6d3e9SLang Hames [&](const CustomError &CE) { 305f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 306f7f6d3e9SLang Hames // before the 307f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 308f7f6d3e9SLang Hames // ordering. 309f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 310f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 311f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 312f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 313f7f6d3e9SLang Hames }); 314f7f6d3e9SLang Hames 315f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 316f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 317f7f6d3e9SLang Hames << "Failed handling compound Error."; 318f7f6d3e9SLang Hames } 319f7f6d3e9SLang Hames 320f7f6d3e9SLang Hames // Test consumeError for both success and error cases. 321f7f6d3e9SLang Hames { 322f7f6d3e9SLang Hames Error E; 323f7f6d3e9SLang Hames consumeError(std::move(E)); 324f7f6d3e9SLang Hames } 325f7f6d3e9SLang Hames { 326f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 327f7f6d3e9SLang Hames consumeError(std::move(E)); 328f7f6d3e9SLang Hames } 329f7f6d3e9SLang Hames 330f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 331f7f6d3e9SLang Hames // Test runs in debug mode only. 332f7f6d3e9SLang Hames #ifndef NDEBUG 333f7f6d3e9SLang Hames { 334f7f6d3e9SLang Hames auto FailToHandle = []() { 335f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 336f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 337f7f6d3e9SLang Hames errs() << "This should never be called"; 338f7f6d3e9SLang Hames exit(1); 339f7f6d3e9SLang Hames }); 340f7f6d3e9SLang Hames }; 341f7f6d3e9SLang Hames 342f7f6d3e9SLang Hames EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") 343f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 344f7f6d3e9SLang Hames "abort()"; 345f7f6d3e9SLang Hames } 346f7f6d3e9SLang Hames #endif 347f7f6d3e9SLang Hames 348f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 349f7f6d3e9SLang Hames // handler. 350f7f6d3e9SLang Hames // Test runs in debug mode only. 351f7f6d3e9SLang Hames #ifndef NDEBUG 352f7f6d3e9SLang Hames { 353f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 354f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 355f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 356f7f6d3e9SLang Hames return Error(std::move(SE)); 357f7f6d3e9SLang Hames }); 358f7f6d3e9SLang Hames }; 359f7f6d3e9SLang Hames 360f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 361f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 362f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 363f7f6d3e9SLang Hames "cause abort()"; 364f7f6d3e9SLang Hames } 365f7f6d3e9SLang Hames #endif 366f7f6d3e9SLang Hames 367f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 368f7f6d3e9SLang Hames { 369f7f6d3e9SLang Hames int ErrorInfo = 0; 370f7f6d3e9SLang Hames 371f7f6d3e9SLang Hames Error E = handleErrors( 372f7f6d3e9SLang Hames make_error<CustomError>(7), 373f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 374f7f6d3e9SLang Hames 375f7f6d3e9SLang Hames handleAllErrors(std::move(E), 376f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 377f7f6d3e9SLang Hames 378f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 379f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 380f7f6d3e9SLang Hames } 381*6935c2d3SLang Hames 382*6935c2d3SLang Hames // Test ExitOnError 383*6935c2d3SLang Hames { 384*6935c2d3SLang Hames ExitOnError ExitOnErr; 385*6935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 386*6935c2d3SLang Hames ExitOnErr.setExitCodeMapper( 387*6935c2d3SLang Hames [](const Error &E) { 388*6935c2d3SLang Hames if (E.isA<CustomSubError>()) 389*6935c2d3SLang Hames return 2; 390*6935c2d3SLang Hames return 1; 391*6935c2d3SLang Hames }); 392*6935c2d3SLang Hames 393*6935c2d3SLang Hames // Make sure we don't bail on success. 394*6935c2d3SLang Hames ExitOnErr(Error::success()); 395*6935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 396*6935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 397*6935c2d3SLang Hames 398*6935c2d3SLang Hames // Exit tests. 399*6935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 400*6935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 401*6935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 402*6935c2d3SLang Hames 403*6935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 404*6935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 405*6935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 406*6935c2d3SLang Hames } 407f7f6d3e9SLang Hames } 408f7f6d3e9SLang Hames 409f7f6d3e9SLang Hames // Test Expected behavior. 410f7f6d3e9SLang Hames TEST(Error, CheckExpected) { 411f7f6d3e9SLang Hames 412f7f6d3e9SLang Hames // Check that non-errors convert to 'true'. 413f7f6d3e9SLang Hames { 414f7f6d3e9SLang Hames Expected<int> A = 7; 415f7f6d3e9SLang Hames EXPECT_TRUE(!!A) 416f7f6d3e9SLang Hames << "Expected with non-error value doesn't convert to 'true'"; 417f7f6d3e9SLang Hames } 418f7f6d3e9SLang Hames 419f7f6d3e9SLang Hames // Check that non-error values are accessible via operator*. 420f7f6d3e9SLang Hames { 421f7f6d3e9SLang Hames Expected<int> A = 7; 422f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 423f7f6d3e9SLang Hames } 424f7f6d3e9SLang Hames 425f7f6d3e9SLang Hames // Check that errors convert to 'false'. 426f7f6d3e9SLang Hames { 427f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 428f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 429f7f6d3e9SLang Hames consumeError(A.takeError()); 430f7f6d3e9SLang Hames } 431f7f6d3e9SLang Hames 432f7f6d3e9SLang Hames // Check that error values are accessible via takeError(). 433f7f6d3e9SLang Hames { 434f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 435f7f6d3e9SLang Hames Error E = A.takeError(); 436f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 437f7f6d3e9SLang Hames consumeError(std::move(E)); 438f7f6d3e9SLang Hames } 439f7f6d3e9SLang Hames 440f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 441f7f6d3e9SLang Hames // operator*. 442f7f6d3e9SLang Hames // Test runs in debug mode only. 443f7f6d3e9SLang Hames #ifndef NDEBUG 444f7f6d3e9SLang Hames { 445f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 4469fb8e1b2SLang Hames EXPECT_DEATH(*A, "!HasError && \"Cannot get value when an error exists!\"") 447f7f6d3e9SLang Hames << "Incorrect Expected error value"; 448f7f6d3e9SLang Hames consumeError(A.takeError()); 449f7f6d3e9SLang Hames } 450f7f6d3e9SLang Hames #endif 451f7f6d3e9SLang Hames 452f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 453f7f6d3e9SLang Hames // unhandled. 454f7f6d3e9SLang Hames // Test runs in debug mode only. 455f7f6d3e9SLang Hames #ifndef NDEBUG 456f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 457f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 458f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 459f7f6d3e9SLang Hames #endif 460f7f6d3e9SLang Hames 461f7f6d3e9SLang Hames // Test covariance of Expected. 462f7f6d3e9SLang Hames { 463f7f6d3e9SLang Hames class B {}; 464f7f6d3e9SLang Hames class D : public B {}; 465f7f6d3e9SLang Hames 466f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 467f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 468f7f6d3e9SLang Hames 469f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 470f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 471f7f6d3e9SLang Hames } 472f7f6d3e9SLang Hames } 473f7f6d3e9SLang Hames 474f7f6d3e9SLang Hames TEST(Error, ECError) { 475f7f6d3e9SLang Hames 476f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 477f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 478f7f6d3e9SLang Hames std::error_code()) 479f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 480f7f6d3e9SLang Hames 481f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 482f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 483f7f6d3e9SLang Hames errc::invalid_argument) 484f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 485f7f6d3e9SLang Hames "conversions"; 486f7f6d3e9SLang Hames } 487f7f6d3e9SLang Hames 488f7f6d3e9SLang Hames } // end anon namespace 489