1 /***************************************************************************
2 copyright : (C) 2003-2005 by Stefano Barbato
3 email : stefano@codesink.org
5 $Id: cutee.h,v 1.14 2008-10-07 15:43:55 tat Exp $
6 ***************************************************************************/
8 /***************************************************************************
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 ***************************************************************************/
17 #ifndef _CUTEE_CUTEE_H_
18 #define _CUTEE_CUTEE_H_
25 typedef unsigned int uint;
27 #define CUTEE_VERSION "0.4.2"
29 #define MAX_TEST_COUNT 1000
32 #define TEST_CLASS( name ) \
33 dummy_##name: public cutee::CuteeTest { \
38 classFileName(__FILE__); \
39 classLineNo(__LINE__); \
42 struct name: public dummy_##name
43 #define TEST_FUNCTION_EX( funcname, filename, lineno ) \
46 functionName(#funcname); \
47 functionLineNo(lineno); \
48 mEvt->enterFunction(*this); \
51 if(mFuncExitCode) mFailed++; \
52 mEvt->leaveFunction(*this, mFuncExitCode == 0); \
57 #define TEST_FUNCTION( funcname ) \
58 TEST_FUNCTION_EX( funcname, __FILE__, __LINE__)
60 #define PRINT_VALUE( a ) \
61 "\t[" << #a << ": " << a << "]" << std::endl
63 #define PRINT_ON_FAILURE_1( a ) \
65 #define PRINT_ON_FAILURE_2( a, b ) \
66 PRINT_VALUE( a ) << PRINT_VALUE( b )
67 #define PRINT_ON_FAILURE_3( a, b, c ) \
68 PRINT_VALUE( a ) << PRINT_VALUE( b ) << PRINT_VALUE( c )
69 #define PRINT_ON_FAILURE_4( a, b, c, d ) \
70 PRINT_VALUE( a ) << PRINT_VALUE( b ) << \
71 PRINT_VALUE( c ) << PRINT_VALUE( d )
73 #define TEST_ASSERT_EX( e, file, line ) \
74 do { expr(#e); exprFileName(file); exprLineNo(line); \
75 testAssert(e); } while(0)
77 #define TEST_ASSERT_EX_M( e, p, file, line ) \
78 do { expr(#e); exprFileName(file); exprLineNo(line); \
79 std::stringstream _l_ss; _l_ss << p << std::endl; \
80 testAssertM(e, _l_ss ); } while(0)
84 #define TEST_ASSERT( expr ) TEST_ASSERT_EX( expr, __FILE__, __LINE__ )
85 #define TEST_ASSERT_EQUALS( a, b ) TEST_ASSERT_EX( (a == b), __FILE__,__LINE__ )
86 #define TEST_ASSERT_DIFFERS( a, b ) TEST_ASSERT_EX( (a != b),__FILE__,__LINE__ )
88 // print p on test fail
89 #define TEST_ASSERT_M( expr , p) TEST_ASSERT_EX_M( expr, p, __FILE__,__LINE__ )
90 #define TEST_ASSERT_EQUALS_M( a, b, p ) TEST_ASSERT_EX_M( (a == b), p,__FILE__,__LINE__ )
91 #define TEST_ASSERT_DIFFERS_M( a, b, p ) TEST_ASSERT_EX_M( (a != b), p,__FILE__,__LINE__)
93 // print a and b on error
94 #define TEST_ASSERT_P( expr ) TEST_ASSERT_EX_M( expr, PRINT_ON_FAILURE_1( expr ), __FILE__,__LINE__ )
95 #define TEST_ASSERT_EQUALS_P( a, b ) TEST_ASSERT_EX_M( (a == b), PRINT_ON_FAILURE_2( a, b ), __FILE__,__LINE__ )
96 #define TEST_ASSERT_DIFFERS_P( a, b ) TEST_ASSERT_EX_M( (a != b), PRINT_ON_FAILURE_2( a, b ), __FILE__,__LINE__)
98 #define TEST_ASSERT_PM( expr, m ) TEST_ASSERT_EX_M( expr, PRINT_ON_FAILURE_2( expr, m ), __FILE__,__LINE__ )
99 #define TEST_ASSERT_EQUALS_PM( a, b, m ) TEST_ASSERT_EX_M( (a == b), PRINT_ON_FAILURE_3( a, b, m ), __FILE__,__LINE__ )
100 #define TEST_ASSERT_DIFFERS_PM( a, b, m ) TEST_ASSERT_EX_M( (a != b), PRINT_ON_FAILURE_3( a, b, m ), __FILE__,__LINE__)
102 #define TEST_ASSERT_OR_RET(expr, msg) \
103 do { if(!expr) { TEST_ASSERT_M(expr, msg); return; } } while(0)
106 namespace cutee // c++ unit testing environment
111 // store runtime context (class name, function name, line numbers, etc.)
114 typedef std::string string;
116 : mClassLineNo(0), mFunctionLineNo(0), mExprLineNo(0)
119 const string& className() const { return mClassName; }
120 uint classLineNo() const { return mClassLineNo; }
121 const string& classFileName() const { return mClassFileName; }
123 const string& fileName() const { return mFileName; }
125 const string& functionName() const { return mFunctionName; }
126 uint functionLineNo() const { return mFunctionLineNo; }
128 const string& expr() const { return mExpr; }
129 const string& exprFileName() const { return mExprFileName; }
130 uint exprLineNo() const { return mExprLineNo; }
132 void className(const string& s) { mClassName = s; }
133 void classFileName(const string& s) { mClassFileName = s; }
134 void classLineNo(uint i) { mClassLineNo = i; }
136 void filename(const string& s) { mFileName = s; }
138 void functionName(const string& s) { mFunctionName = s; }
139 void functionLineNo(uint i) { mFunctionLineNo = i; }
141 void expr(const string& s) { mExpr = s; }
142 void exprFileName(const string& s) { mExprFileName = s; }
143 void exprLineNo(uint i) { mExprLineNo = i; }
145 std::string mClassName, mClassFileName, mFunctionName,
146 mFileName, mExpr, mExprFileName;
147 uint mClassLineNo, mFunctionLineNo, mExprLineNo;
151 // execution monitor interface
152 struct TestRunMonitor
154 virtual ~TestRunMonitor() {}
156 virtual void beginTesting() {}
157 virtual void endTesting() {}
159 // virtual void enterSuite(const CuteeTest&) {}
160 // virtual void leaveSuite(const CuteeTest&, int b) {}
162 virtual void enterClass(const CuteeTest&) {}
163 virtual void leaveClass(const CuteeTest&, int) {}
165 virtual void enterFunction(const CuteeTest&) {}
166 virtual void leaveFunction(const CuteeTest&, int ) {}
168 virtual void assertion(const CuteeTest&, int,
169 const std::string& u = "") {}
172 // statically store pointers to test classes
175 virtual ~TestList() {}
176 // FIXME add dynamic array alloc to avoid fixed limit
177 static CuteeTest* list[MAX_TEST_COUNT];
183 // this is the base class of all cutee test classes
184 struct CuteeTest: public cutee::Context
187 : mEvt(&mNullMonitor), mFuncExitCode(0), mFailed(0)
190 virtual ~CuteeTest() {}
191 virtual void setUp() {}
192 virtual void tearDown() {}
193 void testRunMonitor(TestRunMonitor *evt) { mEvt = evt; }
194 int passed() const { return mFailed == 0; }
195 virtual void run() = 0;
196 virtual uint count() = 0;
198 void testAssert(int b)
200 if( b == 0 ) // assertion failed
202 mEvt->assertion(*this, b);
204 void testAssertM(int b, std::stringstream& os)
206 if( b == 0 ) // assertion failed
208 mEvt->assertion(*this, b, os.str());
211 TestRunMonitor *mEvt, mNullMonitor;
212 uint mFuncExitCode, mFailed;
217 // monitors execution and keep statistics on classes/functions/tests
218 struct StatsMonitor: public TestRunMonitor
221 : mAssertPassed(0), mAssertFailed(0), mAssertCount(0),
222 mFuncPassed(0), mFuncFailed(0), mFuncCount(0),
223 mClassPassed(0), mClassFailed(0), mClassCount(0)
226 // void enterSuite(const CuteeTest& t) {}
227 // void leaveSuite(const CuteeTest& t, int b) {}
228 void enterClass(const CuteeTest& t)
232 void leaveClass(const CuteeTest& t, int b)
239 void enterFunction(const CuteeTest&)
243 void leaveFunction(const CuteeTest&, int b)
250 void assertion(const CuteeTest& t, int b, const std::string& userMsg)
259 uint mAssertPassed, mAssertFailed, mAssertCount, mFuncPassed,
260 mFuncFailed, mFuncCount, mClassPassed, mClassFailed, mClassCount;
263 // keep stats and print results on exit
264 struct ConsoleRunMonitor: public StatsMonitor
266 void assertion(const CuteeTest& t, int b, const std::string& userMsg)
269 StatsMonitor::assertion(t, b, userMsg);
273 << t.exprFileName() << ":"
274 << t.exprLineNo()<< "] "
275 << t.className() << "::"
276 << t.functionName() << "(): "
277 << t.expr() << " assertion failed"
280 cout << userMsg << endl;
286 cout << endl << endl;
287 cout << " ======================================" << endl;
288 cout << " Tests Statistics " << endl;
289 cout << " --------------------------------------" << endl;
290 cout << " Functions Checks " << endl;
291 cout << " Success "<< setw(8) << mFuncPassed <<
292 " " << setw(8) << mAssertPassed << endl;
293 cout << " Failed "<< setw(8) << mFuncFailed <<
294 " " << setw(8) << mAssertFailed << endl;
295 cout << " --------------------------------------" << endl;
296 cout << " Total "<< setw(8) << mFuncCount <<
297 " " << setw(8) << mAssertCount << endl;
298 cout << " ======================================" << endl;
302 // keep stats and print skimmer xml output on exit
303 struct SkimmerRunMonitor: public StatsMonitor
308 cout << "<?xml version=\"1.0\"?>" << endl;
309 cout << "<tests>" << endl;
314 cout << "</tests>" << endl;
316 void enterClass(const CuteeTest&)
319 void leaveClass(const CuteeTest&, int)
322 void enterFunction(const CuteeTest& t)
325 cout << "<test>" << endl;
327 cout << t.className() << "::" << t.functionName() << "()";
328 cout << "</name>" << endl;
330 void leaveFunction(const CuteeTest& t, int b)
333 cout << "<type>" << (b ? "pass" : "fail") << "</type>" << endl;
334 cout << "</test>" << endl << endl << endl;
336 void assertion(const CuteeTest& t, int b, const std::string& u = "")
341 cout << " <info>" << endl;
342 cout << " <type>" << (b ? "pass" : "fail") << "</type>" << endl;
343 cout << " <data>" << endl;
344 cout << " <file>" << t.exprFileName() << "</file>" << endl;
345 cout << " <line>" << t.exprLineNo() << "</line>" << endl;
346 cout << " <expression>" << t.expr() << "</expression>" <<endl;
348 cout << " <output>" << u << endl << " </output>" << endl;
349 cout << " </expression>" << endl;
350 cout << " </data>" << endl;
351 cout << " </info>" << endl << endl;
355 // create the appropriate TestRunMonitor based on environment variables
356 // or command line parameters and run tests
359 Runner(int argc, char** argv)
362 if(getenv("SKIMMER_MODE"))
363 mEvt = new SkimmerRunMonitor;
365 mEvt = new ConsoleRunMonitor;
369 mEvt->beginTesting();
370 for(int i =0; i < TestList::list_idx; i++)
372 CuteeTest *ct = TestList::list[i];
373 ct->testRunMonitor(mEvt);
374 mEvt->enterClass(*ct);
376 mEvt->leaveClass(*ct, ct->passed());
381 TestRunMonitor *mEvt;