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