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) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
39 #ifndef LIB_TEST_TEST_HELPER_H
40 #define LIB_TEST_TEST_HELPER_H
41 
42 
43 #include "lib/symbol.hpp"
44 #include "lib/meta/trait.hpp"
45 #include "lib/time/timevalue.hpp"
46 #include "lib/test/transiently.hpp"
47 #include "lib/format-obj.hpp"
48 
49 #include <boost/lexical_cast.hpp>
50 #include <typeinfo>
51 #include <cstdlib>
52 #include <limits>
53 #include <string>
54 #include <cmath>
55 
56 
57 
58 namespace lib {
59 namespace test{
60 
61  using lib::Literal;
62  using std::string;
63  using std::rand;
65 
66 
67  constexpr auto ROUGH_PRECISION = pow (10, -3);
68  constexpr auto EPSILON_ULP = 5;
69 
70 
71  template<typename F, typename N>
72  constexpr inline meta::enable_if< std::is_floating_point<F>,
73  bool >
74  roughEQ (F val, N target, F limit =ROUGH_PRECISION)
75  {
76  REQUIRE (0 < limit);
77  return abs (val/target - F(1)) < limit;
78  }
79 
80 
81  template<typename F>
82  constexpr inline meta::enable_if< std::is_floating_point<F>,
83  F >
84  ulp (F val)
85  {
86  val = fabs (val);
87  const int exp = val < std::numeric_limits<F>::min()
88  ? std::numeric_limits<F>::min_exponent - 1 // fixed exponent for subnormals
89  : std::ilogb (val);
90  auto scaledUlp = std::ldexp (std::numeric_limits<F>::epsilon(), exp);
91  ENSURE (F(0) < scaledUlp);
92  return scaledUlp;
93  }
94 
95  template<typename F, typename N>
96  constexpr inline meta::enable_if< std::is_floating_point<F>,
97  bool >
98  epsEQ (F val, N target, uint ulps =EPSILON_ULP)
99  {
100  return abs (val - target) < ulps * ulp<F> (target);
101  }
102 
103 
106  string
107  showSizeof (size_t siz, string name);
108 
113  template<typename T>
114  inline string
115  showSizeof (T const* obj =0, const char* name =0)
116  {
117  return showSizeof (obj? sizeof(*obj) : sizeof(T),
118  name? name : util::typeStr(obj));
119  }
120 
121  template<typename T>
122  inline meta::disable_if<std::is_pointer<T>,
123  string > // note:: force invocations with pointer to the first overload
124  showSizeof (T const& obj, const char* name=0)
125  {
126  return showSizeof (&obj, name);
127  }
128 
129  template<typename T>
130  inline string
131  showSizeof (const char* name)
132  {
133  return showSizeof<T> (nullptr, name);
134  }
135 
136 
137 
139  template<typename R>
140  string
142  {
143  return std::is_lvalue_reference<R>::value? "REF"
144  : std::is_rvalue_reference<R>::value? "MOV"
145  : "VAL";
146  }
147 
155  template<typename... EMPTY>
156  inline string
158  {
159  return " :.";
160  }
161 
162  template<typename X, typename... XS>
163  inline string
164  showVariadicTypes (X const& x, XS const&... xs)
165  {
166  return " :---#"
167  + boost::lexical_cast<string>(1 + sizeof...(xs))
168  + " -- Type: " + util::typeStr(x)
169  + " " + showRefKind<X>()
170  + " Address* " + boost::lexical_cast<string>(&x)
171  + "\n"
172  + showVariadicTypes<XS...> (xs...);
173  }
174 
175 
176 
183  template<typename X>
185  {
186  static_assert (not sizeof(X), "### Type Debugging ###");
187  };
188 
189  template<typename X>
190  void
191  typeDebugger(X&& x)
192  {
193  static_assert (not sizeof(X), "### Type Debugging ###");
194  }
195 
196 
197 
198  namespace { // helper for printing type diagnostics
199 
200  template<typename X>
202  {
203  using Type = X;
204  static constexpr auto prefix = "";
205  static constexpr auto postfix = "";
206  };
207  template<typename X>
208  struct TypeDiagnostics<const X>
209  {
210  using Type = X;
211  static constexpr auto prefix = "const ";
212  static constexpr auto postfix = "";
213  };
214  template<typename X>
216  {
217  using Type = X;
218  static constexpr auto prefix = "";
219  static constexpr auto postfix = "&";
220  };
221  template<typename X>
222  struct TypeDiagnostics<X&&>
223  {
224  using Type = X;
225  static constexpr auto prefix = "";
226  static constexpr auto postfix = " &&";
227  };
228  template<typename X>
229  struct TypeDiagnostics<X const&>
230  {
231  using Type = X;
232  static constexpr auto prefix = "";
233  static constexpr auto postfix = " const&";
234  };
235  template<typename X>
236  struct TypeDiagnostics<X const&&>
237  {
238  using Type = X;
239  static constexpr auto prefix = "const ";
240  static constexpr auto postfix = " &&";
241  };
242  template<typename X>
243  struct TypeDiagnostics<X *>
244  {
245  using Type = X;
246  static constexpr auto prefix = "";
247  static constexpr auto postfix = " *";
248  };
249  template<typename X>
250  struct TypeDiagnostics<const X *>
251  {
252  using Type = X;
253  static constexpr auto prefix = "const ";
254  static constexpr auto postfix = " *";
255  };
256  template<typename X>
257  struct TypeDiagnostics<const X * const>
258  {
259  using Type = X;
260  static constexpr auto prefix = "const ";
261  static constexpr auto postfix = " * const";
262  };
263  template<typename X>
264  struct TypeDiagnostics<X * const>
265  {
266  using Type = X;
267  static constexpr auto prefix = "";
268  static constexpr auto postfix = " * const";
269  };
270  template<typename X>
271  struct TypeDiagnostics<X * const *>
272  {
273  using Type = X;
274  static constexpr auto prefix = "";
275  static constexpr auto postfix = " * const *";
276  };
277  }
278 
287  template<typename X>
288  inline string
290  {
291  using Case = TypeDiagnostics<X>;
292  using Type = typename Case::Type;
293 
294  return Case::prefix
295  + meta::humanReadableTypeID (typeid(Type).name())
296  + Case::postfix;
297  }
298 
299 
300 
301 
303  inline lib::time::Time
305  {
306  return lib::time::Time (500 * (rand() % 2), (rand() % 600) + 1);
307  }
308 
312  string randStr (size_t len);
313 
314 
324  : public std::string
325  {
326  using std::string::string;
327 
328  template<typename X>
329  friend bool
330  operator== (X const& x, ExpectString const& expected)
331  {
332  std::string actual{util::StringConv<X>::invoke (x)};
333  return expected.verify (actual);
334  }
335 
336  template<typename X>
337  friend bool
338  operator== (ExpectString const& expected, X const& x)
339  {
340  std::string actual{util::StringConv<X>::invoke (x)};
341  return expected.verify (actual);
342  }
343 
344  friend ExpectString
345  operator+ (std::string&& l, ExpectString&& r)
346  {
347  return ExpectString{(l+r).c_str()};
348  }
349 
350  bool verify (std::string const& actual) const;
351  };
352 
353 }} // namespace lib::test
354 
355 
356 
368 operator""_expect (const char* lit, size_t siz)
369 {
370  return lib::test::ExpectString{lit, siz};
371 }
372 
373 
374 
375 /* === test helper macros === */
376 
383 #define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT) \
384  try \
385  { \
386  ERRONEOUS_STATEMENT ; \
387  NOTREACHED("expected »%s« failure in: %s", \
388  #ERROR_ID, #ERRONEOUS_STATEMENT); \
389  } \
390  catch (lumiera::Error& ex) \
391  { \
392  CHECK (ex.getID() \
393  == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} );\
394  lumiera_error(); \
395  } \
396  catch (...) \
397  { \
398  CHECK (lumiera_error_peek() \
399  == lib::test::ExpectString{LUMIERA_ERROR_##ERROR_ID} ); \
400  lumiera_error(); \
401  }
402 
407 #define VERIFY_FAIL(FAILURE_MSG, ERRONEOUS_STATEMENT) \
408  try \
409  { \
410  ERRONEOUS_STATEMENT ; \
411  NOTREACHED("expected »%s«-failure in: %s" \
412  , FAILURE_MSG, #ERRONEOUS_STATEMENT);\
413  } \
414  catch (std::exception& sex) \
415  { \
416  CHECK (util::contains (sex.what(), FAILURE_MSG) \
417  ,"expected failure with »%s« -- but got: %s" \
418  ,FAILURE_MSG, sex.what()); \
419  lumiera_error(); \
420  } \
421  catch (...) \
422  { \
423  NOTREACHED("expected »%s«-failure, " \
424  "yet something scary happened instead...", \
425  FAILURE_MSG); \
426  }
427 
428 
433 #define MARK_TEST_FUN \
434  cout << "|" << endl << "| »"<<__FUNCTION__<<"«" <<endl;
435 
436 #endif /*LIB_TEST_TEST_HELPER_H*/
Helper to produce better diagnostic messages when comparing to an expected result string...
Definition: run.hpp:49
bool verify(std::string const &actual) const
Definition: test-helper.cpp:88
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
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:57
Implementation namespace for support and library code.
string randStr(size_t len)
create garbage string of given length
Definition: test-helper.cpp:69
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:308
std::string operator+(std::string str, Literal const &sym)
string concatenation
Definition: symbol.hpp:222
Marker types to indicate a literal string and a Symbol.
string demangleCxx(Literal rawName)
Fallback type-ID:
Definition: format-obj.cpp:168
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
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:399
ElementBoxWidget::Config::Qualifier name(string id)
define the name-ID displayed in the caption