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(
caf/test/nesting_error.cpp
caf/test/registry.cpp
caf/test/reporter.cpp
caf/test/requirement_error.cpp
caf/test/requirement_failed.cpp
caf/test/runnable.cpp
caf/test/runner.cpp
caf/test/scenario.cpp
......
......@@ -386,6 +386,19 @@ public:
' ', 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 {
auto result = level_;
level_ = level;
......
......@@ -75,6 +75,10 @@ public:
info(std::string_view msg, const detail::source_location& location)
= 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.
virtual unsigned verbosity(unsigned level) = 0;
......
......@@ -2,23 +2,22 @@
// the main distribution directory for license terms and copyright or visit
// 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"
namespace caf::test {
std::string requirement_error::message() const {
return detail::format("requirement failed at {}:{}", loc_.file_name(),
loc_.line());
std::string requirement_failed::message() const {
return detail::format("requirement failed\n");
}
[[noreturn]] void
requirement_error::raise_impl(const detail::source_location& loc) {
requirement_failed::raise_impl(const detail::source_location& loc) {
#ifdef CAF_ENABLE_EXCEPTIONS
throw requirement_error{loc};
throw requirement_failed{loc};
#else
auto msg = requirement_error{loc}.message();
auto msg = requirement_failed{loc}.message();
fprintf(stderr, "[FATAL] critical error: %s\n", msg.c_str());
abort();
#endif
......
......@@ -13,11 +13,11 @@ namespace caf::test {
/// Thrown when a requirement check fails. When `CAF_ENABLE_EXCEPTIONS` is off,
/// the `raise` functions terminate the program instead.
class CAF_TEST_EXPORT requirement_error {
class CAF_TEST_EXPORT requirement_failed {
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;
/// Returns a human-readable error message.
......@@ -28,14 +28,14 @@ public:
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
= detail::source_location::current()) {
raise_impl(loc);
}
private:
constexpr explicit requirement_error(
constexpr explicit requirement_failed(
const detail::source_location& loc) noexcept
: loc_(loc) {
// nop
......
......@@ -58,6 +58,11 @@ bool runnable::check(bool value, const detail::source_location& location) {
return value;
}
void runnable::require(bool value, const detail::source_location& location) {
if (!check(value, location))
requirement_failed::raise(location);
}
runnable& runnable::current() {
auto ptr = current_runnable;
if (!ptr)
......
......@@ -8,7 +8,7 @@
#include "caf/test/block_type.hpp"
#include "caf/test/fwd.hpp"
#include "caf/test/reporter.hpp"
#include "caf/test/requirement_error.hpp"
#include "caf/test/requirement_failed.hpp"
#include "caf/config.hpp"
#include "caf/deep_to_string.hpp"
......@@ -54,7 +54,7 @@ public:
} else {
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.
......@@ -162,6 +162,65 @@ public:
bool check(bool value, const detail::source_location& location
= 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.
static runnable& current();
......
......@@ -170,7 +170,8 @@ int runner::run(int argc, char** argv) {
} catch (const nesting_error& ex) {
default_reporter->unhandled_exception(ex.message(), ex.location());
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();
} catch (const std::exception& ex) {
default_reporter->unhandled_exception(ex.what());
......
......@@ -4,6 +4,7 @@
#include "caf/test/test.hpp"
#include "caf/test/caf_test_main.hpp"
#include "caf/test/requirement_failed.hpp"
using caf::test::block_type;
......@@ -40,6 +41,52 @@ TEST("tests can contain different types of checks") {
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") {
check_eq(1, 2);
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