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" 11c5e0bbd7SLang Hames 12c5e0bbd7SLang Hames #include "llvm/ADT/Twine.h" 13f7f6d3e9SLang Hames #include "llvm/Support/Errc.h" 14e7aad357SLang Hames #include "llvm/Support/ErrorHandling.h" 15f7f6d3e9SLang Hames #include "gtest/gtest.h" 16f7f6d3e9SLang Hames #include <memory> 17f7f6d3e9SLang Hames 18f7f6d3e9SLang Hames using namespace llvm; 19f7f6d3e9SLang Hames 20f7f6d3e9SLang Hames namespace { 21f7f6d3e9SLang Hames 22f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached. 23f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> { 24f7f6d3e9SLang Hames public: 25f7f6d3e9SLang Hames // Create an error with some info attached. 26f7f6d3e9SLang Hames CustomError(int Info) : Info(Info) {} 27f7f6d3e9SLang Hames 28f7f6d3e9SLang Hames // Get the info attached to this error. 29f7f6d3e9SLang Hames int getInfo() const { return Info; } 30f7f6d3e9SLang Hames 31f7f6d3e9SLang Hames // Log this error to a stream. 32f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 33f7f6d3e9SLang Hames OS << "CustomError { " << getInfo() << "}"; 34f7f6d3e9SLang Hames } 35f7f6d3e9SLang Hames 36e7aad357SLang Hames std::error_code convertToErrorCode() const override { 37e7aad357SLang Hames llvm_unreachable("CustomError doesn't support ECError conversion"); 38e7aad357SLang Hames } 39e7aad357SLang Hames 40a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 41a15b76b3SReid Kleckner static char ID; 42a15b76b3SReid Kleckner 43f7f6d3e9SLang Hames protected: 44f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 45f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 46f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 47f7f6d3e9SLang Hames // fields. 48f7f6d3e9SLang Hames CustomError() : Info(0) {} 49f7f6d3e9SLang Hames 50f7f6d3e9SLang Hames int Info; 51f7f6d3e9SLang Hames }; 52f7f6d3e9SLang Hames 53a15b76b3SReid Kleckner char CustomError::ID = 0; 54a15b76b3SReid Kleckner 55f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 56f7f6d3e9SLang Hames // 'info'. 57f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 58f7f6d3e9SLang Hames public: 59f7f6d3e9SLang Hames // Create a sub-error with some info attached. 60f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 61f7f6d3e9SLang Hames this->Info = Info; 62f7f6d3e9SLang Hames } 63f7f6d3e9SLang Hames 64f7f6d3e9SLang Hames // Get the extra info attached to this error. 65f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 66f7f6d3e9SLang Hames 67f7f6d3e9SLang Hames // Log this error to a stream. 68f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 69f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 70f7f6d3e9SLang Hames } 71f7f6d3e9SLang Hames 72e7aad357SLang Hames std::error_code convertToErrorCode() const override { 73e7aad357SLang Hames llvm_unreachable("CustomSubError doesn't support ECError conversion"); 74e7aad357SLang Hames } 75e7aad357SLang Hames 76a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 77a15b76b3SReid Kleckner static char ID; 78a15b76b3SReid Kleckner 79f7f6d3e9SLang Hames protected: 80f7f6d3e9SLang Hames int ExtraInfo; 81f7f6d3e9SLang Hames }; 82f7f6d3e9SLang Hames 83a15b76b3SReid Kleckner char CustomSubError::ID = 0; 84a15b76b3SReid Kleckner 8541af4309SMehdi Amini static Error handleCustomError(const CustomError &CE) { 8641af4309SMehdi Amini return Error::success(); 8741af4309SMehdi Amini } 88f7f6d3e9SLang Hames 89f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 90f7f6d3e9SLang Hames 91f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 9241af4309SMehdi Amini return Error::success(); 93f7f6d3e9SLang Hames } 94f7f6d3e9SLang Hames 95f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 96f7f6d3e9SLang Hames 9701864a2dSLang Hames // Test that success values implicitly convert to false, and don't cause crashes 9801864a2dSLang Hames // once they've been implicitly converted. 9901864a2dSLang Hames TEST(Error, CheckedSuccess) { 100c1edf566SMehdi Amini Error E = Error::success(); 10101864a2dSLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 10201864a2dSLang Hames } 10301864a2dSLang Hames 10401864a2dSLang Hames // Test that unchecked succes values cause an abort. 105cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 10601864a2dSLang Hames TEST(Error, UncheckedSuccess) { 107c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); }, 108c1edf566SMehdi Amini "Program aborted due to an unhandled Error:") 10901864a2dSLang Hames << "Unchecked Error Succes value did not cause abort()"; 11001864a2dSLang Hames } 11101864a2dSLang Hames #endif 11201864a2dSLang Hames 113d1af8fceSLang Hames // ErrorAsOutParameter tester. 114d1af8fceSLang Hames void errAsOutParamHelper(Error &Err) { 1155e51a2e3SLang Hames ErrorAsOutParameter ErrAsOutParam(&Err); 116d1af8fceSLang Hames // Verify that checked flag is raised - assignment should not crash. 117d1af8fceSLang Hames Err = Error::success(); 118d1af8fceSLang Hames // Raise the checked bit manually - caller should still have to test the 119d1af8fceSLang Hames // error. 120d1af8fceSLang Hames (void)!!Err; 121d0ac31a7SLang Hames } 122d0ac31a7SLang Hames 123d1af8fceSLang Hames // Test that ErrorAsOutParameter sets the checked flag on construction. 124d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterChecked) { 125c1edf566SMehdi Amini Error E = Error::success(); 126d1af8fceSLang Hames errAsOutParamHelper(E); 127d1af8fceSLang Hames (void)!!E; 128d1af8fceSLang Hames } 129d1af8fceSLang Hames 130d1af8fceSLang Hames // Test that ErrorAsOutParameter clears the checked flag on destruction. 131cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 132d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterUnchecked) { 133c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); errAsOutParamHelper(E); }, 134d1af8fceSLang Hames "Program aborted due to an unhandled Error:") 135d1af8fceSLang Hames << "ErrorAsOutParameter did not clear the checked flag on destruction."; 136d1af8fceSLang Hames } 137d1af8fceSLang Hames #endif 138d1af8fceSLang Hames 139f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 140f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 141f7f6d3e9SLang Hames // Test runs in debug mode only. 142cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 14301864a2dSLang Hames TEST(Error, UncheckedError) { 144f7f6d3e9SLang Hames auto DropUnhandledError = []() { 145f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 146f7f6d3e9SLang Hames (void)!E; 147f7f6d3e9SLang Hames }; 148f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 149f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 150f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 151f7f6d3e9SLang Hames } 152f7f6d3e9SLang Hames #endif 153f7f6d3e9SLang Hames 15401864a2dSLang Hames // Check 'Error::isA<T>' method handling. 15501864a2dSLang Hames TEST(Error, IsAHandling) { 156f7f6d3e9SLang Hames // Check 'isA' handling. 157f7f6d3e9SLang Hames Error E = make_error<CustomError>(1); 158f7f6d3e9SLang Hames Error F = make_error<CustomSubError>(1, 2); 15901a3cf4dSLang Hames Error G = Error::success(); 160f7f6d3e9SLang Hames 161f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()); 162f7f6d3e9SLang Hames EXPECT_FALSE(E.isA<CustomSubError>()); 163f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomError>()); 164f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomSubError>()); 16501a3cf4dSLang Hames EXPECT_FALSE(G.isA<CustomError>()); 166f7f6d3e9SLang Hames 167f7f6d3e9SLang Hames consumeError(std::move(E)); 168f7f6d3e9SLang Hames consumeError(std::move(F)); 16901a3cf4dSLang Hames consumeError(std::move(G)); 170f7f6d3e9SLang Hames } 171f7f6d3e9SLang Hames 172f7f6d3e9SLang Hames // Check that we can handle a custom error. 17301864a2dSLang Hames TEST(Error, HandleCustomError) { 174f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 175f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 176f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 177f7f6d3e9SLang Hames }); 178f7f6d3e9SLang Hames 17901864a2dSLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 180f7f6d3e9SLang Hames } 181f7f6d3e9SLang Hames 182f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 183f7f6d3e9SLang Hames // of the following types: 184f7f6d3e9SLang Hames // void (const Err&) 185f7f6d3e9SLang Hames // Error (const Err&) mutable 186f7f6d3e9SLang Hames // void (const Err&) mutable 187f7f6d3e9SLang Hames // Error (Err&) 188f7f6d3e9SLang Hames // void (Err&) 189f7f6d3e9SLang Hames // Error (Err&) mutable 190f7f6d3e9SLang Hames // void (Err&) mutable 191f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 192f7f6d3e9SLang Hames // void (unique_ptr<Err>) 193f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 194f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 19501864a2dSLang Hames TEST(Error, HandlerTypeDeduction) { 196f7f6d3e9SLang Hames 197f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 198f7f6d3e9SLang Hames 199f7f6d3e9SLang Hames handleAllErrors( 200f7f6d3e9SLang Hames make_error<CustomError>(42), 201c1edf566SMehdi Amini [](const CustomError &CE) mutable -> Error { return Error::success(); }); 202f7f6d3e9SLang Hames 203f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 204f7f6d3e9SLang Hames [](const CustomError &CE) mutable {}); 205f7f6d3e9SLang Hames 206f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 207c1edf566SMehdi Amini [](CustomError &CE) -> Error { return Error::success(); }); 208f7f6d3e9SLang Hames 209f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 210f7f6d3e9SLang Hames 211f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 212c1edf566SMehdi Amini [](CustomError &CE) mutable -> Error { return Error::success(); }); 213f7f6d3e9SLang Hames 214f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 215f7f6d3e9SLang Hames 216f7f6d3e9SLang Hames handleAllErrors( 217f7f6d3e9SLang Hames make_error<CustomError>(42), 218c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) -> Error { return Error::success(); }); 219f7f6d3e9SLang Hames 220f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 221f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) {}); 222f7f6d3e9SLang Hames 223f7f6d3e9SLang Hames handleAllErrors( 224f7f6d3e9SLang Hames make_error<CustomError>(42), 225c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) mutable -> Error { return Error::success(); }); 226f7f6d3e9SLang Hames 227f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 228f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable {}); 229f7f6d3e9SLang Hames 230f7f6d3e9SLang Hames // Check that named handlers of type 'Error (const Err&)' work. 231f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomError); 232f7f6d3e9SLang Hames 233f7f6d3e9SLang Hames // Check that named handlers of type 'void (const Err&)' work. 234f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 235f7f6d3e9SLang Hames 236f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 237f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 238f7f6d3e9SLang Hames 239f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 240f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 24101864a2dSLang Hames } 242f7f6d3e9SLang Hames 24301864a2dSLang Hames // Test that we can handle errors with custom base classes. 24401864a2dSLang Hames TEST(Error, HandleCustomErrorWithCustomBaseClass) { 245f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 246f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 247f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 248f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 249f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 250f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 251f7f6d3e9SLang Hames }); 252f7f6d3e9SLang Hames 253f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 254f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 255f7f6d3e9SLang Hames } 256f7f6d3e9SLang Hames 257f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 25801864a2dSLang Hames TEST(Error, FirstHandlerOnly) { 259f7f6d3e9SLang Hames int DummyInfo = 0; 260f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 261f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 262f7f6d3e9SLang Hames 263f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 264f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 265f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 266f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 267f7f6d3e9SLang Hames }, 268f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 269f7f6d3e9SLang Hames 270f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 271f7f6d3e9SLang Hames DummyInfo == 0) 272f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 273f7f6d3e9SLang Hames } 274f7f6d3e9SLang Hames 275f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 27601864a2dSLang Hames TEST(Error, HandlerShadowing) { 277f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 278f7f6d3e9SLang Hames int DummyInfo = 0; 279f7f6d3e9SLang Hames int DummyExtraInfo = 0; 280f7f6d3e9SLang Hames 281f7f6d3e9SLang Hames handleAllErrors( 282f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 283f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 284f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 285f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 286f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 287f7f6d3e9SLang Hames }); 288f7f6d3e9SLang Hames 289b2cef64bSNAKAMURA Takumi EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) 290f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 291f7f6d3e9SLang Hames } 292f7f6d3e9SLang Hames 29301864a2dSLang Hames // Test joinErrors. 29401864a2dSLang Hames TEST(Error, CheckJoinErrors) { 295f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 296f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 297f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 29801864a2dSLang Hames Error E = 29901864a2dSLang Hames joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 300f7f6d3e9SLang Hames 301f7f6d3e9SLang Hames handleAllErrors(std::move(E), 302f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 303f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 304f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 305f7f6d3e9SLang Hames }, 306f7f6d3e9SLang Hames [&](const CustomError &CE) { 307f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 308f7f6d3e9SLang Hames // before the 309f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 310f7f6d3e9SLang Hames // ordering. 311f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 312f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 313f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 314f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 315f7f6d3e9SLang Hames }); 316f7f6d3e9SLang Hames 317f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 318f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 319f7f6d3e9SLang Hames << "Failed handling compound Error."; 320759b30edSLang Hames 321759b30edSLang Hames // Test appending a single item to a list. 322759b30edSLang Hames { 323759b30edSLang Hames int Sum = 0; 324759b30edSLang Hames handleAllErrors( 325759b30edSLang Hames joinErrors( 326759b30edSLang Hames joinErrors(make_error<CustomError>(7), 327759b30edSLang Hames make_error<CustomError>(7)), 328759b30edSLang Hames make_error<CustomError>(7)), 329759b30edSLang Hames [&](const CustomError &CE) { 330759b30edSLang Hames Sum += CE.getInfo(); 331759b30edSLang Hames }); 332759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list."; 333759b30edSLang Hames } 334759b30edSLang Hames 335759b30edSLang Hames // Test prepending a single item to a list. 336759b30edSLang Hames { 337759b30edSLang Hames int Sum = 0; 338759b30edSLang Hames handleAllErrors( 339759b30edSLang Hames joinErrors( 340759b30edSLang Hames make_error<CustomError>(7), 341759b30edSLang Hames joinErrors(make_error<CustomError>(7), 342759b30edSLang Hames make_error<CustomError>(7))), 343759b30edSLang Hames [&](const CustomError &CE) { 344759b30edSLang Hames Sum += CE.getInfo(); 345759b30edSLang Hames }); 346759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list."; 347759b30edSLang Hames } 348759b30edSLang Hames 349759b30edSLang Hames // Test concatenating two error lists. 350759b30edSLang Hames { 351759b30edSLang Hames int Sum = 0; 352759b30edSLang Hames handleAllErrors( 353759b30edSLang Hames joinErrors( 354759b30edSLang Hames joinErrors( 355759b30edSLang Hames make_error<CustomError>(7), 356759b30edSLang Hames make_error<CustomError>(7)), 357759b30edSLang Hames joinErrors( 358759b30edSLang Hames make_error<CustomError>(7), 359759b30edSLang Hames make_error<CustomError>(7))), 360759b30edSLang Hames [&](const CustomError &CE) { 361759b30edSLang Hames Sum += CE.getInfo(); 362759b30edSLang Hames }); 363759b30edSLang Hames EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate erorr lists."; 364759b30edSLang Hames } 365f7f6d3e9SLang Hames } 366f7f6d3e9SLang Hames 36701864a2dSLang Hames // Test that we can consume success values. 36801864a2dSLang Hames TEST(Error, ConsumeSuccess) { 369c1edf566SMehdi Amini Error E = Error::success(); 370f7f6d3e9SLang Hames consumeError(std::move(E)); 371f7f6d3e9SLang Hames } 37201864a2dSLang Hames 37301864a2dSLang Hames TEST(Error, ConsumeError) { 374f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 375f7f6d3e9SLang Hames consumeError(std::move(E)); 376f7f6d3e9SLang Hames } 377f7f6d3e9SLang Hames 378f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 379f7f6d3e9SLang Hames // Test runs in debug mode only. 380cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 38101864a2dSLang Hames TEST(Error, FailureToHandle) { 382f7f6d3e9SLang Hames auto FailToHandle = []() { 38301864a2dSLang Hames handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 384f7f6d3e9SLang Hames errs() << "This should never be called"; 385f7f6d3e9SLang Hames exit(1); 386f7f6d3e9SLang Hames }); 387f7f6d3e9SLang Hames }; 388f7f6d3e9SLang Hames 389f7f6d3e9SLang Hames EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") 390f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 391f7f6d3e9SLang Hames "abort()"; 392f7f6d3e9SLang Hames } 393f7f6d3e9SLang Hames #endif 394f7f6d3e9SLang Hames 395f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 396f7f6d3e9SLang Hames // handler. 397f7f6d3e9SLang Hames // Test runs in debug mode only. 398cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 39901864a2dSLang Hames TEST(Error, FailureFromHandler) { 400f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 401f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 402f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 403f7f6d3e9SLang Hames return Error(std::move(SE)); 404f7f6d3e9SLang Hames }); 405f7f6d3e9SLang Hames }; 406f7f6d3e9SLang Hames 407f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 408f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 409f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 410f7f6d3e9SLang Hames "cause abort()"; 411f7f6d3e9SLang Hames } 412f7f6d3e9SLang Hames #endif 413f7f6d3e9SLang Hames 414f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 41501864a2dSLang Hames TEST(Error, CatchErrorFromHandler) { 416f7f6d3e9SLang Hames int ErrorInfo = 0; 417f7f6d3e9SLang Hames 418f7f6d3e9SLang Hames Error E = handleErrors( 419f7f6d3e9SLang Hames make_error<CustomError>(7), 420f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 421f7f6d3e9SLang Hames 422f7f6d3e9SLang Hames handleAllErrors(std::move(E), 423f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 424f7f6d3e9SLang Hames 425f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 426f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 427f7f6d3e9SLang Hames } 4286935c2d3SLang Hames 429c5e0bbd7SLang Hames TEST(Error, StringError) { 430c5e0bbd7SLang Hames std::string Msg; 431c5e0bbd7SLang Hames raw_string_ostream S(Msg); 432c5e0bbd7SLang Hames logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42), 433bd8e9542SLang Hames inconvertibleErrorCode()), 434c5e0bbd7SLang Hames S, ""); 435c5e0bbd7SLang Hames EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result"; 436c5e0bbd7SLang Hames 437c5e0bbd7SLang Hames auto EC = 438c5e0bbd7SLang Hames errorToErrorCode(make_error<StringError>("", errc::invalid_argument)); 439c5e0bbd7SLang Hames EXPECT_EQ(EC, errc::invalid_argument) 440c5e0bbd7SLang Hames << "Failed to convert StringError to error_code."; 441c5e0bbd7SLang Hames } 442c5e0bbd7SLang Hames 44301864a2dSLang Hames // Test that the ExitOnError utility works as expected. 44401864a2dSLang Hames TEST(Error, ExitOnError) { 4456935c2d3SLang Hames ExitOnError ExitOnErr; 4466935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 44701864a2dSLang Hames ExitOnErr.setExitCodeMapper([](const Error &E) { 4486935c2d3SLang Hames if (E.isA<CustomSubError>()) 4496935c2d3SLang Hames return 2; 4506935c2d3SLang Hames return 1; 4516935c2d3SLang Hames }); 4526935c2d3SLang Hames 4536935c2d3SLang Hames // Make sure we don't bail on success. 4546935c2d3SLang Hames ExitOnErr(Error::success()); 4556935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 4566935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 4576935c2d3SLang Hames 458285639f8SLang Hames int A = 7; 459285639f8SLang Hames int &B = ExitOnErr(Expected<int&>(A)); 460285639f8SLang Hames EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference"; 461285639f8SLang Hames 4626935c2d3SLang Hames // Exit tests. 4636935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 4646935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 4656935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4666935c2d3SLang Hames 4676935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 4686935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 4696935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4706935c2d3SLang Hames } 471f7f6d3e9SLang Hames 472*fd4de910SLang Hames // Test that the ExitOnError utility works as expected. 473*fd4de910SLang Hames TEST(Error, CantFailSuccess) { 474*fd4de910SLang Hames cantFail(Error::success()); 475*fd4de910SLang Hames 476*fd4de910SLang Hames int X = cantFail(Expected<int>(42)); 477*fd4de910SLang Hames EXPECT_EQ(X, 42) << "Expected value modified by cantFail"; 478*fd4de910SLang Hames } 479*fd4de910SLang Hames 480*fd4de910SLang Hames // Test that cantFail results in a crash if you pass it a failure value. 481*fd4de910SLang Hames #if LLVM_ENABLE_ABI_BREAKING_CHECKS 482*fd4de910SLang Hames TEST(Error, CantFailDeath) { 483*fd4de910SLang Hames EXPECT_DEATH( 484*fd4de910SLang Hames cantFail(make_error<StringError>("foo", inconvertibleErrorCode())), 485*fd4de910SLang Hames "Failure value returned from cantFail wrapped call") 486*fd4de910SLang Hames << "cantFail(Error) did not cause an abort for failure value"; 487*fd4de910SLang Hames 488*fd4de910SLang Hames EXPECT_DEATH( 489*fd4de910SLang Hames { 490*fd4de910SLang Hames auto IEC = inconvertibleErrorCode(); 491*fd4de910SLang Hames int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC))); 492*fd4de910SLang Hames (void)X; 493*fd4de910SLang Hames }, 494*fd4de910SLang Hames "Failure value returned from cantFail wrapped call") 495*fd4de910SLang Hames << "cantFail(Expected<int>) did not cause an abort for failure value"; 496*fd4de910SLang Hames } 497*fd4de910SLang Hames #endif 498*fd4de910SLang Hames 499*fd4de910SLang Hames 500580ca237SLang Hames // Test Checked Expected<T> in success mode. 501580ca237SLang Hames TEST(Error, CheckedExpectedInSuccessMode) { 502f7f6d3e9SLang Hames Expected<int> A = 7; 50301864a2dSLang Hames EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 504580ca237SLang Hames // Access is safe in second test, since we checked the error in the first. 505f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 506f7f6d3e9SLang Hames } 507f7f6d3e9SLang Hames 508285639f8SLang Hames // Test Expected with reference type. 509285639f8SLang Hames TEST(Error, ExpectedWithReferenceType) { 510285639f8SLang Hames int A = 7; 511285639f8SLang Hames Expected<int&> B = A; 512285639f8SLang Hames // 'Check' B. 513285639f8SLang Hames (void)!!B; 514285639f8SLang Hames int &C = *B; 515285639f8SLang Hames EXPECT_EQ(&A, &C) << "Expected failed to propagate reference"; 516285639f8SLang Hames } 517285639f8SLang Hames 518580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 519580ca237SLang Hames // We expect this to blow up the same way Error would. 520580ca237SLang Hames // Test runs in debug mode only. 521cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 522580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeDestruction) { 523580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; }, 524580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 525580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 526580ca237SLang Hames } 527580ca237SLang Hames #endif 528580ca237SLang Hames 529580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 530580ca237SLang Hames // We expect this to blow up the same way Error would. 531580ca237SLang Hames // Test runs in debug mode only. 532cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 533580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAccess) { 534580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; *A; }, 535580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 536580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 537580ca237SLang Hames } 538580ca237SLang Hames #endif 539580ca237SLang Hames 540580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 541580ca237SLang Hames // We expect this to blow up the same way Error would. 542580ca237SLang Hames // Test runs in debug mode only. 543cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 544580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAssignment) { 545580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, 546580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 547580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 548580ca237SLang Hames } 549580ca237SLang Hames #endif 550580ca237SLang Hames 55101864a2dSLang Hames // Test Expected<T> in failure mode. 55201864a2dSLang Hames TEST(Error, ExpectedInFailureMode) { 553f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 554f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 555f7f6d3e9SLang Hames Error E = A.takeError(); 556f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 557f7f6d3e9SLang Hames consumeError(std::move(E)); 558f7f6d3e9SLang Hames } 559f7f6d3e9SLang Hames 560f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 561f7f6d3e9SLang Hames // operator*. 562f7f6d3e9SLang Hames // Test runs in debug mode only. 563cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 56401864a2dSLang Hames TEST(Error, AccessExpectedInFailureMode) { 565f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 566580ca237SLang Hames EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.") 567f7f6d3e9SLang Hames << "Incorrect Expected error value"; 568f7f6d3e9SLang Hames consumeError(A.takeError()); 569f7f6d3e9SLang Hames } 570f7f6d3e9SLang Hames #endif 571f7f6d3e9SLang Hames 572f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 573f7f6d3e9SLang Hames // unhandled. 574f7f6d3e9SLang Hames // Test runs in debug mode only. 575cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 57601864a2dSLang Hames TEST(Error, UnhandledExpectedInFailureMode) { 577f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 578580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 579f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 58001864a2dSLang Hames } 581f7f6d3e9SLang Hames #endif 582f7f6d3e9SLang Hames 583f7f6d3e9SLang Hames // Test covariance of Expected. 58401864a2dSLang Hames TEST(Error, ExpectedCovariance) { 585f7f6d3e9SLang Hames class B {}; 586f7f6d3e9SLang Hames class D : public B {}; 587f7f6d3e9SLang Hames 588f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 589580ca237SLang Hames // Check A1 by converting to bool before assigning to it. 590580ca237SLang Hames (void)!!A1; 591f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 592580ca237SLang Hames // Check A1 again before destruction. 593580ca237SLang Hames (void)!!A1; 594f7f6d3e9SLang Hames 595f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 596580ca237SLang Hames // Check A2 by converting to bool before assigning to it. 597580ca237SLang Hames (void)!!A2; 598f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 599580ca237SLang Hames // Check A2 again before destruction. 600580ca237SLang Hames (void)!!A2; 601f7f6d3e9SLang Hames } 602f7f6d3e9SLang Hames 603d21a535bSLang Hames TEST(Error, ErrorCodeConversions) { 604f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 605f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 606f7f6d3e9SLang Hames std::error_code()) 607f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 608f7f6d3e9SLang Hames 609f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 610f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 611f7f6d3e9SLang Hames errc::invalid_argument) 612f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 613f7f6d3e9SLang Hames "conversions"; 614d21a535bSLang Hames 615d21a535bSLang Hames // Round-trip a success value through ErrorOr/Expected to check that it 616d21a535bSLang Hames // converts correctly. 617d21a535bSLang Hames { 618d21a535bSLang Hames auto Orig = ErrorOr<int>(42); 619d21a535bSLang Hames auto RoundTripped = 620d21a535bSLang Hames expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); 621d21a535bSLang Hames EXPECT_EQ(*Orig, *RoundTripped) 622d21a535bSLang Hames << "ErrorOr<T> success value should round-trip via Expected<T> " 623d21a535bSLang Hames "conversions."; 624d21a535bSLang Hames } 625d21a535bSLang Hames 626d21a535bSLang Hames // Round-trip a failure value through ErrorOr/Expected to check that it 627d21a535bSLang Hames // converts correctly. 628d21a535bSLang Hames { 629d21a535bSLang Hames auto Orig = ErrorOr<int>(errc::invalid_argument); 630d21a535bSLang Hames auto RoundTripped = 631d21a535bSLang Hames expectedToErrorOr( 632d21a535bSLang Hames errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); 633d21a535bSLang Hames EXPECT_EQ(Orig.getError(), RoundTripped.getError()) 634d21a535bSLang Hames << "ErrorOr<T> failure value should round-trip via Expected<T> " 635d21a535bSLang Hames "conversions."; 636d21a535bSLang Hames } 637f7f6d3e9SLang Hames } 638f7f6d3e9SLang Hames 63927370a09SVedant Kumar // Test that error messages work. 64027370a09SVedant Kumar TEST(Error, ErrorMessage) { 64127370a09SVedant Kumar EXPECT_EQ(toString(Error::success()).compare(""), 0); 64227370a09SVedant Kumar 64327370a09SVedant Kumar Error E1 = make_error<CustomError>(0); 64427370a09SVedant Kumar EXPECT_EQ(toString(std::move(E1)).compare("CustomError { 0}"), 0); 64527370a09SVedant Kumar 64627370a09SVedant Kumar Error E2 = make_error<CustomError>(0); 64727370a09SVedant Kumar handleAllErrors(std::move(E2), [](const CustomError &CE) { 64827370a09SVedant Kumar EXPECT_EQ(CE.message().compare("CustomError { 0}"), 0); 64927370a09SVedant Kumar }); 65027370a09SVedant Kumar 65127370a09SVedant Kumar Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)); 65227370a09SVedant Kumar EXPECT_EQ(toString(std::move(E3)) 65327370a09SVedant Kumar .compare("CustomError { 0}\n" 65427370a09SVedant Kumar "CustomError { 1}"), 65527370a09SVedant Kumar 0); 65627370a09SVedant Kumar } 65727370a09SVedant Kumar 658f7f6d3e9SLang Hames } // end anon namespace 659