generated from sdaveb/gnu-automake-project
parent
323448ee9d
commit
400be25557
@ -1,37 +0,0 @@
|
||||
---
|
||||
BasedOnStyle: Mozilla
|
||||
Language: Cpp
|
||||
|
||||
IndentWidth: 8
|
||||
UseTab: AlignWithSpaces
|
||||
ColumnLimit: 81
|
||||
AccessModifierOffset: -4
|
||||
BinPackParameters: true
|
||||
AlwaysBreakAfterDefinitionReturnType: TopLevel
|
||||
AlwaysBreakAfterReturnType: None
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 4
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: MultiLine
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
|
||||
BeforeCatch: true
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
|
||||
---
|
@ -20,7 +20,8 @@ namespace engine {
|
||||
class Exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
Exception(const std::string& message, const_c_string file, unsigned line)
|
||||
explicit Exception(const std::string& message, const_c_string file,
|
||||
unsigned line)
|
||||
: std::runtime_error(message), error_message(file)
|
||||
{
|
||||
error_message += ":" + std::to_string(line) + " : " + message;
|
||||
@ -32,14 +33,13 @@ class Exception : public std::runtime_error
|
||||
static void rethrow(const std::string& message, const_c_string file,
|
||||
unsigned line);
|
||||
|
||||
static void handler(const std::exception& ex,
|
||||
const std::string& caller_name = "");
|
||||
|
||||
static void backtrace(const std::exception& ex);
|
||||
|
||||
static void handler(const std::exception& ex,
|
||||
const std::string& caller_name = "");
|
||||
const_c_string what() const noexcept { return error_message.c_str(); }
|
||||
|
||||
private:
|
||||
protected:
|
||||
inline static std::reference_wrapper<std::ostream> output = std::cerr;
|
||||
std::string error_message;
|
||||
};
|
||||
@ -54,6 +54,17 @@ catch (...) {
|
||||
std::throw_with_nested(Exception(message, file, line));
|
||||
}
|
||||
|
||||
inline void
|
||||
Exception::backtrace(const std::exception& ex)
|
||||
try {
|
||||
auto& out = output.get();
|
||||
out << ex.what() << std::endl;
|
||||
std::rethrow_if_nested(ex);
|
||||
}
|
||||
catch (std::exception& nested_ex) {
|
||||
backtrace(nested_ex);
|
||||
}
|
||||
|
||||
inline void
|
||||
Exception::handler(const std::exception& ex, const std::string& caller_name)
|
||||
try {
|
||||
@ -72,29 +83,18 @@ catch (...) {
|
||||
out << "Fatal error in Exception::handler! Terminating!" << std::endl;
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
inline void
|
||||
Exception::backtrace(const std::exception& ex)
|
||||
try {
|
||||
auto& out = output.get();
|
||||
out << ex.what() << std::endl;
|
||||
std::rethrow_if_nested(ex);
|
||||
}
|
||||
catch (std::exception& nested_ex) {
|
||||
backtrace(nested_ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Shorthand for throwing an Exception with file and line info using macros
|
||||
#define throw_exception(message) \
|
||||
throw engine::Exception(message, __FILE__, __LINE__);
|
||||
throw engine::Exception(message, __FILE__, __LINE__)
|
||||
|
||||
// Shorthand for rethrowing and Exception with file and line info using macros
|
||||
#define rethrow_exception(message) \
|
||||
engine::Exception::rethrow(message, __FILE__, __LINE__);
|
||||
engine::Exception::rethrow(message, __FILE__, __LINE__)
|
||||
|
||||
// Shorthand for handling an exception, including a backtrace
|
||||
#define handle_exception(ex) engine::Exception::handler(ex, __func__);
|
||||
#define handle_exception(ex) engine::Exception::handler(ex, __func__)
|
||||
|
||||
// clang-format off
|
||||
// vim: set foldmethod=marker foldmarker=#region,#endregion textwidth=80 ts=8 sts=0 sw=8 noexpandtab ft=cpp.doxygen :
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "test-includes.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@ -17,8 +18,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include "src/engine/Exception.hpp"
|
||||
|
||||
using namespace engine;
|
||||
#include "src/engine/types.hpp"
|
||||
|
||||
BEGIN_TEST_SUITE("Exception.tests")
|
||||
|
||||
@ -26,39 +26,112 @@ void
|
||||
some_random_function()
|
||||
try {
|
||||
|
||||
throw_exception("Inner Exception")
|
||||
throw_exception("Inner Exception");
|
||||
}
|
||||
catch (std::exception& ex) {
|
||||
rethrow_exception("Rethrowing Inner");
|
||||
}
|
||||
|
||||
CATCH_CASE("Exception collects a backtrace that can be unwound un handler "
|
||||
"static method")
|
||||
class ExceptionInspector : public engine::Exception
|
||||
{
|
||||
private:
|
||||
explicit ExceptionInspector(engine::Exception& other)
|
||||
: engine::Exception(other)
|
||||
{
|
||||
}
|
||||
virtual ~ExceptionInspector() {}
|
||||
|
||||
public:
|
||||
static std::ostream& get_ostream(engine::Exception& instance)
|
||||
{
|
||||
return instance.output;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestFixture
|
||||
{
|
||||
TestFixture() : test_subject("Test", __FILE__, __LINE__) {}
|
||||
~TestFixture() = default;
|
||||
|
||||
engine::Exception test_subject;
|
||||
};
|
||||
|
||||
CATCH_CASE("Construction")
|
||||
try {
|
||||
// Test ptr construciton as well as compiler macros
|
||||
auto* ptr = new engine::Exception("Hello", __FILE__, __LINE__);
|
||||
|
||||
REQUIRE(nullptr != ptr);
|
||||
|
||||
// Test macros from header file that construct Exceptions
|
||||
REQUIRE_THROWS_AS(throw_exception("Message"), engine::Exception);
|
||||
}
|
||||
catch (...) {
|
||||
throw std::runtime_error("Error occurred during construction");
|
||||
}
|
||||
|
||||
FIXTURE_CASE("Output stream is interchangeable")
|
||||
try {
|
||||
std::stringstream buffer;
|
||||
|
||||
REQUIRE(&std::cerr == &ExceptionInspector::get_ostream(test_subject));
|
||||
test_subject.set_ostream(buffer);
|
||||
|
||||
REQUIRE(&buffer == &ExceptionInspector::get_ostream(test_subject));
|
||||
}
|
||||
catch (...) {
|
||||
throw std::runtime_error("Error occurred during set_outputstream test");
|
||||
}
|
||||
|
||||
FIXTURE_CASE("rethrow() behaves as expected and nests the exceptions")
|
||||
{
|
||||
REQUIRE(true == false);
|
||||
}
|
||||
FIXTURE_CASE("backtrace() behaves as expected and outputs a backtrace")
|
||||
{
|
||||
REQUIRE(true == false);
|
||||
}
|
||||
|
||||
FIXTURE_CASE(
|
||||
"handler() behaves as expected and outputs exception text to ostream")
|
||||
{
|
||||
REQUIRE(true == false);
|
||||
}
|
||||
|
||||
FIXTURE_CASE("what() returns the error message contents with file and lineinfo")
|
||||
{
|
||||
const auto result = test_subject.what();
|
||||
|
||||
REQUIRE(0 == std::strcmp("../src/tests/Exception.tests.cpp:54 : Test",
|
||||
result));
|
||||
}
|
||||
|
||||
CATCH_CASE("Integration Tests: handler method can generate stacktrace.")
|
||||
{
|
||||
std::stringstream buffer;
|
||||
std::vector<std::string> result_lines;
|
||||
std::vector<std::string> output_lines;
|
||||
|
||||
engine::Exception::set_ostream(buffer);
|
||||
|
||||
Exception::set_ostream(buffer);
|
||||
try {
|
||||
some_random_function();
|
||||
}
|
||||
catch (Exception& ex) {
|
||||
catch (engine::Exception& ex) {
|
||||
handle_exception(ex);
|
||||
engine::Exception::set_ostream(std::cerr);
|
||||
}
|
||||
buffer.flush();
|
||||
|
||||
for (std::string line; std::getline(buffer, line, '\n');) {
|
||||
result_lines.push_back(line);
|
||||
output_lines.push_back(line);
|
||||
}
|
||||
|
||||
REQUIRE(result_lines[2].find("Backtrace:") != std::string::npos);
|
||||
REQUIRE(result_lines[3].find("Exception.tests.cpp") !=
|
||||
std::string::npos);
|
||||
REQUIRE(result_lines[3].find("Rethrowing Inner") != std::string::npos);
|
||||
REQUIRE(result_lines[4].find(
|
||||
"tests/Exception.tests.cpp:29 : Inner Exception") !=
|
||||
REQUIRE(output_lines[2].find("Backtrace:") != std::string::npos);
|
||||
REQUIRE(output_lines[3].find("Exception.tests.cpp") !=
|
||||
std::string::npos);
|
||||
REQUIRE(output_lines[3].find("Rethrowing Inner") != std::string::npos);
|
||||
REQUIRE(output_lines[4].find("Inner Exception") != std::string::npos);
|
||||
}
|
||||
|
||||
END_TEST_SUITE
|
||||
|
||||
// clang-format off
|
||||
|
Loading…
Reference in New Issue
Block a user