Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_TESTUTILS_HH__ 00003 #define __RAPICORN_TESTUTILS_HH__ 00004 00005 #include <rcore/rcore.hh> 00006 00007 namespace Rapicorn { 00008 00009 void init_core_test (const String &app_ident, int *argcp, char **argv, const StringVector &args = StringVector()); 00010 00011 namespace Test { 00012 00013 // Test Macros 00014 #define TTITLE(...) Rapicorn::Test::test_format (3, __VA_ARGS__) ///< Print out the test program title. 00015 #define TSTART(...) Rapicorn::Test::test_format (4, __VA_ARGS__) ///< Print message once a test case starts. 00016 #define TDONE() Rapicorn::Test::test_format (5, "%s", "") ///< Print message for test case end. 00017 #define TOUT(...) Rapicorn::Test::test_format (0, __VA_ARGS__) ///< Test output for verbose mode, like fputs(). 00018 #define TMSG(...) Rapicorn::Test::test_format (1, __VA_ARGS__) ///< Unconditional test message. 00019 #define TINFO(...) Rapicorn::Test::test_format (2, __VA_ARGS__) ///< Conditional test message (for verbose mode). 00020 #define TWARN(...) Rapicorn::Test::test_format (6, __VA_ARGS__) ///< Issue a non-fatal test warning. 00021 #define TOK() do {} while (0) ///< Indicator for successful test progress. 00022 #define TASSERT(cond) TASSERT__AT (__LINE__, cond) ///< Unconditional test assertion, enters breakpoint if not fullfilled. 00023 #define TASSERT_AT(LINE, cond) TASSERT__AT (LINE, cond) ///< Unconditional test assertion for deputy __LINE__. 00024 #define TCMP(a,cmp,b) TCMP_op (a,cmp,b,#a,#b,) ///< Compare @a a and @a b according to operator @a cmp. 00025 #define TCMPS(a,cmp,b) TCMP_op (a,cmp,b,#a,#b,Rapicorn::Test::_as_strptr) ///< Variant of TCMP() for C strings. 00026 00028 #define TASSERT__AT(LINE,cond) do { if (RAPICORN_LIKELY (cond)) break; \ 00029 Rapicorn::Test::assertion_failed (RAPICORN_PRETTY_FILE, LINE, #cond); } while (0) 00030 #define TCMP_op(a,cmp,b,sa,sb,cast) do { if (a cmp b) break; \ 00031 Rapicorn::String __tassert_va = Rapicorn::Test::stringify_arg (cast (a), #a); \ 00032 Rapicorn::String __tassert_vb = Rapicorn::Test::stringify_arg (cast (b), #b), \ 00033 __tassert_as = Rapicorn::string_format ("'%s %s %s': %s %s %s", \ 00034 sa, #cmp, sb, __tassert_va.c_str(), #cmp, __tassert_vb.c_str()); \ 00035 Rapicorn::Test::assertion_failed (RAPICORN_PRETTY_FILE, __LINE__, __tassert_as.c_str()); \ 00036 } while (0) 00037 00038 00042 class Timer { 00043 const double deadline_; 00044 vector<double> samples_; 00045 double test_duration_; 00046 int64 n_runs_; 00047 int64 loops_needed () const; 00048 void reset (); 00049 void submit (double elapsed, int64 repetitions); 00050 static double bench_time (); 00051 public: 00053 explicit Timer (double deadline_in_secs = 0); 00054 virtual ~Timer (); 00055 int64 n_runs () const { return n_runs_; } 00056 double test_elapsed () const { return test_duration_; } 00057 double min_elapsed () const; 00058 double max_elapsed () const; 00059 template<typename Callee> 00060 double benchmark (Callee callee); 00061 }; 00062 00068 template<typename Callee> double 00069 Timer::benchmark (Callee callee) 00070 { 00071 reset(); 00072 for (int64 runs = loops_needed(); runs; runs = loops_needed()) 00073 { 00074 int64 n = runs; 00075 const double start = bench_time(); 00076 while (RAPICORN_LIKELY (n--)) 00077 callee(); 00078 const double stop = bench_time(); 00079 submit (stop - start, runs); 00080 } 00081 return min_elapsed(); 00082 } 00083 00084 // === test maintenance === 00085 int run (void); 00086 bool verbose (void); 00087 bool logging (void); 00088 bool slow (void); 00089 bool ui_test (void); 00090 00091 void set_assertion_hook (const std::function<void()> &hook); 00092 void assertion_failed (const char *file, int line, const char *message); 00093 00095 void add_internal (const String &testname, void (*test_func) (void*), void *data); 00096 void add (const String &funcname, void (*test_func) (void)); 00097 template<typename D> void add (const String &testname, void (*test_func) (D*), D *data) 00098 { add_internal (testname, (void(*)(void*)) test_func, (void*) data); } 00099 void test_output (int kind, const String &string); 00100 template<class... Args> RAPICORN_PRINTF (2, 0) 00101 void test_format (int kind, const char *format, const Args &...args) 00102 { test_output (kind, string_format (format, args...)); } 00104 00106 inline String stringify_arg (const char *a, const char *str_a) { return a ? string_to_cquote (a) : "(__null)"; } 00107 template<class V> inline String stringify_arg (const V *a, const char *str_a) { return string_format ("%p", a); } 00108 template<class A> inline String stringify_arg (const A &a, const char *str_a) { return str_a; } 00109 template<> inline String stringify_arg<float> (const float &a, const char *str_a) { return string_format ("%.8g", a); } 00110 template<> inline String stringify_arg<double> (const double &a, const char *str_a) { return string_format ("%.17g", a); } 00111 template<> inline String stringify_arg<bool> (const bool &a, const char *str_a) { return string_format ("%u", a); } 00112 template<> inline String stringify_arg<int8> (const int8 &a, const char *str_a) { return string_format ("%d", a); } 00113 template<> inline String stringify_arg<int16> (const int16 &a, const char *str_a) { return string_format ("%d", a); } 00114 template<> inline String stringify_arg<int32> (const int32 &a, const char *str_a) { return string_format ("%d", a); } 00115 template<> inline String stringify_arg<int64> (const int64 &a, const char *str_a) { return string_format ("%lld", a); } 00116 template<> inline String stringify_arg<uint8> (const uint8 &a, const char *str_a) { return string_format ("0x%02x", a); } 00117 template<> inline String stringify_arg<uint16> (const uint16 &a, const char *str_a) { return string_format ("0x%04x", a); } 00118 template<> inline String stringify_arg<uint32> (const uint32 &a, const char *str_a) { return string_format ("0x%08x", a); } 00119 template<> inline String stringify_arg<uint64> (const uint64 &a, const char *str_a) { return string_format ("0x%08Lx", a); } 00120 template<> inline String stringify_arg<String> (const String &a, const char *str_a) { return string_to_cquote (a); } 00121 inline const char* _as_strptr (const char *s) { return s; } // implementation detail 00122 00123 class RegisterTest { 00124 static void add_test (char kind, const String &testname, void (*test_func) (void*), void *data); 00125 public: 00126 RegisterTest (const char k, const String &testname, void (*test_func) (void)) 00127 { add_test (k, testname, (void(*)(void*)) test_func, NULL); } 00128 RegisterTest (const char k, const String &testname, void (*test_func) (ptrdiff_t), ptrdiff_t data) 00129 { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); } 00130 template<typename D> 00131 RegisterTest (const char k, const String &testname, void (*test_func) (D*), D *data) 00132 { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); } 00133 typedef void (*TestTrigger) (void (*runner) (void)); 00134 static void test_set_trigger (TestTrigger func); 00135 }; 00136 00137 // == Deterministic random numbers for tests === 00138 char rand_bit (void); 00139 int32 rand_int (void); 00140 int32 rand_int_range (int32 begin, int32 end); 00141 double test_rand_double (void); 00142 double test_rand_double_range (double range_start, double range_end); 00143 00144 enum TrapFlags { 00145 TRAP_INHERIT_STDIN = 1 << 0, 00146 TRAP_SILENCE_STDOUT = 1 << 1, 00147 TRAP_SILENCE_STDERR = 1 << 2, 00148 TRAP_NO_FATAL_SYSLOG = 1 << 3, 00149 }; 00150 00151 bool trap_fork (uint64 usec_timeout, uint test_trap_flags); 00152 bool trap_fork_silent (); 00153 bool trap_timed_out (); 00154 bool trap_passed (); 00155 bool trap_aborted (); 00156 bool trap_sigtrap (); 00157 String trap_stdout (); 00158 String trap_stderr (); 00159 00161 #define REGISTER_TEST(name, ...) static const Rapicorn::Test::RegisterTest \ 00162 RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('t', name, __VA_ARGS__) 00163 00165 #define REGISTER_SLOWTEST(name, ...) static const Rapicorn::Test::RegisterTest \ 00166 RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('s', name, __VA_ARGS__) 00167 00169 #define REGISTER_LOGTEST(name, ...) static const Rapicorn::Test::RegisterTest \ 00170 RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('l', name, __VA_ARGS__) 00171 00172 enum ModeType { 00173 MODE_TESTING = 0x1, 00174 MODE_VERBOSE = 0x2, 00175 MODE_READOUT = 0x4, 00176 MODE_SLOW = 0x8, 00177 }; 00178 00179 } // Test 00180 } // Rapicorn 00181 00182 #endif /* __RAPICORN_TESTUTILS_HH__ */