Skip to content

Commit 4042135

Browse files
committed
Add custom what() description for exception
1 parent d8b72c4 commit 4042135

File tree

2 files changed

+46
-31
lines changed

2 files changed

+46
-31
lines changed

src/ystdlib/error_handling/TraceableException.hpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <exception>
55
#include <source_location>
6+
#include <string>
67
#include <system_error>
78

89
namespace ystdlib::error_handling {
@@ -19,15 +20,21 @@ namespace ystdlib::error_handling {
1920
*/
2021
class TraceableException : public std::exception, public std::source_location {
2122
public:
22-
// Constructor
23-
TraceableException(
23+
// Constructors
24+
explicit TraceableException(
2425
std::error_code error_code,
2526
std::source_location const& location = std::source_location::current()
27+
)
28+
: TraceableException{error_code, location.function_name(), location} {}
29+
30+
explicit TraceableException(
31+
std::error_code error_code,
32+
char const* what,
33+
std::source_location const& location = std::source_location::current()
2634
)
2735
: std::source_location{location},
28-
m_error_code{error_code} {
29-
m_what = std::string{function_name()} + " failed.";
30-
}
36+
m_error_code{error_code},
37+
m_what{what} {}
3138

3239
// Methods
3340
[[nodiscard]] auto error_code() const -> std::error_code { return m_error_code; }

src/ystdlib/error_handling/test-TraceableException.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <cassert>
2+
#include <string>
13
#include <system_error>
24

35
#include <ystdlib/error_handling/TraceableException.hpp>
@@ -7,19 +9,24 @@
79
#include "test-Defs.hpp"
810

911
namespace {
12+
constexpr auto cCustomFailureDescription{"This operation has failed."};
13+
1014
class Worker {
1115
public:
1216
YSTDLIB_ERROR_HANDLING_DEFINE_TRACEABLE_EXCEPTION(OperationFailed);
1317

14-
static void execute_with_success() {
18+
static auto execute_with_success() -> void {
1519
throw OperationFailed(BinaryErrorCode{BinaryErrorCodeEnum::Success});
1620
}
1721

18-
static void execute_with_failure() {
19-
throw OperationFailed(BinaryErrorCode{BinaryErrorCodeEnum::Failure});
22+
static auto execute_with_failure() -> void {
23+
throw OperationFailed(
24+
BinaryErrorCode{BinaryErrorCodeEnum::Failure},
25+
cCustomFailureDescription
26+
);
2027
}
2128

22-
static void execute_with_invalid_args() {
29+
static auto execute_with_invalid_args() -> void {
2330
throw OperationFailed(std::make_error_code(std::errc::invalid_argument));
2431
}
2532
};
@@ -34,62 +41,63 @@ constexpr auto cExecuteWithInvalidArgsFunctionName{
3441
"static void {anonymous}::Worker::execute_with_invalid_args()"
3542
};
3643
constexpr auto cInvalidArgsErrorMsg{"Invalid argument"};
37-
constexpr auto cExecuteWithSuccessLineNumber{15};
38-
constexpr auto cExecuteWithFailureLineNumber{19};
39-
constexpr auto cExecuteWithInvalidArgsLineNumber{23};
44+
constexpr auto cExecuteWithSuccessLineNumber{19};
45+
constexpr auto cExecuteWithFailureLineNumber{26};
46+
constexpr auto cExecuteWithInvalidArgsLineNumber{30};
4047

4148
#ifdef SOURCE_PATH_SIZE
4249
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
4350
constexpr auto cRelativePathFileName{static_cast<char const*>(__FILE__) + SOURCE_PATH_SIZE};
4451
#else
4552
constexpr auto cRelativePathFileName{__FILE__};
4653
#endif
47-
} // namespace
4854

49-
TEST_CASE("test_traceable_exception_success", "[error_handling][TraceableException]") {
50-
ystdlib::error_handling::TraceableException success_exception{std::error_code{}};
55+
template <typename Callable>
56+
[[nodiscard]] auto capture_exception(Callable&& f) -> ystdlib::error_handling::TraceableException;
57+
58+
template <typename Callable>
59+
auto capture_exception(Callable&& f) -> ystdlib::error_handling::TraceableException {
5160
try {
52-
Worker::execute_with_success();
61+
std::forward<Callable>(f)();
5362
} catch (ystdlib::error_handling::TraceableException& e) {
54-
success_exception = e;
63+
return e;
5564
}
65+
assert(false && "Needs to pass in a workflow that throws.");
66+
return ystdlib::error_handling::TraceableException{std::error_code{}};
67+
}
68+
} // namespace
69+
70+
TEST_CASE("test_traceable_exception_success", "[error_handling][TraceableException]") {
71+
auto const success_exception{capture_exception(Worker::execute_with_success)};
5672
std::error_code const success_error_code{BinaryErrorCode{BinaryErrorCodeEnum::Success}};
5773
REQUIRE((success_error_code.category() == success_exception.error_code().category()));
5874
REQUIRE((success_error_code.value() == success_exception.error_code().value()));
5975
REQUIRE((cSuccessErrorMsg == success_exception.error_code().message()));
76+
REQUIRE((cExecuteWithSuccessFunctionName == std::string{success_exception.what()}));
6077
REQUIRE((cExecuteWithSuccessFunctionName == success_exception.function_name()));
6178
REQUIRE((cExecuteWithSuccessLineNumber == success_exception.line()));
6279
REQUIRE((cRelativePathFileName == success_exception.file_name()));
6380
}
6481

6582
TEST_CASE("test_traceable_exception_failure", "[error_handling][TraceableException]") {
66-
ystdlib::error_handling::TraceableException failure_exception{std::error_code{}};
67-
try {
68-
Worker::execute_with_failure();
69-
} catch (ystdlib::error_handling::TraceableException& e) {
70-
failure_exception = e;
71-
}
83+
auto const failure_exception{capture_exception(Worker::execute_with_failure)};
7284
std::error_code const failure_error_code{BinaryErrorCode{BinaryErrorCodeEnum::Failure}};
7385
REQUIRE((failure_error_code.category() == failure_exception.error_code().category()));
7486
REQUIRE((failure_error_code.value() == failure_exception.error_code().value()));
7587
REQUIRE((cFailureErrorMsg == failure_exception.error_code().message()));
88+
REQUIRE((cCustomFailureDescription == std::string{failure_exception.what()}));
7689
REQUIRE((cExecuteWithFailureFunctionName == failure_exception.function_name()));
7790
REQUIRE((cExecuteWithFailureLineNumber == failure_exception.line()));
7891
REQUIRE((cRelativePathFileName == failure_exception.file_name()));
7992
}
8093

8194
TEST_CASE("test_traceable_exception_invalid_args", "[error_handling][TraceableException]") {
82-
ystdlib::error_handling::TraceableException invalid_args_exception{std::error_code{}};
83-
try {
84-
Worker::execute_with_invalid_args();
85-
} catch (ystdlib::error_handling::TraceableException& e) {
86-
invalid_args_exception = e;
87-
}
88-
std::error_code const invalid_args_error_code{std::make_error_code(std::errc::invalid_argument)
89-
};
95+
auto const invalid_args_exception{capture_exception(Worker::execute_with_invalid_args)};
96+
auto const invalid_args_error_code{std::make_error_code(std::errc::invalid_argument)};
9097
REQUIRE((invalid_args_error_code.category() == invalid_args_exception.error_code().category()));
9198
REQUIRE((invalid_args_error_code.value() == invalid_args_exception.error_code().value()));
9299
REQUIRE((cInvalidArgsErrorMsg == invalid_args_exception.error_code().message()));
100+
REQUIRE((cExecuteWithInvalidArgsFunctionName == std::string{invalid_args_exception.what()}));
93101
REQUIRE((cExecuteWithInvalidArgsFunctionName == invalid_args_exception.function_name()));
94102
REQUIRE((cExecuteWithInvalidArgsLineNumber == invalid_args_exception.line()));
95103
REQUIRE((cRelativePathFileName == invalid_args_exception.file_name()));

0 commit comments

Comments
 (0)