wibble 0.1.28
|
00001 // -*- C++ -*- 00002 00003 #include <wibble/string.h> 00004 #include <iostream> 00005 #include <cstdlib> 00006 00007 #ifndef WIBBLE_TEST_H 00008 #define WIBBLE_TEST_H 00009 00010 // TODO use TLS 00011 extern int assertFailure; 00012 00013 struct Location { 00014 const char *file; 00015 int line, iteration; 00016 const char *stmt; 00017 Location( const char *f, int l, const char *st, int iter = -1 ) 00018 : file( f ), line( l ), iteration( iter ), stmt( st ) {} 00019 }; 00020 00021 #define LOCATION(stmt) Location( __FILE__, __LINE__, stmt ) 00022 00023 #ifndef NDEBUG 00024 #define LOCATION_I(stmt, i) Location( __FILE__, __LINE__, stmt, i ) 00025 #define assert(x) assert_fn( LOCATION( #x ), x ) 00026 #define assert_pred(p, x) assert_pred_fn( \ 00027 LOCATION( #p "( " #x " )" ), x, p( x ) ) 00028 #define assert_eq(x, y) assert_eq_fn( LOCATION( #x " == " #y ), x, y ) 00029 #define assert_leq(x, y) assert_leq_fn( LOCATION( #x " <= " #y ), x, y ) 00030 #define assert_eq_l(i, x, y) assert_eq_fn( LOCATION_I( #x " == " #y, i ), x, y ) 00031 #define assert_neq(x, y) assert_neq_fn( LOCATION( #x " != " #y ), x, y ) 00032 #define assert_list_eq(x, y) \ 00033 assert_list_eq_fn( LOCATION( #x " == " #y ), \ 00034 sizeof( y ) / sizeof( y[0] ), x, y ) 00035 #else 00036 #define assert(x) ((void)0) 00037 #define assert_pred(p, x) ((void)0) 00038 #define assert_eq(x, y) ((void)0) 00039 #define assert_leq(x, y) ((void)0) 00040 #define assert_eq_l(i, x, y) ((void)0) 00041 #define assert_neq(x, y) ((void)0) 00042 #define assert_list_eq(x, y) ((void)0) 00043 #endif 00044 00045 #define assert_die() assert_die_fn( LOCATION( "forbidden code path tripped" ) ) 00046 00047 struct AssertFailed { 00048 std::ostream &stream; 00049 std::ostringstream str; 00050 bool expect; 00051 AssertFailed( Location l, std::ostream &s = std::cerr ) 00052 : stream( s ) 00053 { 00054 expect = assertFailure > 0; 00055 str << l.file << ": " << l.line; 00056 if ( l.iteration != -1 ) 00057 str << " (iteration " << l.iteration << ")"; 00058 str << ": assertion `" << l.stmt << "' failed;"; 00059 } 00060 00061 ~AssertFailed() { 00062 if ( expect ) 00063 ++assertFailure; 00064 else { 00065 stream << str.str() << std::endl; 00066 abort(); 00067 } 00068 } 00069 }; 00070 00071 template< typename X > 00072 inline AssertFailed &operator<<( AssertFailed &f, X x ) 00073 { 00074 f.str << x; 00075 return f; 00076 } 00077 00078 template< typename X > 00079 void assert_fn( Location l, X x ) 00080 { 00081 if ( !x ) { 00082 AssertFailed f( l ); 00083 } 00084 } 00085 00086 void assert_die_fn( Location l ) __attribute__((noreturn)); 00087 00088 template< typename X, typename Y > 00089 void assert_eq_fn( Location l, X x, Y y ) 00090 { 00091 if ( !( x == y ) ) { 00092 AssertFailed f( l ); 00093 f << " got [" 00094 << x << "] != [" << y 00095 << "] instead"; 00096 } 00097 } 00098 00099 template< typename X, typename Y > 00100 void assert_leq_fn( Location l, X x, Y y ) 00101 { 00102 if ( !( x <= y ) ) { 00103 AssertFailed f( l ); 00104 f << " got [" 00105 << x << "] > [" << y 00106 << "] instead"; 00107 } 00108 } 00109 00110 template< typename X > 00111 void assert_pred_fn( Location l, X x, bool p ) 00112 { 00113 if ( !p ) { 00114 AssertFailed f( l ); 00115 f << " for " << x; 00116 } 00117 } 00118 00119 template< typename X > 00120 void assert_list_eq_fn( 00121 Location loc, int c, X l, const typename X::Type check[] ) 00122 { 00123 int i = 0; 00124 while ( !l.empty() ) { 00125 if ( l.head() != check[ i ] ) { 00126 AssertFailed f( loc ); 00127 f << " list disagrees at position " 00128 << i << ": [" << wibble::str::fmt( l.head() ) 00129 << "] != [" << wibble::str::fmt( check[ i ] ) 00130 << "]"; 00131 } 00132 l = l.tail(); 00133 ++ i; 00134 } 00135 if ( i != c ) { 00136 AssertFailed f( loc ); 00137 f << " got [" 00138 << i << "] != [" << c << "] instead"; 00139 } 00140 } 00141 00142 template< typename X, typename Y > 00143 void assert_neq_fn( Location l, X x, Y y ) 00144 { 00145 if ( x != y ) 00146 return; 00147 AssertFailed f( l ); 00148 f << " got [" 00149 << x << "] == [" << y << "] instead"; 00150 } 00151 00152 inline void beginAssertFailure() { 00153 assertFailure = 1; 00154 } 00155 00156 inline void endAssertFailure() { 00157 int f = assertFailure; 00158 assertFailure = 0; 00159 assert( f > 1 ); 00160 } 00161 00162 struct ExpectFailure { 00163 ExpectFailure() { beginAssertFailure(); } 00164 ~ExpectFailure() { endAssertFailure(); } 00165 }; 00166 00167 typedef void Test; 00168 00169 #endif