Lumiera  0.pre.03
»edit your freedom«
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"
36 #include "lib/time/timevalue.hpp"
37 #include "lib/test/transiently.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 <limits>
45 #include <string>
46 #include <cmath>
47 
48 
49 
50 namespace lib {
51 namespace test{
52 
53  using lib::Literal;
54  using std::string;
55  using lib::rani;
57 
58 
59  constexpr auto ROUGH_PRECISION = pow (10, -3);
60  constexpr auto EPSILON_ULP = 5;
61 
62 
63  template<typename F, typename N>
64  constexpr inline meta::enable_if< std::is_floating_point<F>,
65  bool >
66  roughEQ (F val, N target, F limit =ROUGH_PRECISION)
67  {
68  REQUIRE (0 < limit);
69  return abs (val - target) < limit * abs(target);
70  }
71 
72 
73  template<typename F>
74  constexpr inline meta::enable_if< std::is_floating_point<F>,
75  F >
76  ulp (F val)
77  {
78  val = fabs (val);
79  const int exp = val < std::numeric_limits<F>::min()
80  ? std::numeric_limits<F>::min_exponent - 1 // fixed exponent for subnormals
81  : std::ilogb (val);
82  auto scaledUlp = std::ldexp (std::numeric_limits<F>::epsilon(), exp);
83  ENSURE (F(0) < scaledUlp);
84  return scaledUlp;
85  }
86 
87  template<typename F, typename N>
88  constexpr inline meta::enable_if< std::is_floating_point<F>,
89  bool >
90  epsEQ (F val, N target, uint ulps =EPSILON_ULP)
91  {
92  return abs (val - target) < ulps * ulp<F> (target);
93  }
94 
95 
98  string
99  showSizeof (size_t siz, string name);
100 
105  template<typename T>
106  inline string
107  showSizeof (T const* obj =0, const char* name =0)
108  {
109  return showSizeof (obj? sizeof(*obj) : sizeof(T),
110  name? name : util::typeStr(obj));
111  }
112 
113  template<typename T>
114  inline meta::disable_if<std::is_pointer<T>,
115  string > // note:: force invocations with pointer to the first overload
116  showSizeof (T const& obj, const char* name=0)
117  {
118  return showSizeof (&obj, name);
119  }
120 
121  template<typename T>
122  inline string
123  showSizeof (const char* name)
124  {
125  return showSizeof<T> (nullptr, name);
126  }
127 
128 
129 
131  template<typename R>
132  string
134  {
135  return std::is_lvalue_reference<R>::value? "REF"
136  : std::is_rvalue_reference<R>::value? "MOV"
137  : "VAL";
138  }
139 
140 
141 
148  template<typename X>
150  {
151  static_assert (not sizeof(X), "### Type Debugging ###");
152  };
153 
154  template<typename X>
155  void
156  typeDebugger(X&& x)
157  {
158  static_assert (not sizeof(X), "### Type Debugging ###");
159  }
160 
161 
162 
163 
164 
165  namespace { // helper for printing type diagnostics
166 
167  template<typename X>
169  {
170  using Type = X;
171  static constexpr auto prefix = "";
172  static constexpr auto postfix = "";
173  };
174  template<typename X>
175  struct TypeDiagnostics<const X>
176  {
177  using Type = X;
178  static constexpr auto prefix = "const ";
179  static constexpr auto postfix = "";
180  };
181  template<typename X>
183  {
184  using Type = X;
185  static constexpr auto prefix = "";
186  static constexpr auto postfix = "&";
187  };
188  template<typename X>
189  struct TypeDiagnostics<X&&>
190  {
191  using Type = X;
192  static constexpr auto prefix = "";
193  static constexpr auto postfix = " &&";
194  };
195  template<typename X>
196  struct TypeDiagnostics<X const&>
197  {
198  using Type = X;
199  static constexpr auto prefix = "";
200  static constexpr auto postfix = " const&";
201  };
202  template<typename X>
203  struct TypeDiagnostics<X const&&>
204  {
205  using Type = X;
206  static constexpr auto prefix = "const ";
207  static constexpr auto postfix = " &&";
208  };
209  template<typename X>
210  struct TypeDiagnostics<X *>
211  {
212  using Type = X;
213  static constexpr auto prefix = "";
214  static constexpr auto postfix = " *";
215  };
216  template<typename X>
217  struct TypeDiagnostics<const X *>
218  {
219  using Type = X;
220  static constexpr auto prefix = "const ";
221  static constexpr auto postfix = " *";
222  };
223  template<typename X>
224  struct TypeDiagnostics<const X * const>
225  {
226  using Type = X;
227  static constexpr auto prefix = "const ";
228  static constexpr auto postfix = " * const";
229  };
230  template<typename X>
231  struct TypeDiagnostics<X * const>
232  {
233  using Type = X;
234  static constexpr auto prefix = "";
235  static constexpr auto postfix = " * const";
236  };
237  template<typename X>
238  struct TypeDiagnostics<X * const *>
239  {
240  using Type = X;
241  static constexpr auto prefix = "";
242  static constexpr auto postfix = " * const *";
243  };
244  }
245 
254  template<typename X>
255  inline string
257  {
258  using Case = TypeDiagnostics<X>;
259  using Type = typename Case::Type;
260 
261  return Case::prefix
262  + meta::humanReadableTypeID (typeid(Type).name())
263  + Case::postfix;
264  }
265 
266  template<typename...TS>
267  string
268  showTypes()
269  {
270  return "<| " + ((showType<TS>()+", ") + ... + "|>");
271  }
272 
273 
282  template<typename... EMPTY>
283  inline string
285  {
286  return " :.";
287  }
288 
289  template<typename XX, typename... XS>
290  inline string
291  showVariadicTypes (XX&& x, XS&&... xs)
292  {
293  return " :---#"
294  + util::toString (1 + sizeof...(xs))
295  + " -- Type: " + showType<XX&&>()
296  + " \tAdr" + util::showAdr (x)
297  + "\n"
298  + showVariadicTypes (std::forward<XS>(xs)...);
299  }
300 
301 
302 
303 
304 
305 
307  inline lib::time::Time
309  {
310  return lib::time::Time (500 * rani(2), 1 + rani(600));
311  }
312 
316  string randStr (size_t len);
317 
318 
328  : public std::string
329  {
330  using std::string::string;
331 
332  template<typename X>
333  friend bool
334  operator== (X const& x, ExpectString const& expected)
335  {
336  std::string actual{util::StringConv<X>::invoke (x)};
337  return expected.verify (actual);
338  }
339 
340  template<typename X>
341  friend bool
342  operator== (ExpectString const& expected, X const& x)
343  {
344  std::string actual{util::StringConv<X>::invoke (x)};
345  return expected.verify (actual);
346  }
347 
348  friend ExpectString
349  operator+ (std::string&& l, ExpectString&& r)
350  {
351  return ExpectString{(l+r).c_str()};
352  }
353 
354  bool verify (std::string const& actual) const;
355  };
356 
357 }} // namespace lib::test
358 
359 
360 
372 operator""_expect (const char* lit, size_t siz)
373 {
374  return lib::test::ExpectString{lit, siz};
375 }
376 
377 
378 
379 /* === test helper macros === */
380 
387 #define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT) \
388  try \
389  { \
390  ERRONEOUS_STATEMENT ; \
391  NOTREACHED("expected »%s« failure in: %s", \
392  #ERROR_ID, #ERRONEOUS_STATEMENT); \
393  } \
394  catch (lumiera::Error& ex) \
395  { \
396  CHECK (ex.getID() \
397  == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} );\
398  lumiera_error(); \
399  } \
400  catch (...) \
401  { \
402  CHECK (lumiera_error_peek() \
403  == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} ); \
404  lumiera_error(); \
405  }
406 
411 #define VERIFY_FAIL(FAILURE_MSG, ERRONEOUS_STATEMENT) \
412  try \
413  { \
414  ERRONEOUS_STATEMENT ; \
415  NOTREACHED("expected »%s«-failure in: %s" \
416  , FAILURE_MSG, #ERRONEOUS_STATEMENT);\
417  } \
418  catch (std::exception& sex) \
419  { \
420  CHECK (util::contains (sex.what(), FAILURE_MSG) \
421  ,"expected failure with »%s« -- but got: %s" \
422  ,FAILURE_MSG, sex.what()); \
423  lumiera_error(); \
424  } \
425  catch (...) \
426  { \
427  NOTREACHED("expected »%s«-failure, " \
428  "yet something scary happened instead...", \
429  FAILURE_MSG); \
430  }
431 
432 
437 #define MARK_TEST_FUN \
438  cout << "|" << endl << "| »"<<__FUNCTION__<<"«" <<endl;
439 
440 #endif /*LIB_TEST_TEST_HELPER_H*/
Helper to produce better diagnostic messages when comparing to an expected result string...
Definition: run.hpp:40
bool verify(std::string const &actual) const
Definition: test-helper.cpp:80
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
string showVariadicTypes()
helper for investigating a variadic argument pack
string showSizeof(size_t siz, string name)
for printing sizeof().
Definition: test-helper.cpp:49
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:61
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
std::string operator+(std::string str, Literal const &sym)
string concatenation
Definition: symbol.hpp:213
Marker types to indicate a literal string and a Symbol.
string demangleCxx(Literal rawName)
Fallback type-ID:
Definition: format-obj.cpp:159
Test helper to perform temporary manipulations within a test scope.
Helpers for type detection, type rewriting and metaprogramming.
Simple functions to represent objects, for debugging and diagnostics.
string showType()
diagnostic type output, including const and similar adornments
string showRefKind()
helper to discern the kind of reference of the argument type
Generating (pseudo) random numbers with controlled seed.
lib::time::Time randTime()
create a random but not insane Time value between 1s ...
a family of time value like entities and their relationships.
Helper to show types involved in metaprogramming.
failsafe invocation of custom string conversion.
Definition: meta/util.hpp:390
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption