// framework.h
/**
* Copyright (C) 2008 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
/*
simple portable regression system
*/
#include "../pch.h"
#define ASSERT_EXCEPTION(a,b) \
try { \
a; \
mongo::regression::assert_fail( #a , __FILE__ , __LINE__ ); \
} catch ( b& ){ \
mongo::regression::assert_pass(); \
}
#define ASSERT_EQUALS(a,b) (mongo::regression::MyAsserts( #a , #b , __FILE__ , __LINE__ ) ).ae( (a) , (b) )
#define ASSERT(x) (void)( (!(!(x))) ? mongo::regression::assert_pass() : mongo::regression::assert_fail( #x , __FILE__ , __LINE__ ) )
#define FAIL(x) mongo::regression::fail( #x , __FILE__ , __LINE__ )
#include "../db/instance.h"
namespace mongo {
namespace regression {
class Result;
class TestCase {
public:
virtual ~TestCase(){}
virtual void run() = 0;
virtual string getName() = 0;
};
template< class T >
class TestHolderBase : public TestCase {
public:
TestHolderBase(){}
virtual ~TestHolderBase(){}
virtual void run(){
auto_ptr t;
t.reset( create() );
t->run();
}
virtual T * create() = 0;
virtual string getName(){
return demangleName( typeid(T) );
}
};
template< class T >
class TestHolder0 : public TestHolderBase {
public:
virtual T * create(){
return new T();
}
};
template< class T , typename A >
class TestHolder1 : public TestHolderBase {
public:
TestHolder1( const A& a ) : _a(a){}
virtual T * create(){
return new T( _a );
}
const A& _a;
};
class Suite {
public:
Suite( string name ) : _name( name ){
registerSuite( name , this );
_ran = 0;
}
virtual ~Suite() {
if ( _ran ){
DBDirectClient c;
c.dropDatabase( "unittests" );
}
}
template
void add(){
_tests.push_back( new TestHolder0() );
}
template
void add( const A& a ){
_tests.push_back( new TestHolder1(a) );
}
Result * run();
static int run( vector suites );
static int run( int argc , char ** argv , string default_dbpath );
protected:
virtual void setupTests() = 0;
private:
string _name;
list _tests;
bool _ran;
static map * _suites;
void registerSuite( string name , Suite * s );
};
void assert_pass();
void assert_fail( const char * exp , const char * file , unsigned line );
void fail( const char * exp , const char * file , unsigned line );
class MyAssertionException : boost::noncopyable {
public:
MyAssertionException(){
ss << "assertion: ";
}
stringstream ss;
};
class MyAsserts {
public:
MyAsserts( const char * aexp , const char * bexp , const char * file , unsigned line )
: _aexp( aexp ) , _bexp( bexp ) , _file( file ) , _line( line ){
}
template
void ae( A a , B b ){
_gotAssert();
if ( a == b )
return;
printLocation();
MyAssertionException * e = getBase();
e->ss << a << " != " << b << endl;
log() << e->ss.str() << endl;
throw e;
}
void printLocation();
private:
void _gotAssert();
MyAssertionException * getBase();
string _aexp;
string _bexp;
string _file;
unsigned _line;
};
}
}