// 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 "../stdafx.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; string demangleName( const type_info& typeinfo ); 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; }; } }