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