wibble  0.1.28
test.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 #include <wibble/string.h>
4 #include <iostream>
5 #include <cstdlib>
6 
7 #ifndef WIBBLE_TEST_H
8 #define WIBBLE_TEST_H
9 
10 // TODO use TLS
11 extern int assertFailure;
12 
13 struct Location {
14  const char *file;
16  const char *stmt;
17  Location( const char *f, int l, const char *st, int iter = -1 )
18  : file( f ), line( l ), iteration( iter ), stmt( st ) {}
19 };
20 
21 #define LOCATION(stmt) Location( __FILE__, __LINE__, stmt )
22 
23 #ifndef NDEBUG
24 #define LOCATION_I(stmt, i) Location( __FILE__, __LINE__, stmt, i )
25 #define assert(x) assert_fn( LOCATION( #x ), x )
26 #define assert_pred(p, x) assert_pred_fn( \
27  LOCATION( #p "( " #x " )" ), x, p( x ) )
28 #define assert_eq(x, y) assert_eq_fn( LOCATION( #x " == " #y ), x, y )
29 #define assert_leq(x, y) assert_leq_fn( LOCATION( #x " <= " #y ), x, y )
30 #define assert_eq_l(i, x, y) assert_eq_fn( LOCATION_I( #x " == " #y, i ), x, y )
31 #define assert_neq(x, y) assert_neq_fn( LOCATION( #x " != " #y ), x, y )
32 #define assert_list_eq(x, y) \
33  assert_list_eq_fn( LOCATION( #x " == " #y ), \
34  sizeof( y ) / sizeof( y[0] ), x, y )
35 #else
36 #define assert(x) ((void)0)
37 #define assert_pred(p, x) ((void)0)
38 #define assert_eq(x, y) ((void)0)
39 #define assert_leq(x, y) ((void)0)
40 #define assert_eq_l(i, x, y) ((void)0)
41 #define assert_neq(x, y) ((void)0)
42 #define assert_list_eq(x, y) ((void)0)
43 #endif
44 
45 #define assert_die() assert_die_fn( LOCATION( "forbidden code path tripped" ) )
46 
47 struct AssertFailed {
48  std::ostream &stream;
49  std::ostringstream str;
50  bool expect;
51  AssertFailed( Location l, std::ostream &s = std::cerr )
52  : stream( s )
53  {
54  expect = assertFailure > 0;
55  str << l.file << ": " << l.line;
56  if ( l.iteration != -1 )
57  str << " (iteration " << l.iteration << ")";
58  str << ": assertion `" << l.stmt << "' failed;";
59  }
60 
62  if ( expect )
63  ++assertFailure;
64  else {
65  stream << str.str() << std::endl;
66  abort();
67  }
68  }
69 };
70 
71 template< typename X >
73 {
74  f.str << x;
75  return f;
76 }
77 
78 template< typename X >
79 void assert_fn( Location l, X x )
80 {
81  if ( !x ) {
82  AssertFailed f( l );
83  }
84 }
85 
86 void assert_die_fn( Location l ) __attribute__((noreturn));
87 
88 template< typename X, typename Y >
89 void assert_eq_fn( Location l, X x, Y y )
90 {
91  if ( !( x == y ) ) {
92  AssertFailed f( l );
93  f << " got ["
94  << x << "] != [" << y
95  << "] instead";
96  }
97 }
98 
99 template< typename X, typename Y >
100 void assert_leq_fn( Location l, X x, Y y )
101 {
102  if ( !( x <= y ) ) {
103  AssertFailed f( l );
104  f << " got ["
105  << x << "] > [" << y
106  << "] instead";
107  }
108 }
109 
110 template< typename X >
111 void assert_pred_fn( Location l, X x, bool p )
112 {
113  if ( !p ) {
114  AssertFailed f( l );
115  f << " for " << x;
116  }
117 }
118 
119 template< typename X >
121  Location loc, int c, X l, const typename X::Type check[] )
122 {
123  int i = 0;
124  while ( !l.empty() ) {
125  if ( l.head() != check[ i ] ) {
126  AssertFailed f( loc );
127  f << " list disagrees at position "
128  << i << ": [" << wibble::str::fmt( l.head() )
129  << "] != [" << wibble::str::fmt( check[ i ] )
130  << "]";
131  }
132  l = l.tail();
133  ++ i;
134  }
135  if ( i != c ) {
136  AssertFailed f( loc );
137  f << " got ["
138  << i << "] != [" << c << "] instead";
139  }
140 }
141 
142 template< typename X, typename Y >
143 void assert_neq_fn( Location l, X x, Y y )
144 {
145  if ( x != y )
146  return;
147  AssertFailed f( l );
148  f << " got ["
149  << x << "] == [" << y << "] instead";
150 }
151 
152 inline void beginAssertFailure() {
153  assertFailure = 1;
154 }
155 
156 inline void endAssertFailure() {
157  int f = assertFailure;
158  assertFailure = 0;
159  assert( f > 1 );
160 }
161 
165 };
166 
167 typedef void Test;
168 
169 #endif