Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
testutils.hh
Go to the documentation of this file.
00001 /* Rapicorn
00002  * Copyright (C) 2008 Tim Janik
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * A copy of the GNU Lesser General Public License should ship along
00015  * with this library; if not, see http://www.gnu.org/copyleft/.
00016  */
00017 #ifndef __RAPICORN_TESTUTILS_HH__
00018 #define __RAPICORN_TESTUTILS_HH__
00019 
00020 #include <rcore/rcore.hh>
00021 
00022 // Test Macros
00023 #define TTITLE(...)             Rapicorn::Test::test_output (3, __VA_ARGS__)
00024 #define TSTART(...)             Rapicorn::Test::test_output (4, __VA_ARGS__)
00025 #define TDONE()                 Rapicorn::Test::test_output (5, "%s", "")
00026 #define TOUT(...)               Rapicorn::Test::test_output (0, __VA_ARGS__)
00027 #define TMSG(...)               Rapicorn::Test::test_output (1, __VA_ARGS__)
00028 #define TINFO(...)              Rapicorn::Test::test_output (2, __VA_ARGS__)
00029 #define TWARN(...)              Rapicorn::Test::test_output (6, __VA_ARGS__)
00030 #define TRUN(name, func)        ({ TSTART (name); func(); TDONE(); })
00031 #define TCMP(a,cmp,b)           TCMP_implf (a,cmp,b)
00032 #define TCMPHEX(a,cmp,b)        TCMP_implx (a,cmp,b)
00033 #define TCMPSIGNED(a,cmp,b)     TCMP_impls (a,cmp,b)
00034 #define TCHECK(code)            TCHECK_impl (code)
00035 #define TASSERT(code)           TCHECK_impl (code)
00036 #define TOK()           do {} while (0) // printerr (".")
00037 #define TCHECK_impl(code)       do { if (code) TOK(); else      \
00038       Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
00039                                   "assertion failed: %s", #code);       \
00040   } while (0)
00041 #define TCMP_implf(a,cmp,b)     do { if (a cmp b) TOK(); else { \
00042   double __tassert_va = a; double __tassert_vb = b;             \
00043   Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
00044                               "assertion failed: %s %s %s: %.17g %s %.17g", \
00045                               #a, #cmp, #b, __tassert_va, #cmp, __tassert_vb); \
00046     } } while (0)
00047 #define TCMP_implx(a,cmp,b)     do { if (a cmp b) TOK(); else { \
00048   uint64 __tassert_va = a; uint64 __tassert_vb = b;             \
00049   Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
00050                               "assertion failed: %s %s %s: 0x%08Lx %s 0x%08Lx", \
00051                               #a, #cmp, #b, __tassert_va, #cmp, __tassert_vb); \
00052     } } while (0)
00053 #define TCMP_impls(a,cmp,b)     do { if (a cmp b) TOK(); else { \
00054   int64 __tassert_va = a; int64 __tassert_vb = b;               \
00055   Rapicorn::Logging::message ("ABORT", RAPICORN__FILE__, __LINE__, RAPICORN__FUNC__.c_str(), \
00056     "assertion failed: %s %s %s: %lld %s %lld",                         \
00057                               #a, #cmp, #b, __tassert_va, #cmp, __tassert_vb); \
00058     } } while (0)
00059 
00060 namespace Rapicorn {
00061 
00062 void init_core_test (const String &app_ident, int *argcp, char **argv, const StringVector &args = StringVector());
00063 
00064 namespace Test {
00065 
00070 class Timer {
00071   const double   m_deadline;
00072   vector<double> m_samples;
00073   double         m_test_duration;
00074   int64          m_n_runs;
00075   int64          loops_needed () const;
00076   void           reset        ();
00077   void           submit       (double elapsed, int64 repetitions);
00078   static double  bench_time   ();
00079 public:
00081   explicit       Timer        (double deadline_in_secs = 0);
00082   virtual       ~Timer        ();
00083   int64          n_runs       () const { return m_n_runs; }             
00084   double         test_elapsed () const { return m_test_duration; }      
00085   double         min_elapsed  () const;         
00086   double         max_elapsed  () const;         
00087   template<typename Callee>
00088   double         benchmark    (Callee callee);
00089 };
00090 
00096 template<typename Callee> double
00097 Timer::benchmark (Callee callee)
00098 {
00099   reset();
00100   for (int64 runs = loops_needed(); runs; runs = loops_needed())
00101     {
00102       int64 n = runs;
00103       const double start = bench_time();
00104       while (RAPICORN_LIKELY (n--))
00105         callee();
00106       const double stop = bench_time();
00107       submit (stop - start, runs);
00108     }
00109   return min_elapsed();
00110 }
00111 
00112 // === test maintenance ===
00113 int     run             (void);         
00114 bool    verbose         (void);         
00115 bool    logging         (void);         
00116 bool    slow            (void);         
00117 bool    ui_test         (void);         
00118 
00119 void    test_output     (int kind, const char *format, ...) RAPICORN_PRINTF (2, 3);
00120 
00121 void    add_internal    (const String &testname,
00122                          void        (*test_func) (void*),
00123                          void         *data);
00124 void    add             (const String &funcname,
00125                          void (*test_func) (void));
00126 template<typename D>
00127 void    add             (const String &testname,
00128                          void        (*test_func) (D*),
00129                          D            *data)
00130 {
00131   add_internal (testname, (void(*)(void*)) test_func, (void*) data);
00132 }
00133 
00134 class RegisterTest {
00135   static void add_test (char kind, const String &testname, void (*test_func) (void*), void *data);
00136 public:
00137   RegisterTest (const char k, const String &testname, void (*test_func) (void))
00138   { add_test (k, testname, (void(*)(void*)) test_func, NULL); }
00139   RegisterTest (const char k, const String &testname, void (*test_func) (ptrdiff_t), ptrdiff_t data)
00140   { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
00141   template<typename D>
00142   RegisterTest (const char k, const String &testname, void (*test_func) (D*), D *data)
00143   { add_test (k, testname, (void(*)(void*)) test_func, (void*) data); }
00144   typedef void (*TestTrigger)  (void (*runner) (void));
00145   static void test_set_trigger (TestTrigger func);
00146 };
00147 
00149 #define REGISTER_TEST(name, ...)     static const Rapicorn::Test::RegisterTest \
00150   RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('t', name, __VA_ARGS__)
00151 
00153 #define REGISTER_SLOWTEST(name, ...) static const Rapicorn::Test::RegisterTest \
00154   RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('s', name, __VA_ARGS__)
00155 
00157 #define REGISTER_LOGTEST(name, ...) static const Rapicorn::Test::RegisterTest \
00158   RAPICORN_CPP_PASTE2 (__Rapicorn_RegisterTest__line, __LINE__) ('l', name, __VA_ARGS__)
00159 
00160 // == Deterministic random numbers for tests ===
00161 char    rand_bit                (void);                                 
00162 int32   rand_int                (void);                                 
00163 int32   rand_int_range          (int32 begin, int32 end);               
00164 double  test_rand_double        (void);                                 
00165 double  test_rand_double_range  (double range_start, double range_end); 
00166 
00167 } // Test
00168 } // Rapicorn
00169 
00170 #endif /* __RAPICORN_TESTUTILS_HH__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines