/*
$Id: UnitTest.h 15564 2013-01-07 14:25:32Z sloot $
$URL: https://ilk.uvt.nl/svn/sources/libticcutils/trunk/include/ticcutils/UnitTest.h $
Copyright (c) 1998 - 2013
ILK - Tilburg University
CLiPS - University of Antwerp
This file is part of ticcutils
ticcutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ticcutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see .
For questions and suggestions, see:
http://ilk.uvt.nl/software.html
or send mail to:
timbl@uvt.nl
*/
#ifndef TICC_UNITTEST_H
#define TICC_UNITTEST_H
#include
const std::string OK = "\033[1;32m OK \033[0m";
const std::string FAIL = "\033[1;31m FAILED \033[0m";
class MyTSerie {
public:
MyTSerie( const std::string& fun, int lineno, const std::string& line ){
start( fun, lineno, line );
}
~MyTSerie(){
stop( _fun, 0 );
}
bool isDefault() const {return _fun =="default"; };
int _fails;
int _tests;
std::string _fun;
private:
void start( const std::string& fun, int lineno, const std::string& line ){
_fun = fun;
_fails = 0;
_tests = 0;
if ( !isDefault() )
std::cout << "Serie:\t" << fun << " (" << line << ")" << std::endl;
};
void stop( const std::string& fun, int line );
};
static MyTSerie currentTestContext( "default", 0, "default" );
int exit_status = 0;
bool summarized = false;
bool testSilent = false;
#define TEST_SILENT_ON() testSilent = true;
#define TEST_SILENT_OFF() testSilent = false;
inline void summarize_tests( int expected=0 ){
summarized = true;
std::cout << "TiCC tests performed " << currentTestContext._tests
<< " tests, with " << currentTestContext._fails << " failures.";
int diff = currentTestContext._fails - expected;
if ( diff > 0 ){
std::cout << " We expected " << expected << " failures." << std::endl;
std::cout << "overall " << FAIL << std::endl;
}
else if ( diff < 0 ){
std::cout << " This is less than the " << expected << " we expected." << std::endl;
std::cout << "overall: " << FAIL << std::endl;
}
else {
std::cout << " that was what we expected." << std::endl;
std::cout << "overall: " << OK << std::endl;
}
exit_status = diff;
}
void MyTSerie::stop( const std::string& fun, int line ){
if ( isDefault() ){
if ( !summarized ){
summarize_tests( 0 );
}
exit( exit_status );
}
else {
currentTestContext._tests += _tests;
if ( _fails ){
std::cout << "\t" << fun << "(): " << _fails
<< " out of " << _tests << " tests" << FAIL << std::endl;
currentTestContext._fails += _fails;
}
else
std::cout << "\t" << fun << "(): all " << _tests << " tests" << OK << std::endl;
};
}
#define assertEqual( XX , YY ) test_eq( __func__, __LINE__, (XX), (YY), currentTestContext )
#define assertThrow( XX, EE ) \
do { \
++currentTestContext._tests; \
if ( !testSilent && currentTestContext.isDefault() ) \
std::cout << "test: " << __func__ << "(" << __LINE__ << "): "; \
try { \
XX; } \
catch( const EE& ){ \
if ( !testSilent && currentTestContext.isDefault() ) \
std::cerr << OK << std::endl; \
break; \
} \
catch ( const std::exception& e ){ \
++currentTestContext._fails; \
if ( currentTestContext.isDefault() ) \
std::cout << FAIL << std::endl; \
else \
std::cerr << "\t"; \
std::cerr << __func__ << "(" << __LINE__ << ") : wrong exception, what='" << e.what() << "'" << std::endl; \
break; \
} \
++currentTestContext._fails; \
if ( currentTestContext.isDefault() ) \
std::cout << FAIL << std::endl; \
else \
std::cerr << "\t"; \
std::cerr << __func__ << "(" << __LINE__ << ") : no exception thrown" << std::endl; \
} \
while( false ) \
#define assertNoThrow( XX ) \
do { \
++currentTestContext._tests; \
if ( !testSilent && currentTestContext.isDefault() ) \
std::cout << "test: " << __func__ << "(" << __LINE__ << "): "; \
try { \
XX; } \
catch ( const std::exception& e ){ \
++currentTestContext._fails; \
if ( currentTestContext.isDefault() ) \
std::cout << FAIL << std::endl; \
else \
std::cerr << "\t"; \
std::cerr << __func__ << "(" << __LINE__ << ") : throws, what='" << e.what() << "'" << std::endl; \
break; \
} \
if ( !testSilent && currentTestContext.isDefault() ) \
std::cout << OK << std::endl; \
} \
while( false ) \
#define assertTrue( YY ) test_true( __func__, __LINE__, (YY), currentTestContext )
#define assertMessage( MM, YY ) test_true_message( __func__, __LINE__, (MM), (YY), currentTestContext )
#define startTestSerie( SS ) MyTSerie currentTestContext( __func__, __LINE__, (SS) )
template
inline void test_eq( const char* F, int L,
const T1& s1, const T2& s2, MyTSerie& T ){
if ( !testSilent && T.isDefault() )
std::cout << "test: " << F << "(" << L << "): ";
++T._tests;
if ( s1 != s2 ){
++T._fails;
if ( T.isDefault() )
std::cout << FAIL << std::endl;
else
std::cerr << "\t";
std::cerr << F << "(" << L << ") : '" << s1 << "' != '"
<< s2 << "'" << std::endl;
}
else {
if ( !testSilent && T.isDefault() )
std::cout << OK << std::endl;
}
}
inline void test_true( const char* F, int L, bool b, MyTSerie& T ){
if ( !testSilent && T.isDefault() )
std::cout << "test: " << F << "(" << L << "): ";
++T._tests;
if ( !b ){
++T._fails;
if ( T.isDefault() )
std::cout << FAIL << std::endl;
else
std::cerr << "\t";
std::cerr << F << "(" << L << ") : '" << b << "' != TRUE" << std::endl;
}
else {
if ( !testSilent && T.isDefault() )
std::cout << OK << std::endl;
}
}
inline void test_true_message( const char* F, int L, const std::string& m,
bool b, MyTSerie& T ){
if ( !testSilent && T.isDefault() )
std::cout << "test: " << F << "(" << L << "): ";
++T._tests;
if ( !b ){
++T._fails;
if ( T.isDefault() )
std::cout << FAIL << std::endl;
else
std::cerr << "\t";
std::cerr << F << "(" << L << ") : '" << m << "'" << std::endl;
}
else {
if ( !testSilent && T.isDefault() )
std::cout << OK << std::endl;
}
}
#endif