Commit f39e3fea authored by Dominik Charousset's avatar Dominik Charousset

Fix build on GCC/Linux

parent 7a77a40e
......@@ -30,7 +30,7 @@ IndentCaseLabels: true
IndentPPDirectives: AfterHash
IndentWidth: 2
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
KeepEmptyLinesAtTheStartOfBlocks: false
Language: Cpp
MacroBlockBegin: "^BEGIN_STATE$|CAF_BEGIN_TYPE_ID_BLOCK"
MacroBlockEnd: "^END_STATE$|CAF_END_TYPE_ID_BLOCK"
......
......@@ -90,6 +90,7 @@ config = [
tags: ['docker', 'LeakSanitizer'],
builds: ['debug'],
extraBuildFlags: [
'BUILD_SHARED_LIBS:BOOL=OFF',
'CAF_LOG_LEVEL:STRING=TRACE',
'CAF_ENABLE_ROBOT_TESTS:BOOL=ON',
'CAF_SANITIZERS:STRING=address',
......@@ -104,9 +105,9 @@ config = [
tags: ['docker', 'UBSanitizer'],
builds: ['debug'],
extraBuildFlags: [
'BUILD_SHARED_LIBS:BOOL=OFF',
'CAF_LOG_LEVEL:STRING=TRACE',
'CAF_ENABLE_ROBOT_TESTS:BOOL=ON',
'BUILD_SHARED_LIBS:BOOL=OFF',
'CAF_SANITIZERS:STRING=address,undefined',
],
extraBuildEnv: [
......
......@@ -17,7 +17,9 @@ namespace caf::test {
/// structure.
class CAF_TEST_EXPORT block {
public:
block(context_ptr ctx, int id, std::string_view description,
// Note: the context owns the block. Hence, we can use a raw pointer for
// pointing back to the parent object here.
block(context* ctx, int id, std::string_view description,
const detail::source_location& loc);
virtual ~block();
......@@ -100,7 +102,7 @@ public:
protected:
std::unique_ptr<block>& get_nested_or_construct(int id);
context_ptr ctx_;
context* ctx_;
int id_ = 0;
std::string_view description_;
bool active_ = false;
......
......@@ -16,10 +16,10 @@
namespace caf::test {
/// Represents the exeuction context of a test. The context stores all steps of
/// Represents the execution context of a test. The context stores all steps of
/// the test and the current execution stack. The context persists across
/// multiple runs of the test in order to select one execution path per run.
class CAF_TEST_EXPORT context : public std::enable_shared_from_this<context> {
class CAF_TEST_EXPORT context {
public:
/// Returns whether the test is still active. A test is active as long as
/// no unwinding is in progress.
......@@ -42,9 +42,7 @@ public:
/// Checks whether `ptr` has been activated this run, i.e., whether we can
/// find it in `unwind_stack`.
bool activated(block* ptr) {
return std::find(path.begin(), path.end(), ptr) != path.end();
}
bool activated(block* ptr) const noexcept;
/// Stores the current execution stack for the run.
std::vector<block*> call_stack;
......@@ -55,7 +53,6 @@ public:
/// Stores all steps that we have reached at least once during the run.
std::vector<block*> path;
/// Stores all steps of the test with their run-time ID.
std::map<int, std::unique_ptr<block>> steps;
......@@ -64,7 +61,7 @@ public:
const detail::source_location& loc) {
auto& result = steps[id];
if (!result) {
result = std::make_unique<T>(shared_from_this(), id, description, loc);
result = std::make_unique<T>(this, id, description, loc);
}
return static_cast<T*>(result.get());
}
......
......@@ -87,4 +87,4 @@ private:
detail::source_location loc_;
};
} // namespace caf::test
} // namespace caf::test
......@@ -18,7 +18,6 @@ namespace caf::test {
/// A registry for our factories.
class registry {
public:
/// Maps test names to factories. Elements are sorted by the order of their
/// registration.
using tests_map = unordered_flat_map<std::string_view, factory*>;
......
......@@ -16,7 +16,7 @@ public:
static constexpr block_type type_token = block_type::when;
then* get_then(int id, std::string_view description,
const detail::source_location& loc) override ;
const detail::source_location& loc) override;
and_then* get_and_then(int id, std::string_view description,
const detail::source_location& loc) override;
......
......@@ -7,9 +7,11 @@
#include "caf/test/context.hpp"
#include "caf/test/nesting_error.hpp"
#include <algorithm>
namespace caf::test {
block::block(context_ptr ctx, int id, std::string_view description,
block::block(context* ctx, int id, std::string_view description,
const detail::source_location& loc)
: ctx_(ctx), id_(id), description_(description), loc_(loc) {
// nop
......
......@@ -7,6 +7,8 @@
#include "caf/test/block.hpp"
#include "caf/test/reporter.hpp"
#include <algorithm>
namespace caf::test {
void context::on_enter(block* ptr) {
......@@ -22,6 +24,10 @@ void context::on_leave(block* ptr) {
reporter::instance->end_step(ptr);
}
bool context::activated(block* ptr) const noexcept {
return std::find(path.begin(), path.end(), ptr) != path.end();
}
bool context::can_run() {
auto pred = [](auto& kvp) { return kvp.second->can_run(); };
return !steps.empty() && std::any_of(steps.begin(), steps.end(), pred);
......
......@@ -39,4 +39,4 @@ scope given::commit() {
return scope{this};
}
} // namespace caf::test
} // namespace caf::test
......@@ -32,9 +32,9 @@ nesting_error::raise_impl(nesting_error::code what, block_type parent,
#ifdef CAF_ENABLE_EXCEPTIONS
throw nesting_error{what, parent, child, loc};
#else
auto msg = nesting_error{code::not_allowed, parent, child}.message();
fprintf(stderr, "[FATAL] critical error (%s:%d): %s\n", msg.c_str(),
loc.file_name, static_cast<int>(loc.line));
auto msg = nesting_error{what, parent, child, loc}.message();
fprintf(stderr, "[FATAL] critical error (%s:%d): %s\n", loc.file_name(),
static_cast<int>(loc.line()), msg.c_str());
abort();
#endif
}
......
......@@ -34,6 +34,12 @@ namespace {
/// - $C(cyan text)
/// - $0 turns off coloring completely (enter verbatim mode)
struct colorizing_iterator {
using difference_type = void;
using value_type = void;
using pointer = void;
using reference = void;
using iterator_category = std::output_iterator_tag;
enum mode_t {
normal,
read_color,
......@@ -240,7 +246,7 @@ public:
failed_tests_.push_back(current_test_);
suite_stats_ += test_stats_;
current_ctx_.reset();
if(live_)
if (live_)
std::cout << std::endl;
}
......@@ -252,7 +258,7 @@ public:
CAF_RAISE_ERROR(std::logic_error, "begin_test was not called");
format_to(colored(), "$C(Suite): $0{}\n", current_suite_);
indent_ = 2;
live_= true;
live_ = true;
for (auto* frame : current_ctx_->call_stack)
begin_step(frame);
}
......
......@@ -22,33 +22,38 @@ namespace caf::test {
namespace {
config_option_set make_option_set() {
config_option_set make_option_set() {
config_option_set result;
config_option_adder{result, "global"}
.add<bool>("help,h?", "print this help text")
.add<bool>("available-suites,a", "print all available suites")
.add<bool>("help,h?", "print this help text")
.add<bool>("no-colors,n", "disable coloring (ignored on Windows)")
.add<size_t>("max-runtime,r", "set a maximum runtime in seconds")
.add<std::string>("suites,s", "regex for selecting suites")
.add<std::string>("available-tests,A", "print tests for a suite")
.add<std::string>("verbosity,v", "set verbosity level of the reporter");
return result;
}
}
std::optional<unsigned> parse_log_level(std::string_view x) {
if (x == "quiet")
std::optional<unsigned> parse_log_level(std::string_view x) {
// Note: the 0-5 aliases are for compatibility with the old unit testing
// framework.
if (x == "quiet" || x == "0")
return CAF_LOG_LEVEL_QUIET;
if (x == "error")
if (x == "error" || x == "1")
return CAF_LOG_LEVEL_ERROR;
if (x == "warning")
if (x == "warning" || x == "2")
return CAF_LOG_LEVEL_WARNING;
if (x == "info")
if (x == "info" || x == "3")
return CAF_LOG_LEVEL_INFO;
if (x == "debug")
if (x == "debug" || x == "4")
return CAF_LOG_LEVEL_DEBUG;
if (x == "trace")
if (x == "trace" || x == "5")
return CAF_LOG_LEVEL_TRACE;
return {};
}
}
}//
} // namespace
runner::runner() : suites_(caf::test::registry::suites()) {
// nop
......@@ -67,6 +72,7 @@ int runner::run(int argc, char** argv) {
default_reporter->begin_suite(suite_name);
for (auto [test_name, factory_instance] : suite) {
auto state = std::make_shared<context>();
#ifdef CAF_ENABLE_EXCEPTIONS
try {
do {
default_reporter->begin_test(state, test_name);
......@@ -85,6 +91,15 @@ int runner::run(int argc, char** argv) {
default_reporter->unhandled_exception("unknown exception type");
default_reporter->end_test();
}
#else
do {
default_reporter->begin_test(state, test_name);
auto def = factory_instance->make(state);
def->run();
default_reporter->end_test();
state->clear_stacks();
} while (state->can_run());
#endif
}
default_reporter->end_suite(suite_name);
}
......@@ -100,8 +115,8 @@ runner::parse_cli_result runner::parse_cli(int argc, char** argv) {
auto res = options.parse(cfg, args_cpy);
auto err = std::ostream_iterator<char>{std::cerr};
if (res.first != caf::pec::success) {
format_to(err, "error while parsing argument '{}': {}\n\n{}\n",
*res.second, to_string(res.first), options.help_text());
format_to(err, "error while parsing argument '{}': {}\n\n{}\n", *res.second,
to_string(res.first), options.help_text());
return {false, true};
}
if (get_or(cfg, "help", false)) {
......
......@@ -14,35 +14,35 @@
namespace caf::test {
block_type scenario::type() const noexcept {
block_type scenario::type() const noexcept {
return block_type::scenario;
}
}
given* scenario::get_given(int id, std::string_view description,
given* scenario::get_given(int id, std::string_view description,
const detail::source_location& loc) {
return get_nested<given>(id, description, loc);
}
}
and_given* scenario::get_and_given(int id, std::string_view description,
and_given* scenario::get_and_given(int id, std::string_view description,
const detail::source_location& loc) {
return get_nested<and_given>(id, description, loc);
}
}
when* scenario::get_when(int id, std::string_view description,
when* scenario::get_when(int id, std::string_view description,
const detail::source_location& loc) {
return get_nested<when>(id, description, loc);
}
}
and_when* scenario::get_and_when(int id, std::string_view description,
and_when* scenario::get_and_when(int id, std::string_view description,
const detail::source_location& loc) {
return get_nested<and_when>(id, description, loc);
}
}
scope scenario::commit() {
scope scenario::commit() {
if (!ctx_->active() || !can_run())
return {};
enter();
return scope{this};
}
}
} // namespace caf::test
......@@ -44,7 +44,6 @@ SCENARIO("each run starts with fresh local variables") {
}
}
struct int_fixture {
int my_int = 0;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment