ErrorHandlingTests.cpp (7409B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 4 #include "ErrorHandling.h" 5 #include "ReportingHandler.h" 6 #include "Result.h" 7 #include "SFSException.h" 8 9 #include <catch2/catch_test_macros.hpp> 10 11 #define TEST(...) TEST_CASE("[ErrorHandlingTests] " __VA_ARGS__) 12 13 using namespace SFS; 14 using namespace SFS::details; 15 16 namespace 17 { 18 Result TestSFS_Catch_Return_bad_alloc() 19 try 20 { 21 throw std::bad_alloc(); 22 } 23 SFS_CATCH_RETURN(); 24 25 class MyException : public std::exception 26 { 27 }; 28 29 Result TestSFS_Catch_Return_std_exception() 30 try 31 { 32 throw MyException(); 33 } 34 SFS_CATCH_RETURN(); 35 36 Result TestSFS_Catch_Return_unknown() 37 try 38 { 39 throw std::error_code(); 40 } 41 SFS_CATCH_RETURN(); 42 } // namespace 43 44 TEST("Testing ErrorHandling's SFS_CATCH_RETURN()") 45 { 46 REQUIRE(TestSFS_Catch_Return_bad_alloc() == Result::OutOfMemory); 47 REQUIRE(TestSFS_Catch_Return_std_exception() == Result::Unexpected); 48 REQUIRE(TestSFS_Catch_Return_unknown() == Result::Unexpected); 49 } 50 51 namespace 52 { 53 void TestSFS_Catch_Log_Rethrow_bad_alloc(const ReportingHandler& handler) 54 try 55 { 56 throw std::bad_alloc(); 57 } 58 SFS_CATCH_LOG_RETHROW(handler); 59 60 void TestSFS_Catch_Log_Rethrow_SFSException(const ReportingHandler& handler) 61 try 62 { 63 throw SFS::details::SFSException(Result::Unexpected); 64 } 65 SFS_CATCH_LOG_RETHROW(handler); 66 } // namespace 67 68 TEST("Testing ErrorHandling's SFS_CATCH_LOG_RETHROW()") 69 { 70 ReportingHandler handler; 71 bool called = false; 72 handler.SetLoggingCallback([&](const auto&) { called = true; }); 73 74 SECTION("Test that SFS_CATCH_LOG_RETHROW does not rethrow if not SFSException") 75 { 76 REQUIRE_THROWS_AS(TestSFS_Catch_Log_Rethrow_bad_alloc(handler), std::bad_alloc); 77 REQUIRE(!called); 78 } 79 80 SECTION("Test that SFS_CATCH_LOG_RETHROW rethrows and logs if SFSException") 81 { 82 REQUIRE_THROWS_AS(TestSFS_Catch_Log_Rethrow_SFSException(handler), SFSException); 83 REQUIRE(called); 84 } 85 } 86 87 namespace 88 { 89 Result TestSFS_ReturnIfFailed(const Result& result, const Result& ifNotFailed = Result::Success) 90 { 91 RETURN_IF_FAILED(result); 92 return ifNotFailed; 93 } 94 } // namespace 95 96 TEST("Testing ErrorHandling's RETURN_IF_FAILED()") 97 { 98 SECTION("Test that RETURN_IF_FAILED returns the result if it is a failure") 99 { 100 REQUIRE(TestSFS_ReturnIfFailed(Result::Code::Unexpected) == Result::Code::Unexpected); 101 } 102 103 SECTION("Test that RETURN_IF_FAILED does not return if the result is a success") 104 { 105 REQUIRE(TestSFS_ReturnIfFailed(Result::Code::Success) == Result::Code::Success); 106 REQUIRE(TestSFS_ReturnIfFailed(Result::Code::Success, Result::Code::Unexpected) == Result::Code::Unexpected); 107 } 108 } 109 110 namespace 111 { 112 Result TestSFS_ReturnIfFailedLog(const ReportingHandler& handler, 113 const Result& result, 114 const Result& ifNotFailed = Result::Success) 115 { 116 RETURN_IF_FAILED_LOG(result, handler); 117 return ifNotFailed; 118 } 119 } // namespace 120 121 TEST("Testing ErrorHandling's RETURN_IF_FAILED_LOG()") 122 { 123 ReportingHandler handler; 124 bool called = false; 125 handler.SetLoggingCallback([&](const auto&) { called = true; }); 126 127 SECTION("Test that RETURN_IF_FAILED_LOG returns and logs if the result is a failure") 128 { 129 REQUIRE(TestSFS_ReturnIfFailedLog(handler, Result::Code::Unexpected) == Result::Code::Unexpected); 130 REQUIRE(called); 131 } 132 133 SECTION("Test that RETURN_IF_FAILED_LOG does not return and log if the result is a success") 134 { 135 REQUIRE(TestSFS_ReturnIfFailedLog(handler, Result::Code::Success) == Result::Code::Success); 136 REQUIRE(!called); 137 } 138 } 139 140 TEST("Testing ErrorHandling's LOG_IF_FAILED()") 141 { 142 ReportingHandler handler; 143 bool called = false; 144 handler.SetLoggingCallback([&](const auto&) { called = true; }); 145 146 SECTION("Test that LOG_IF_FAILED logs if the result is a failure") 147 { 148 LOG_IF_FAILED(Result(Result::Unexpected), handler); 149 REQUIRE(called); 150 } 151 152 SECTION("Test that LOG_IF_FAILED does not log if the result is a success") 153 { 154 LOG_IF_FAILED(Result(Result::Success), handler); 155 REQUIRE(!called); 156 } 157 } 158 159 namespace 160 { 161 void TestSFS_ThrowLog(const ReportingHandler& handler, const Result& result) 162 { 163 THROW_LOG(result, handler); 164 } 165 } // namespace 166 167 TEST("Testing ErrorHandling's THROW_LOG()") 168 { 169 INFO("Test that ErrorHandling's THROW_LOG throws and logs the result"); 170 171 ReportingHandler handler; 172 bool called = false; 173 handler.SetLoggingCallback([&](const auto&) { called = true; }); 174 175 REQUIRE_THROWS_AS(TestSFS_ThrowLog(handler, Result::Code::Unexpected), SFSException); 176 REQUIRE(called); 177 } 178 179 namespace 180 { 181 void TestSFS_ThrowIfFailedLog(const ReportingHandler& handler, const Result& result) 182 { 183 THROW_IF_FAILED_LOG(result, handler); 184 } 185 } // namespace 186 187 TEST("Testing ErrorHandling's THROW_IF_FAILED_LOG()") 188 { 189 ReportingHandler handler; 190 bool called = false; 191 handler.SetLoggingCallback([&](const auto&) { called = true; }); 192 193 SECTION("Test that ErrorHandling's THROW_IF_FAILED_LOG throws and logs the result if it is a failure") 194 { 195 REQUIRE_THROWS_AS(TestSFS_ThrowIfFailedLog(handler, Result::Code::Unexpected), SFSException); 196 REQUIRE(called); 197 } 198 199 SECTION("Test that ErrorHandling's THROW_IF_FAILED_LOG does not throw and log the result if it is not a failure") 200 { 201 REQUIRE_NOTHROW(TestSFS_ThrowIfFailedLog(handler, Result::Code::Success)); 202 REQUIRE(!called); 203 } 204 } 205 206 TEST("Testing ErrorHandling's THROW_CODE_IF()") 207 { 208 SECTION("Test that THROW_CODE_IF throws if the condition is true") 209 { 210 REQUIRE_THROWS_AS([]() { THROW_CODE_IF(Unexpected, true); }(), SFSException); 211 } 212 213 SECTION("Test that THROW_CODE_IF does not throw if the condition is false") 214 { 215 REQUIRE_NOTHROW([]() { THROW_CODE_IF(Unexpected, false); }()); 216 } 217 } 218 219 TEST("Testing ErrorHandling's THROW_CODE_IF_LOG()") 220 { 221 ReportingHandler handler; 222 bool called = false; 223 handler.SetLoggingCallback([&](const auto&) { called = true; }); 224 225 SECTION("Test that THROW_CODE_IF_LOG throws and logs the result if the condition is true") 226 { 227 REQUIRE_THROWS_AS([&handler]() { THROW_CODE_IF_LOG(Unexpected, true, handler); }(), SFSException); 228 REQUIRE(called); 229 } 230 231 SECTION("Test that THROW_CODE_IF_LOG does not throw and log if the condition is false") 232 { 233 REQUIRE_NOTHROW([&handler]() { THROW_CODE_IF_LOG(Unexpected, false, handler); }()); 234 REQUIRE(!called); 235 } 236 } 237 238 TEST("Testing ErrorHandling's THROW_CODE_IF_NOT_LOG()") 239 { 240 ReportingHandler handler; 241 bool called = false; 242 handler.SetLoggingCallback([&](const auto&) { called = true; }); 243 244 SECTION("Test that THROW_CODE_IF_NOT_LOG throws and logs the result if the condition is false") 245 { 246 REQUIRE_THROWS_AS([&handler]() { THROW_CODE_IF_NOT_LOG(Unexpected, false, handler); }(), SFSException); 247 REQUIRE(called); 248 } 249 250 SECTION("Test that THROW_CODE_IF_NOT_LOG does not throw and log if the condition is true") 251 { 252 REQUIRE_NOTHROW([&handler]() { THROW_CODE_IF_NOT_LOG(Unexpected, true, handler); }()); 253 REQUIRE(!called); 254 } 255 }