Unverified Commit 4c684ddf authored by Shariar Azad Riday's avatar Shariar Azad Riday Committed by GitHub

Add require function for all predicates

parent 9ebf640e
...@@ -30,7 +30,7 @@ caf_add_component( ...@@ -30,7 +30,7 @@ caf_add_component(
caf/test/nesting_error.cpp caf/test/nesting_error.cpp
caf/test/registry.cpp caf/test/registry.cpp
caf/test/reporter.cpp caf/test/reporter.cpp
caf/test/requirement_error.cpp caf/test/requirement_failed.cpp
caf/test/runnable.cpp caf/test/runnable.cpp
caf/test/runner.cpp caf/test/runner.cpp
caf/test/scenario.cpp caf/test/scenario.cpp
......
...@@ -386,6 +386,19 @@ public: ...@@ -386,6 +386,19 @@ public:
' ', indent_, location.file_name(), location.line(), msg); ' ', indent_, location.file_name(), location.line(), msg);
} }
void print_error(std::string_view msg,
const detail::source_location& location) override {
using detail::format_to;
if (level_ < CAF_LOG_LEVEL_ERROR)
return;
set_live();
format_to(colored(),
"{0:{1}}$R(error):\n"
"{0:{1}} loc: $C({2}):$Y({3})$0\n"
"{0:{1}} msg: {4}\n",
' ', indent_, location.file_name(), location.line(), msg);
}
unsigned verbosity(unsigned level) override { unsigned verbosity(unsigned level) override {
auto result = level_; auto result = level_;
level_ = level; level_ = level;
......
...@@ -75,6 +75,10 @@ public: ...@@ -75,6 +75,10 @@ public:
info(std::string_view msg, const detail::source_location& location) info(std::string_view msg, const detail::source_location& location)
= 0; = 0;
virtual void
print_error(std::string_view msg, const detail::source_location& location)
= 0;
/// Sets the verbosity level of the reporter and returns the previous value. /// Sets the verbosity level of the reporter and returns the previous value.
virtual unsigned verbosity(unsigned level) = 0; virtual unsigned verbosity(unsigned level) = 0;
......
...@@ -2,23 +2,22 @@ ...@@ -2,23 +2,22 @@
// the main distribution directory for license terms and copyright or visit // the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE. // https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#include "caf/test/requirement_error.hpp" #include "caf/test/requirement_failed.hpp"
#include "caf/detail/format.hpp" #include "caf/detail/format.hpp"
namespace caf::test { namespace caf::test {
std::string requirement_error::message() const { std::string requirement_failed::message() const {
return detail::format("requirement failed at {}:{}", loc_.file_name(), return detail::format("requirement failed\n");
loc_.line());
} }
[[noreturn]] void [[noreturn]] void
requirement_error::raise_impl(const detail::source_location& loc) { requirement_failed::raise_impl(const detail::source_location& loc) {
#ifdef CAF_ENABLE_EXCEPTIONS #ifdef CAF_ENABLE_EXCEPTIONS
throw requirement_error{loc}; throw requirement_failed{loc};
#else #else
auto msg = requirement_error{loc}.message(); auto msg = requirement_failed{loc}.message();
fprintf(stderr, "[FATAL] critical error: %s\n", msg.c_str()); fprintf(stderr, "[FATAL] critical error: %s\n", msg.c_str());
abort(); abort();
#endif #endif
......
...@@ -13,11 +13,11 @@ namespace caf::test { ...@@ -13,11 +13,11 @@ namespace caf::test {
/// Thrown when a requirement check fails. When `CAF_ENABLE_EXCEPTIONS` is off, /// Thrown when a requirement check fails. When `CAF_ENABLE_EXCEPTIONS` is off,
/// the `raise` functions terminate the program instead. /// the `raise` functions terminate the program instead.
class CAF_TEST_EXPORT requirement_error { class CAF_TEST_EXPORT requirement_failed {
public: public:
constexpr requirement_error(const requirement_error&) noexcept = default; constexpr requirement_failed(const requirement_failed&) noexcept = default;
constexpr requirement_error& operator=(const requirement_error&) noexcept constexpr requirement_failed& operator=(const requirement_failed&) noexcept
= default; = default;
/// Returns a human-readable error message. /// Returns a human-readable error message.
...@@ -28,14 +28,14 @@ public: ...@@ -28,14 +28,14 @@ public:
return loc_; return loc_;
} }
/// Throws a `requirement_error` to indicate that requirement check failed. /// Throws a `requirement_failed` to indicate that requirement check failed.
[[noreturn]] static void raise(const detail::source_location& loc [[noreturn]] static void raise(const detail::source_location& loc
= detail::source_location::current()) { = detail::source_location::current()) {
raise_impl(loc); raise_impl(loc);
} }
private: private:
constexpr explicit requirement_error( constexpr explicit requirement_failed(
const detail::source_location& loc) noexcept const detail::source_location& loc) noexcept
: loc_(loc) { : loc_(loc) {
// nop // nop
......
...@@ -58,6 +58,11 @@ bool runnable::check(bool value, const detail::source_location& location) { ...@@ -58,6 +58,11 @@ bool runnable::check(bool value, const detail::source_location& location) {
return value; return value;
} }
void runnable::require(bool value, const detail::source_location& location) {
if (!check(value, location))
requirement_failed::raise(location);
}
runnable& runnable::current() { runnable& runnable::current() {
auto ptr = current_runnable; auto ptr = current_runnable;
if (!ptr) if (!ptr)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "caf/test/block_type.hpp" #include "caf/test/block_type.hpp"
#include "caf/test/fwd.hpp" #include "caf/test/fwd.hpp"
#include "caf/test/reporter.hpp" #include "caf/test/reporter.hpp"
#include "caf/test/requirement_error.hpp" #include "caf/test/requirement_failed.hpp"
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/deep_to_string.hpp" #include "caf/deep_to_string.hpp"
...@@ -54,7 +54,7 @@ public: ...@@ -54,7 +54,7 @@ public:
} else { } else {
reporter::instance().fail(fwl.value, fwl.location); reporter::instance().fail(fwl.value, fwl.location);
} }
requirement_error::raise(fwl.location); requirement_failed::raise(fwl.location);
} }
/// Generates a message with the INFO severity level. /// Generates a message with the INFO severity level.
...@@ -162,6 +162,65 @@ public: ...@@ -162,6 +162,65 @@ public:
bool check(bool value, const detail::source_location& location bool check(bool value, const detail::source_location& location
= detail::source_location::current()); = detail::source_location::current());
/// Evaluates whether `lhs` and `rhs` are equal and fails otherwise.
template <class T0, class T1>
void require_eq(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_eq(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `lhs` and `rhs` are unequal and fails otherwise.
template <class T0, class T1>
void require_ne(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_ne(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `lhs` is less than `rhs` and fails otherwise
template <class T0, class T1>
void require_lt(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_lt(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `lhs` less than or equal to `rhs` and fails otherwise.
template <class T0, class T1>
void require_le(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_le(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `lhs` is greater than `rhs` and fails otherwise.
template <class T0, class T1>
void require_gt(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_gt(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `lhs` greater than or equal to `rhs` and fails
/// otherwise.
template <class T0, class T1>
void require_ge(const T0& lhs, const T1& rhs,
const detail::source_location& location
= detail::source_location::current()) {
if (!check_ge(lhs, rhs, location))
requirement_failed::raise(location);
}
/// Evaluates whether `value` is `true` and fails otherwise.
void require(bool value, const detail::source_location& location
= detail::source_location::current());
/// Returns the `runnable` instance that is currently running. /// Returns the `runnable` instance that is currently running.
static runnable& current(); static runnable& current();
......
...@@ -170,7 +170,8 @@ int runner::run(int argc, char** argv) { ...@@ -170,7 +170,8 @@ int runner::run(int argc, char** argv) {
} catch (const nesting_error& ex) { } catch (const nesting_error& ex) {
default_reporter->unhandled_exception(ex.message(), ex.location()); default_reporter->unhandled_exception(ex.message(), ex.location());
default_reporter->end_test(); default_reporter->end_test();
} catch (const requirement_error& ex) { } catch (const requirement_failed& ex) {
default_reporter->print_error(ex.message(), ex.location());
default_reporter->end_test(); default_reporter->end_test();
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
default_reporter->unhandled_exception(ex.what()); default_reporter->unhandled_exception(ex.what());
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "caf/test/test.hpp" #include "caf/test/test.hpp"
#include "caf/test/caf_test_main.hpp" #include "caf/test/caf_test_main.hpp"
#include "caf/test/requirement_failed.hpp"
using caf::test::block_type; using caf::test::block_type;
...@@ -40,6 +41,52 @@ TEST("tests can contain different types of checks") { ...@@ -40,6 +41,52 @@ TEST("tests can contain different types of checks") {
info("this test had {} checks", rep.test_stats().total()); info("this test had {} checks", rep.test_stats().total());
} }
#ifdef CAF_ENABLE_EXCEPTIONS
TEST("tests fail when requirement errors occur") {
using caf::test::requirement_failed;
auto& rep = caf::test::reporter::instance();
SECTION("require_eq fails when lhs != rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_eq(1, 2); });
require_eq(1, 1);
}
SECTION("require_ne fails when lhs == rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_ne(1, 1); });
require_ne(1, 2);
}
SECTION("require_le fails when lhs > rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_le(2, 1); });
require_le(1, 2);
require_le(2, 2);
}
SECTION("require_lt fails when lhs >= rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_lt(2, 2); });
should_fail_with_exception<requirement_failed>(
[this]() { require_lt(2, 1); });
require_lt(1, 2);
}
SECTION("require_ge fails when lhs < rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_ge(1, 2); });
require_ge(2, 1);
require_ge(2, 2);
}
SECTION("require_gt fails when lhs <= rhs") {
should_fail_with_exception<requirement_failed>(
[this]() { require_gt(1, 1); });
should_fail_with_exception<requirement_failed>(
[this]() { require_gt(1, 2); });
require_gt(2, 1);
}
info("this test had {} checks", rep.test_stats().total());
}
#endif // CAF_ENABLE_EXCEPTIONS
TEST("failed checks increment the failed counter") { TEST("failed checks increment the failed counter") {
check_eq(1, 2); check_eq(1, 2);
auto stats = caf::test::reporter::instance().test_stats(); auto stats = caf::test::reporter::instance().test_stats();
......
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