1 #ifndef __cxxtest__ErrorFormatter_h__
2 #define __cxxtest__ErrorFormatter_h__
4 //
5 // The ErrorFormatter is a TestListener that
6 // prints reports of the errors to an output
7 // stream. Since we cannot rely ou the standard
8 // iostreams, this header defines a base class
9 // analogout to std::ostream.
10 //
12 #include <cxxtest/TestRunner.h>
13 #include <cxxtest/TestListener.h>
14 #include <cxxtest/TestTracker.h>
15 #include <cxxtest/ValueTraits.h>
17 namespace CxxTest
18 {
19 class OutputStream
20 {
21 public:
22 virtual ~OutputStream() {}
23 virtual void flush() {};
24 virtual OutputStream &operator<<( unsigned /*number*/ ) { return *this; }
25 virtual OutputStream &operator<<( const char * /*string*/ ) { return *this; }
27 typedef void (*Manipulator)( OutputStream & );
29 virtual OutputStream &operator<<( Manipulator m ) { m( *this ); return *this; }
30 static void endl( OutputStream &o ) { (o << "\n").flush(); }
31 };
33 class ErrorFormatter : public TestListener
34 {
35 public:
36 ErrorFormatter( OutputStream *o, const char *preLine = ":", const char *postLine = "" ) :
37 _dotting( true ),
38 _reported( false ),
39 _o(o),
40 _preLine(preLine),
41 _postLine(postLine)
42 {
43 }
45 int run()
46 {
47 TestRunner::runAllTests( *this );
48 return tracker().failedTests();
49 }
51 void enterWorld( const WorldDescription & /*desc*/ )
52 {
53 (*_o) << "Running " << totalTests;
54 _o->flush();
55 _dotting = true;
56 _reported = false;
57 }
59 static void totalTests( OutputStream &o )
60 {
61 char s[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
62 const WorldDescription &wd = tracker().world();
63 o << wd.strTotalTests( s ) << (wd.numTotalTests() == 1 ? " test" : " tests");
64 }
66 void enterSuite( const SuiteDescription & )
67 {
68 _reported = false;
69 }
71 void enterTest( const TestDescription & )
72 {
73 _reported = false;
74 }
76 void leaveTest( const TestDescription & )
77 {
78 if ( !tracker().testFailed() ) {
79 ((*_o) << ".").flush();
80 _dotting = true;
81 }
82 }
84 void leaveWorld( const WorldDescription &desc )
85 {
86 if ( !tracker().failedTests() ) {
87 (*_o) << "OK!" << endl;
88 return;
89 }
90 newLine();
91 (*_o) << "Failed " << tracker().failedTests() << " of " << totalTests << endl;
92 unsigned numPassed = desc.numTotalTests() - tracker().failedTests();
93 (*_o) << "Success rate: " << (numPassed * 100 / desc.numTotalTests()) << "%" << endl;
94 }
96 void trace( const char *file, unsigned line, const char *expression )
97 {
98 stop( file, line ) << "Trace: " <<
99 expression << endl;
100 }
102 void warning( const char *file, unsigned line, const char *expression )
103 {
104 stop( file, line ) << "Warning: " <<
105 expression << endl;
106 }
108 void failedTest( const char *file, unsigned line, const char *expression )
109 {
110 stop( file, line ) << "Error: Test failed: " <<
111 expression << endl;
112 }
114 void failedAssert( const char *file, unsigned line, const char *expression )
115 {
116 stop( file, line ) << "Error: Assertion failed: " <<
117 expression << endl;
118 }
120 void failedAssertEquals( const char *file, unsigned line,
121 const char *xStr, const char *yStr,
122 const char *x, const char *y )
123 {
124 stop( file, line ) << "Error: Expected (" <<
125 xStr << " == " << yStr << "), found (" <<
126 x << " != " << y << ")" << endl;
127 }
129 void failedAssertSameData( const char *file, unsigned line,
130 const char *xStr, const char *yStr,
131 const char *sizeStr, const void *x,
132 const void *y, unsigned size )
133 {
134 stop( file, line ) << "Error: Expected " << sizeStr << " (" << size << ") bytes to be equal at (" <<
135 xStr << ") and (" << yStr << "), found:" << endl;
136 dump( x, size );
137 (*_o) << " differs from" << endl;
138 dump( y, size );
139 }
141 void failedAssertDelta( const char *file, unsigned line,
142 const char *xStr, const char *yStr, const char *dStr,
143 const char *x, const char *y, const char *d )
144 {
145 stop( file, line ) << "Error: Expected (" <<
146 xStr << " == " << yStr << ") up to " << dStr << " (" << d << "), found (" <<
147 x << " != " << y << ")" << endl;
148 }
150 void failedAssertDiffers( const char *file, unsigned line,
151 const char *xStr, const char *yStr,
152 const char *value )
153 {
154 stop( file, line ) << "Error: Expected (" <<
155 xStr << " != " << yStr << "), found (" <<
156 value << ")" << endl;
157 }
159 void failedAssertLessThan( const char *file, unsigned line,
160 const char *xStr, const char *yStr,
161 const char *x, const char *y )
162 {
163 stop( file, line ) << "Error: Expected (" <<
164 xStr << " < " << yStr << "), found (" <<
165 x << " >= " << y << ")" << endl;
166 }
168 void failedAssertLessThanEquals( const char *file, unsigned line,
169 const char *xStr, const char *yStr,
170 const char *x, const char *y )
171 {
172 stop( file, line ) << "Error: Expected (" <<
173 xStr << " <= " << yStr << "), found (" <<
174 x << " > " << y << ")" << endl;
175 }
177 void failedAssertRelation( const char *file, unsigned line,
178 const char *relation, const char *xStr, const char *yStr,
179 const char *x, const char *y )
180 {
181 stop( file, line ) << "Error: Expected " << relation << "( " <<
182 xStr << ", " << yStr << " ), found !" << relation << "( " << x << ", " << y << " )" << endl;
183 }
185 void failedAssertPredicate( const char *file, unsigned line,
186 const char *predicate, const char *xStr, const char *x )
187 {
188 stop( file, line ) << "Error: Expected " << predicate << "( " <<
189 xStr << " ), found !" << predicate << "( " << x << " )" << endl;
190 }
192 void failedAssertThrows( const char *file, unsigned line,
193 const char *expression, const char *type,
194 bool otherThrown )
195 {
196 stop( file, line ) << "Error: Expected (" << expression << ") to throw (" <<
197 type << ") but it " << (otherThrown ? "threw something else" : "didn't throw") <<
198 endl;
199 }
201 void failedAssertThrowsNot( const char *file, unsigned line, const char *expression )
202 {
203 stop( file, line ) << "Error: Expected (" << expression << ") not to throw, but it did" <<
204 endl;
205 }
207 protected:
208 OutputStream *outputStream() const
209 {
210 return _o;
211 }
213 private:
214 ErrorFormatter( const ErrorFormatter & );
215 ErrorFormatter &operator=( const ErrorFormatter & );
217 OutputStream &stop( const char *file, unsigned line )
218 {
219 newLine();
220 reportTest();
221 return (*_o) << file << _preLine << line << _postLine << ": ";
222 }
224 void newLine( void )
225 {
226 if ( _dotting ) {
227 (*_o) << endl;
228 _dotting = false;
229 }
230 }
232 void reportTest( void )
233 {
234 if( _reported )
235 return;
236 (*_o) << "In " << tracker().suite().suiteName() << "::" << tracker().test().testName() << ":" << endl;
237 _reported = true;
238 }
240 void dump( const void *buffer, unsigned size )
241 {
242 if ( !buffer )
243 dumpNull();
244 else
245 dumpBuffer( buffer, size );
246 }
248 void dumpNull()
249 {
250 (*_o) << " (null)" << endl;
251 }
253 void dumpBuffer( const void *buffer, unsigned size )
254 {
255 unsigned dumpSize = size;
256 if ( maxDumpSize() && dumpSize > maxDumpSize() )
257 dumpSize = maxDumpSize();
259 const unsigned char *p = (const unsigned char *)buffer;
260 (*_o) << " { ";
261 for ( unsigned i = 0; i < dumpSize; ++ i )
262 (*_o) << byteToHex( *p++ ) << " ";
263 if ( dumpSize < size )
264 (*_o) << "... ";
265 (*_o) << "}" << endl;
266 }
268 static void endl( OutputStream &o )
269 {
270 OutputStream::endl( o );
271 }
273 bool _dotting;
274 bool _reported;
275 OutputStream *_o;
276 const char *_preLine;
277 const char *_postLine;
278 };
279 };
281 #endif // __cxxtest__ErrorFormatter_h__