Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
test-helper.hpp
Go to the documentation of this file.
1/*
2 TEST-HELPER.hpp - collection of functions supporting unit testing
3
4 Copyright (C)
5 2009, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
14
30#ifndef LIB_TEST_TEST_HELPER_H
31#define LIB_TEST_TEST_HELPER_H
32
33
34#include "lib/symbol.hpp"
35#include "lib/meta/trait.hpp"
38#include "lib/format-obj.hpp"
39#include "lib/random.hpp"
40
41#include <boost/lexical_cast.hpp>
42#include <typeinfo>
43#include <cstdlib>
44#include <utility>
45#include <limits>
46#include <string>
47#include <cmath>
48
49
50
51namespace lib {
52namespace test{
53
54 using lib::Literal;
55 using std::string;
56 using lib::rani;
58
59
60 constexpr auto ROUGH_PRECISION = pow (10, -3);
61 constexpr auto EPSILON_ULP = 5;
62
63
64 template<typename F, typename N>
66 bool >
67 roughEQ (F val, N target, F limit =ROUGH_PRECISION)
68 {
69 REQUIRE (0 < limit);
70 return abs (val - target) < limit * abs(target);
71 }
72
73
74 template<typename F>
76 F >
77 ulp (F val)
78 {
79 val = fabs (val);
80 const int exp = val < std::numeric_limits<F>::min()
81 ? std::numeric_limits<F>::min_exponent - 1 // fixed exponent for subnormals
82 : std::ilogb (val);
83 auto scaledUlp = std::ldexp (std::numeric_limits<F>::epsilon(), exp);
84 ENSURE (F(0) < scaledUlp);
85 return scaledUlp;
86 }
87
88 template<typename F, typename N>
90 bool >
91 epsEQ (F val, N target, uint ulps =EPSILON_ULP)
92 {
93 return abs (val - target) < ulps * ulp<F> (target);
94 }
95
96
99 string
100 showSizeof (size_t siz, string name);
101
106 template<typename T>
107 inline string
108 showSizeof (T const* obj =0, CStr name =0)
109 {
110 return showSizeof (obj? sizeof(*obj) : sizeof(T),
111 name? name : util::typeStr(obj));
112 }
113
114 template<typename T>
116 string > // note:: force invocations with pointer to the first overload
117 showSizeof (T const& obj, CStr name =nullptr)
118 {
119 return showSizeof (&obj, name);
120 }
121
122 template<typename T>
123 inline string
125 {
126 return showSizeof<T> (nullptr, name);
127 }
128
129
130
132 template<typename R>
133 string
135 {
136 return std::is_lvalue_reference<R>::value? "REF"
137 : std::is_rvalue_reference<R>::value? "MOV"
138 : "VAL";
139 }
140
141
142
149 template<typename X>
151 {
152 static_assert (not sizeof(X), "### Type Debugging ###");
153 };
154
155 template<typename X>
156 void
158 {
159 static_assert (not sizeof(X), "### Type Debugging ###");
160 }
161
162
163
164
165
166 namespace { // helper for printing type diagnostics
167
168 template<typename X>
170 {
171 using Type = X;
172 static constexpr auto prefix = "";
173 static constexpr auto postfix = "";
174 };
175 template<typename X>
176 struct TypeDiagnostics<const X>
177 {
178 using Type = X;
179 static constexpr auto prefix = "const ";
180 static constexpr auto postfix = "";
181 };
182 template<typename X>
184 {
185 using Type = X;
186 static constexpr auto prefix = "";
187 static constexpr auto postfix = "&";
188 };
189 template<typename X>
191 {
192 using Type = X;
193 static constexpr auto prefix = "";
194 static constexpr auto postfix = " &&";
195 };
196 template<typename X>
197 struct TypeDiagnostics<X const&>
198 {
199 using Type = X;
200 static constexpr auto prefix = "";
201 static constexpr auto postfix = " const&";
202 };
203 template<typename X>
204 struct TypeDiagnostics<X const&&>
205 {
206 using Type = X;
207 static constexpr auto prefix = "const ";
208 static constexpr auto postfix = " &&";
209 };
210 template<typename X>
212 {
213 using Type = X;
214 static constexpr auto prefix = "";
215 static constexpr auto postfix = " *";
216 };
217 template<typename X>
218 struct TypeDiagnostics<const X *>
219 {
220 using Type = X;
221 static constexpr auto prefix = "const ";
222 static constexpr auto postfix = " *";
223 };
224 template<typename X>
225 struct TypeDiagnostics<const X * const>
226 {
227 using Type = X;
228 static constexpr auto prefix = "const ";
229 static constexpr auto postfix = " * const";
230 };
231 template<typename X>
232 struct TypeDiagnostics<X * const>
233 {
234 using Type = X;
235 static constexpr auto prefix = "";
236 static constexpr auto postfix = " * const";
237 };
238 template<typename X>
239 struct TypeDiagnostics<X * const *>
240 {
241 using Type = X;
242 static constexpr auto prefix = "";
243 static constexpr auto postfix = " * const *";
244 };
245 }
246
255 template<typename X>
256 inline string
258 {
259 using Case = TypeDiagnostics<X>;
260 using Type = Case::Type;
261
262 return Case::prefix
263 + meta::humanReadableTypeID (typeid(Type).name())
264 + Case::postfix;
265 }
266
267 template<typename...TS>
268 string
270 {
271 return "<| " + ((showType<TS>()+", ") + ... + "|>");
272 }
273
274
283 template<typename... EMPTY>
284 inline string
286 {
287 return " :.";
288 }
289
290 template<typename XX, typename... XS>
291 inline string
292 showVariadicTypes (XX&& x, XS&&... xs)
293 {
294 return " :---#"
295 + util::toString (1 + sizeof...(xs))
296 + " -- Type: " + showType<XX&&>()
297 + " \tAdr" + util::showAdr (x)
298 + "\n"
299 + showVariadicTypes (std::forward<XS>(xs)...);
300 }
301
302
303
304
305
306
308 inline lib::time::Time
310 {
311 return lib::time::Time (500 * rani(2), 1 + rani(600));
312 }
313
317 string randStr (size_t len);
318
319
329 : public std::string
330 {
331 public:
332 using std::string::string;
333
334 ExpectString(std::string && s) : std::string{std::move(s)}{ }
335 ExpectString(std::string const& s) : std::string{s} { }
336
337
338 template<typename X>
339 friend bool
340 operator== (X const& x, ExpectString const& expected)
341 {
342 std::string actual{util::StringConv<X>::invoke (x)};
343 return expected.verify (actual);
344 }
345
346 template<typename X>
347 friend bool
348 operator== (ExpectString const& expected, X const& x)
349 {
350 std::string actual{util::StringConv<X>::invoke (x)};
351 return expected.verify (actual);
352 }
353
354 friend ExpectString
355 operator+ (std::string&& l, ExpectString&& r)
356 {
357 return ExpectString{(l+r).c_str()};
358 }
359
360 bool verify (std::string const& actual) const;
361 };
362
363}} // namespace lib::test
364
365
366
378operator""_expect (CStr lit, size_t siz)
379{
380 return lib::test::ExpectString{lit, siz};
381}
382
383
384
385/* === test helper macros === */
386
393#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT) \
394 try \
395 { \
396 ERRONEOUS_STATEMENT ; \
397 NOTREACHED("expected »%s« failure in: %s", \
398 #ERROR_ID, #ERRONEOUS_STATEMENT); \
399 } \
400 catch (lumiera::Error& ex) \
401 { \
402 CHECK (ex.getID() \
403 == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} );\
404 lumiera_error(); \
405 } \
406 catch (...) \
407 { \
408 CHECK (lumiera_error_peek() \
409 == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} ); \
410 lumiera_error(); \
411 }
412
417#define VERIFY_FAIL(FAILURE_MSG, ERRONEOUS_STATEMENT) \
418 try \
419 { \
420 ERRONEOUS_STATEMENT ; \
421 NOTREACHED("expected »%s«-failure in: %s" \
422 , FAILURE_MSG, #ERRONEOUS_STATEMENT);\
423 } \
424 catch (std::exception& sex) \
425 { \
426 CHECK (util::contains (sex.what(), FAILURE_MSG) \
427 ,"expected failure with »%s« -- but got: %s" \
428 ,FAILURE_MSG, sex.what()); \
429 lumiera_error(); \
430 } \
431 catch (...) \
432 { \
433 NOTREACHED("expected »%s«-failure, " \
434 "yet something scary happened instead...", \
435 FAILURE_MSG); \
436 }
437
438
443#define MARK_TEST_FUN \
444 cout << "|" << endl << "| »"<<__FUNCTION__<<"«" <<endl;
445
446#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.
ExpectString(std::string const &s)
ExpectString(std::string &&s)
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 showSizeof(size_t siz, string name)
for printing sizeof().
string showTypes()
string showType()
diagnostic type output, including const and similar adornments
lib::time::Time randTime()
create a random but not insane Time value between 1s ... 10min + 500ms
constexpr auto EPSILON_ULP
constexpr auto ROUGH_PRECISION
constexpr meta::enable_if< std::is_floating_point< F >, F > ulp(F val)
constexpr meta::enable_if< std::is_floating_point< F >, bool > roughEQ(F val, N target, F limit=ROUGH_PRECISION)
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)
Helper to show types involved in metaprogramming.
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
STL namespace.
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.