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" 15e8354fe6SPavel Labath #include "llvm/Testing/Support/Error.h" 16e8354fe6SPavel Labath #include "gtest/gtest-spi.h" 17f7f6d3e9SLang Hames #include "gtest/gtest.h" 18f7f6d3e9SLang Hames #include <memory> 19f7f6d3e9SLang Hames 20f7f6d3e9SLang Hames using namespace llvm; 21f7f6d3e9SLang Hames 22f7f6d3e9SLang Hames namespace { 23f7f6d3e9SLang Hames 24f7f6d3e9SLang Hames // Custom error class with a default base class and some random 'info' attached. 25f7f6d3e9SLang Hames class CustomError : public ErrorInfo<CustomError> { 26f7f6d3e9SLang Hames public: 27f7f6d3e9SLang Hames // Create an error with some info attached. 28f7f6d3e9SLang Hames CustomError(int Info) : Info(Info) {} 29f7f6d3e9SLang Hames 30f7f6d3e9SLang Hames // Get the info attached to this error. 31f7f6d3e9SLang Hames int getInfo() const { return Info; } 32f7f6d3e9SLang Hames 33f7f6d3e9SLang Hames // Log this error to a stream. 34f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 35f7f6d3e9SLang Hames OS << "CustomError { " << getInfo() << "}"; 36f7f6d3e9SLang Hames } 37f7f6d3e9SLang Hames 38e7aad357SLang Hames std::error_code convertToErrorCode() const override { 39e7aad357SLang Hames llvm_unreachable("CustomError doesn't support ECError conversion"); 40e7aad357SLang Hames } 41e7aad357SLang Hames 42a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 43a15b76b3SReid Kleckner static char ID; 44a15b76b3SReid Kleckner 45f7f6d3e9SLang Hames protected: 46f7f6d3e9SLang Hames // This error is subclassed below, but we can't use inheriting constructors 47f7f6d3e9SLang Hames // yet, so we can't propagate the constructors through ErrorInfo. Instead 48f7f6d3e9SLang Hames // we have to have a default constructor and have the subclass initialize all 49f7f6d3e9SLang Hames // fields. 50f7f6d3e9SLang Hames CustomError() : Info(0) {} 51f7f6d3e9SLang Hames 52f7f6d3e9SLang Hames int Info; 53f7f6d3e9SLang Hames }; 54f7f6d3e9SLang Hames 55a15b76b3SReid Kleckner char CustomError::ID = 0; 56a15b76b3SReid Kleckner 57f7f6d3e9SLang Hames // Custom error class with a custom base class and some additional random 58f7f6d3e9SLang Hames // 'info'. 59f7f6d3e9SLang Hames class CustomSubError : public ErrorInfo<CustomSubError, CustomError> { 60f7f6d3e9SLang Hames public: 61f7f6d3e9SLang Hames // Create a sub-error with some info attached. 62f7f6d3e9SLang Hames CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) { 63f7f6d3e9SLang Hames this->Info = Info; 64f7f6d3e9SLang Hames } 65f7f6d3e9SLang Hames 66f7f6d3e9SLang Hames // Get the extra info attached to this error. 67f7f6d3e9SLang Hames int getExtraInfo() const { return ExtraInfo; } 68f7f6d3e9SLang Hames 69f7f6d3e9SLang Hames // Log this error to a stream. 70f7f6d3e9SLang Hames void log(raw_ostream &OS) const override { 71f7f6d3e9SLang Hames OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}"; 72f7f6d3e9SLang Hames } 73f7f6d3e9SLang Hames 74e7aad357SLang Hames std::error_code convertToErrorCode() const override { 75e7aad357SLang Hames llvm_unreachable("CustomSubError doesn't support ECError conversion"); 76e7aad357SLang Hames } 77e7aad357SLang Hames 78a15b76b3SReid Kleckner // Used by ErrorInfo::classID. 79a15b76b3SReid Kleckner static char ID; 80a15b76b3SReid Kleckner 81f7f6d3e9SLang Hames protected: 82f7f6d3e9SLang Hames int ExtraInfo; 83f7f6d3e9SLang Hames }; 84f7f6d3e9SLang Hames 85a15b76b3SReid Kleckner char CustomSubError::ID = 0; 86a15b76b3SReid Kleckner 8741af4309SMehdi Amini static Error handleCustomError(const CustomError &CE) { 8841af4309SMehdi Amini return Error::success(); 8941af4309SMehdi Amini } 90f7f6d3e9SLang Hames 91f7f6d3e9SLang Hames static void handleCustomErrorVoid(const CustomError &CE) {} 92f7f6d3e9SLang Hames 93f7f6d3e9SLang Hames static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) { 9441af4309SMehdi Amini return Error::success(); 95f7f6d3e9SLang Hames } 96f7f6d3e9SLang Hames 97f7f6d3e9SLang Hames static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {} 98f7f6d3e9SLang Hames 9901864a2dSLang Hames // Test that success values implicitly convert to false, and don't cause crashes 10001864a2dSLang Hames // once they've been implicitly converted. 10101864a2dSLang Hames TEST(Error, CheckedSuccess) { 102c1edf566SMehdi Amini Error E = Error::success(); 10301864a2dSLang Hames EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'"; 10401864a2dSLang Hames } 10501864a2dSLang Hames 10601864a2dSLang Hames // Test that unchecked succes values cause an abort. 107cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 10801864a2dSLang Hames TEST(Error, UncheckedSuccess) { 109c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); }, 110c1edf566SMehdi Amini "Program aborted due to an unhandled Error:") 11101864a2dSLang Hames << "Unchecked Error Succes value did not cause abort()"; 11201864a2dSLang Hames } 11301864a2dSLang Hames #endif 11401864a2dSLang Hames 115d1af8fceSLang Hames // ErrorAsOutParameter tester. 116d1af8fceSLang Hames void errAsOutParamHelper(Error &Err) { 1175e51a2e3SLang Hames ErrorAsOutParameter ErrAsOutParam(&Err); 118d1af8fceSLang Hames // Verify that checked flag is raised - assignment should not crash. 119d1af8fceSLang Hames Err = Error::success(); 120d1af8fceSLang Hames // Raise the checked bit manually - caller should still have to test the 121d1af8fceSLang Hames // error. 122d1af8fceSLang Hames (void)!!Err; 123d0ac31a7SLang Hames } 124d0ac31a7SLang Hames 125d1af8fceSLang Hames // Test that ErrorAsOutParameter sets the checked flag on construction. 126d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterChecked) { 127c1edf566SMehdi Amini Error E = Error::success(); 128d1af8fceSLang Hames errAsOutParamHelper(E); 129d1af8fceSLang Hames (void)!!E; 130d1af8fceSLang Hames } 131d1af8fceSLang Hames 132d1af8fceSLang Hames // Test that ErrorAsOutParameter clears the checked flag on destruction. 133cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 134d1af8fceSLang Hames TEST(Error, ErrorAsOutParameterUnchecked) { 135c1edf566SMehdi Amini EXPECT_DEATH({ Error E = Error::success(); errAsOutParamHelper(E); }, 136d1af8fceSLang Hames "Program aborted due to an unhandled Error:") 137d1af8fceSLang Hames << "ErrorAsOutParameter did not clear the checked flag on destruction."; 138d1af8fceSLang Hames } 139d1af8fceSLang Hames #endif 140d1af8fceSLang Hames 141f7f6d3e9SLang Hames // Check that we abort on unhandled failure cases. (Force conversion to bool 142f7f6d3e9SLang Hames // to make sure that we don't accidentally treat checked errors as handled). 143f7f6d3e9SLang Hames // Test runs in debug mode only. 144cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 14501864a2dSLang Hames TEST(Error, UncheckedError) { 146f7f6d3e9SLang Hames auto DropUnhandledError = []() { 147f7f6d3e9SLang Hames Error E = make_error<CustomError>(42); 148f7f6d3e9SLang Hames (void)!E; 149f7f6d3e9SLang Hames }; 150f7f6d3e9SLang Hames EXPECT_DEATH(DropUnhandledError(), 151f7f6d3e9SLang Hames "Program aborted due to an unhandled Error:") 152f7f6d3e9SLang Hames << "Unhandled Error failure value did not cause abort()"; 153f7f6d3e9SLang Hames } 154f7f6d3e9SLang Hames #endif 155f7f6d3e9SLang Hames 15601864a2dSLang Hames // Check 'Error::isA<T>' method handling. 15701864a2dSLang Hames TEST(Error, IsAHandling) { 158f7f6d3e9SLang Hames // Check 'isA' handling. 159f7f6d3e9SLang Hames Error E = make_error<CustomError>(1); 160f7f6d3e9SLang Hames Error F = make_error<CustomSubError>(1, 2); 16101a3cf4dSLang Hames Error G = Error::success(); 162f7f6d3e9SLang Hames 163f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()); 164f7f6d3e9SLang Hames EXPECT_FALSE(E.isA<CustomSubError>()); 165f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomError>()); 166f7f6d3e9SLang Hames EXPECT_TRUE(F.isA<CustomSubError>()); 16701a3cf4dSLang Hames EXPECT_FALSE(G.isA<CustomError>()); 168f7f6d3e9SLang Hames 169f7f6d3e9SLang Hames consumeError(std::move(E)); 170f7f6d3e9SLang Hames consumeError(std::move(F)); 17101a3cf4dSLang Hames consumeError(std::move(G)); 172f7f6d3e9SLang Hames } 173f7f6d3e9SLang Hames 174f7f6d3e9SLang Hames // Check that we can handle a custom error. 17501864a2dSLang Hames TEST(Error, HandleCustomError) { 176f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 177f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) { 178f7f6d3e9SLang Hames CaughtErrorInfo = CE.getInfo(); 179f7f6d3e9SLang Hames }); 180f7f6d3e9SLang Hames 18101864a2dSLang Hames EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler"; 182f7f6d3e9SLang Hames } 183f7f6d3e9SLang Hames 184f7f6d3e9SLang Hames // Check that handler type deduction also works for handlers 185f7f6d3e9SLang Hames // of the following types: 186f7f6d3e9SLang Hames // void (const Err&) 187f7f6d3e9SLang Hames // Error (const Err&) mutable 188f7f6d3e9SLang Hames // void (const Err&) mutable 189f7f6d3e9SLang Hames // Error (Err&) 190f7f6d3e9SLang Hames // void (Err&) 191f7f6d3e9SLang Hames // Error (Err&) mutable 192f7f6d3e9SLang Hames // void (Err&) mutable 193f7f6d3e9SLang Hames // Error (unique_ptr<Err>) 194f7f6d3e9SLang Hames // void (unique_ptr<Err>) 195f7f6d3e9SLang Hames // Error (unique_ptr<Err>) mutable 196f7f6d3e9SLang Hames // void (unique_ptr<Err>) mutable 19701864a2dSLang Hames TEST(Error, HandlerTypeDeduction) { 198f7f6d3e9SLang Hames 199f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {}); 200f7f6d3e9SLang Hames 201f7f6d3e9SLang Hames handleAllErrors( 202f7f6d3e9SLang Hames make_error<CustomError>(42), 203c1edf566SMehdi Amini [](const CustomError &CE) mutable -> Error { return Error::success(); }); 204f7f6d3e9SLang Hames 205f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 206f7f6d3e9SLang Hames [](const CustomError &CE) mutable {}); 207f7f6d3e9SLang Hames 208f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 209c1edf566SMehdi Amini [](CustomError &CE) -> Error { return Error::success(); }); 210f7f6d3e9SLang Hames 211f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {}); 212f7f6d3e9SLang Hames 213f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 214c1edf566SMehdi Amini [](CustomError &CE) mutable -> Error { return Error::success(); }); 215f7f6d3e9SLang Hames 216f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {}); 217f7f6d3e9SLang Hames 218f7f6d3e9SLang Hames handleAllErrors( 219f7f6d3e9SLang Hames make_error<CustomError>(42), 220c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) -> Error { return Error::success(); }); 221f7f6d3e9SLang Hames 222f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 223f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) {}); 224f7f6d3e9SLang Hames 225f7f6d3e9SLang Hames handleAllErrors( 226f7f6d3e9SLang Hames make_error<CustomError>(42), 227c1edf566SMehdi Amini [](std::unique_ptr<CustomError> CE) mutable -> Error { return Error::success(); }); 228f7f6d3e9SLang Hames 229f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), 230f7f6d3e9SLang Hames [](std::unique_ptr<CustomError> CE) mutable {}); 231f7f6d3e9SLang Hames 232f7f6d3e9SLang Hames // Check that named handlers of type 'Error (const Err&)' work. 233f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomError); 234f7f6d3e9SLang Hames 235f7f6d3e9SLang Hames // Check that named handlers of type 'void (const Err&)' work. 236f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid); 237f7f6d3e9SLang Hames 238f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 239f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP); 240f7f6d3e9SLang Hames 241f7f6d3e9SLang Hames // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work. 242f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid); 24301864a2dSLang Hames } 244f7f6d3e9SLang Hames 24501864a2dSLang Hames // Test that we can handle errors with custom base classes. 24601864a2dSLang Hames TEST(Error, HandleCustomErrorWithCustomBaseClass) { 247f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 248f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 249f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 250f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 251f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 252f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 253f7f6d3e9SLang Hames }); 254f7f6d3e9SLang Hames 255f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7) 256f7f6d3e9SLang Hames << "Wrong result from CustomSubError handler"; 257f7f6d3e9SLang Hames } 258f7f6d3e9SLang Hames 259f7f6d3e9SLang Hames // Check that we trigger only the first handler that applies. 26001864a2dSLang Hames TEST(Error, FirstHandlerOnly) { 261f7f6d3e9SLang Hames int DummyInfo = 0; 262f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 263f7f6d3e9SLang Hames int CaughtErrorExtraInfo = 0; 264f7f6d3e9SLang Hames 265f7f6d3e9SLang Hames handleAllErrors(make_error<CustomSubError>(42, 7), 266f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 267f7f6d3e9SLang Hames CaughtErrorInfo = SE.getInfo(); 268f7f6d3e9SLang Hames CaughtErrorExtraInfo = SE.getExtraInfo(); 269f7f6d3e9SLang Hames }, 270f7f6d3e9SLang Hames [&](const CustomError &CE) { DummyInfo = CE.getInfo(); }); 271f7f6d3e9SLang Hames 272f7f6d3e9SLang Hames EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 && 273f7f6d3e9SLang Hames DummyInfo == 0) 274f7f6d3e9SLang Hames << "Activated the wrong Error handler(s)"; 275f7f6d3e9SLang Hames } 276f7f6d3e9SLang Hames 277f7f6d3e9SLang Hames // Check that general handlers shadow specific ones. 27801864a2dSLang Hames TEST(Error, HandlerShadowing) { 279f7f6d3e9SLang Hames int CaughtErrorInfo = 0; 280f7f6d3e9SLang Hames int DummyInfo = 0; 281f7f6d3e9SLang Hames int DummyExtraInfo = 0; 282f7f6d3e9SLang Hames 283f7f6d3e9SLang Hames handleAllErrors( 284f7f6d3e9SLang Hames make_error<CustomSubError>(42, 7), 285f7f6d3e9SLang Hames [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); }, 286f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 287f7f6d3e9SLang Hames DummyInfo = SE.getInfo(); 288f7f6d3e9SLang Hames DummyExtraInfo = SE.getExtraInfo(); 289f7f6d3e9SLang Hames }); 290f7f6d3e9SLang Hames 291b2cef64bSNAKAMURA Takumi EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0) 292f7f6d3e9SLang Hames << "General Error handler did not shadow specific handler"; 293f7f6d3e9SLang Hames } 294f7f6d3e9SLang Hames 29501864a2dSLang Hames // Test joinErrors. 29601864a2dSLang Hames TEST(Error, CheckJoinErrors) { 297f7f6d3e9SLang Hames int CustomErrorInfo1 = 0; 298f7f6d3e9SLang Hames int CustomErrorInfo2 = 0; 299f7f6d3e9SLang Hames int CustomErrorExtraInfo = 0; 30001864a2dSLang Hames Error E = 30101864a2dSLang Hames joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7)); 302f7f6d3e9SLang Hames 303f7f6d3e9SLang Hames handleAllErrors(std::move(E), 304f7f6d3e9SLang Hames [&](const CustomSubError &SE) { 305f7f6d3e9SLang Hames CustomErrorInfo2 = SE.getInfo(); 306f7f6d3e9SLang Hames CustomErrorExtraInfo = SE.getExtraInfo(); 307f7f6d3e9SLang Hames }, 308f7f6d3e9SLang Hames [&](const CustomError &CE) { 309f7f6d3e9SLang Hames // Assert that the CustomError instance above is handled 310f7f6d3e9SLang Hames // before the 311f7f6d3e9SLang Hames // CustomSubError - joinErrors should preserve error 312f7f6d3e9SLang Hames // ordering. 313f7f6d3e9SLang Hames EXPECT_EQ(CustomErrorInfo2, 0) 314f7f6d3e9SLang Hames << "CustomErrorInfo2 should be 0 here. " 315f7f6d3e9SLang Hames "joinErrors failed to preserve ordering.\n"; 316f7f6d3e9SLang Hames CustomErrorInfo1 = CE.getInfo(); 317f7f6d3e9SLang Hames }); 318f7f6d3e9SLang Hames 319f7f6d3e9SLang Hames EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 && 320f7f6d3e9SLang Hames CustomErrorExtraInfo == 7) 321f7f6d3e9SLang Hames << "Failed handling compound Error."; 322759b30edSLang Hames 323759b30edSLang Hames // Test appending a single item to a list. 324759b30edSLang Hames { 325759b30edSLang Hames int Sum = 0; 326759b30edSLang Hames handleAllErrors( 327759b30edSLang Hames joinErrors( 328759b30edSLang Hames joinErrors(make_error<CustomError>(7), 329759b30edSLang Hames make_error<CustomError>(7)), 330759b30edSLang Hames make_error<CustomError>(7)), 331759b30edSLang Hames [&](const CustomError &CE) { 332759b30edSLang Hames Sum += CE.getInfo(); 333759b30edSLang Hames }); 334759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list."; 335759b30edSLang Hames } 336759b30edSLang Hames 337759b30edSLang Hames // Test prepending a single item to a list. 338759b30edSLang Hames { 339759b30edSLang Hames int Sum = 0; 340759b30edSLang Hames handleAllErrors( 341759b30edSLang Hames joinErrors( 342759b30edSLang Hames make_error<CustomError>(7), 343759b30edSLang Hames joinErrors(make_error<CustomError>(7), 344759b30edSLang Hames make_error<CustomError>(7))), 345759b30edSLang Hames [&](const CustomError &CE) { 346759b30edSLang Hames Sum += CE.getInfo(); 347759b30edSLang Hames }); 348759b30edSLang Hames EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list."; 349759b30edSLang Hames } 350759b30edSLang Hames 351759b30edSLang Hames // Test concatenating two error lists. 352759b30edSLang Hames { 353759b30edSLang Hames int Sum = 0; 354759b30edSLang Hames handleAllErrors( 355759b30edSLang Hames joinErrors( 356759b30edSLang Hames joinErrors( 357759b30edSLang Hames make_error<CustomError>(7), 358759b30edSLang Hames make_error<CustomError>(7)), 359759b30edSLang Hames joinErrors( 360759b30edSLang Hames make_error<CustomError>(7), 361759b30edSLang Hames make_error<CustomError>(7))), 362759b30edSLang Hames [&](const CustomError &CE) { 363759b30edSLang Hames Sum += CE.getInfo(); 364759b30edSLang Hames }); 3650ca79dcfSHiroshi Inoue EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate error lists."; 366759b30edSLang Hames } 367f7f6d3e9SLang Hames } 368f7f6d3e9SLang Hames 36901864a2dSLang Hames // Test that we can consume success values. 37001864a2dSLang Hames TEST(Error, ConsumeSuccess) { 371c1edf566SMehdi Amini Error E = Error::success(); 372f7f6d3e9SLang Hames consumeError(std::move(E)); 373f7f6d3e9SLang Hames } 37401864a2dSLang Hames 37501864a2dSLang Hames TEST(Error, ConsumeError) { 376f7f6d3e9SLang Hames Error E = make_error<CustomError>(7); 377f7f6d3e9SLang Hames consumeError(std::move(E)); 378f7f6d3e9SLang Hames } 379f7f6d3e9SLang Hames 380f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is not caught. 381f7f6d3e9SLang Hames // Test runs in debug mode only. 382cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 38301864a2dSLang Hames TEST(Error, FailureToHandle) { 384f7f6d3e9SLang Hames auto FailToHandle = []() { 38501864a2dSLang Hames handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) { 386f7f6d3e9SLang Hames errs() << "This should never be called"; 387f7f6d3e9SLang Hames exit(1); 388f7f6d3e9SLang Hames }); 389f7f6d3e9SLang Hames }; 390f7f6d3e9SLang Hames 3917febf2baSLang Hames EXPECT_DEATH(FailToHandle(), 3927febf2baSLang Hames "Failure value returned from cantFail wrapped call") 393f7f6d3e9SLang Hames << "Unhandled Error in handleAllErrors call did not cause an " 394f7f6d3e9SLang Hames "abort()"; 395f7f6d3e9SLang Hames } 396f7f6d3e9SLang Hames #endif 397f7f6d3e9SLang Hames 398f7f6d3e9SLang Hames // Test that handleAllUnhandledErrors crashes if an error is returned from a 399f7f6d3e9SLang Hames // handler. 400f7f6d3e9SLang Hames // Test runs in debug mode only. 401cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 40201864a2dSLang Hames TEST(Error, FailureFromHandler) { 403f7f6d3e9SLang Hames auto ReturnErrorFromHandler = []() { 404f7f6d3e9SLang Hames handleAllErrors(make_error<CustomError>(7), 405f7f6d3e9SLang Hames [&](std::unique_ptr<CustomSubError> SE) { 406f7f6d3e9SLang Hames return Error(std::move(SE)); 407f7f6d3e9SLang Hames }); 408f7f6d3e9SLang Hames }; 409f7f6d3e9SLang Hames 410f7f6d3e9SLang Hames EXPECT_DEATH(ReturnErrorFromHandler(), 4117febf2baSLang Hames "Failure value returned from cantFail wrapped call") 412f7f6d3e9SLang Hames << " Error returned from handler in handleAllErrors call did not " 413f7f6d3e9SLang Hames "cause abort()"; 414f7f6d3e9SLang Hames } 415f7f6d3e9SLang Hames #endif 416f7f6d3e9SLang Hames 417f7f6d3e9SLang Hames // Test that we can return values from handleErrors. 41801864a2dSLang Hames TEST(Error, CatchErrorFromHandler) { 419f7f6d3e9SLang Hames int ErrorInfo = 0; 420f7f6d3e9SLang Hames 421f7f6d3e9SLang Hames Error E = handleErrors( 422f7f6d3e9SLang Hames make_error<CustomError>(7), 423f7f6d3e9SLang Hames [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); }); 424f7f6d3e9SLang Hames 425f7f6d3e9SLang Hames handleAllErrors(std::move(E), 426f7f6d3e9SLang Hames [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); }); 427f7f6d3e9SLang Hames 428f7f6d3e9SLang Hames EXPECT_EQ(ErrorInfo, 7) 429f7f6d3e9SLang Hames << "Failed to handle Error returned from handleErrors."; 430f7f6d3e9SLang Hames } 4316935c2d3SLang Hames 432c5e0bbd7SLang Hames TEST(Error, StringError) { 433c5e0bbd7SLang Hames std::string Msg; 434c5e0bbd7SLang Hames raw_string_ostream S(Msg); 435c5e0bbd7SLang Hames logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42), 436bd8e9542SLang Hames inconvertibleErrorCode()), 437c5e0bbd7SLang Hames S, ""); 438c5e0bbd7SLang Hames EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result"; 439c5e0bbd7SLang Hames 440c5e0bbd7SLang Hames auto EC = 441c5e0bbd7SLang Hames errorToErrorCode(make_error<StringError>("", errc::invalid_argument)); 442c5e0bbd7SLang Hames EXPECT_EQ(EC, errc::invalid_argument) 443c5e0bbd7SLang Hames << "Failed to convert StringError to error_code."; 444c5e0bbd7SLang Hames } 445c5e0bbd7SLang Hames 44601864a2dSLang Hames // Test that the ExitOnError utility works as expected. 44701864a2dSLang Hames TEST(Error, ExitOnError) { 4486935c2d3SLang Hames ExitOnError ExitOnErr; 4496935c2d3SLang Hames ExitOnErr.setBanner("Error in tool:"); 45001864a2dSLang Hames ExitOnErr.setExitCodeMapper([](const Error &E) { 4516935c2d3SLang Hames if (E.isA<CustomSubError>()) 4526935c2d3SLang Hames return 2; 4536935c2d3SLang Hames return 1; 4546935c2d3SLang Hames }); 4556935c2d3SLang Hames 4566935c2d3SLang Hames // Make sure we don't bail on success. 4576935c2d3SLang Hames ExitOnErr(Error::success()); 4586935c2d3SLang Hames EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7) 4596935c2d3SLang Hames << "exitOnError returned an invalid value for Expected"; 4606935c2d3SLang Hames 461285639f8SLang Hames int A = 7; 462285639f8SLang Hames int &B = ExitOnErr(Expected<int&>(A)); 463285639f8SLang Hames EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference"; 464285639f8SLang Hames 4656935c2d3SLang Hames // Exit tests. 4666935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)), 4676935c2d3SLang Hames ::testing::ExitedWithCode(1), "Error in tool:") 4686935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4696935c2d3SLang Hames 4706935c2d3SLang Hames EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))), 4716935c2d3SLang Hames ::testing::ExitedWithCode(2), "Error in tool:") 4726935c2d3SLang Hames << "exitOnError returned an unexpected error result"; 4736935c2d3SLang Hames } 474f7f6d3e9SLang Hames 475fd4de910SLang Hames // Test that the ExitOnError utility works as expected. 476fd4de910SLang Hames TEST(Error, CantFailSuccess) { 477fd4de910SLang Hames cantFail(Error::success()); 478fd4de910SLang Hames 479fd4de910SLang Hames int X = cantFail(Expected<int>(42)); 480fd4de910SLang Hames EXPECT_EQ(X, 42) << "Expected value modified by cantFail"; 481cd227536SLang Hames 482cd227536SLang Hames int Dummy = 42; 483cd227536SLang Hames int &Y = cantFail(Expected<int&>(Dummy)); 484cd227536SLang Hames EXPECT_EQ(&Dummy, &Y) << "Reference mangled by cantFail"; 485fd4de910SLang Hames } 486fd4de910SLang Hames 487fd4de910SLang Hames // Test that cantFail results in a crash if you pass it a failure value. 488cc14a386SStephen Hines #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG) 489fd4de910SLang Hames TEST(Error, CantFailDeath) { 490fd4de910SLang Hames EXPECT_DEATH( 4913025e48aSLang Hames cantFail(make_error<StringError>("foo", inconvertibleErrorCode()), 4923025e48aSLang Hames "Cantfail call failed"), 4933025e48aSLang Hames "Cantfail call failed") 494fd4de910SLang Hames << "cantFail(Error) did not cause an abort for failure value"; 495fd4de910SLang Hames 496fd4de910SLang Hames EXPECT_DEATH( 497fd4de910SLang Hames { 498fd4de910SLang Hames auto IEC = inconvertibleErrorCode(); 499fd4de910SLang Hames int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC))); 500fd4de910SLang Hames (void)X; 501fd4de910SLang Hames }, 502fd4de910SLang Hames "Failure value returned from cantFail wrapped call") 503fd4de910SLang Hames << "cantFail(Expected<int>) did not cause an abort for failure value"; 504fd4de910SLang Hames } 505fd4de910SLang Hames #endif 506fd4de910SLang Hames 507fd4de910SLang Hames 508580ca237SLang Hames // Test Checked Expected<T> in success mode. 509580ca237SLang Hames TEST(Error, CheckedExpectedInSuccessMode) { 510f7f6d3e9SLang Hames Expected<int> A = 7; 51101864a2dSLang Hames EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'"; 512580ca237SLang Hames // Access is safe in second test, since we checked the error in the first. 513f7f6d3e9SLang Hames EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value"; 514f7f6d3e9SLang Hames } 515f7f6d3e9SLang Hames 516285639f8SLang Hames // Test Expected with reference type. 517285639f8SLang Hames TEST(Error, ExpectedWithReferenceType) { 518285639f8SLang Hames int A = 7; 519285639f8SLang Hames Expected<int&> B = A; 520285639f8SLang Hames // 'Check' B. 521285639f8SLang Hames (void)!!B; 522285639f8SLang Hames int &C = *B; 523285639f8SLang Hames EXPECT_EQ(&A, &C) << "Expected failed to propagate reference"; 524285639f8SLang Hames } 525285639f8SLang Hames 526580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 527580ca237SLang Hames // We expect this to blow up the same way Error would. 528580ca237SLang Hames // Test runs in debug mode only. 529cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 530580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeDestruction) { 531580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; }, 532580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 533580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 534580ca237SLang Hames } 535580ca237SLang Hames #endif 536580ca237SLang Hames 537580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 538580ca237SLang Hames // We expect this to blow up the same way Error would. 539580ca237SLang Hames // Test runs in debug mode only. 540cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 541580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAccess) { 542580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; *A; }, 543580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 544580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 545580ca237SLang Hames } 546580ca237SLang Hames #endif 547580ca237SLang Hames 548580ca237SLang Hames // Test Unchecked Expected<T> in success mode. 549580ca237SLang Hames // We expect this to blow up the same way Error would. 550580ca237SLang Hames // Test runs in debug mode only. 551cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 552580ca237SLang Hames TEST(Error, UncheckedExpectedInSuccessModeAssignment) { 553580ca237SLang Hames EXPECT_DEATH({ Expected<int> A = 7; A = 7; }, 554580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 555580ca237SLang Hames << "Unchecekd Expected<T> success value did not cause an abort()."; 556580ca237SLang Hames } 557580ca237SLang Hames #endif 558580ca237SLang Hames 55901864a2dSLang Hames // Test Expected<T> in failure mode. 56001864a2dSLang Hames TEST(Error, ExpectedInFailureMode) { 561f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 562f7f6d3e9SLang Hames EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'"; 563f7f6d3e9SLang Hames Error E = A.takeError(); 564f7f6d3e9SLang Hames EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value"; 565f7f6d3e9SLang Hames consumeError(std::move(E)); 566f7f6d3e9SLang Hames } 567f7f6d3e9SLang Hames 568f7f6d3e9SLang Hames // Check that an Expected instance with an error value doesn't allow access to 569f7f6d3e9SLang Hames // operator*. 570f7f6d3e9SLang Hames // Test runs in debug mode only. 571cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 57201864a2dSLang Hames TEST(Error, AccessExpectedInFailureMode) { 573f7f6d3e9SLang Hames Expected<int> A = make_error<CustomError>(42); 574580ca237SLang Hames EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.") 575f7f6d3e9SLang Hames << "Incorrect Expected error value"; 576f7f6d3e9SLang Hames consumeError(A.takeError()); 577f7f6d3e9SLang Hames } 578f7f6d3e9SLang Hames #endif 579f7f6d3e9SLang Hames 580f7f6d3e9SLang Hames // Check that an Expected instance with an error triggers an abort if 581f7f6d3e9SLang Hames // unhandled. 582f7f6d3e9SLang Hames // Test runs in debug mode only. 583cb79c079SMehdi Amini #if LLVM_ENABLE_ABI_BREAKING_CHECKS 58401864a2dSLang Hames TEST(Error, UnhandledExpectedInFailureMode) { 585f7f6d3e9SLang Hames EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); }, 586580ca237SLang Hames "Expected<T> must be checked before access or destruction.") 587f7f6d3e9SLang Hames << "Unchecked Expected<T> failure value did not cause an abort()"; 58801864a2dSLang Hames } 589f7f6d3e9SLang Hames #endif 590f7f6d3e9SLang Hames 591f7f6d3e9SLang Hames // Test covariance of Expected. 59201864a2dSLang Hames TEST(Error, ExpectedCovariance) { 593f7f6d3e9SLang Hames class B {}; 594f7f6d3e9SLang Hames class D : public B {}; 595f7f6d3e9SLang Hames 596f7f6d3e9SLang Hames Expected<B *> A1(Expected<D *>(nullptr)); 597580ca237SLang Hames // Check A1 by converting to bool before assigning to it. 598580ca237SLang Hames (void)!!A1; 599f7f6d3e9SLang Hames A1 = Expected<D *>(nullptr); 600580ca237SLang Hames // Check A1 again before destruction. 601580ca237SLang Hames (void)!!A1; 602f7f6d3e9SLang Hames 603f7f6d3e9SLang Hames Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr)); 604580ca237SLang Hames // Check A2 by converting to bool before assigning to it. 605580ca237SLang Hames (void)!!A2; 606f7f6d3e9SLang Hames A2 = Expected<std::unique_ptr<D>>(nullptr); 607580ca237SLang Hames // Check A2 again before destruction. 608580ca237SLang Hames (void)!!A2; 609f7f6d3e9SLang Hames } 610f7f6d3e9SLang Hames 6115d06c23dSLang Hames // Test that handleExpected just returns success values. 6125d06c23dSLang Hames TEST(Error, HandleExpectedSuccess) { 6135d06c23dSLang Hames auto ValOrErr = 6145d06c23dSLang Hames handleExpected(Expected<int>(42), 6155d06c23dSLang Hames []() { return Expected<int>(43); }); 6165d06c23dSLang Hames EXPECT_TRUE(!!ValOrErr) 6175d06c23dSLang Hames << "handleExpected should have returned a success value here"; 6185d06c23dSLang Hames EXPECT_EQ(*ValOrErr, 42) 6195d06c23dSLang Hames << "handleExpected should have returned the original success value here"; 6205d06c23dSLang Hames } 6215d06c23dSLang Hames 6225d06c23dSLang Hames enum FooStrategy { Aggressive, Conservative }; 6235d06c23dSLang Hames 6245d06c23dSLang Hames static Expected<int> foo(FooStrategy S) { 6255d06c23dSLang Hames if (S == Aggressive) 6265d06c23dSLang Hames return make_error<CustomError>(7); 6275d06c23dSLang Hames return 42; 6285d06c23dSLang Hames } 6295d06c23dSLang Hames 6305d06c23dSLang Hames // Test that handleExpected invokes the error path if errors are not handled. 6315d06c23dSLang Hames TEST(Error, HandleExpectedUnhandledError) { 6325d06c23dSLang Hames // foo(Aggressive) should return a CustomError which should pass through as 6335d06c23dSLang Hames // there is no handler for CustomError. 6345d06c23dSLang Hames auto ValOrErr = 6355d06c23dSLang Hames handleExpected( 6365d06c23dSLang Hames foo(Aggressive), 6375d06c23dSLang Hames []() { return foo(Conservative); }); 6385d06c23dSLang Hames 6395d06c23dSLang Hames EXPECT_FALSE(!!ValOrErr) 6405d06c23dSLang Hames << "handleExpected should have returned an error here"; 6415d06c23dSLang Hames auto Err = ValOrErr.takeError(); 6425d06c23dSLang Hames EXPECT_TRUE(Err.isA<CustomError>()) 6435d06c23dSLang Hames << "handleExpected should have returned the CustomError generated by " 6445d06c23dSLang Hames "foo(Aggressive) here"; 6455d06c23dSLang Hames consumeError(std::move(Err)); 6465d06c23dSLang Hames } 6475d06c23dSLang Hames 6485d06c23dSLang Hames // Test that handleExpected invokes the fallback path if errors are handled. 6495d06c23dSLang Hames TEST(Error, HandleExpectedHandledError) { 6505d06c23dSLang Hames // foo(Aggressive) should return a CustomError which should handle triggering 6515d06c23dSLang Hames // the fallback path. 6525d06c23dSLang Hames auto ValOrErr = 6535d06c23dSLang Hames handleExpected( 6545d06c23dSLang Hames foo(Aggressive), 6555d06c23dSLang Hames []() { return foo(Conservative); }, 6565d06c23dSLang Hames [](const CustomError&) { /* do nothing */ }); 6575d06c23dSLang Hames 6585d06c23dSLang Hames EXPECT_TRUE(!!ValOrErr) 6595d06c23dSLang Hames << "handleExpected should have returned a success value here"; 6605d06c23dSLang Hames EXPECT_EQ(*ValOrErr, 42) 6615d06c23dSLang Hames << "handleExpected returned the wrong success value"; 6625d06c23dSLang Hames } 6635d06c23dSLang Hames 664d21a535bSLang Hames TEST(Error, ErrorCodeConversions) { 665f7f6d3e9SLang Hames // Round-trip a success value to check that it converts correctly. 666f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), 667f7f6d3e9SLang Hames std::error_code()) 668f7f6d3e9SLang Hames << "std::error_code() should round-trip via Error conversions"; 669f7f6d3e9SLang Hames 670f7f6d3e9SLang Hames // Round-trip an error value to check that it converts correctly. 671f7f6d3e9SLang Hames EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)), 672f7f6d3e9SLang Hames errc::invalid_argument) 673f7f6d3e9SLang Hames << "std::error_code error value should round-trip via Error " 674f7f6d3e9SLang Hames "conversions"; 675d21a535bSLang Hames 676d21a535bSLang Hames // Round-trip a success value through ErrorOr/Expected to check that it 677d21a535bSLang Hames // converts correctly. 678d21a535bSLang Hames { 679d21a535bSLang Hames auto Orig = ErrorOr<int>(42); 680d21a535bSLang Hames auto RoundTripped = 681d21a535bSLang Hames expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42))); 682d21a535bSLang Hames EXPECT_EQ(*Orig, *RoundTripped) 683d21a535bSLang Hames << "ErrorOr<T> success value should round-trip via Expected<T> " 684d21a535bSLang Hames "conversions."; 685d21a535bSLang Hames } 686d21a535bSLang Hames 687d21a535bSLang Hames // Round-trip a failure value through ErrorOr/Expected to check that it 688d21a535bSLang Hames // converts correctly. 689d21a535bSLang Hames { 690d21a535bSLang Hames auto Orig = ErrorOr<int>(errc::invalid_argument); 691d21a535bSLang Hames auto RoundTripped = 692d21a535bSLang Hames expectedToErrorOr( 693d21a535bSLang Hames errorOrToExpected(ErrorOr<int>(errc::invalid_argument))); 694d21a535bSLang Hames EXPECT_EQ(Orig.getError(), RoundTripped.getError()) 695d21a535bSLang Hames << "ErrorOr<T> failure value should round-trip via Expected<T> " 696d21a535bSLang Hames "conversions."; 697d21a535bSLang Hames } 698f7f6d3e9SLang Hames } 699f7f6d3e9SLang Hames 70027370a09SVedant Kumar // Test that error messages work. 70127370a09SVedant Kumar TEST(Error, ErrorMessage) { 70227370a09SVedant Kumar EXPECT_EQ(toString(Error::success()).compare(""), 0); 70327370a09SVedant Kumar 70427370a09SVedant Kumar Error E1 = make_error<CustomError>(0); 70527370a09SVedant Kumar EXPECT_EQ(toString(std::move(E1)).compare("CustomError { 0}"), 0); 70627370a09SVedant Kumar 70727370a09SVedant Kumar Error E2 = make_error<CustomError>(0); 70827370a09SVedant Kumar handleAllErrors(std::move(E2), [](const CustomError &CE) { 70927370a09SVedant Kumar EXPECT_EQ(CE.message().compare("CustomError { 0}"), 0); 71027370a09SVedant Kumar }); 71127370a09SVedant Kumar 71227370a09SVedant Kumar Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)); 71327370a09SVedant Kumar EXPECT_EQ(toString(std::move(E3)) 71427370a09SVedant Kumar .compare("CustomError { 0}\n" 71527370a09SVedant Kumar "CustomError { 1}"), 71627370a09SVedant Kumar 0); 71727370a09SVedant Kumar } 71827370a09SVedant Kumar 719e8354fe6SPavel Labath TEST(Error, ErrorMatchers) { 720e8354fe6SPavel Labath EXPECT_THAT_ERROR(Error::success(), Succeeded()); 721e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 722e8354fe6SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Succeeded()), 723e8354fe6SPavel Labath "Expected: succeeded\n Actual: failed (CustomError { 0})"); 724e8354fe6SPavel Labath 725e8354fe6SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed()); 726e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE(EXPECT_THAT_ERROR(Error::success(), Failed()), 727e8354fe6SPavel Labath "Expected: failed\n Actual: succeeded"); 728e8354fe6SPavel Labath 729510725c2SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomError>()); 730510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 731510725c2SPavel Labath EXPECT_THAT_ERROR(Error::success(), Failed<CustomError>()), 732510725c2SPavel Labath "Expected: failed with Error of given type\n Actual: succeeded"); 733510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 734510725c2SPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<CustomSubError>()), 735510725c2SPavel Labath "Error was not of given type"); 736510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 737510725c2SPavel Labath EXPECT_THAT_ERROR( 738510725c2SPavel Labath joinErrors(make_error<CustomError>(0), make_error<CustomError>(1)), 739510725c2SPavel Labath Failed<CustomError>()), 740510725c2SPavel Labath "multiple errors"); 741510725c2SPavel Labath 742510725c2SPavel Labath EXPECT_THAT_ERROR( 743510725c2SPavel Labath make_error<CustomError>(0), 744510725c2SPavel Labath Failed<CustomError>(testing::Property(&CustomError::getInfo, 0))); 745510725c2SPavel Labath EXPECT_NONFATAL_FAILURE( 746510725c2SPavel Labath EXPECT_THAT_ERROR( 747510725c2SPavel Labath make_error<CustomError>(0), 748510725c2SPavel Labath Failed<CustomError>(testing::Property(&CustomError::getInfo, 1))), 749510725c2SPavel Labath "Expected: failed with Error of given type and the error is an object " 750510725c2SPavel Labath "whose given property is equal to 1\n" 751510725c2SPavel Labath " Actual: failed (CustomError { 0})"); 752*397e150dSPavel Labath EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed<ErrorInfoBase>()); 753510725c2SPavel Labath 754e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), Succeeded()); 755e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 756e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 757e8354fe6SPavel Labath Succeeded()), 758e8354fe6SPavel Labath "Expected: succeeded\n Actual: failed (CustomError { 0})"); 759e8354fe6SPavel Labath 760e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), Failed()); 761e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 762e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), Failed()), 76356c2d999SPavel Labath "Expected: failed\n Actual: succeeded with value 0"); 764e8354fe6SPavel Labath 765e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(0)); 766e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 767e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 768e8354fe6SPavel Labath HasValue(0)), 76956c2d999SPavel Labath "Expected: succeeded with value (is equal to 0)\n" 770e8354fe6SPavel Labath " Actual: failed (CustomError { 0})"); 771e8354fe6SPavel Labath EXPECT_NONFATAL_FAILURE( 772e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(0)), 77356c2d999SPavel Labath "Expected: succeeded with value (is equal to 0)\n" 77456c2d999SPavel Labath " Actual: succeeded with value 1, (isn't equal to 0)"); 775e8354fe6SPavel Labath 776e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(make_error<CustomError>(0)), Failed()); 777e8354fe6SPavel Labath int a = 1; 778e8354fe6SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(a), Succeeded()); 77956c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(testing::Eq(1))); 78056c2d999SPavel Labath 78156c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(testing::Gt(0))); 78256c2d999SPavel Labath EXPECT_NONFATAL_FAILURE( 78356c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(testing::Gt(1))), 78456c2d999SPavel Labath "Expected: succeeded with value (is > 1)\n" 78556c2d999SPavel Labath " Actual: succeeded with value 0, (isn't > 1)"); 78656c2d999SPavel Labath EXPECT_NONFATAL_FAILURE( 78756c2d999SPavel Labath EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), 78856c2d999SPavel Labath HasValue(testing::Gt(1))), 78956c2d999SPavel Labath "Expected: succeeded with value (is > 1)\n" 79056c2d999SPavel Labath " Actual: failed (CustomError { 0})"); 791e8354fe6SPavel Labath } 792e8354fe6SPavel Labath 793f7f6d3e9SLang Hames } // end anon namespace 794