00001
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
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)
00037 #define assert_pred(p, x)
00038 #define assert_eq(x, y)
00039 #define assert_leq(x, y)
00040 #define assert_eq_l(i, x, y)
00041 #define assert_neq(x, y)
00042 #define assert_list_eq(x, y)
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