X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/3156083fd0c328d46be22536720ae33e1ab48090..39c6313308afb248b140d98b8052f1b484549df2:/tests/tut/tut_assert.hpp diff --git a/tests/tut/tut_assert.hpp b/tests/tut/tut_assert.hpp index 7ee44bc2..c1959012 100644 --- a/tests/tut/tut_assert.hpp +++ b/tests/tut/tut_assert.hpp @@ -1,29 +1,34 @@ #ifndef TUT_ASSERT_H_GUARD #define TUT_ASSERT_H_GUARD +#include -#include "tut_exception.hpp" #include #include +#include +#include +#include #if defined(TUT_USE_POSIX) #include #include #endif +#include "tut_exception.hpp" + namespace tut { namespace detail { template - std::ostream &msg_prefix(std::ostream &str, const M &msg) + std::ostringstream &msg_prefix(std::ostringstream &str, const M &msg) { - std::stringstream ss; + std::ostringstream ss; ss << msg; if(!ss.str().empty()) { - str << ss.rdbuf() << ": "; + str << msg << ": "; } return str; @@ -83,7 +88,7 @@ void ensure_not(const M& msg, bool cond) * Tests two objects for being equal. * Throws if false. * - * NB: both T and Q must have operator << defined somewhere, or + * NB: both LHS and RHS must have operator << defined somewhere, or * client code will not compile at all! */ template @@ -91,42 +96,128 @@ void ensure_equals(const M& msg, const LHS& actual, const RHS& expected) { if (expected != actual) { - std::stringstream ss; + std::ostringstream ss; detail::msg_prefix(ss,msg) - << "expected '" + << "expected `" << expected - << "' actual '" + << "` actual `" << actual - << '\''; + << "`"; throw failure(ss.str()); } } -template -void ensure_equals(const LHS& actual, const RHS& expected) +/** + * Tests two pointers for being equal. + * Throws if false. + * + * NB: both T and Q must have operator << defined somewhere, or + * client code will not compile at all! + */ +template +void ensure_equals(const M& msg, const LHS * const actual, const RHS * const expected) { - ensure_equals("Values are not equal", actual, expected); + if (expected != actual) + { + std::ostringstream ss; + detail::msg_prefix(ss,msg) + << "expected `" + << (void*)expected + << "` actual `" + << (void*)actual + << "`"; + throw failure(ss.str()); + } } template -void ensure_equals(const M& msg, const double& actual, const double& expected, - const double& epsilon = std::numeric_limits::epsilon()) +void ensure_equals(const M& msg, const double& actual, const double& expected, const double& epsilon) { const double diff = actual - expected; - if ( !((diff <= epsilon) && (diff >= -epsilon )) ) + if ( (actual != expected) && !((diff <= epsilon) && (diff >= -epsilon )) ) { - std::stringstream ss; + std::ostringstream ss; detail::msg_prefix(ss,msg) << std::scientific << std::showpoint << std::setprecision(16) - << "expected " << expected - << " actual " << actual - << " with precision " << epsilon; + << "expected `" << expected + << "` actual `" << actual + << "` with precision `" << epsilon << "`"; throw failure(ss.str()); } } + +template +void ensure_equals(const M& msg, const double& actual, const double& expected) +{ + ensure_equals(msg, actual, expected, std::numeric_limits::epsilon()); +} + +template +void ensure_equals(const LHS& actual, const RHS& expected) +{ + ensure_equals("Values are not equal", actual, expected); +} + + +template +void ensure_equals(const std::string &msg, + const LhsIterator &lhs_begin, const LhsIterator &lhs_end, + const RhsIterator &rhs_begin, const RhsIterator &rhs_end) +{ + typename std::iterator_traits::difference_type lhs_size = std::distance(lhs_begin, lhs_end); + typename std::iterator_traits::difference_type rhs_size = std::distance(rhs_begin, rhs_end); + + if(lhs_size < rhs_size) + { + ensure_equals(msg + ": range is too short", lhs_size, rhs_size); + } + + if(lhs_size > rhs_size) + { + ensure_equals(msg + ": range is too long", lhs_size, rhs_size); + } + + assert(lhs_size == rhs_size); + + LhsIterator lhs_i = lhs_begin; + RhsIterator rhs_i = rhs_begin; + while( (lhs_i != lhs_end) && (rhs_i != rhs_end) ) + { + if(*lhs_i != *rhs_i) + { + std::ostringstream ss; + detail::msg_prefix(ss,msg) + << "expected `" << *rhs_i + << "` actual `" << *lhs_i + << "` at offset " << std::distance(lhs_begin, lhs_i); + throw failure(ss.str()); + } + + lhs_i++; + rhs_i++; + } + + assert(lhs_i == lhs_end); + assert(rhs_i == rhs_end); +} + +template +void ensure_equals(const LhsIterator &lhs_begin, const LhsIterator &lhs_end, + const RhsIterator &rhs_begin, const RhsIterator &rhs_end) +{ + ensure_equals("Ranges are not equal", lhs_begin, lhs_end, rhs_begin, rhs_end); +} + +template +void ensure_equals(const LhsType *lhs_begin, const LhsType *lhs_end, + const RhsType *rhs_begin, const RhsType *rhs_end) +{ + ensure_equals("Ranges are not equal", lhs_begin, lhs_end, rhs_begin, rhs_end); +} + /** * Tests two objects for being at most in given distance one from another. * Borders are excluded. @@ -143,15 +234,15 @@ void ensure_distance(const M& msg, const T& actual, const T& expected, const T& { if (expected-distance >= actual || expected+distance <= actual) { - std::stringstream ss; + std::ostringstream ss; detail::msg_prefix(ss,msg) - << " expected (" + << " expected `" << expected-distance - << " - " + << "` - `" << expected+distance - << ") actual '" + << "` actual `" << actual - << '\''; + << "`"; throw failure(ss.str()); } } @@ -169,7 +260,7 @@ void ensure_errno(const M& msg, bool cond) { #if defined(TUT_USE_POSIX) char e[512]; - std::stringstream ss; + std::ostringstream ss; detail::msg_prefix(ss,msg) << strerror_r(errno, e, sizeof(e)); throw failure(ss.str()); @@ -193,6 +284,20 @@ void fail(const M& msg) throw failure(msg); } +/** + * Mark test case as known failure and skip execution. + */ +void skip(const char* msg = "") +{ + throw skipped(msg); +} + +template +void skip(const M& msg) +{ + throw skipped(msg); +} + } // end of namespace }