1 | #ifndef __cxxtest__ErrorFormatter_h__ |
---|
2 | #define __cxxtest__ErrorFormatter_h__ |
---|
3 | |
---|
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 | // |
---|
11 | |
---|
12 | #include <cxxtest/TestRunner.h> |
---|
13 | #include <cxxtest/TestListener.h> |
---|
14 | #include <cxxtest/TestTracker.h> |
---|
15 | #include <cxxtest/ValueTraits.h> |
---|
16 | |
---|
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; } |
---|
26 | |
---|
27 | typedef void (*Manipulator)( OutputStream & ); |
---|
28 | |
---|
29 | virtual OutputStream &operator<<( Manipulator m ) { m( *this ); return *this; } |
---|
30 | static void endl( OutputStream &o ) { (o << "\n").flush(); } |
---|
31 | }; |
---|
32 | |
---|
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 | } |
---|
44 | |
---|
45 | int run() |
---|
46 | { |
---|
47 | TestRunner::runAllTests( *this ); |
---|
48 | return tracker().failedTests(); |
---|
49 | } |
---|
50 | |
---|
51 | void enterWorld( const WorldDescription & /*desc*/ ) |
---|
52 | { |
---|
53 | (*_o) << "Running " << totalTests; |
---|
54 | _o->flush(); |
---|
55 | _dotting = true; |
---|
56 | _reported = false; |
---|
57 | } |
---|
58 | |
---|
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 | } |
---|
65 | |
---|
66 | void enterSuite( const SuiteDescription & ) |
---|
67 | { |
---|
68 | _reported = false; |
---|
69 | } |
---|
70 | |
---|
71 | void enterTest( const TestDescription & ) |
---|
72 | { |
---|
73 | _reported = false; |
---|
74 | } |
---|
75 | |
---|
76 | void leaveTest( const TestDescription & ) |
---|
77 | { |
---|
78 | if ( !tracker().testFailed() ) { |
---|
79 | ((*_o) << ".").flush(); |
---|
80 | _dotting = true; |
---|
81 | } |
---|
82 | } |
---|
83 | |
---|
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 | } |
---|
95 | |
---|
96 | void trace( const char *file, unsigned line, const char *expression ) |
---|
97 | { |
---|
98 | stop( file, line ) << "Trace: " << |
---|
99 | expression << endl; |
---|
100 | } |
---|
101 | |
---|
102 | void warning( const char *file, unsigned line, const char *expression ) |
---|
103 | { |
---|
104 | stop( file, line ) << "Warning: " << |
---|
105 | expression << endl; |
---|
106 | } |
---|
107 | |
---|
108 | void failedTest( const char *file, unsigned line, const char *expression ) |
---|
109 | { |
---|
110 | stop( file, line ) << "Error: Test failed: " << |
---|
111 | expression << endl; |
---|
112 | } |
---|
113 | |
---|
114 | void failedAssert( const char *file, unsigned line, const char *expression ) |
---|
115 | { |
---|
116 | stop( file, line ) << "Error: Assertion failed: " << |
---|
117 | expression << endl; |
---|
118 | } |
---|
119 | |
---|
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 | } |
---|
128 | |
---|
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 | } |
---|
140 | |
---|
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 | } |
---|
149 | |
---|
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 | } |
---|
158 | |
---|
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 | } |
---|
167 | |
---|
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 | } |
---|
176 | |
---|
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 | } |
---|
184 | |
---|
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 | } |
---|
191 | |
---|
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 | } |
---|
200 | |
---|
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 | } |
---|
206 | |
---|
207 | protected: |
---|
208 | OutputStream *outputStream() const |
---|
209 | { |
---|
210 | return _o; |
---|
211 | } |
---|
212 | |
---|
213 | private: |
---|
214 | ErrorFormatter( const ErrorFormatter & ); |
---|
215 | ErrorFormatter &operator=( const ErrorFormatter & ); |
---|
216 | |
---|
217 | OutputStream &stop( const char *file, unsigned line ) |
---|
218 | { |
---|
219 | newLine(); |
---|
220 | reportTest(); |
---|
221 | return (*_o) << file << _preLine << line << _postLine << ": "; |
---|
222 | } |
---|
223 | |
---|
224 | void newLine( void ) |
---|
225 | { |
---|
226 | if ( _dotting ) { |
---|
227 | (*_o) << endl; |
---|
228 | _dotting = false; |
---|
229 | } |
---|
230 | } |
---|
231 | |
---|
232 | void reportTest( void ) |
---|
233 | { |
---|
234 | if( _reported ) |
---|
235 | return; |
---|
236 | (*_o) << "In " << tracker().suite().suiteName() << "::" << tracker().test().testName() << ":" << endl; |
---|
237 | _reported = true; |
---|
238 | } |
---|
239 | |
---|
240 | void dump( const void *buffer, unsigned size ) |
---|
241 | { |
---|
242 | if ( !buffer ) |
---|
243 | dumpNull(); |
---|
244 | else |
---|
245 | dumpBuffer( buffer, size ); |
---|
246 | } |
---|
247 | |
---|
248 | void dumpNull() |
---|
249 | { |
---|
250 | (*_o) << " (null)" << endl; |
---|
251 | } |
---|
252 | |
---|
253 | void dumpBuffer( const void *buffer, unsigned size ) |
---|
254 | { |
---|
255 | unsigned dumpSize = size; |
---|
256 | if ( maxDumpSize() && dumpSize > maxDumpSize() ) |
---|
257 | dumpSize = maxDumpSize(); |
---|
258 | |
---|
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 | } |
---|
267 | |
---|
268 | static void endl( OutputStream &o ) |
---|
269 | { |
---|
270 | OutputStream::endl( o ); |
---|
271 | } |
---|
272 | |
---|
273 | bool _dotting; |
---|
274 | bool _reported; |
---|
275 | OutputStream *_o; |
---|
276 | const char *_preLine; |
---|
277 | const char *_postLine; |
---|
278 | }; |
---|
279 | }; |
---|
280 | |
---|
281 | #endif // __cxxtest__ErrorFormatter_h__ |
---|