Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
/Werk/devel/lumi/src/lib/test/test-helper.hpp

user defined literal for expected result strings.

user defined literal for expected result strings.On equality comparison to any other string convertible object, the difference to this expected string is printed to STDERR

CHECK (result23 == "[-100..100]"_expect);
/*
TEST-HELPER.hpp - collection of functions supporting unit testing
Copyright (C)
2009, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
*/
#ifndef LIB_TEST_TEST_HELPER_H
#define LIB_TEST_TEST_HELPER_H
#include "lib/symbol.hpp"
#include "lib/random.hpp"
#include <boost/lexical_cast.hpp>
#include <typeinfo>
#include <cstdlib>
#include <utility>
#include <limits>
#include <string>
#include <cmath>
namespace lib {
namespace test{
using lib::Literal;
using std::string;
using lib::rani;
constexpr auto ROUGH_PRECISION = pow (10, -3);
constexpr auto EPSILON_ULP = 5;
template<typename F, typename N>
bool >
roughEQ (F val, N target, F limit =ROUGH_PRECISION)
{
REQUIRE (0 < limit);
return abs (val - target) < limit * abs(target);
}
template<typename F>
F >
ulp (F val)
{
val = fabs (val);
const int exp = val < std::numeric_limits<F>::min()
? std::numeric_limits<F>::min_exponent - 1 // fixed exponent for subnormals
: std::ilogb (val);
auto scaledUlp = std::ldexp (std::numeric_limits<F>::epsilon(), exp);
ENSURE (F(0) < scaledUlp);
return scaledUlp;
}
template<typename F, typename N>
bool >
epsEQ (F val, N target, uint ulps =EPSILON_ULP)
{
return abs (val - target) < ulps * ulp<F> (target);
}
string
showSizeof (size_t siz, string name);
template<typename T>
inline string
showSizeof (T const* obj =0, CStr name =0)
{
return showSizeof (obj? sizeof(*obj) : sizeof(T),
name? name : util::typeStr(obj));
}
template<typename T>
string > // note:: force invocations with pointer to the first overload
showSizeof (T const& obj, CStr name =nullptr)
{
return showSizeof (&obj, name);
}
template<typename T>
inline string
showSizeof (CStr name)
{
return showSizeof<T> (nullptr, name);
}
template<typename R>
string
{
return std::is_lvalue_reference<R>::value? "REF"
: std::is_rvalue_reference<R>::value? "MOV"
: "VAL";
}
template<typename X>
struct TypeDebugger
{
static_assert (not sizeof(X), "### Type Debugging ###");
};
template<typename X>
void
typeDebugger(X&& x)
{
static_assert (not sizeof(X), "### Type Debugging ###");
}
namespace { // helper for printing type diagnostics
template<typename X>
struct TypeDiagnostics
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = "";
};
template<typename X>
struct TypeDiagnostics<const X>
{
using Type = X;
static constexpr auto prefix = "const ";
static constexpr auto postfix = "";
};
template<typename X>
struct TypeDiagnostics<X&>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = "&";
};
template<typename X>
struct TypeDiagnostics<X&&>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = " &&";
};
template<typename X>
struct TypeDiagnostics<X const&>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = " const&";
};
template<typename X>
struct TypeDiagnostics<X const&&>
{
using Type = X;
static constexpr auto prefix = "const ";
static constexpr auto postfix = " &&";
};
template<typename X>
struct TypeDiagnostics<X *>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = " *";
};
template<typename X>
struct TypeDiagnostics<const X *>
{
using Type = X;
static constexpr auto prefix = "const ";
static constexpr auto postfix = " *";
};
template<typename X>
struct TypeDiagnostics<const X * const>
{
using Type = X;
static constexpr auto prefix = "const ";
static constexpr auto postfix = " * const";
};
template<typename X>
struct TypeDiagnostics<X * const>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = " * const";
};
template<typename X>
struct TypeDiagnostics<X * const *>
{
using Type = X;
static constexpr auto prefix = "";
static constexpr auto postfix = " * const *";
};
}
template<typename X>
inline string
{
using Case = TypeDiagnostics<X>;
using Type = Case::Type;
return Case::prefix
+ meta::humanReadableTypeID (typeid(Type).name())
+ Case::postfix;
}
template<typename...TS>
string
{
return "<| " + ((showType<TS>()+", ") + ... + "|>");
}
template<typename... EMPTY>
inline string
{
return " :.";
}
template<typename XX, typename... XS>
inline string
showVariadicTypes (XX&& x, XS&&... xs)
{
return " :---#"
+ util::toString (1 + sizeof...(xs))
+ " -- Type: " + showType<XX&&>()
+ " \tAdr" + util::showAdr (x)
+ "\n"
+ showVariadicTypes (std::forward<XS>(xs)...);
}
randTime ()
{
return lib::time::Time (500 * rani(2), 1 + rani(600));
}
string randStr (size_t len);
class ExpectString
: public std::string
{
public:
using std::string::string;
ExpectString(std::string && s) : std::string{std::move(s)}{ }
ExpectString(std::string const& s) : std::string{s} { }
template<typename X>
friend bool
operator== (X const& x, ExpectString const& expected)
{
std::string actual{util::StringConv<X>::invoke (x)};
return expected.verify (actual);
}
template<typename X>
friend bool
operator== (ExpectString const& expected, X const& x)
{
std::string actual{util::StringConv<X>::invoke (x)};
return expected.verify (actual);
}
friend ExpectString
operator+ (std::string&& l, ExpectString&& r)
{
return ExpectString{(l+r).c_str()};
}
bool verify (std::string const& actual) const;
};
}} // namespace lib::test
operator""_expect (CStr lit, size_t siz)
{
return lib::test::ExpectString{lit, siz};
}
/* === test helper macros === */
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT) \
try \
{ \
ERRONEOUS_STATEMENT ; \
NOTREACHED("expected »%s« failure in: %s", \
#ERROR_ID, #ERRONEOUS_STATEMENT); \
} \
catch (lumiera::Error& ex) \
{ \
CHECK (ex.getID() \
== lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} );\
lumiera_error(); \
} \
catch (...) \
{ \
CHECK (lumiera_error_peek() \
== lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} ); \
lumiera_error(); \
}
#define VERIFY_FAIL(FAILURE_MSG, ERRONEOUS_STATEMENT) \
try \
{ \
ERRONEOUS_STATEMENT ; \
NOTREACHED("expected »%s«-failure in: %s" \
, FAILURE_MSG, #ERRONEOUS_STATEMENT);\
} \
catch (std::exception& sex) \
{ \
CHECK (util::contains (sex.what(), FAILURE_MSG) \
,"expected failure with »%s« -- but got: %s" \
,FAILURE_MSG, sex.what()); \
lumiera_error(); \
} \
catch (...) \
{ \
NOTREACHED("expected »%s«-failure, " \
"yet something scary happened instead...", \
FAILURE_MSG); \
}
#define MARK_TEST_FUN \
cout << "|" << endl << "| »"<<__FUNCTION__<<"«" <<endl;
#endif /*LIB_TEST_TEST_HELPER_H*/
Inline string literal.
Definition symbol.hpp:78
Helper to produce better diagnostic messages when comparing to an expected result string.
friend bool operator==(X const &x, ExpectString const &expected)
bool verify(std::string const &actual) const
friend ExpectString operator+(std::string &&l, ExpectString &&r)
Lumiera's internal time value datatype.
const char * CStr
Definition error.hpp:42
Simple functions to represent objects, for debugging and diagnostics.
unsigned int uint
Definition integral.hpp:29
string humanReadableTypeID(Literal rawType)
pretty-print an internal C++ type representation
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
string demangleCxx(Literal rawName)
Fallback type-ID:
string showTypes()
string showType()
diagnostic type output, including const and similar adornments
constexpr auto EPSILON_ULP
constexpr auto ROUGH_PRECISION
constexpr meta::enable_if< std::is_floating_point< F >, F > ulp(F val)
void typeDebugger(X &&x)
string showVariadicTypes()
helper for investigating a variadic argument pack
string showRefKind()
helper to discern the kind of reference of the argument type
constexpr meta::enable_if< std::is_floating_point< F >, bool > epsEQ(F val, N target, uint ulps=EPSILON_ULP)
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
Test runner and basic definitions for tests.
ostream & showAdr(ostream &stream, void const *addr)
preconfigured format for pretty-printing of addresses
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Generating (pseudo) random numbers with controlled seed.
#define Type(_EXPR_)
static std::string invoke(X const &x) noexcept
Marker types to indicate a literal string and a Symbol.
a family of time value like entities and their relationships.
Helpers for type detection, type rewriting and metaprogramming.
Test helper to perform temporary manipulations within a test scope.