Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
testing.hh
Go to the documentation of this file.
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2#ifndef __ASE_TESTING_HH__
3#define __ASE_TESTING_HH__
4
5#include <ase/utils.hh>
6#include <ase/strings.hh>
7
8namespace Ase {
9
11namespace Test {
12
13// Test Macros
14#define TSTART(...) Ase::Test::test_output ('S', ::Ase::string_format (__VA_ARGS__))
15#define TDONE() Ase::Test::test_output ('D', "")
16#define TPASS(...) Ase::Test::test_output ('P', ::Ase::string_format (__VA_ARGS__))
17#define TBENCH(...) Ase::Test::test_output ('B', ::Ase::string_format (__VA_ARGS__))
18#define TNOTE(...) Ase::Test::test_output ('I', ::Ase::string_format (__VA_ARGS__))
19#define TCHECK(cond, ...) Ase::Test::test_output (bool (cond) ? 'P' : 'F', \
20 ::Ase::string_format (__VA_ARGS__))
21#define TCMPS(a,cmp,b) TCMP_op (a,cmp,b,#a,#b,Ase::Test::_as_strptr)
22#define TCMP(a,cmp,b) TCMP_op (a,cmp,b,#a,#b,)
23#define TASSERT(cond) TASSERT__AT (__LINE__, cond)
24#define TASSERT_AT(LINE, cond) TASSERT__AT (LINE, cond)
25#define TOK() do {} while (0)
27#define TFLOATS(a,b,eps) do { if (fabsl ((long double) (a) - (long double) (b)) > (long double) (eps)) TCMP (a,==,b); } while (0)
30#define TEST_ADD(fun) static const ::Ase::Test::TestChain ASE_CPP_PASTE2 (__Ase__Test__TestChain_, __LINE__) (fun, ASE_CPP_STRINGIFY (fun), ::Ase::Test::PLAIN)
31#define TEST_SLOW(fun) static const ::Ase::Test::TestChain ASE_CPP_PASTE2 (__Ase__Test__TestChain_, __LINE__) (fun, ASE_CPP_STRINGIFY (fun), ::Ase::Test::SLOW)
32#define TEST_BENCH(fun) static const ::Ase::Test::TestChain ASE_CPP_PASTE2 (__Ase__Test__TestChain_, __LINE__) (fun, ASE_CPP_STRINGIFY (fun), ::Ase::Test::BENCH)
33#define TEST_BROKEN(fun) static const ::Ase::Test::TestChain ASE_CPP_PASTE2 (__Ase__Test__TestChain_, __LINE__) (fun, ASE_CPP_STRINGIFY (fun), ::Ase::Test::BROKEN)
34
38class Timer {
39 const double deadline_;
40 std::vector<double> samples_;
41 double test_duration_;
42 int64 n_reps_;
43 int64 loops_needed ();
44 void reset ();
45 void submit (double elapsed, int64 repetitions);
46 static double bench_time ();
47public:
49 explicit Timer (double deadline_in_secs = 0);
50 virtual ~Timer ();
51 int64 n_reps () const { return n_reps_; }
52 double test_elapsed () const { return test_duration_; }
53 double min_elapsed () const;
54 double max_elapsed () const;
60 template<typename Callee>
61 double benchmark (Callee callee);
62};
63
64// == test array ==
65enum Kind {
66 PLAIN = 0,
67 SLOW = 1,
68 BENCH = 2,
69 BROKEN = 4,
70 INTEGRITY = 8,
71};
72struct TestEntry {
74 int64 flags = 0;
75 TestEntry (const std::string &identi = "", int64 flagsi = 0) :
76 ident (identi), flags (flagsi)
77 {}
78};
79using TestEntries = std::vector<TestEntry>;
80TestEntries list_tests ();
81int run_test (const std::string &test_identifier);
82
83// === test maintenance ===
84int run ();
85int run (const StringS &test_names);
86bool verbose ();
87bool slow ();
88void test_output (int kind, const String &string);
89
91inline String stringify_arg (const char *a, const char *str_a) { return a ? string_to_cquote (a) : "(__null)"; }
92template<class V> inline String stringify_arg (const V *a, const char *str_a) { return string_format ("%p", a); }
93template<class A> inline String stringify_arg (const A &a, const char *str_a) { return str_a; }
94template<> inline String stringify_arg<float> (const float &a, const char *str_a) { return string_format ("%.8g", a); }
95template<> inline String stringify_arg<double> (const double &a, const char *str_a) { return string_format ("%.17g", a); }
96template<> inline String stringify_arg<bool> (const bool &a, const char *str_a) { return string_format ("%u", a); }
97template<> inline String stringify_arg<int8> (const int8 &a, const char *str_a) { return string_format ("%d", a); }
98template<> inline String stringify_arg<int16> (const int16 &a, const char *str_a) { return string_format ("%d", a); }
99template<> inline String stringify_arg<int32> (const int32 &a, const char *str_a) { return string_format ("%d", a); }
100template<> inline String stringify_arg<int64> (const int64 &a, const char *str_a) { return string_format ("%lld", a); }
101template<> inline String stringify_arg<uint8> (const uint8 &a, const char *str_a) { return string_format ("0x%02x", a); }
102template<> inline String stringify_arg<uint16> (const uint16 &a, const char *str_a) { return string_format ("0x%04x", a); }
103template<> inline String stringify_arg<uint32> (const uint32 &a, const char *str_a) { return string_format ("0x%08x", a); }
104template<> inline String stringify_arg<uint64> (const uint64 &a, const char *str_a) { return string_format ("0x%08Lx", a); }
105template<> inline String stringify_arg<String> (const String &a, const char *str_a) { return string_to_cquote (a); }
106inline const char* _as_strptr (const char *s) { return s; } // implementation detail
107
108// == Deterministic random numbers for tests ===
110int64_t random_irange (int64_t begin, int64_t end);
111double random_float ();
112double random_frange (double begin, double end);
113
114
115// == Implementations ==
117
118#define TASSERT__AT(LINE, cond) \
119 do { if (ASE_ISLIKELY (cond)) break; \
120 ::Ase::assertion_failed (#cond); } while (0)
121
122#define TCMP_op(a,cmp,b,sa,sb,cast) \
123 do { \
124 const auto &__tcmp_va = a ; \
125 const auto &__tcmp_vb = b ; \
126 if (__tcmp_va cmp __tcmp_vb) break; \
127 Ase::String __tcmp_sa = Ase::Test::stringify_arg (cast (__tcmp_va), #a); \
128 Ase::String __tcmp_sb = Ase::Test::stringify_arg (cast (__tcmp_vb), #b), \
129 __tcmp_as = Ase::string_format ("'%s %s %s': %s %s %s", \
130 sa, #cmp, sb, \
131 __tcmp_sa.c_str(), \
132 #cmp, \
133 __tcmp_sb.c_str()); \
134 ::Ase::assertion_failed (__tcmp_as.c_str()); \
135 } while (0)
136
137template<typename Callee> double
138Timer::benchmark (Callee callee)
139{
140 reset();
141 for (int64 runs = loops_needed(); runs; runs = loops_needed())
142 {
143 int64 n = runs;
144 const double start = bench_time();
145 while (ASE_ISLIKELY (n--))
146 callee();
147 const double stop = bench_time();
148 submit (stop - start, runs);
149 }
150 return min_elapsed();
151}
152
153class TestChain {
154public:
155 explicit TestChain (std::function<void()> tfunc, const std::string &tname, Kind kind);
156 static void run (ptrdiff_t internal_token, const StringS *test_names);
157 const TestChain* next () const { return next_; }
158 std::string name () const { return name_; }
159 int64 flags () const { return kind_; }
160 void run () const { func_(); }
161private:
162 const std::string name_;
163 std::function<void()> func_;
164 const TestChain *const next_ = NULL;
165 Kind kind_ = PLAIN;
166};
167
169
170} // Test
171} // Ase
172
173#endif /* __ASE_TESTING_HH__ */
double benchmark(Callee callee)
double min_elapsed() const
Minimum time benchmarked for a callee() call.
Definition testing.cc:91
int64 n_reps() const
Number of benchmark repetitions to execute.
Definition testing.hh:52
double max_elapsed() const
Maximum time benchmarked for a callee() call.
Definition testing.cc:100
double test_elapsed() const
Seconds spent in benchmark()
Definition testing.hh:53
#define ASE_ISLIKELY(expr)
Compiler hint to optimize for expr evaluating to true.
Definition cxxaux.hh:45
int run(const StringS &test_names)
Run named tests.
Definition testing.cc:256
bool verbose()
Indicates whether tests should run verbosely.
Definition testing.cc:178
int64_t random_irange(int64_t begin, int64_t end)
Return random int within range for reproduceble tests.
Definition testing.cc:191
uint64_t random_int64()
Return random int for reproduceble tests.
Definition testing.cc:185
int run(void)
Run all registered tests.
Definition testing.cc:264
String stringify_arg(const char *a, const char *str_a)
== Stringify Args ==
Definition testing.hh:92
double random_float()
Return random double for reproduceble tests.
Definition testing.cc:197
double random_frange(double begin, double end)
Return random double within range for reproduceble tests.
Definition testing.cc:203
bool slow()
Indicates whether slow tests should be run.
Definition testing.cc:171
The Anklang C++ API namespace.
Definition api.hh:9
std::string string_format(const char *format, const Args &...args) __attribute__((__format__(__printf__
Format a string similar to sprintf(3) with support for std::string and std::ostringstream convertible...
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
Definition cxxaux.hh:25
int32_t int32
A 32-bit signed integer.
Definition cxxaux.hh:28
int16_t int16
A 16-bit signed integer.
Definition cxxaux.hh:27
uint8_t uint8
An 8-bit unsigned integer.
Definition cxxaux.hh:22
int8_t int8
An 8-bit signed integer.
Definition cxxaux.hh:26
int64_t int64
A 64-bit unsigned integer, use PRI*64 in format strings.
Definition cxxaux.hh:29
uint16_t uint16
A 16-bit unsigned integer.
Definition cxxaux.hh:23
std::string String
Convenience alias for std::string.
Definition cxxaux.hh:35
uint32_t uint32
A 32-bit unsigned integer.
Definition cxxaux.hh:24
String string_to_cquote(const String &str)
Returns a string as C string including double quotes.
Definition strings.cc:1036
T next(T... args)
typedef uint64_t