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_eq_l(i, x, y) assert_eq_fn( LOCATION_I( #x " == " #y, i ), x, y )
00030 #define assert_neq(x, y) assert_neq_fn( LOCATION( #x " != " #y ), x, y )
00031 #define assert_list_eq(x, y) \
00032 assert_list_eq_fn( LOCATION( #x " == " #y ), \
00033 sizeof( y ) / sizeof( y[0] ), x, y )
00034 #else
00035 #define assert(x)
00036 #define assert_pred(p, x)
00037 #define assert_eq(x, y)
00038 #define assert_eq_l(i, x, y)
00039 #define assert_neq(x, y)
00040 #define assert_list_eq(x, y)
00041 #endif
00042
00043 #define assert_die() assert_die_fn( LOCATION( "forbidden code path tripped" ) )
00044
00045 struct AssertFailed {
00046 std::ostream &stream;
00047 std::ostringstream str;
00048 bool expect;
00049 AssertFailed( Location l, std::ostream &s = std::cerr )
00050 : stream( s )
00051 {
00052 expect = assertFailure > 0;
00053 str << l.file << ": " << l.line;
00054 if ( l.iteration != -1 )
00055 str << " (iteration " << l.iteration << ")";
00056 str << ": assertion `" << l.stmt << "' failed;";
00057 }
00058
00059 ~AssertFailed() {
00060 if ( expect )
00061 ++assertFailure;
00062 else {
00063 stream << str.str() << std::endl;
00064 abort();
00065 }
00066 }
00067 };
00068
00069 template< typename X >
00070 inline AssertFailed &operator<<( AssertFailed &f, X x )
00071 {
00072 f.str << x;
00073 return f;
00074 }
00075
00076 template< typename X >
00077 void assert_fn( Location l, X x )
00078 {
00079 if ( !x ) {
00080 AssertFailed f( l );
00081 }
00082 }
00083
00084 void assert_die_fn( Location l ) __attribute__((noreturn));
00085
00086 template< typename X, typename Y >
00087 void assert_eq_fn( Location l, X x, Y y )
00088 {
00089 if ( !( x == y ) ) {
00090 AssertFailed f( l );
00091 f << " got ["
00092 << x << "] != [" << y
00093 << "] instead";
00094 }
00095 }
00096
00097 template< typename X >
00098 void assert_pred_fn( Location l, X x, bool p )
00099 {
00100 if ( !p ) {
00101 AssertFailed f( l );
00102 f << " for " << x;
00103 }
00104 }
00105
00106 template< typename X >
00107 void assert_list_eq_fn(
00108 Location loc, int c, X l, const typename X::Type check[] )
00109 {
00110 int i = 0;
00111 while ( !l.empty() ) {
00112 if ( l.head() != check[ i ] ) {
00113 AssertFailed f( loc );
00114 f << " list disagrees at position "
00115 << i << ": [" << wibble::str::fmt( l.head() )
00116 << "] != [" << wibble::str::fmt( check[ i ] )
00117 << "]";
00118 }
00119 l = l.tail();
00120 ++ i;
00121 }
00122 if ( i != c ) {
00123 AssertFailed f( loc );
00124 f << " got ["
00125 << i << "] != [" << c << "] instead";
00126 }
00127 }
00128
00129 template< typename X, typename Y >
00130 void assert_neq_fn( Location l, X x, Y y )
00131 {
00132 if ( x != y )
00133 return;
00134 AssertFailed f( l );
00135 f << " got ["
00136 << x << "] == [" << y << "] instead";
00137 }
00138
00139 inline void beginAssertFailure() {
00140 assertFailure = 1;
00141 }
00142
00143 inline void endAssertFailure() {
00144 int f = assertFailure;
00145 assertFailure = 0;
00146 assert( f > 1 );
00147 }
00148
00149 struct ExpectFailure {
00150 ExpectFailure() { beginAssertFailure(); }
00151 ~ExpectFailure() { endAssertFailure(); }
00152 };
00153
00154 typedef void Test;
00155
00156 #endif