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" 1100fb14daSLang Hames #include "llvm-c/Error.h" 12c5e0bbd7SLang Hames 13c5e0bbd7SLang Hames #include "llvm/ADT/Twine.h" 14f7f6d3e9SLang Hames #include "llvm/Support/Errc.h" 15e7aad357SLang Hames #include "llvm/Support/ErrorHandling.h" 16*e11f2217SAlexandre Ganea #include "llvm/Support/ManagedStatic.h" 17e8354fe6SPavel Labath #include "llvm/Testing/Support/Error.h" 18e8354fe6SPavel Labath #include "gtest/gtest-spi.h" 19f7f6d3e9SLang Hames #include "gtest/gtest.h" 20f7f6d3e9SLang Hames #include <memory> 21f7f6d3e9SLang Hames 22f7f6d3e9SLang Hames using namespace llvm; 23f7f6d3e9SLang Hames 24f7f6d3e9SLang Hames namespace { 25f7f6d3e9SLang Hames 26f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached. 27f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> { 28f7f6d3e9SLang Hames public: 29f7f6d3e9SLang Hames // Create an error with some info attached. 30f7f6d3e9SLang Hames CustomError(int Info) : Info(Info) {} 31f7f6d3e9SLang Hames 32f7f6d3e9SLang Hames // Get the info attached to this error. 33f7f6d3e9SLang Hames int getInfo() const { return Info; } 34f7f6d3e9SLang Hames 35f7f6d3e9SLang Hames // Log this error to a stream. 36f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 37f7f6d3e9SLang Hames OS << "CustomError {" << getInfo() << "}"; 38f7f6d3e9SLang Hames } 39f7f6d3e9SLang Hames 40e7aad357SLang Hames std::error_code convertToErrorCode() const override { 41e7aad357SLang Hames llvm_unreachable("CustomError doesn't support ECError conversion"); 42e7aad357SLang Hames } 43e7aad357SLang Hames 44a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 45a15b76b3SReid Kleckner static char ID; 46a15b76b3SReid Kleckner 47f7f6d3e9SLang Hames protected: 48f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 49f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 50f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 51f7f6d3e9SLang Hames // fields. 52f7f6d3e9SLang Hames CustomError() : Info(0) {} 53f7f6d3e9SLang Hames 54f7f6d3e9SLang Hames int Info; 55f7f6d3e9SLang Hames }; 56f7f6d3e9SLang Hames 57a15b76b3SReid Kleckner char CustomError::ID = 0; 58a15b76b3SReid Kleckner 59f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 60f7f6d3e9SLang Hames // 'info'. 61f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 62f7f6d3e9SLang Hames public: 63f7f6d3e9SLang Hames // Create a sub-error with some info attached. 64f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 65f7f6d3e9SLang Hames this->Info = Info; 66f7f6d3e9SLang Hames } 67f7f6d3e9SLang Hames 68f7f6d3e9SLang Hames // Get the extra info attached to this error. 69f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 70f7f6d3e9SLang Hames 71f7f6d3e9SLang Hames // Log this error to a stream. 72f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 73f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 74f7f6d3e9SLang Hames } 75f7f6d3e9SLang Hames 76e7aad357SLang Hames std::error_code convertToErrorCode() const override { 77e7aad357SLang Hames llvm_unreachable("CustomSubError doesn't support ECError conversion"); 78e7aad357SLang Hames } 79e7aad357SLang Hames 80a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 81a15b76b3SReid Kleckner static char ID; 82a15b76b3SReid Kleckner 83f7f6d3e9SLang Hames protected: 84f7f6d3e9SLang Hames int ExtraInfo; 85f7f6d3e9SLang Hames }; 86f7f6d3e9SLang Hames 87a15b76b3SReid Kleckner char CustomSubError::ID = 0; 88a15b76b3SReid Kleckner 8941af4309SMehdi Amini static Error handleCustomError(const CustomError &CE) { 9041af4309SMehdi Amini return Error::success(); 9141af4309SMehdi Amini } 92f7f6d3e9SLang Hames 93f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 94f7f6d3e9SLang Hames 95f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 9641af4309SMehdi Amini return Error::success(); 97f7f6d3e9SLang Hames } 98f7f6d3e9SLang Hames 99f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 100f7f6d3e9SLang Hames 10101864a2dSLang Hames // Test that success values implicitly convert to false, and don't cause crashes 10201864a2dSLang Hames // once they've been implicitly converted. 10301864a2dSLang Hames TEST(Error, CheckedSuccess) { 104c1edf566SMehdi Amini Error E = Error::success(); 10501864a2dSLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 10601864a2dSLang Hames } 10701864a2dSLang Hames 108*e11f2217SAlexandre Ganea // Test that unchecked success values cause an abort. 109cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 11001864a2dSLang Hames TEST(Error, UncheckedSuccess) { 111c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); }, 112c1edf566SMehdi Amini "Program aborted due to an unhandled Error:") 11301864a2dSLang Hames << "Unchecked Error Succes value did not cause abort()"; 11401864a2dSLang Hames } 11501864a2dSLang Hames #endif 11601864a2dSLang Hames 117d1af8fceSLang Hames // ErrorAsOutParameter tester. 118d1af8fceSLang Hames void errAsOutParamHelper(Error &Err) { 1195e51a2e3SLang Hames ErrorAsOutParameter ErrAsOutParam(&Err); 120d1af8fceSLang Hames // Verify that checked flag is raised - assignment should not crash. 121d1af8fceSLang Hames Err = Error::success(); 122d1af8fceSLang Hames // Raise the checked bit manually - caller should still have to test the 123d1af8fceSLang Hames // error. 124d1af8fceSLang Hames (void)!!Err; 125d0ac31a7SLang Hames } 126d0ac31a7SLang Hames 127d1af8fceSLang Hames // Test that ErrorAsOutParameter sets the checked flag on construction. 128d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterChecked) { 129c1edf566SMehdi Amini Error E = Error::success(); 130d1af8fceSLang Hames errAsOutParamHelper(E); 131d1af8fceSLang Hames (void)!!E; 132d1af8fceSLang Hames } 133d1af8fceSLang Hames 134d1af8fceSLang Hames // Test that ErrorAsOutParameter clears the checked flag on destruction. 135cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 136d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterUnchecked) { 137c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); errAsOutParamHelper(E); }, 138d1af8fceSLang Hames "Program aborted due to an unhandled Error:") 139d1af8fceSLang Hames << "ErrorAsOutParameter did not clear the checked flag on destruction."; 140d1af8fceSLang Hames } 141d1af8fceSLang Hames #endif 142d1af8fceSLang Hames 143f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 144f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 145f7f6d3e9SLang Hames // Test runs in debug mode only. 146cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 14701864a2dSLang Hames TEST(Error, UncheckedError) { 148f7f6d3e9SLang Hames auto DropUnhandledError = []() { 149f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 150f7f6d3e9SLang Hames (void)!E; 151f7f6d3e9SLang Hames }; 152f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 153f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 154f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 155f7f6d3e9SLang Hames } 156f7f6d3e9SLang Hames #endif 157f7f6d3e9SLang Hames 15801864a2dSLang Hames // Check 'Error::isA<T>' method handling. 15901864a2dSLang Hames TEST(Error, IsAHandling) { 160f7f6d3e9SLang Hames // Check 'isA' handling. 161f7f6d3e9SLang Hames Error E = make_error<CustomError>(1); 162f7f6d3e9SLang Hames Error F = make_error<CustomSubError>(1, 2); 16301a3cf4dSLang Hames Error G = Error::success(); 164f7f6d3e9SLang Hames 165f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()); 166f7f6d3e9SLang Hames EXPECT_FALSE(E.isA<CustomSubError>()); 167f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomError>()); 168f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomSubError>()); 16901a3cf4dSLang Hames EXPECT_FALSE(G.isA<CustomError>()); 170f7f6d3e9SLang Hames 171f7f6d3e9SLang Hames consumeError(std::move(E)); 172f7f6d3e9SLang Hames consumeError(std::move(F)); 17301a3cf4dSLang Hames consumeError(std::move(G)); 174f7f6d3e9SLang Hames } 175f7f6d3e9SLang Hames 176f7f6d3e9SLang Hames // Check that we can handle a custom error. 17701864a2dSLang Hames TEST(Error, HandleCustomError) { 178f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 179f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 180f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 181f7f6d3e9SLang Hames }); 182f7f6d3e9SLang Hames 18301864a2dSLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 184f7f6d3e9SLang Hames } 185f7f6d3e9SLang Hames 186f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 187f7f6d3e9SLang Hames // of the following types: 188f7f6d3e9SLang Hames // void (const Err&) 189f7f6d3e9SLang Hames // Error (const Err&) mutable 190f7f6d3e9SLang Hames // void (const Err&) mutable 191f7f6d3e9SLang Hames // Error (Err&) 192f7f6d3e9SLang Hames // void (Err&) 193f7f6d3e9SLang Hames // Error (Err&) mutable 194f7f6d3e9SLang Hames // void (Err&) mutable 195f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 196f7f6d3e9SLang Hames // void (unique_ptr<Err>) 197f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 198f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 19901864a2dSLang Hames TEST(Error, HandlerTypeDeduction) { 200f7f6d3e9SLang Hames 201f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 202f7f6d3e9SLang Hames 203f7f6d3e9SLang Hames handleAllErrors( 204f7f6d3e9SLang Hames make_error<CustomError>(42), 205c1edf566SMehdi Amini [](const CustomError &CE) mutable -> Error { return Error::success(); }); 206f7f6d3e9SLang Hames 207f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 208f7f6d3e9SLang Hames [](const CustomError &CE) mutable {}); 209f7f6d3e9SLang Hames 210f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 211c1edf566SMehdi Amini [](CustomError &CE) -> Error { return Error::success(); }); 212f7f6d3e9SLang Hames 213f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 214f7f6d3e9SLang Hames 215f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 216c1edf566SMehdi Amini [](CustomError &CE) mutable -> Error { return Error::success(); }); 217f7f6d3e9SLang Hames 218f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 219f7f6d3e9SLang Hames 220f7f6d3e9SLang Hames handleAllErrors( 221f7f6d3e9SLang Hames make_error<CustomError>(42), 222c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) -> Error { return Error::success(); }); 223f7f6d3e9SLang Hames 224f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 225f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) {}); 226f7f6d3e9SLang Hames 227f7f6d3e9SLang Hames handleAllErrors( 228f7f6d3e9SLang Hames make_error<CustomError>(42), 229c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) mutable -> Error { return Error::success(); }); 230f7f6d3e9SLang Hames 231f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 232f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable {}); 233f7f6d3e9SLang Hames 234f7f6d3e9SLang Hames // Check that named handlers of type 'Error (const Err&)' work. 235f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomError); 236f7f6d3e9SLang Hames 237f7f6d3e9SLang Hames // Check that named handlers of type 'void (const Err&)' work. 238f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 239f7f6d3e9SLang Hames 240f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 241f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 242f7f6d3e9SLang Hames 243f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 244f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 24501864a2dSLang Hames } 246f7f6d3e9SLang Hames 24701864a2dSLang Hames // Test that we can handle errors with custom base classes. 24801864a2dSLang Hames TEST(Error, HandleCustomErrorWithCustomBaseClass) { 249f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 250f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 251f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 252f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 253f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 254f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 255f7f6d3e9SLang Hames }); 256f7f6d3e9SLang Hames 257f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 258f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 259f7f6d3e9SLang Hames } 260f7f6d3e9SLang Hames 261f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 26201864a2dSLang Hames TEST(Error, FirstHandlerOnly) { 263f7f6d3e9SLang Hames int DummyInfo = 0; 264f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 265f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 266f7f6d3e9SLang Hames 267f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 268f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 269f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 270f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 271f7f6d3e9SLang Hames }, 272f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 273f7f6d3e9SLang Hames 274f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 275f7f6d3e9SLang Hames DummyInfo == 0) 276f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 277f7f6d3e9SLang Hames } 278f7f6d3e9SLang Hames 279f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 28001864a2dSLang Hames TEST(Error, HandlerShadowing) { 281f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 282f7f6d3e9SLang Hames int DummyInfo = 0; 283f7f6d3e9SLang Hames int DummyExtraInfo = 0; 284f7f6d3e9SLang Hames 285f7f6d3e9SLang Hames handleAllErrors( 286f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 287f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 288f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 289f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 290f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 291f7f6d3e9SLang Hames }); 292f7f6d3e9SLang Hames 293b2cef64bSNAKAMURA Takumi EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) 294f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 295f7f6d3e9SLang Hames } 296f7f6d3e9SLang Hames 29701864a2dSLang Hames // Test joinErrors. 29801864a2dSLang Hames TEST(Error, CheckJoinErrors) { 299f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 300f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 301f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 30201864a2dSLang Hames Error E = 30301864a2dSLang Hames joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 304f7f6d3e9SLang Hames 305f7f6d3e9SLang Hames handleAllErrors(std::move(E), 306f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 307f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 308f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 309f7f6d3e9SLang Hames }, 310f7f6d3e9SLang Hames [&](const CustomError &CE) { 311f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 312f7f6d3e9SLang Hames // before the 313f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 314f7f6d3e9SLang Hames // ordering. 315f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 316f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 317f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 318f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 319f7f6d3e9SLang Hames }); 320f7f6d3e9SLang Hames 321f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 322f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 323f7f6d3e9SLang Hames << "Failed handling compound Error."; 324759b30edSLang Hames 325759b30edSLang Hames // Test appending a single item to a list. 326759b30edSLang Hames { 327759b30edSLang Hames int Sum = 0; 328759b30edSLang Hames handleAllErrors( 329759b30edSLang Hames joinErrors( 330759b30edSLang Hames joinErrors(make_error<CustomError>(7), 331759b30edSLang Hames make_error<CustomError>(7)), 332759b30edSLang Hames make_error<CustomError>(7)), 333759b30edSLang Hames [&](const CustomError &CE) { 334759b30edSLang Hames Sum += CE.getInfo(); 335759b30edSLang Hames }); 336759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list."; 337759b30edSLang Hames } 338759b30edSLang Hames 339759b30edSLang Hames // Test prepending a single item to a list. 340759b30edSLang Hames { 341759b30edSLang Hames int Sum = 0; 342759b30edSLang Hames handleAllErrors( 343759b30edSLang Hames joinErrors( 344759b30edSLang Hames make_error<CustomError>(7), 345759b30edSLang Hames joinErrors(make_error<CustomError>(7), 346759b30edSLang Hames make_error<CustomError>(7))), 347759b30edSLang Hames [&](const CustomError &CE) { 348759b30edSLang Hames Sum += CE.getInfo(); 349759b30edSLang Hames }); 350759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list."; 351759b30edSLang Hames } 352759b30edSLang Hames 353759b30edSLang Hames // Test concatenating two error lists. 354759b30edSLang Hames { 355759b30edSLang Hames int Sum = 0; 356759b30edSLang Hames handleAllErrors( 357759b30edSLang Hames joinErrors( 358759b30edSLang Hames joinErrors( 359759b30edSLang Hames make_error<CustomError>(7), 360759b30edSLang Hames make_error<CustomError>(7)), 361759b30edSLang Hames joinErrors( 362759b30edSLang Hames make_error<CustomError>(7), 363759b30edSLang Hames make_error<CustomError>(7))), 364759b30edSLang Hames [&](const CustomError &CE) { 365759b30edSLang Hames Sum += CE.getInfo(); 366759b30edSLang Hames }); 3670ca79dcfSHiroshi Inoue EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate error lists."; 368759b30edSLang Hames } 369f7f6d3e9SLang Hames } 370f7f6d3e9SLang Hames 37101864a2dSLang Hames // Test that we can consume success values. 37201864a2dSLang Hames TEST(Error, ConsumeSuccess) { 373c1edf566SMehdi Amini Error E = Error::success(); 374f7f6d3e9SLang Hames consumeError(std::move(E)); 375f7f6d3e9SLang Hames } 37601864a2dSLang Hames 37701864a2dSLang Hames TEST(Error, ConsumeError) { 378f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 379f7f6d3e9SLang Hames consumeError(std::move(E)); 380f7f6d3e9SLang Hames } 381f7f6d3e9SLang Hames 382f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 383f7f6d3e9SLang Hames // Test runs in debug mode only. 384cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 38501864a2dSLang Hames TEST(Error, FailureToHandle) { 386f7f6d3e9SLang Hames auto FailToHandle = []() { 38701864a2dSLang Hames handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 388f7f6d3e9SLang Hames errs() << "This should never be called"; 389f7f6d3e9SLang Hames exit(1); 390f7f6d3e9SLang Hames }); 391f7f6d3e9SLang Hames }; 392f7f6d3e9SLang Hames 3937febf2baSLang Hames EXPECT_DEATH(FailToHandle(), 3947febf2baSLang Hames "Failure value returned from cantFail wrapped call") 395f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 396f7f6d3e9SLang Hames "abort()"; 397f7f6d3e9SLang Hames } 398f7f6d3e9SLang Hames #endif 399f7f6d3e9SLang Hames 400f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 401f7f6d3e9SLang Hames // handler. 402f7f6d3e9SLang Hames // Test runs in debug mode only. 403cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 40401864a2dSLang Hames TEST(Error, FailureFromHandler) { 405f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 406f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 407f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 408f7f6d3e9SLang Hames return Error(std::move(SE)); 409f7f6d3e9SLang Hames }); 410f7f6d3e9SLang Hames }; 411f7f6d3e9SLang Hames 412f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 4137febf2baSLang Hames "Failure value returned from cantFail wrapped call") 414f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 415f7f6d3e9SLang Hames "cause abort()"; 416f7f6d3e9SLang Hames } 417f7f6d3e9SLang Hames #endif 418f7f6d3e9SLang Hames 419f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 42001864a2dSLang Hames TEST(Error, CatchErrorFromHandler) { 421f7f6d3e9SLang Hames int ErrorInfo = 0; 422f7f6d3e9SLang Hames 423f7f6d3e9SLang Hames Error E = handleErrors( 424f7f6d3e9SLang Hames make_error<CustomError>(7), 425f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 426f7f6d3e9SLang Hames 427f7f6d3e9SLang Hames handleAllErrors(std::move(E), 428f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 429f7f6d3e9SLang Hames 430f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 431f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 432f7f6d3e9SLang Hames } 4336935c2d3SLang Hames 434c5e0bbd7SLang Hames TEST(Error, StringError) { 435c5e0bbd7SLang Hames std::string Msg; 436c5e0bbd7SLang Hames raw_string_ostream S(Msg); 437c5e0bbd7SLang Hames logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42), 438bd8e9542SLang Hames inconvertibleErrorCode()), 439c5e0bbd7SLang Hames S, ""); 440c5e0bbd7SLang Hames EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result"; 441c5e0bbd7SLang Hames 442c5e0bbd7SLang Hames auto EC = 443c5e0bbd7SLang Hames errorToErrorCode(make_error<StringError>("", errc::invalid_argument)); 444c5e0bbd7SLang Hames EXPECT_EQ(EC, errc::invalid_argument) 445c5e0bbd7SLang Hames << "Failed to convert StringError to error_code."; 446c5e0bbd7SLang Hames } 447c5e0bbd7SLang Hames 448e58e9907SVictor Leschuk TEST(Error, createStringError) { 449e58e9907SVictor Leschuk static const char *Bar = "bar"; 450e58e9907SVictor Leschuk static const std::error_code EC = errc::invalid_argument; 451e58e9907SVictor Leschuk std::string Msg; 452e58e9907SVictor Leschuk raw_string_ostream S(Msg); 453e58e9907SVictor Leschuk logAllUnhandledErrors(createStringError(EC, "foo%s%d0x%" PRIx8, Bar, 1, 0xff), 454e58e9907SVictor Leschuk S, ""); 455e58e9907SVictor Leschuk EXPECT_EQ(S.str(), "foobar10xff\n") 456e58e9907SVictor Leschuk << "Unexpected createStringError() log result"; 457e58e9907SVictor Leschuk 458e58e9907SVictor Leschuk S.flush(); 459e58e9907SVictor Leschuk Msg.clear(); 460e58e9907SVictor Leschuk logAllUnhandledErrors(createStringError(EC, Bar), S, ""); 461e58e9907SVictor Leschuk EXPECT_EQ(S.str(), "bar\n") 462e58e9907SVictor Leschuk << "Unexpected createStringError() (overloaded) log result"; 463e58e9907SVictor Leschuk 464e58e9907SVictor Leschuk S.flush(); 465e58e9907SVictor Leschuk Msg.clear(); 466e58e9907SVictor Leschuk auto Res = errorToErrorCode(createStringError(EC, "foo%s", Bar)); 467e58e9907SVictor Leschuk EXPECT_EQ(Res, EC) 468e58e9907SVictor Leschuk << "Failed to convert createStringError() result to error_code."; 469e58e9907SVictor Leschuk } 470e58e9907SVictor Leschuk 47101864a2dSLang Hames // Test that the ExitOnError utility works as expected. 47201864a2dSLang Hames TEST(Error, ExitOnError) { 4736935c2d3SLang Hames ExitOnError ExitOnErr; 4746935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 47501864a2dSLang Hames ExitOnErr.setExitCodeMapper([](const Error &E) { 4766935c2d3SLang Hames if (E.isA<CustomSubError>()) 4776935c2d3SLang Hames return 2; 4786935c2d3SLang Hames return 1; 4796935c2d3SLang Hames }); 4806935c2d3SLang Hames 4816935c2d3SLang Hames // Make sure we don't bail on success. 4826935c2d3SLang Hames ExitOnErr(Error::success()); 4836935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 4846935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 4856935c2d3SLang Hames 486285639f8SLang Hames int A = 7; 487285639f8SLang Hames int &B = ExitOnErr(Expected<int&>(A)); 488285639f8SLang Hames EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference"; 489285639f8SLang Hames 4906935c2d3SLang Hames // Exit tests. 4916935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 4926935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 4936935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4946935c2d3SLang Hames 4956935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 4966935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 4976935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4986935c2d3SLang Hames } 499f7f6d3e9SLang Hames 500fd4de910SLang Hames // Test that the ExitOnError utility works as expected. 501fd4de910SLang Hames TEST(Error, CantFailSuccess) { 502fd4de910SLang Hames cantFail(Error::success()); 503fd4de910SLang Hames 504fd4de910SLang Hames int X = cantFail(Expected<int>(42)); 505fd4de910SLang Hames EXPECT_EQ(X, 42) << "Expected value modified by cantFail"; 506cd227536SLang Hames 507cd227536SLang Hames int Dummy = 42; 508cd227536SLang Hames int &Y = cantFail(Expected<int&>(Dummy)); 509cd227536SLang Hames EXPECT_EQ(&Dummy, &Y) << "Reference mangled by cantFail"; 510fd4de910SLang Hames } 511fd4de910SLang Hames 512fd4de910SLang Hames // Test that cantFail results in a crash if you pass it a failure value. 513cc14a386SStephen Hines #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG) 514fd4de910SLang Hames TEST(Error, CantFailDeath) { 515fd4de910SLang Hames EXPECT_DEATH( 5163025e48aSLang Hames cantFail(make_error<StringError>("foo", inconvertibleErrorCode()), 5173025e48aSLang Hames "Cantfail call failed"), 5183025e48aSLang Hames "Cantfail call failed") 519fd4de910SLang Hames << "cantFail(Error) did not cause an abort for failure value"; 520fd4de910SLang Hames 521fd4de910SLang Hames EXPECT_DEATH( 522fd4de910SLang Hames { 523fd4de910SLang Hames auto IEC = inconvertibleErrorCode(); 524fd4de910SLang Hames int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC))); 525fd4de910SLang Hames (void)X; 526fd4de910SLang Hames }, 527fd4de910SLang Hames "Failure value returned from cantFail wrapped call") 528fd4de910SLang Hames << "cantFail(Expected<int>) did not cause an abort for failure value"; 529fd4de910SLang Hames } 530fd4de910SLang Hames #endif 531fd4de910SLang Hames 532fd4de910SLang Hames 533580ca237SLang Hames // Test Checked Expected<T> in success mode. 534580ca237SLang Hames TEST(Error, CheckedExpectedInSuccessMode) { 535f7f6d3e9SLang Hames Expected<int> A = 7; 53601864a2dSLang Hames EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 537580ca237SLang Hames // Access is safe in second test, since we checked the error in the first. 538f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 539f7f6d3e9SLang Hames } 540f7f6d3e9SLang Hames 541285639f8SLang Hames // Test Expected with reference type. 542285639f8SLang Hames TEST(Error, ExpectedWithReferenceType) { 543285639f8SLang Hames int A = 7; 544285639f8SLang Hames Expected<int&> B = A; 545285639f8SLang Hames // 'Check' B. 546285639f8SLang Hames (void)!!B; 547285639f8SLang Hames int &C = *B; 548285639f8SLang Hames EXPECT_EQ(&A, &C) << "Expected failed to propagate reference"; 549285639f8SLang Hames } 550285639f8SLang Hames 551580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 552580ca237SLang Hames // We expect this to blow up the same way Error would. 553580ca237SLang Hames // Test runs in debug mode only. 554cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 555580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeDestruction) { 556580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; }, 557580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 558580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 559580ca237SLang Hames } 560580ca237SLang Hames #endif 561580ca237SLang Hames 562580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 563580ca237SLang Hames // We expect this to blow up the same way Error would. 564580ca237SLang Hames // Test runs in debug mode only. 565cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 566580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAccess) { 567580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; *A; }, 568580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 569580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 570580ca237SLang Hames } 571580ca237SLang Hames #endif 572580ca237SLang Hames 573580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 574580ca237SLang Hames // We expect this to blow up the same way Error would. 575580ca237SLang Hames // Test runs in debug mode only. 576cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 577580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAssignment) { 578580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, 579580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 580580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 581580ca237SLang Hames } 582580ca237SLang Hames #endif 583580ca237SLang Hames 58401864a2dSLang Hames // Test Expected<T> in failure mode. 58501864a2dSLang Hames TEST(Error, ExpectedInFailureMode) { 586f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 587f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 588f7f6d3e9SLang Hames Error E = A.takeError(); 589f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 590f7f6d3e9SLang Hames consumeError(std::move(E)); 591f7f6d3e9SLang Hames } 592f7f6d3e9SLang Hames 593f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 594f7f6d3e9SLang Hames // operator*. 595f7f6d3e9SLang Hames // Test runs in debug mode only. 596cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 59701864a2dSLang Hames TEST(Error, AccessExpectedInFailureMode) { 598f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 599580ca237SLang Hames EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.") 600f7f6d3e9SLang Hames << "Incorrect Expected error value"; 601f7f6d3e9SLang Hames consumeError(A.takeError()); 602f7f6d3e9SLang Hames } 603f7f6d3e9SLang Hames #endif 604f7f6d3e9SLang Hames 605f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 606f7f6d3e9SLang Hames // unhandled. 607f7f6d3e9SLang Hames // Test runs in debug mode only. 608cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 60901864a2dSLang Hames TEST(Error, UnhandledExpectedInFailureMode) { 610f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 611580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 612f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 61301864a2dSLang Hames } 614f7f6d3e9SLang Hames #endif 615f7f6d3e9SLang Hames 616f7f6d3e9SLang Hames // Test covariance of Expected. 61701864a2dSLang Hames TEST(Error, ExpectedCovariance) { 618f7f6d3e9SLang Hames class B {}; 619f7f6d3e9SLang Hames class D : public B {}; 620f7f6d3e9SLang Hames 621f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 622580ca237SLang Hames // Check A1 by converting to bool before assigning to it. 623580ca237SLang Hames (void)!!A1; 624f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 625580ca237SLang Hames // Check A1 again before destruction. 626580ca237SLang Hames (void)!!A1; 627f7f6d3e9SLang Hames 628f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 629580ca237SLang Hames // Check A2 by converting to bool before assigning to it. 630580ca237SLang Hames (void)!!A2; 631f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 632580ca237SLang Hames // Check A2 again before destruction. 633580ca237SLang Hames (void)!!A2; 634f7f6d3e9SLang Hames } 635f7f6d3e9SLang Hames 6365d06c23dSLang Hames // Test that handleExpected just returns success values. 6375d06c23dSLang Hames TEST(Error, HandleExpectedSuccess) { 6385d06c23dSLang Hames auto ValOrErr = 6395d06c23dSLang Hames handleExpected(Expected<int>(42), 6405d06c23dSLang Hames []() { return Expected<int>(43); }); 6415d06c23dSLang Hames EXPECT_TRUE(!!ValOrErr) 6425d06c23dSLang Hames << "handleExpected should have returned a success value here"; 6435d06c23dSLang Hames EXPECT_EQ(*ValOrErr, 42) 6445d06c23dSLang Hames << "handleExpected should have returned the original success value here"; 6455d06c23dSLang Hames } 6465d06c23dSLang Hames 6475d06c23dSLang Hames enum FooStrategy { Aggressive, Conservative }; 6485d06c23dSLang Hames 6495d06c23dSLang Hames static Expected<int> foo(FooStrategy S) { 6505d06c23dSLang Hames if (S == Aggressive) 6515d06c23dSLang Hames return make_error<CustomError>(7); 6525d06c23dSLang Hames return 42; 6535d06c23dSLang Hames } 6545d06c23dSLang Hames 6555d06c23dSLang Hames // Test that handleExpected invokes the error path if errors are not handled. 6565d06c23dSLang Hames TEST(Error, HandleExpectedUnhandledError) { 6575d06c23dSLang Hames // foo(Aggressive) should return a CustomError which should pass through as 6585d06c23dSLang Hames // there is no handler for CustomError. 6595d06c23dSLang Hames auto ValOrErr = 6605d06c23dSLang Hames handleExpected( 6615d06c23dSLang Hames foo(Aggressive), 6625d06c23dSLang Hames []() { return foo(Conservative); }); 6635d06c23dSLang Hames 6645d06c23dSLang Hames EXPECT_FALSE(!!ValOrErr) 6655d06c23dSLang Hames << "handleExpected should have returned an error here"; 6665d06c23dSLang Hames auto Err = ValOrErr.takeError(); 6675d06c23dSLang Hames EXPECT_TRUE(Err.isA<CustomError>()) 6685d06c23dSLang Hames << "handleExpected should have returned the CustomError generated by " 6695d06c23dSLang Hames "foo(Aggressive) here"; 6705d06c23dSLang Hames consumeError(std::move(Err)); 6715d06c23dSLang Hames } 6725d06c23dSLang Hames 6735d06c23dSLang Hames // Test that handleExpected invokes the fallback path if errors are handled. 6745d06c23dSLang Hames TEST(Error, HandleExpectedHandledError) { 6755d06c23dSLang Hames // foo(Aggressive) should return a CustomError which should handle triggering 6765d06c23dSLang Hames // the fallback path. 6775d06c23dSLang Hames auto ValOrErr = 6785d06c23dSLang Hames handleExpected( 6795d06c23dSLang Hames foo(Aggressive), 6805d06c23dSLang Hames []() { return foo(Conservative); }, 6815d06c23dSLang Hames [](const CustomError&) { /* do nothing */ }); 6825d06c23dSLang Hames 6835d06c23dSLang Hames EXPECT_TRUE(!!ValOrErr) 6845d06c23dSLang Hames << "handleExpected should have returned a success value here"; 6855d06c23dSLang Hames EXPECT_EQ(*ValOrErr, 42) 6865d06c23dSLang Hames << "handleExpected returned the wrong success value"; 6875d06c23dSLang Hames } 6885d06c23dSLang Hames 689d21a535bSLang Hames TEST(Error, ErrorCodeConversions) { 690f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 691f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 692f7f6d3e9SLang Hames std::error_code()) 693f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 694f7f6d3e9SLang Hames 695f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 696f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 697f7f6d3e9SLang Hames errc::invalid_argument) 698f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 699f7f6d3e9SLang Hames "conversions"; 700d21a535bSLang Hames 701d21a535bSLang Hames // Round-trip a success value through ErrorOr/Expected to check that it 702d21a535bSLang Hames // converts correctly. 703d21a535bSLang Hames { 704d21a535bSLang Hames auto Orig = ErrorOr<int>(42); 705d21a535bSLang Hames auto RoundTripped = 706d21a535bSLang Hames expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); 707d21a535bSLang Hames EXPECT_EQ(*Orig, *RoundTripped) 708d21a535bSLang Hames << "ErrorOr<T> success value should round-trip via Expected<T> " 709d21a535bSLang Hames "conversions."; 710d21a535bSLang Hames } 711d21a535bSLang Hames 712d21a535bSLang Hames // Round-trip a failure value through ErrorOr/Expected to check that it 713d21a535bSLang Hames // converts correctly. 714d21a535bSLang Hames { 715d21a535bSLang Hames auto Orig = ErrorOr<int>(errc::invalid_argument); 716d21a535bSLang Hames auto RoundTripped = 717d21a535bSLang Hames expectedToErrorOr( 718d21a535bSLang Hames errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); 719d21a535bSLang Hames EXPECT_EQ(Orig.getError(), RoundTripped.getError()) 720d21a535bSLang Hames << "ErrorOr<T> failure value should round-trip via Expected<T> " 721d21a535bSLang Hames "conversions."; 722d21a535bSLang Hames } 723f7f6d3e9SLang Hames } 724f7f6d3e9SLang Hames 72527370a09SVedant Kumar // Test that error messages work. 72627370a09SVedant Kumar TEST(Error, ErrorMessage) { 72727370a09SVedant Kumar EXPECT_EQ(toString(Error::success()).compare(""), 0); 72827370a09SVedant Kumar 72927370a09SVedant Kumar Error E1 = make_error<CustomError>(0); 73027370a09SVedant Kumar EXPECT_EQ(toString(std::move(E1)).compare("CustomError {0}"), 0); 73127370a09SVedant Kumar 73227370a09SVedant Kumar Error E2 = make_error<CustomError>(0); 73327370a09SVedant Kumar handleAllErrors(std::move(E2), [](const CustomError &CE) { 73427370a09SVedant Kumar EXPECT_EQ(CE.message().compare("CustomError {0}"), 0); 73527370a09SVedant Kumar }); 73627370a09SVedant Kumar 73727370a09SVedant Kumar Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)); 73827370a09SVedant Kumar EXPECT_EQ(toString(std::move(E3)) 73927370a09SVedant Kumar .compare("CustomError {0}\n" 74027370a09SVedant Kumar "CustomError {1}"), 74127370a09SVedant Kumar 0); 74227370a09SVedant Kumar } 74327370a09SVedant Kumar 7448ca99100SSam McCall TEST(Error, Stream) { 7458ca99100SSam McCall { 7468ca99100SSam McCall Error OK = Error::success(); 7478ca99100SSam McCall std::string Buf; 7488ca99100SSam McCall llvm::raw_string_ostream S(Buf); 7498ca99100SSam McCall S << OK; 7508ca99100SSam McCall EXPECT_EQ("success", S.str()); 7518ca99100SSam McCall consumeError(std::move(OK)); 7528ca99100SSam McCall } 7538ca99100SSam McCall { 7548ca99100SSam McCall Error E1 = make_error<CustomError>(0); 7558ca99100SSam McCall std::string Buf; 7568ca99100SSam McCall llvm::raw_string_ostream S(Buf); 7578ca99100SSam McCall S << E1; 7588ca99100SSam McCall EXPECT_EQ("CustomError {0}", S.str()); 7598ca99100SSam McCall consumeError(std::move(E1)); 7608ca99100SSam McCall } 7618ca99100SSam McCall } 7628ca99100SSam McCall 763e8354fe6SPavel Labath TEST(Error, ErrorMatchers) { 764e8354fe6SPavel Labath EXPECT_THAT_ERROR(Error::success(), Succeeded()); 765e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 766e8354fe6SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Succeeded()), 767e8354fe6SPavel Labath "Expected: succeeded\n Actual: failed (CustomError {0})"); 768e8354fe6SPavel Labath 769e8354fe6SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed()); 770e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE(EXPECT_THAT_ERROR(Error::success(), Failed()), 771e8354fe6SPavel Labath "Expected: failed\n Actual: succeeded"); 772e8354fe6SPavel Labath 773510725c2SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomError>()); 774510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 775510725c2SPavel Labath EXPECT_THAT_ERROR(Error::success(), Failed<CustomError>()), 776510725c2SPavel Labath "Expected: failed with Error of given type\n Actual: succeeded"); 777510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 778510725c2SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomSubError>()), 779510725c2SPavel Labath "Error was not of given type"); 780510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 781510725c2SPavel Labath EXPECT_THAT_ERROR( 782510725c2SPavel Labath joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)), 783510725c2SPavel Labath Failed<CustomError>()), 784510725c2SPavel Labath "multiple errors"); 785510725c2SPavel Labath 786510725c2SPavel Labath EXPECT_THAT_ERROR( 787510725c2SPavel Labath make_error<CustomError>(0), 788510725c2SPavel Labath Failed<CustomError>(testing::Property(&CustomError::getInfo, 0))); 789510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 790510725c2SPavel Labath EXPECT_THAT_ERROR( 791510725c2SPavel Labath make_error<CustomError>(0), 792510725c2SPavel Labath Failed<CustomError>(testing::Property(&CustomError::getInfo, 1))), 793510725c2SPavel Labath "Expected: failed with Error of given type and the error is an object " 794510725c2SPavel Labath "whose given property is equal to 1\n" 795510725c2SPavel Labath " Actual: failed (CustomError {0})"); 796397e150dSPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<ErrorInfoBase>()); 797510725c2SPavel Labath 798e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), Succeeded()); 799e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 800e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 801e8354fe6SPavel Labath Succeeded()), 802e8354fe6SPavel Labath "Expected: succeeded\n Actual: failed (CustomError {0})"); 803e8354fe6SPavel Labath 804e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), Failed()); 805e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 806e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), Failed()), 80756c2d999SPavel Labath "Expected: failed\n Actual: succeeded with value 0"); 808e8354fe6SPavel Labath 809e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(0)); 810e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 811e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 812e8354fe6SPavel Labath HasValue(0)), 81356c2d999SPavel Labath "Expected: succeeded with value (is equal to 0)\n" 814e8354fe6SPavel Labath " Actual: failed (CustomError {0})"); 815e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 816e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(0)), 81756c2d999SPavel Labath "Expected: succeeded with value (is equal to 0)\n" 81856c2d999SPavel Labath " Actual: succeeded with value 1, (isn't equal to 0)"); 819e8354fe6SPavel Labath 820e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(make_error<CustomError>(0)), Failed()); 821e8354fe6SPavel Labath int a = 1; 822e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(a), Succeeded()); 82356c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(testing::Eq(1))); 82456c2d999SPavel Labath 82556c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(testing::Gt(0))); 82656c2d999SPavel Labath EXPECT_NONFATAL_FAILURE( 82756c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(testing::Gt(1))), 82856c2d999SPavel Labath "Expected: succeeded with value (is > 1)\n" 82956c2d999SPavel Labath " Actual: succeeded with value 0, (isn't > 1)"); 83056c2d999SPavel Labath EXPECT_NONFATAL_FAILURE( 83156c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 83256c2d999SPavel Labath HasValue(testing::Gt(1))), 83356c2d999SPavel Labath "Expected: succeeded with value (is > 1)\n" 83456c2d999SPavel Labath " Actual: failed (CustomError {0})"); 835e8354fe6SPavel Labath } 836e8354fe6SPavel Labath 83700fb14daSLang Hames TEST(Error, C_API) { 83800fb14daSLang Hames EXPECT_THAT_ERROR(unwrap(wrap(Error::success())), Succeeded()) 83900fb14daSLang Hames << "Failed to round-trip Error success value via C API"; 84000fb14daSLang Hames EXPECT_THAT_ERROR(unwrap(wrap(make_error<CustomError>(0))), 84100fb14daSLang Hames Failed<CustomError>()) 84200fb14daSLang Hames << "Failed to round-trip Error failure value via C API"; 84300fb14daSLang Hames 84400fb14daSLang Hames auto Err = 84500fb14daSLang Hames wrap(make_error<StringError>("test message", inconvertibleErrorCode())); 84600fb14daSLang Hames EXPECT_EQ(LLVMGetErrorTypeId(Err), LLVMGetStringErrorTypeId()) 84700fb14daSLang Hames << "Failed to match error type ids via C API"; 84800fb14daSLang Hames char *ErrMsg = LLVMGetErrorMessage(Err); 84900fb14daSLang Hames EXPECT_STREQ(ErrMsg, "test message") 85000fb14daSLang Hames << "Failed to roundtrip StringError error message via C API"; 85100fb14daSLang Hames LLVMDisposeErrorMessage(ErrMsg); 85200fb14daSLang Hames 85300fb14daSLang Hames bool GotCSE = false; 85400fb14daSLang Hames bool GotCE = false; 85500fb14daSLang Hames handleAllErrors( 85600fb14daSLang Hames unwrap(wrap(joinErrors(make_error<CustomSubError>(42, 7), 85700fb14daSLang Hames make_error<CustomError>(42)))), 85800fb14daSLang Hames [&](CustomSubError &CSE) { 85900fb14daSLang Hames GotCSE = true; 86000fb14daSLang Hames }, 86100fb14daSLang Hames [&](CustomError &CE) { 86200fb14daSLang Hames GotCE = true; 86300fb14daSLang Hames }); 86400fb14daSLang Hames EXPECT_TRUE(GotCSE) << "Failed to round-trip ErrorList via C API"; 86500fb14daSLang Hames EXPECT_TRUE(GotCE) << "Failed to round-trip ErrorList via C API"; 86600fb14daSLang Hames } 86700fb14daSLang Hames 868*e11f2217SAlexandre Ganea TEST(Error, FileErrorTest) { 869*e11f2217SAlexandre Ganea #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 870*e11f2217SAlexandre Ganea EXPECT_DEATH( 871*e11f2217SAlexandre Ganea { 872*e11f2217SAlexandre Ganea Error S = Error::success(); 873*e11f2217SAlexandre Ganea createFileError("file.bin", std::move(S)); 874*e11f2217SAlexandre Ganea }, 875*e11f2217SAlexandre Ganea ""); 876*e11f2217SAlexandre Ganea #endif 877*e11f2217SAlexandre Ganea Error E1 = make_error<CustomError>(1); 878*e11f2217SAlexandre Ganea Error FE1 = createFileError("file.bin", std::move(E1)); 879*e11f2217SAlexandre Ganea EXPECT_EQ(toString(std::move(FE1)).compare("'file.bin': CustomError {1}"), 0); 880*e11f2217SAlexandre Ganea 881*e11f2217SAlexandre Ganea Error E2 = make_error<CustomError>(2); 882*e11f2217SAlexandre Ganea Error FE2 = createFileError("file.bin", std::move(E2)); 883*e11f2217SAlexandre Ganea handleAllErrors(std::move(FE2), [](const FileError &F) { 884*e11f2217SAlexandre Ganea EXPECT_EQ(F.message().compare("'file.bin': CustomError {2}"), 0); 885*e11f2217SAlexandre Ganea }); 886*e11f2217SAlexandre Ganea 887*e11f2217SAlexandre Ganea Error E3 = make_error<CustomError>(3); 888*e11f2217SAlexandre Ganea Error FE3 = createFileError("file.bin", std::move(E3)); 889*e11f2217SAlexandre Ganea auto E31 = handleErrors(std::move(FE3), [](std::unique_ptr<FileError> F) { 890*e11f2217SAlexandre Ganea return F->takeError(); 891*e11f2217SAlexandre Ganea }); 892*e11f2217SAlexandre Ganea handleAllErrors(std::move(E31), [](const CustomError &C) { 893*e11f2217SAlexandre Ganea EXPECT_EQ(C.message().compare("CustomError {3}"), 0); 894*e11f2217SAlexandre Ganea }); 895*e11f2217SAlexandre Ganea 896*e11f2217SAlexandre Ganea Error FE4 = 897*e11f2217SAlexandre Ganea joinErrors(createFileError("file.bin", make_error<CustomError>(41)), 898*e11f2217SAlexandre Ganea createFileError("file2.bin", make_error<CustomError>(42))); 899*e11f2217SAlexandre Ganea EXPECT_EQ(toString(std::move(FE4)) 900*e11f2217SAlexandre Ganea .compare("'file.bin': CustomError {41}\n" 901*e11f2217SAlexandre Ganea "'file2.bin': CustomError {42}"), 902*e11f2217SAlexandre Ganea 0); 903*e11f2217SAlexandre Ganea } 904*e11f2217SAlexandre Ganea 905*e11f2217SAlexandre Ganea enum class test_error_code { 906*e11f2217SAlexandre Ganea unspecified = 1, 907*e11f2217SAlexandre Ganea error_1, 908*e11f2217SAlexandre Ganea error_2, 909*e11f2217SAlexandre Ganea }; 910*e11f2217SAlexandre Ganea 911f7f6d3e9SLang Hames } // end anon namespace 912*e11f2217SAlexandre Ganea 913*e11f2217SAlexandre Ganea namespace std { 914*e11f2217SAlexandre Ganea template <> 915*e11f2217SAlexandre Ganea struct is_error_code_enum<test_error_code> : std::true_type {}; 916*e11f2217SAlexandre Ganea } // namespace std 917*e11f2217SAlexandre Ganea 918*e11f2217SAlexandre Ganea namespace { 919*e11f2217SAlexandre Ganea 920*e11f2217SAlexandre Ganea const std::error_category &TErrorCategory(); 921*e11f2217SAlexandre Ganea 922*e11f2217SAlexandre Ganea inline std::error_code make_error_code(test_error_code E) { 923*e11f2217SAlexandre Ganea return std::error_code(static_cast<int>(E), TErrorCategory()); 924*e11f2217SAlexandre Ganea } 925*e11f2217SAlexandre Ganea 926*e11f2217SAlexandre Ganea class TestDebugError : public ErrorInfo<TestDebugError, StringError> { 927*e11f2217SAlexandre Ganea public: 928*e11f2217SAlexandre Ganea using ErrorInfo<TestDebugError, StringError >::ErrorInfo; // inherit constructors 929*e11f2217SAlexandre Ganea TestDebugError(const Twine &S) : ErrorInfo(S, test_error_code::unspecified) {} 930*e11f2217SAlexandre Ganea static char ID; 931*e11f2217SAlexandre Ganea }; 932*e11f2217SAlexandre Ganea 933*e11f2217SAlexandre Ganea class TestErrorCategory : public std::error_category { 934*e11f2217SAlexandre Ganea public: 935*e11f2217SAlexandre Ganea const char *name() const noexcept override { return "error"; } 936*e11f2217SAlexandre Ganea std::string message(int Condition) const override { 937*e11f2217SAlexandre Ganea switch (static_cast<test_error_code>(Condition)) { 938*e11f2217SAlexandre Ganea case test_error_code::unspecified: 939*e11f2217SAlexandre Ganea return "An unknown error has occurred."; 940*e11f2217SAlexandre Ganea case test_error_code::error_1: 941*e11f2217SAlexandre Ganea return "Error 1."; 942*e11f2217SAlexandre Ganea case test_error_code::error_2: 943*e11f2217SAlexandre Ganea return "Error 2."; 944*e11f2217SAlexandre Ganea } 945*e11f2217SAlexandre Ganea llvm_unreachable("Unrecognized test_error_code"); 946*e11f2217SAlexandre Ganea } 947*e11f2217SAlexandre Ganea }; 948*e11f2217SAlexandre Ganea 949*e11f2217SAlexandre Ganea static llvm::ManagedStatic<TestErrorCategory> TestErrCategory; 950*e11f2217SAlexandre Ganea const std::error_category &TErrorCategory() { return *TestErrCategory; } 951*e11f2217SAlexandre Ganea 952*e11f2217SAlexandre Ganea char TestDebugError::ID; 953*e11f2217SAlexandre Ganea 954*e11f2217SAlexandre Ganea TEST(Error, SubtypeStringErrorTest) { 955*e11f2217SAlexandre Ganea auto E1 = make_error<TestDebugError>(test_error_code::error_1); 956*e11f2217SAlexandre Ganea EXPECT_EQ(toString(std::move(E1)).compare("Error 1."), 0); 957*e11f2217SAlexandre Ganea 958*e11f2217SAlexandre Ganea auto E2 = make_error<TestDebugError>(test_error_code::error_1, 959*e11f2217SAlexandre Ganea "Detailed information"); 960*e11f2217SAlexandre Ganea EXPECT_EQ(toString(std::move(E2)).compare("Error 1. Detailed information"), 961*e11f2217SAlexandre Ganea 0); 962*e11f2217SAlexandre Ganea 963*e11f2217SAlexandre Ganea auto E3 = make_error<TestDebugError>(test_error_code::error_2); 964*e11f2217SAlexandre Ganea handleAllErrors(std::move(E3), [](const TestDebugError &F) { 965*e11f2217SAlexandre Ganea EXPECT_EQ(F.message().compare("Error 2."), 0); 966*e11f2217SAlexandre Ganea }); 967*e11f2217SAlexandre Ganea 968*e11f2217SAlexandre Ganea auto E4 = joinErrors(make_error<TestDebugError>(test_error_code::error_1, 969*e11f2217SAlexandre Ganea "Detailed information"), 970*e11f2217SAlexandre Ganea make_error<TestDebugError>(test_error_code::error_2)); 971*e11f2217SAlexandre Ganea EXPECT_EQ(toString(std::move(E4)) 972*e11f2217SAlexandre Ganea .compare("Error 1. Detailed information\n" 973*e11f2217SAlexandre Ganea "Error 2."), 974*e11f2217SAlexandre Ganea 0); 975*e11f2217SAlexandre Ganea } 976*e11f2217SAlexandre Ganea 977*e11f2217SAlexandre Ganea } // namespace 978