1 #ifndef PYLOG_FORMATTER_H_SEEN
2 #define PYLOG_FORMATTER_H_SEEN
4 #include <cxxtest/Flags.h>
6 #ifndef _CXXTEST_HAVE_STD
7 # define _CXXTEST_HAVE_STD
8 #endif // _CXXTEST_HAVE_STD
10 #include <cxxtest/ErrorFormatter.h>
11 #include <cxxtest/StdValueTraits.h>
13 #ifdef _CXXTEST_OLD_STD
14 # include <iostream.h>
15 #else // !_CXXTEST_OLD_STD
16 # include <iostream>
17 #endif // _CXXTEST_OLD_STD
19 namespace CxxTest
20 {
21 class PylogFormatter : public TestListener
22 {
23 public:
24 PylogFormatter( OutputStream *o, const char* name = "test" ) :
25 _o(o),
26 _base( _chompPath( name ) ),
27 _runPassed(true),
28 _suiteIndex(-1),
29 _testIndex(-1)
30 {}
31 virtual ~PylogFormatter() { delete outputStream(); }
33 virtual void enterWorld( const WorldDescription & desc )
34 {
35 (*_o) << "**************************************************" << endl;
36 _o->flush();
37 }
39 virtual void leaveWorld( const WorldDescription & desc )
40 {
41 unsigned int skippedCount = 0;
42 unsigned int failedCount = 0;
43 unsigned int warnedCount = 0;
44 unsigned int passedCount = 0;
46 for ( unsigned int i = 0; i < desc.numSuites(); i++ ) {
47 const SuiteDescription& suite = desc.suiteDescription(i);
48 for ( unsigned int j = 0; j < suite.numTests(); j++ ) {
49 const TestDescription& test = suite.testDescription(j);
51 // Test Name
52 (*_o) << _base.c_str() << "_";
53 _padOut( i, 3 );
54 (*_o) << "_";
55 _padOut( j, 3);
56 (*_o) << " ";
58 // Test Description
59 (*_o) << test.suiteName() << "_|_" << test.testName();
60 (*_o) << " ";
62 int sent = strlen( test.suiteName() ) + strlen( test.testName() ) + 1;
63 for ( int z = sent; z < 56; z++ ) {
64 (*_o) << " ";
65 }
67 (*_o) << " : ";
69 switch ( _status[i][j] ) {
70 case OK:
71 (*_o) << "PASS";
72 passedCount++;
73 break;
74 case SKIPPED:
75 (*_o) << "OMIT";
76 skippedCount++;
77 break;
78 case WARNING:
79 (*_o) << "WARNING";
80 warnedCount++;
81 break;
82 case ERROR:
83 (*_o) << "FAILURE";
84 failedCount++;
85 break;
86 }
88 (*_o) << endl;
89 for ( CXXTEST_STD(vector)<CXXTEST_STD(string)>::iterator it = _messages[i][j].begin(); it < _messages[i][j].end(); ++it ) {
90 (*_o) << " " << (*it).c_str() << endl;
91 }
92 }
93 }
95 (*_o) << "**************************************************" << endl;
96 (*_o) << "Command line asked for " << desc.numTotalTests() << " of " << desc.numTotalTests() << " tests" << endl;
97 (*_o) << "Of those: "
98 << skippedCount << " Skipped, "
99 << failedCount << " Failed, "
100 << warnedCount << " Warned, "
101 << passedCount << " Passed"
102 << endl;
103 }
106 virtual void enterSuite( const SuiteDescription & desc )
107 {
108 (void)desc;
109 _suiteIndex++;
110 _testIndex = -1;
111 while ( (_suiteIndex >= 0) && ((int)_status.size() <= _suiteIndex) ) {
112 CXXTEST_STD(vector)<ErrorLevel> tmp;
113 _status.push_back(tmp);
114 CXXTEST_STD(vector)<CXXTEST_STD(vector)<CXXTEST_STD(string)> > tmp2;
115 _messages.push_back(tmp2);
116 }
117 }
119 virtual void leaveSuite( const SuiteDescription & desc )
120 {
121 (void)desc;
122 }
124 virtual void enterTest( const TestDescription & desc )
125 {
126 (void)desc;
127 if ( _suiteIndex >= 0 && (int)_status.size() > _suiteIndex ) {
128 _testIndex++;
129 while ( (_testIndex >= 0) && ((int)_status[_suiteIndex].size() <= _testIndex) ) {
130 ErrorLevel tmp = OK;
131 _status[_suiteIndex].push_back(tmp);
132 CXXTEST_STD(vector)<CXXTEST_STD(string)> tmp2;
133 _messages[_suiteIndex].push_back(tmp2);
134 }
135 }
136 }
138 virtual void leaveTest( const TestDescription & desc )
139 {
140 (void)desc;
141 }
143 virtual void trace( const char * file, unsigned line,
144 const char * expression )
145 {
146 CXXTEST_STD(string)tmp(expression);
147 _traceCurrent( file, line, tmp );
148 }
150 virtual void warning( const char * file, unsigned line,
151 const char * expression )
152 {
153 CXXTEST_STD(string)tmp(expression);
154 _warnCurrent( file, line, tmp );
155 }
157 virtual void failedTest( const char * file, unsigned line,
158 const char * expression )
159 {
160 CXXTEST_STD(string)tmp(expression);
161 _failCurrent( file, line, tmp );
162 }
164 virtual void failedAssert( const char * file, unsigned line,
165 const char * expression )
166 {
167 CXXTEST_STD(string)tmp(expression);
168 _failCurrent( file, line, tmp );
169 }
171 virtual void failedAssertEquals( const char * file, unsigned line,
172 const char * xStr, const char * yStr,
173 const char * x, const char * y )
174 {
175 CXXTEST_STD(string)tmp;
176 tmp += "Expected (";
177 tmp += xStr;
178 tmp += " == ";
179 tmp += yStr;
180 tmp += "), found (";
181 tmp += x;
182 tmp += " != ";
183 tmp += y;
184 tmp += ")";
185 _failCurrent( file, line, tmp );
186 }
188 virtual void failedAssertSameData( const char * file, unsigned line,
189 const char * /*xStr*/, const char * /*yStr*/,
190 const char * /*sizeStr*/, const void * /*x*/,
191 const void * /*y*/, unsigned /*size*/ )
192 {
193 CXXTEST_STD(string)tmp("TODO - fill in error details");
194 _failCurrent( file, line, tmp );
195 }
197 virtual void failedAssertDelta( const char * file, unsigned line,
198 const char * /*xStr*/, const char * /*yStr*/,
199 const char * /*dStr*/, const char * /*x*/,
200 const char * /*y*/, const char * /*d*/ )
201 {
202 CXXTEST_STD(string)tmp("TODO - fill in error details");
203 _failCurrent( file, line, tmp );
204 }
206 virtual void failedAssertDiffers( const char * file, unsigned line,
207 const char * xStr, const char * yStr,
208 const char * value )
209 {
210 CXXTEST_STD(string)tmp;
211 tmp += "Expected (";
212 tmp += xStr;
213 tmp += " != ";
214 tmp += yStr;
215 tmp += "), found (";
216 tmp += value;
217 tmp += ")";
218 _failCurrent( file, line, tmp );
219 }
221 virtual void failedAssertLessThan( const char * file, unsigned line,
222 const char * xStr, const char * yStr,
223 const char * x, const char * y )
224 {
225 CXXTEST_STD(string)tmp;
226 tmp += "Expected (";
227 tmp += xStr;
228 tmp += " < ";
229 tmp += yStr;
230 tmp += "), found (";
231 tmp += x;
232 tmp += " >= ";
233 tmp += y;
234 tmp += ")";
235 _failCurrent( file, line, tmp );
236 }
238 virtual void failedAssertLessThanEquals( const char * file, unsigned line,
239 const char * xStr, const char * yStr,
240 const char * x, const char * y )
241 {
242 CXXTEST_STD(string)tmp;
243 tmp += "Expected (";
244 tmp += xStr;
245 tmp += " <= ";
246 tmp += yStr;
247 tmp += "), found (";
248 tmp += x;
249 tmp += " > ";
250 tmp += y;
251 tmp += ")";
252 _failCurrent( file, line, tmp );
253 }
255 virtual void failedAssertPredicate( const char * file, unsigned line,
256 const char * /*predicate*/, const char * /*xStr*/, const char * /*x*/ )
257 {
258 CXXTEST_STD(string)tmp("TODO - fill in error details");
259 _failCurrent( file, line, tmp );
260 }
262 virtual void failedAssertRelation( const char * file, unsigned line,
263 const char * /*relation*/, const char * /*xStr*/, const char * /*yStr*/,
264 const char * /*x*/, const char * /*y*/ )
265 {
266 CXXTEST_STD(string)tmp("TODO - fill in error details");
267 _failCurrent( file, line, tmp);
268 }
270 virtual void failedAssertThrows( const char * file, unsigned line,
271 const char * /*expression*/, const char * /*type*/,
272 bool /*otherThrown*/ )
273 {
274 CXXTEST_STD(string)tmp("TODO - fill in error details");
275 _failCurrent( file, line, tmp );
276 }
278 virtual void failedAssertThrowsNot( const char * file, unsigned line,
279 const char * expression )
280 {
281 CXXTEST_STD(string)tmp(expression);
282 _failCurrent( file, line, tmp );
283 }
285 protected:
287 enum ErrorLevel {
288 OK,
289 SKIPPED,
290 WARNING,
291 ERROR
292 };
294 OutputStream *outputStream() const
295 {
296 return _o;
297 }
299 void _traceCurrent( const char* file, unsigned line, const CXXTEST_STD(string)& errMsg ) {
300 _runPassed = false;
301 if ( _suiteIndex < (int)_status.size() ) {
302 if ( _testIndex < (int)_status[_suiteIndex].size() ) {
303 _messages[_suiteIndex][_testIndex].push_back( errMsg );
304 }
305 }
306 }
308 void _warnCurrent( const char* file, unsigned line, const CXXTEST_STD(string)& errMsg ) {
309 _runPassed = false;
310 if ( _suiteIndex < (int)_status.size() ) {
311 if ( _testIndex < (int)_status[_suiteIndex].size() ) {
312 if ( _status[_suiteIndex][_testIndex] != ERROR ) {
313 _status[_suiteIndex][_testIndex] = WARNING;
314 }
316 _messages[_suiteIndex][_testIndex].push_back( errMsg );
317 }
318 }
319 }
321 void _failCurrent( const char* file, unsigned line, const CXXTEST_STD(string)& errMsg ) {
322 _runPassed = false;
323 if ( _suiteIndex < (int)_status.size() ) {
324 if ( _testIndex < (int)_status[_suiteIndex].size() ) {
325 _status[_suiteIndex][_testIndex] = ERROR;
327 _messages[_suiteIndex][_testIndex].push_back( errMsg );
328 }
329 }
330 }
332 void _padOut( unsigned int num, int digits )
333 {
334 int match = 1;
335 for ( int j = 1; j < digits; j++ ) {
336 match *= 10;
337 }
339 for ( unsigned int i = match; i > 1 && i > num; i /= 10 )
340 {
341 (*_o) << "0";
342 }
343 (*_o) << num;
344 }
346 private:
347 static void endl( OutputStream &o )
348 {
349 OutputStream::endl( o );
350 }
352 static CXXTEST_STD(string) _chompPath( const char* str )
353 {
354 CXXTEST_STD(string) tmp( str );
355 if ( tmp.length() > 2 && tmp[0] == '.' && tmp[1] == '/' ) {
356 tmp = tmp.substr( 2 );
357 }
358 return tmp;
359 }
361 OutputStream *_o;
362 CXXTEST_STD(string) _base;
363 CXXTEST_STD(vector)< CXXTEST_STD(vector)<ErrorLevel> > _status;
364 CXXTEST_STD(vector)< CXXTEST_STD(vector)< CXXTEST_STD(vector)<CXXTEST_STD(string)> > > _messages;
366 bool _runPassed;
367 int _suiteIndex;
368 int _testIndex;
369 };
371 } // namespace CxxTest
373 /*
374 Local Variables:
375 mode:c++
376 c-file-style:"stroustrup"
377 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
378 indent-tabs-mode:nil
379 fill-column:99
380 End:
381 */
382 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
384 #endif // PYLOG_FORMATTER_H_SEEN