Rapicorn - Experimental UI Toolkit - Source Code  13.07.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
testutils.hh
Go to the documentation of this file.
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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines