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