[complement-svn] SF.net SVN: complement: [1612] trunk/complement/explore/app/exam
Status: Pre-Alpha
Brought to you by:
complement
From: <com...@us...> - 2007-07-16 14:00:52
|
Revision: 1612 http://svn.sourceforge.net/complement/?rev=1612&view=rev Author: complement Date: 2007-07-16 07:00:18 -0700 (Mon, 16 Jul 2007) Log Message: ----------- self test established Modified Paths: -------------- trunk/complement/explore/app/exam/Makefile.inc trunk/complement/explore/app/exam/suite.cc trunk/complement/explore/app/exam/suite.h trunk/complement/explore/app/exam/zero.cc Added Paths: ----------- trunk/complement/explore/app/exam/dummy_test.cc trunk/complement/explore/app/exam/exam_test_suite.cc trunk/complement/explore/app/exam/exam_test_suite.h trunk/complement/explore/app/exam/logger.cc trunk/complement/explore/app/exam/logger.h Modified: trunk/complement/explore/app/exam/Makefile.inc =================================================================== --- trunk/complement/explore/app/exam/Makefile.inc 2007-07-12 07:33:00 UTC (rev 1611) +++ trunk/complement/explore/app/exam/Makefile.inc 2007-07-16 14:00:18 UTC (rev 1612) @@ -1,4 +1,4 @@ # -*- makefile -*- Time-stamp: <02/07/14 14:03:13 ptr> PRGNAME = zero -SRC_CC = zero.cc suite.cc +SRC_CC = zero.cc suite.cc logger.cc exam_test_suite.cc Added: trunk/complement/explore/app/exam/dummy_test.cc =================================================================== --- trunk/complement/explore/app/exam/dummy_test.cc (rev 0) +++ trunk/complement/explore/app/exam/dummy_test.cc 2007-07-16 14:00:18 UTC (rev 1612) @@ -0,0 +1,36 @@ +#include "suite.h" + +int EXAM_IMPL(func) +{ + EXAM_CHECK(false); + + return EXAM_RESULT; +} + +class test_x +{ + public: + + int EXAM_IMPL(f) + { + EXAM_CHECK(false); + EXAM_CHECK(true); + + return EXAM_RESULT; + } + + int EXAM_IMPL(f_good) + { + EXAM_CHECK(true); + EXAM_CHECK(true); + + return EXAM_RESULT; + } +}; + +int EXAM_IMPL(func_good) +{ + EXAM_CHECK(true); + + return EXAM_RESULT; +} Added: trunk/complement/explore/app/exam/exam_test_suite.cc =================================================================== --- trunk/complement/explore/app/exam/exam_test_suite.cc (rev 0) +++ trunk/complement/explore/app/exam/exam_test_suite.cc 2007-07-16 14:00:18 UTC (rev 1612) @@ -0,0 +1,239 @@ +// -*- C++ -*- Time-stamp: <07/07/16 16:33:17 ptr> + +#include "exam_test_suite.h" + +#include "dummy_test.cc" + +int EXAM_IMPL(exam_basic_test::function_good) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, good function" ); + t.set_logger( &logger ); + + test_x tx; + t.add( func_good, "function" ); + t.add( &test_x::f_good, tx, "member function" ); + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r0 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str() << std::endl; + // std::cerr << "%%%\n"; + + return EXAM_RESULT; +} + +int EXAM_IMPL(exam_basic_test::function) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, fail function" ); + t.set_logger( &logger ); + + test_x tx; + t.add( func, "function" ); + t.add( &test_x::f, tx, "member function" ); + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r1 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str() << std::endl; + // std::cerr << "%%%\n"; + + return EXAM_RESULT; +} + +int EXAM_IMPL(exam_basic_test::dep) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, fail function" ); + t.set_logger( &logger ); + + test_x tx; + t.add( func_good, "function good", // "child" + t.add( &test_x::f_good, tx, "member function good" ) ); // "parent" + t.add( func, "function fail", // <- skiped, because depends upon failed (next line) + t.add( &test_x::f, tx, "member function fail" ) ); // <- fail + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r2 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str() << std::endl; + // std::cerr << "%%%\n"; + + return EXAM_RESULT; +} + +int EXAM_IMPL(exam_basic_test::trace) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t( "exam self test, fail function" ); + t.set_logger( &logger ); + + logger.flags( exam::base_logger::trace_suite ); + + test_x tx; + t.add( func_good, "function good", // "child" + t.add( &test_x::f_good, tx, "member function good" ) ); // "parent" + t.add( func, "function fail", // <- skiped, because depends upon failed (next line) + t.add( &test_x::f, tx, "member function fail" ) ); // <- fail + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r3 ); + + buff.str( "" ); + buff.clear(); + + logger.flags( exam::base_logger::silent ); + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r4 ); + + buff.str( "" ); + buff.clear(); + + logger.flags( exam::base_logger::trace ); + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r5 ); + + buff.str( "" ); + buff.clear(); + + logger.flags( exam::base_logger::verbose ); + + t.girdle(); + + logger.flags( 0 ); + + EXAM_REQUIRE( buff.str() == r6 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str() << std::endl; + // std::cerr << "%%%\n"; + + return EXAM_RESULT; +} + +int EXAM_IMPL(exam_basic_test::dep_test_suite) +{ + buff.str( "" ); + buff.clear(); + + exam::test_suite t0( "exam self test, test suite master" ); + t0.set_logger( &logger ); + + test_x tx0; + t0.add( func_good, "function" ); + t0.add( &test_x::f_good, tx0, "member function" ); + + exam::test_suite t1( "exam self test, test suite slave" ); + t1.set_logger( &logger ); + + test_x tx1; + t1.add( func_good, "function good", // "child" + t1.add( &test_x::f_good, tx1, "member function good" ) ); // "parent" + t1.add( func, "function fail", // <- skiped, because depends upon failed (next line) + t1.add( &test_x::f, tx1, "member function fail" ) ); // <- fail + + exam::test_suite t( "exam self test, test suites dependency" ); + t.set_logger( &logger ); + + t.add( &exam::test_suite::run, t1, "slave test suite", + t.add( &exam::test_suite::run, t0, "master test suite" ) ); + + t.girdle(); + + EXAM_REQUIRE( buff.str() == r7 ); + + // std::cerr << "%%%\n"; + // std::cerr << buff.str() << std::endl; + // std::cerr << "%%%\n"; + + return EXAM_RESULT; +} + +const std::string exam_basic_test::r0 = "\ +*** PASS exam self test, good function (+2-0~0/2) ***\n"; + +const std::string exam_basic_test::r1 = "\ +dummy_test.cc:5: fail: false\n\ + FAIL function\n\ +dummy_test.cc:16: fail: false\n\ + FAIL member function\n\ +*** FAIL exam self test, fail function (+0-2~0/2) ***\n"; + +const std::string exam_basic_test::r2 = "\ +dummy_test.cc:16: fail: false\n\ + FAIL member function fail\n\ + SKIP function fail\n\ +*** FAIL exam self test, fail function (+2-1~1/4) ***\n"; + +const std::string exam_basic_test::r3 = "\ +== Begin test suite\n\ +dummy_test.cc:16: fail: false\n\ + FAIL member function fail\n\ + SKIP function fail\n\ +== End test suite\n\ +*** FAIL exam self test, fail function (+2-1~1/4) ***\n"; + +const std::string exam_basic_test::r4 = "\ +*** FAIL exam self test, fail function (+2-1~1/4) ***\n"; + +const std::string exam_basic_test::r5 = "\ +dummy_test.cc:24: pass: true\n\ +dummy_test.cc:25: pass: true\n\ +dummy_test.cc:16: fail: false\n\ +dummy_test.cc:17: pass: true\n\ + FAIL member function fail\n\ + SKIP function fail\n\ +dummy_test.cc:33: pass: true\n\ +*** FAIL exam self test, fail function (+2-1~1/4) ***\n"; + +const std::string exam_basic_test::r6 = "\ + PASS member function good\n\ +dummy_test.cc:16: fail: false\n\ + FAIL member function fail\n\ + SKIP function fail\n\ + PASS function good\n\ +*** FAIL exam self test, fail function (+2-1~1/4) ***\n"; + +const std::string exam_basic_test::r7 = "\ +*** PASS exam self test, test suite master (+2-0~0/2) ***\n\ +dummy_test.cc:16: fail: false\n\ + FAIL member function fail\n\ + SKIP function fail\n\ +*** FAIL exam self test, test suite slave (+2-1~1/4) ***\n\ + FAIL slave test suite\n\ +*** FAIL exam self test, test suites dependency (+1-1~0/2) ***\n"; + +int EXAM_IMPL(exam_self_test) +{ + exam::test_suite t( "exam self test" ); + exam_basic_test exam_basic; + + t.add( &exam_basic_test::function_good, exam_basic, "call test, good calls" ); + t.add( &exam_basic_test::function, exam_basic, "call test, fail calls" ); + exam::test_suite::test_case_type d = t.add( &exam_basic_test::dep, exam_basic, "call test, tests dependency" ); + t.add( &exam_basic_test::trace, exam_basic, "trace flags test", d ); + t.add( &exam_basic_test::dep_test_suite, exam_basic, "test suites grouping", d ); + + return t.girdle(); +} + Added: trunk/complement/explore/app/exam/exam_test_suite.h =================================================================== --- trunk/complement/explore/app/exam/exam_test_suite.h (rev 0) +++ trunk/complement/explore/app/exam/exam_test_suite.h 2007-07-16 14:00:18 UTC (rev 1612) @@ -0,0 +1,42 @@ +// -*- C++ -*- Time-stamp: <07/07/16 16:33:17 ptr> + +#ifndef __exam_test_suite_h +#define __exam_test_suite_h + +#define FIT_EXAM + +#include "suite.h" +#include <string> +#include <sstream> + +class exam_basic_test +{ + public: + exam_basic_test() : + buff(), + logger( buff ) + { } + + int EXAM_DECL(function_good); + int EXAM_DECL(function); + int EXAM_DECL(dep); + int EXAM_DECL(trace); + int EXAM_DECL(dep_test_suite); + + private: + std::stringstream buff; + exam::trivial_logger logger; + + static const std::string r0; + static const std::string r1; + static const std::string r2; + static const std::string r3; + static const std::string r4; + static const std::string r5; + static const std::string r6; + static const std::string r7; +}; + +int EXAM_DECL(exam_self_test); + +#endif // __exam_test_suite_h Added: trunk/complement/explore/app/exam/logger.cc =================================================================== --- trunk/complement/explore/app/exam/logger.cc (rev 0) +++ trunk/complement/explore/app/exam/logger.cc 2007-07-16 14:00:18 UTC (rev 1612) @@ -0,0 +1,111 @@ +// -*- C++ -*- Time-stamp: <07/07/13 10:53:32 ptr> + +#include "logger.h" +#include <iostream> + +namespace exam { + +using namespace std; + +int base_logger::flags() const +{ + return _flags; +} + +bool base_logger::is_trace() const +{ + return (_flags & trace) != 0; +} + +int base_logger::flags( int f ) +{ + int tmp = _flags; + _flags = f; + if ( (f & silent) != 0 ) { + _flags &= ~trace_suite; + } + return tmp; +} + +void trivial_logger::report( const char *file, int line, bool cnd, const char *expr ) +{ + if ( (cnd && ((_flags & trace) == 0)) || ((_flags & silent) != 0) ) { + return; + } + + if ( s != 0 ) { + *s << file << ":" << line << ": " << (cnd ? "pass" : "fail" ) << ": " << expr + << std::endl; + } else { + fprintf( f, "%s:%d: %s: %s\n", file, line, (cnd ? "pass" : "fail" ), expr ); + } +} + +void trivial_logger::begin_ts() +{ + if ( (_flags & trace_suite) == 0 ) { + return; + } + + if ( s != 0 ) { + *s << "== Begin test suite\n"; + } else { + fprintf( f, "== Begin test suite\n" ); + } +} + +void trivial_logger::end_ts() +{ + if ( (_flags & trace_suite) == 0 ) { + return; + } + + if ( *s ) { + *s << "== End test suite\n"; + } else { + fprintf( f, "== End test suite\n" ); + } +} + +void trivial_logger::result( const base_logger::stat& _stat, const string& suite_name ) +{ + if ( s != 0 ) { + *s << "*** " << (_stat.failed != 0 ? "FAIL " : "PASS " ) << suite_name + << " (+" << _stat.passed + << "-" << _stat.failed + << "~" << _stat.skipped << "/" << _stat.total << ") ***" << endl; + } else { + fprintf( f, "*** %s (+%d-%d~%d/%d) ***\n", (_stat.failed != 0 ? "FAIL" : "PASS" ), _stat.passed, _stat.failed, _stat.skipped, _stat.total ); + } +} + +void trivial_logger::tc( base_logger::tc_result r, const std::string& name ) +{ + if ( ((_flags & silent) != 0) || ((r == pass) && ((_flags & verbose) == 0) )) { + return; + } + + static const char *m[] = { " PASS ", " FAIL ", " SKIP " }; + const char *rs = ""; + + switch ( r ) + { + case pass: + rs = m[0]; + break; + case fail: + rs = m[1]; + break; + case skip: + rs = m[2]; + break; + } + + if ( s != 0 ) { + *s << rs << name << endl; + } else { + fprintf( f, "%s%s\n", rs, name.c_str() ); + } +} + +} //namespace exam Added: trunk/complement/explore/app/exam/logger.h =================================================================== --- trunk/complement/explore/app/exam/logger.h (rev 0) +++ trunk/complement/explore/app/exam/logger.h 2007-07-16 14:00:18 UTC (rev 1612) @@ -0,0 +1,94 @@ +// -*- C++ -*- Time-stamp: <07/07/13 11:01:52 ptr> + +#ifndef __logger_h +#define __logger_h + +#include <string> +#include <cstdio> +#include <ostream> + +namespace exam { + +class base_logger +{ + public: + + enum trace_flags { + trace = 1, + trace_suite = 2, + silent = 4, + verbose = 8 + }; + + enum tc_result { + pass = 0, + fail, + skip + }; + + struct stat + { + stat() : + total(0), + passed(0), + failed(0), + skipped(0) + { } + + int total; + int passed; + int failed; + int skipped; + }; + + base_logger() : + _flags( 0 ) + { } + virtual ~base_logger() + { } + + int flags() const; + bool is_trace() const; + + int flags( int ); + + virtual void report( const char *, int, bool, const char * ) = 0; + + virtual void begin_ts() = 0; + virtual void end_ts() = 0; + virtual void result( const base_logger::stat&, const std::string& suite_name ) = 0; + virtual void tc( tc_result, const std::string& ) = 0; + + protected: + int _flags; +}; + +class trivial_logger : + public base_logger +{ + public: + explicit trivial_logger( std::ostream& str ) : + s( &str ), + f( 0 ) + { } + + explicit trivial_logger( FILE *fs ) : + s( 0 ), + f( fs ) + { } + + virtual void report( const char *, int, bool, const char * ); + + virtual void begin_ts(); + virtual void end_ts(); + virtual void result( const base_logger::stat&, const std::string& ); + virtual void tc( base_logger::tc_result, const std::string& ); + + private: + std::ostream *s; + FILE *f; +}; + +} // namespace exam + +#endif // __logger_h Modified: trunk/complement/explore/app/exam/suite.cc =================================================================== --- trunk/complement/explore/app/exam/suite.cc 2007-07-12 07:33:00 UTC (rev 1611) +++ trunk/complement/explore/app/exam/suite.cc 2007-07-16 14:00:18 UTC (rev 1612) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/11 11:10:45 ptr> +// -*- C++ -*- Time-stamp: <07/07/15 16:33:03 ptr> #include "suite.h" #include <boost/graph/breadth_first_search.hpp> @@ -61,39 +61,59 @@ skip_recorder<Tag> record_skip(test_suite& ts, Tag) { return skip_recorder<Tag>(ts); } +template <class Tag> +struct white_recorder : + public base_visitor<white_recorder<Tag> > +{ + typedef Tag event_filter; + + white_recorder(test_suite& ts) : + _suite(ts) + { } + + template <class Vertex, class Graph> + void operator()(Vertex v, const Graph& g) + { + // std::cerr << "On vertex " << v << std::endl; + // boost::put( boost::vertex_color, g, v, white_color ); + _suite.clean_test_case_state( v ); + } + + test_suite& _suite; +}; + +template <class Tag> +white_recorder<Tag> record_white(test_suite& ts, Tag) +{ return white_recorder<Tag>(ts); } + + } // namespace detail -int test_suite::_root_func() +int EXAM_IMPL(test_suite::_root_func) { - return test_suite::init; + throw init_exception(); + + return -1; } test_suite::test_suite( const string& name ) : root( add_vertex( white_color, g ) ), - _suite_name( name ) + _suite_name( name ), + local_logger( logger ) { - color = get( vertex_color, g ); testcase = get( vertex_testcase, g ); _test[root].tc = detail::make_test_case( detail::call( _root_func ) ); _test[root].state = 0; - _stat.total = 0; - _stat.passed = 0; - _stat.failed = 0; - _stat.skipped = 0; } test_suite::test_suite( const char *name ) : root( add_vertex( white_color, g ) ), - _suite_name( name ) + _suite_name( name ), + local_logger( logger ) { - color = get( vertex_color, g ); testcase = get( vertex_testcase, g ); _test[root].tc = detail::make_test_case( detail::call( _root_func ) ); _test[root].state = 0; - _stat.total = 0; - _stat.passed = 0; - _stat.failed = 0; - _stat.skipped = 0; } test_suite::~test_suite() @@ -103,49 +123,34 @@ } } -void test_suite::girdle() +int test_suite::girdle( test_suite::test_case_type start ) { stack<vertex_t> buffer; - cerr << "== Begin test suite\n"; - breadth_first_visit( g, root, buffer, - make_bfs_visitor( - make_pair( record_vertexes(*this,on_discover_vertex()), - record_skip(*this,on_examine_edge()) ) ), - color ); - cerr << "== End test suite\n"; - if ( _stat.failed != 0 ) { - cerr << "*** FAIL "; - } else { - cerr << "*** PASS "; - } - cerr << _suite_name - << " (+" << _stat.passed - << "-" << _stat.failed - << "~" << _stat.skipped << "/" << _stat.total << ") ***" << endl; -} + vertex_color_map_t color = get( vertex_color, g ); -void test_suite::girdle( test_suite::test_case_type start ) -{ - stack<vertex_t> buffer; - cerr << "== Begin test suite\n"; - breadth_first_visit( g, start, buffer, - make_bfs_visitor( - make_pair( record_vertexes(*this,on_discover_vertex()), - record_skip(*this,on_examine_edge()) ) ), - color ); - cerr << "== End test suite\n"; - if ( _stat.failed != 0 ) { - cerr << "*** FAIL "; - } else { - cerr << "*** PASS "; - } - cerr << _suite_name - << " (+" << _stat.passed - << "-" << _stat.failed - << "~" << _stat.skipped << "/" << _stat.total << ") ***" << endl; + // detail::white_recorder<on_initialize_vertex> vis( *this ); + // + // vertex_iterator_t i, i_end; + + // for ( tie(i, i_end) = vertices(g); i != i_end; ++i ) { + // // vis.initialize_vertex( *i, g ); + // put( color, *i, white_color ); + // } + + _stat = base_logger::stat(); + local_logger->begin_ts(); + breadth_first_search( g, start, buffer, + make_bfs_visitor( + make_pair( record_white(*this,on_initialize_vertex()), + make_pair( record_vertexes(*this,on_discover_vertex()), + record_skip(*this,on_examine_edge()) ) ) ), + color ); + local_logger->end_ts(); + local_logger->result( _stat, _suite_name ); + + return _stat.failed; } - test_suite::test_case_type test_suite::add( test_suite::func_type f, const string& name ) { vertex_t v = add_vertex( white_color, g); @@ -153,7 +158,7 @@ _test[v].tc = detail::make_test_case( detail::call( f ) ); _test[v].state = 0; _test[v].name = name; - ++_stat.total; + // ++_stat.total; return v; } @@ -165,69 +170,77 @@ _test[v].tc = detail::make_test_case( detail::call( f ) ); _test[v].state = 0; _test[v].name = name; - ++_stat.total; + // ++_stat.total; return v; } int test_suite::flags() { - return _flags; + return local_logger->flags(); } bool test_suite::is_trace() { - return (_flags & trace) != 0; + return local_logger->is_trace(); } -void _report0( const char *file, int line, bool cnd, const char *expr ) +int test_suite::flags( int f ) { - std::cerr << file << ":" << line << ": " << (cnd ? "pass" : "fail" ) << ": " << expr - << std::endl; + return local_logger->flags( f ); } -void _report1( const char *file, int line, bool cnd, const char *expr ) +trivial_logger __trivial_logger_inst( cerr ); + +base_logger *test_suite::logger = &__trivial_logger_inst; + +base_logger *test_suite::set_global_logger( base_logger *new_logger ) { - printf( "%s:%d: %s: %s\n", file, line, (cnd ? "pass" : "fail"), expr ); + base_logger *tmp = logger; + logger = new_logger; + if ( tmp == local_logger ) { // if local_logger was identical to logger, switch it too + local_logger = logger; + } + return tmp; } -void _report2( const char *file, int line, bool cnd, const char *expr ) +base_logger *test_suite::set_logger( base_logger *new_logger ) { - fprintf( stderr, "%s:%d: %s: %s\n", file, line, (cnd ? "pass" : "fail"), expr ); + base_logger *tmp = local_logger; + local_logger = new_logger; + return tmp; } -int test_suite::_flags = 0; -void (*test_suite::_report)( const char *, int, bool, const char * ) = _report0; - void test_suite::report( const char *file, int line, bool cnd, const char *expr ) { - (*test_suite::_report)( file, line, cnd, expr ); + local_logger->report( file, line, cnd, expr ); } void test_suite::run_test_case( test_suite::vertex_t v ) { try { + ++_stat.total; if ( _test[v].state == 0 ) { - int res = (*_test[v].tc)(); - if ( (res & init) != 0 ) { - // do nothing - } else if ( res == 0 ) { + if ( (*_test[v].tc)( this, 0 ) == 0 ) { ++_stat.passed; - cerr << " PASS " << _test[v].name << "\n"; + local_logger->tc( base_logger::pass, _test[v].name ); } else { _test[v].state = fail; ++_stat.failed; - cerr << " FAIL " << _test[v].name << "\n"; + local_logger->tc( base_logger::fail, _test[v].name ); } } else { ++_stat.skipped; - cerr << " SKIP " << _test[v].name << "\n"; + local_logger->tc( base_logger::skip, _test[v].name ); } } + catch ( init_exception& ) { + --_stat.total; + } catch ( ... ) { ++_stat.failed; _test[v].state = fail; - cerr << " FAIL " << _test[v].name << "\n"; + local_logger->tc( base_logger::fail, _test[v].name ); } } @@ -238,4 +251,15 @@ } } +void test_suite::clean_test_case_state( vertex_t v ) +{ + _test[v].state = 0; +} + +int test_suite::run( test_suite *, int ) +{ + return girdle( root ); +} + + } // namespace exam Modified: trunk/complement/explore/app/exam/suite.h =================================================================== --- trunk/complement/explore/app/exam/suite.h 2007-07-12 07:33:00 UTC (rev 1611) +++ trunk/complement/explore/app/exam/suite.h 2007-07-16 14:00:18 UTC (rev 1612) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/11 11:02:41 ptr> +// -*- C++ -*- Time-stamp: <07/07/15 16:33:17 ptr> #ifndef __suite_h #define __suite_h @@ -8,7 +8,10 @@ #include <map> #include <boost/graph/adjacency_list.hpp> #include <string> +#include <exception> +#include "logger.h" + enum vertex_testcase_t { vertex_testcase }; namespace boost { @@ -17,13 +20,16 @@ namespace exam { +class test_suite; + namespace detail { struct call_impl { virtual ~call_impl() { } - virtual int invoke() = 0; + // virtual int invoke() = 0; + virtual int invoke( test_suite *, int = 0 ) = 0; }; template <typename F> @@ -35,9 +41,13 @@ _f( f ) { } - virtual int invoke() - { return _f(); } + // virtual int invoke() + // { return _f(); } + virtual int invoke( test_suite *s, int count = 0 ) + { return _f( s, count ); } + + private: F _f; }; @@ -45,8 +55,12 @@ class dummy { public: - virtual int f() - { } + // virtual int f() + // { return 0; } + + virtual int f( test_suite *, int count = 0 ) + { return count; } + private: virtual ~dummy() { } @@ -56,7 +70,8 @@ class method_invoker { public: - typedef int (TC::*mf_type)(); + // typedef int (TC::*mf_type_a)(); + typedef int (TC::*mf_type)( test_suite *, int ); explicit method_invoker( TC& instance, mf_type f ) : _inst(instance), @@ -68,9 +83,12 @@ _func( m._func ) { } - int operator()() - { return (_inst.*_func)(); } + // int operator()() + // { return (_inst.*_func)(); } + int operator()( test_suite *ts, int count = 0 ) + { return (_inst.*_func)( ts, count ); } + private: method_invoker& operator =( const method_invoker<TC>& ) { return *this; } @@ -89,9 +107,12 @@ call( F f ) { new (&_buf[0]) call_impl_t<F>(f); } - int operator()() - { return reinterpret_cast<call_impl *>(&_buf[0])->invoke(); } + // int operator()() + // { return reinterpret_cast<call_impl *>(&_buf[0])->invoke(); } + int operator()( test_suite *ts, int count = 0 ) + { return reinterpret_cast<call_impl *>(&_buf[0])->invoke( ts, count ); } + private: // call_impl *_f; char _buf[((sizeof(call_impl_t<method_invoker<dummy> >)+64) / 64) << 6]; @@ -105,9 +126,12 @@ _tc( f ) { } - int operator ()() - { return _tc(); } + // int operator ()() + // { return _tc(); } + int operator ()( test_suite *ts, int count = 0 ) + { return _tc( ts, count ); } + private: call _tc; }; @@ -118,13 +142,18 @@ } template <class TC> -inline test_case *make_test_case( int (TC::*f)(), TC& instance ) +inline test_case *make_test_case( int (TC::*f)( test_suite *, int ), TC& instance ) { return new test_case( method_invoker<TC>(instance, f) ); } } // namespace detail +class init_exception : + public std::exception +{ +}; + class test_suite { private: @@ -139,7 +168,7 @@ typedef boost::property_map<graph_t,vertex_testcase_t>::type vertex_testcase_map_t; public: - typedef int (*func_type)(); + typedef int (*func_type)( test_suite *, int ); typedef vertex_t test_case_type; test_suite( const std::string& name ); @@ -150,45 +179,38 @@ test_case_type add( func_type, const std::string& name, test_case_type ); template <class TC> - test_case_type add( int (TC::*)(), TC&, const std::string& name ); + test_case_type add( int (TC::*)( test_suite *, int ), TC&, const std::string& name ); template <class TC> - test_case_type add( int (TC::*)(), TC&, const std::string& name, test_case_type ); + test_case_type add( int (TC::*)( test_suite *, int ), TC&, const std::string& name, test_case_type ); - struct stat - { - int total; - int passed; - int failed; - int skipped; - }; + int girdle( test_case_type start ); + int girdle() + { return girdle( root ); } + int run( test_suite *, int count = 0 ); - void girdle(); - void girdle( test_case_type start ); - void run_test_case( vertex_t v ); void check_test_case( vertex_t u, vertex_t v ); + void clean_test_case_state( vertex_t v ); - enum { - trace = 1, - trace_suite = 2 - }; + int flags(); + int flags( int ); + bool is_trace(); + void report( const char *, int, bool, const char * ); + base_logger *set_global_logger( base_logger * ); + base_logger *set_logger( base_logger * ); - static int flags(); - static bool is_trace(); - static void report( const char *, int, bool, const char * ); - private: enum { + pass = 0, fail = 1, - skip = 2, - init = 1024 + skip = 2 }; graph_t g; vertex_t root; - vertex_color_map_t color; vertex_testcase_map_t testcase; + base_logger *local_logger; struct test_case_collect { @@ -199,36 +221,36 @@ typedef std::map<vertex_t,test_case_collect> test_case_map_type; test_case_map_type _test; - test_suite::stat _stat; + base_logger::stat _stat; std::string _suite_name; - static int _flags; - static void (*_report)( const char *, int, bool, const char * ); - static int _root_func(); + static int _root_func( test_suite *, int = 0 ); + + static base_logger *logger; }; template <class TC> -test_suite::test_case_type test_suite::add( int (TC::*f)(), TC& instance, const std::string& name ) +test_suite::test_case_type test_suite::add( int (TC::*f)( test_suite *, int ), TC& instance, const std::string& name ) { vertex_t v = boost::add_vertex( boost::white_color, g); boost::add_edge( root, v, g ); _test[v].tc = detail::make_test_case( f, instance ); _test[v].state = 0; _test[v].name = name; - ++_stat.total; + // ++_stat.total; return v; } template <class TC> -test_suite::test_case_type test_suite::add( int (TC::*f)(), TC& instance, const std::string& name, test_suite::test_case_type depends ) +test_suite::test_case_type test_suite::add( int (TC::*f)( test_suite *, int ), TC& instance, const std::string& name, test_suite::test_case_type depends ) { vertex_t v = boost::add_vertex( boost::white_color, g); boost::add_edge( depends, v, g ); _test[v].tc = detail::make_test_case( f, instance ); _test[v].state = 0; _test[v].name = name; - ++_stat.total; + // ++_stat.total; return v; } @@ -238,11 +260,23 @@ } // namespace exam #ifdef FIT_EXAM -# define EXAM_CHECK(C) if ( !(C) ) { exam::test_suite::report( __FILE__, __LINE__, false, #C ); return 1; } else if ( exam::test_suite::is_trace() ) { exam::test_suite::report( __FILE__, __LINE__, true, #C ); } -# define EXAM_MESSAGE(M) +# define EXAM_IMPL(F) F( exam::test_suite *__exam_ts, int __exam_counter ) +# define EXAM_DECL(F) F( exam::test_suite *, int = 0 ) +# define EXAM_RESULT __exam_counter +# define EXAM_CHECK(C) if ( !(C) ) { __exam_ts->report( __FILE__, __LINE__, false, #C ); __exam_counter |= 1; } else __exam_ts->report( __FILE__, __LINE__, true, #C ) +# define EXAM_MESSAGE(M) __exam_ts->report( __FILE__, __LINE__, true, M ) +# define EXAM_REQUIRE(C) if ( !(C) ) { __exam_ts->report( __FILE__, __LINE__, false, #C ); return 1; } else __exam_ts->report( __FILE__, __LINE__, true, #C ) +# define EXAM_FAIL(M) __exam_ts->report( __FILE__, __LINE__, false, M ); return 1 +# define EXAM_ERROR(M) __exam_ts->report( __FILE__, __LINE__, false, M ); __exam_counter |= 1 #else +# define EXAM_IMPL(F) F( exam::test_suite *, int ) +# define EXAM_DECL(F) F( exam::test_suite *, int = 0 ) +# define EXAM_RESULT 0 # define EXAM_CHECK(C) # define EXAM_MESSAGE(M) +# define EXAM_REQUIRE(C) +# define EXAM_FAIL(M) +# define EXAM_ERROR(M) #endif Modified: trunk/complement/explore/app/exam/zero.cc =================================================================== --- trunk/complement/explore/app/exam/zero.cc 2007-07-12 07:33:00 UTC (rev 1611) +++ trunk/complement/explore/app/exam/zero.cc 2007-07-16 14:00:18 UTC (rev 1612) @@ -1,49 +1,14 @@ -#define FIT_EXAM +// -*- C++ -*- Time-stamp: <07/07/16 16:33:17 ptr> -#include "suite.h" +#include "exam_test_suite.h" -int func() +int main( int, char ** ) { - EXAM_CHECK(false); + // exam::test_suite t( "exam self test" ); + // t.add( exam_self_test, "exam self test suite" ); + // + // return t.girdle(); - return 0; + return exam_self_test(0); } -int func2() -{ - EXAM_CHECK(true); - - return 0; -} - -class test_x -{ - public: - - int f() - { - EXAM_CHECK(false); - - return 0; - } -}; - - -int main( int argc, char **argv ) -{ - exam::test_suite t( "exam level 0" ); - - test_x tx; - - t.add( func, "simple function" ); - t.add( &test_x::f, tx, "member function" ); - - t.add( func, "simple function, depends", - t.add( &test_x::f, tx, "member function, depends", - t.add( func2, "simple good function" ) ) ); - - t.girdle(); - - return 0; -} - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |