test.h
Go to the documentation of this file.
// -*- C++ -*-
#include <wibble/string.h>
#include <iostream>
#include <cstdlib>
#ifndef WIBBLE_TEST_H
#define WIBBLE_TEST_H
namespace wibble {
// TODO use TLS
extern int assertFailure;
struct Location {
const char *file;
int line, iteration;
std::string stmt;
Location( const char *f, int l, std::string st, int iter = -1 )
: file( f ), line( l ), iteration( iter ), stmt( st ) {}
};
#define LOCATION(stmt) ::wibble::Location( __FILE__, __LINE__, stmt )
#undef assert // silence a gcc warning if we had assert.h included
#ifndef NDEBUG
#define LOCATION_I(stmt, i) ::wibble::Location( __FILE__, __LINE__, stmt, i )
#define assert(x) assert_fn( LOCATION( #x ), x )
#define assert_pred(p, x) assert_pred_fn( \
LOCATION( #p "( " #x " )" ), x, p( x ) )
#define assert_eq(x, y) assert_eq_fn( LOCATION( #x " == " #y ), x, y )
#define assert_leq(x, y) assert_leq_fn( LOCATION( #x " <= " #y ), x, y )
#define assert_eq_l(i, x, y) assert_eq_fn( LOCATION_I( #x " == " #y, i ), x, y )
#define assert_neq(x, y) assert_neq_fn( LOCATION( #x " != " #y ), x, y )
#define assert_list_eq(x, y) \
assert_list_eq_fn( LOCATION( #x " == " #y ), \
sizeof( y ) / sizeof( y[0] ), x, y )
#else
#define assert(x) ((void)0)
#define assert_pred(p, x) ((void)0)
#define assert_eq(x, y) ((void)0)
#define assert_leq(x, y) ((void)0)
#define assert_eq_l(i, x, y) ((void)0)
#define assert_neq(x, y) ((void)0)
#define assert_list_eq(x, y) ((void)0)
#endif
#define assert_unreachable(...) assert_die_fn( LOCATION( wibble::str::fmtf(__VA_ARGS__) ) )
#define assert_unimplemented() assert_die_fn( LOCATION( "not imlemented" ) )
#define assert_die() assert_die_fn( LOCATION( "forbidden code path tripped" ) )
struct AssertFailed {
std::ostream &stream;
std::ostringstream str;
bool expect;
AssertFailed( Location l, std::ostream &s = std::cerr )
: stream( s )
{
expect = assertFailure > 0;
str << l.file << ": " << l.line;
if ( l.iteration != -1 )
str << " (iteration " << l.iteration << ")";
str << ": assertion `" << l.stmt << "' failed;";
}
~AssertFailed() {
if ( expect )
++assertFailure;
else {
stream << str.str() << std::endl;
abort();
}
}
};
template< typename X >
inline AssertFailed &operator<<( AssertFailed &f, X x )
{
f.str << x;
return f;
}
template< typename X >
void assert_fn( Location l, X x )
{
if ( !x ) {
AssertFailed f( l );
}
}
void assert_die_fn( Location l ) __attribute__((noreturn));
template< typename X, typename Y >
void assert_eq_fn( Location l, X x, Y y )
{
if ( !( x == y ) ) {
AssertFailed f( l );
f << " got ["
<< x << "] != [" << y
<< "] instead";
}
}
template< typename X, typename Y >
void assert_leq_fn( Location l, X x, Y y )
{
if ( !( x <= y ) ) {
AssertFailed f( l );
f << " got ["
<< x << "] > [" << y
<< "] instead";
}
}
template< typename X >
void assert_pred_fn( Location l, X x, bool p )
{
if ( !p ) {
AssertFailed f( l );
f << " for " << x;
}
}
template< typename X >
void assert_list_eq_fn(
Location loc, int c, X l, const typename X::Type check[] )
{
int i = 0;
while ( !l.empty() ) {
if ( l.head() != check[ i ] ) {
AssertFailed f( loc );
f << " list disagrees at position "
<< i << ": [" << wibble::str::fmt( l.head() )
<< "] != [" << wibble::str::fmt( check[ i ] )
<< "]";
}
l = l.tail();
++ i;
}
if ( i != c ) {
AssertFailed f( loc );
f << " got ["
<< i << "] != [" << c << "] instead";
}
}
template< typename X, typename Y >
void assert_neq_fn( Location l, X x, Y y )
{
if ( x != y )
return;
AssertFailed f( l );
f << " got ["
<< x << "] == [" << y << "] instead";
}
inline void beginAssertFailure() {
assertFailure = 1;
}
inline void endAssertFailure() {
#ifndef NDEBUG
const int f = assertFailure;
assertFailure = 0;
#endif
assert( f > 1 );
}
struct ExpectFailure {
ExpectFailure() { beginAssertFailure(); }
~ExpectFailure() { endAssertFailure(); }
};
}
typedef void Test;
#endif
wibble::operator<<
std::ostream & operator<<(std::ostream &o, const std::pair< X, Y > &x)
Definition: parse.h:52
wibble::AssertFailed::str
std::ostringstream str
Definition: test.h:56
string.h
wibble::Location::iteration
int iteration
Definition: test.h:17
Test
void Test
Definition: test.h:178
wibble::assertFailure
int assertFailure
Definition: test.cpp:4
wibble::ExpectFailure::~ExpectFailure
~ExpectFailure()
Definition: test.h:173
wibble::ExpectFailure::ExpectFailure
ExpectFailure()
Definition: test.h:172
wibble::assert_pred_fn
void assert_pred_fn(Location l, X x, bool p)
Definition: test.h:118
wibble::assert_fn
void assert_fn(Location l, X x)
Definition: test.h:86
wibble::ExpectFailure
Definition: test.h:171
wibble::AssertFailed::stream
std::ostream & stream
Definition: test.h:55
wibble::assert_eq_fn
void assert_eq_fn(Location l, X x, Y y)
Definition: test.h:96
assert
#define assert(x)
Definition: test.h:30
wibble::assert_leq_fn
void assert_leq_fn(Location l, X x, Y y)
Definition: test.h:107
wibble::assert_neq_fn
void assert_neq_fn(Location l, X x, Y y)
Definition: test.h:150
wibble::assert_list_eq_fn
void assert_list_eq_fn(Location loc, int c, X l, const typename X::Type check[])
Definition: test.h:127
wibble::AssertFailed::~AssertFailed
~AssertFailed()
Definition: test.h:68
wibble::str::fmt
std::string fmt(const char *f,...)
Definition: string.cpp:123
wibble::Location
Definition: test.h:15
wibble::assert_die_fn
void assert_die_fn(Location l)
Definition: test.cpp:6
wibble::Location::line
int line
Definition: test.h:17
wibble::beginAssertFailure
void beginAssertFailure()
Definition: test.h:159
wibble::Location::Location
Location(const char *f, int l, std::string st, int iter=-1)
Definition: test.h:19
wibble::AssertFailed
Definition: test.h:54
wibble
Definition: amorph.h:17
wibble::AssertFailed::AssertFailed
AssertFailed(Location l, std::ostream &s=std::cerr)
Definition: test.h:58
wibble::Location::file
const char * file
Definition: test.h:16
wibble::Location::stmt
std::string stmt
Definition: test.h:18
wibble::endAssertFailure
void endAssertFailure()
Definition: test.h:163
wibble::AssertFailed::expect
bool expect
Definition: test.h:57