boost/test/unit_test_suite.hpp
// (C) Copyright Gennadiy Rozental 2001-2003. // (C) Copyright Ullrich Koethe 2001. // Use, modification, and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. // // File : $RCSfile: unit_test_suite.hpp,v $ // // Version : $Revision: 1.18 $ // // Description : defines all classes in test_case hierarchy and object generators // for them. // *************************************************************************** #ifndef BOOST_UNIT_TEST_SUITE_HPP #define BOOST_UNIT_TEST_SUITE_HPP // Boost.Test #include <boost/test/detail/unit_test_monitor.hpp> #include <boost/test/detail/unit_test_config.hpp> #include <boost/test/detail/class_properties.hpp> // BOOST #include <boost/shared_ptr.hpp> // STL #include <string> // for std::string //____________________________________________________________________________// #define BOOST_TEST_CASE( function ) \ boost::unit_test_framework::create_test_case((function), #function ) #define BOOST_CLASS_TEST_CASE( function, tc_instance ) \ boost::unit_test_framework::create_test_case((function), #function, tc_instance ) #define BOOST_PARAM_TEST_CASE( function, begin, end ) \ boost::unit_test_framework::create_test_case((function), #function, (begin), (end) ) #define BOOST_PARAM_CLASS_TEST_CASE( function, tc_instance, begin, end ) \ boost::unit_test_framework::create_test_case((function), #function, tc_instance, (begin), (end) ) #define BOOST_TEST_SUITE( testsuite_name ) \ ( new boost::unit_test_framework::test_suite( testsuite_name ) ) namespace boost { namespace unit_test_framework { // ************************************************************************** // // ************** test_case ************** // // ************************************************************************** // class test_case { public: typedef detail::unit_test_monitor::error_level error_level_type; // post creation configuration void depends_on( test_case const* rhs ); // Destructor virtual ~test_case() {} // total number of test cases virtual unit_test_counter size() const; // execute this method to run the test case void run(); // status bool has_passed() const; // public properties BOOST_READONLY_PROPERTY( int, 2, (test_case,test_suite) ) p_timeout; // timeout for the excecution monitor BOOST_READONLY_PROPERTY( unit_test_counter, 1, (test_suite) ) p_expected_failures; // number of assertions that are expected to fail in this test case BOOST_READONLY_PROPERTY( bool, 0, () ) p_type; // true = test case, false - test suite BOOST_READONLY_PROPERTY( std::string, 0, () ) p_name; // name for this test case protected: // protected properties BOOST_READONLY_PROPERTY( bool, 2, (test_case,test_suite) ) p_compound_stage; // used to properly manage progress report BOOST_READWRITE_PROPERTY( unit_test_counter ) p_stages_amount; // number of stages this test consist of; stage could be another test case // like with test_suite, another parameterized test for parameterized_test_case // or 1 stage that reflect single test_case behaviour // access methods void curr_stage_is_compound(); // Constructor explicit test_case( std::string const& name_, bool type_, unit_test_counter stages_amount_, bool monitor_run_ = true ); // test case implementation hooks to be called with unit_test_monitor or alone virtual void do_init() {} virtual void do_run() {} virtual void do_destroy() {} private: // Data members struct Impl; boost::shared_ptr<Impl> m_pimpl; }; //____________________________________________________________________________// extern detail::unit_test_monitor the_monitor; template<typename Exception, typename ExceptionTranslator> void register_exception_translator( ExceptionTranslator const& tr, boost::type<Exception>* d = 0 ) { the_monitor.register_exception_translator( tr, d ); } //____________________________________________________________________________// // ************************************************************************** // // ************** function_test_case ************** // // ************************************************************************** // class function_test_case : public test_case { public: typedef void (*function_type)(); // Constructor function_test_case( function_type f_, std::string const& name_ ) : test_case( name_, true, 1 ), m_function( f_ ) {} protected: // test case implementation void do_run() { m_function(); } private: // Data members function_type m_function; }; // ************************************************************************** // // ************** class_test_case ************** // // ************************************************************************** // template<class UserTestCase> class class_test_case : public test_case { public: typedef void (UserTestCase::*function_type)(); // Constructor class_test_case( function_type f_, std::string const& name_, boost::shared_ptr<UserTestCase> const& user_test_case_ ) : test_case( name_, true, 1 ), m_user_test_case( user_test_case_ ), m_function( f_ ) {} private: // test case implementation void do_run() { if( (!!m_user_test_case) && m_function ) ((*m_user_test_case).*m_function)(); } void do_destroy() { m_user_test_case.reset(); // t ofree the reference to the shared use test case instance } // Data members boost::shared_ptr<UserTestCase> m_user_test_case; function_type m_function; }; // ************************************************************************** // // ************** parametrized_function_test_case ************** // // ************************************************************************** // template <typename ParamIterator, typename ParameterType> class parametrized_function_test_case : public test_case { public: typedef void (*function_type)( ParameterType ); // Constructor parametrized_function_test_case( function_type f_, std::string const& name_, ParamIterator const& par_begin_, ParamIterator const& par_end_ ) : test_case( name_, true, 0 ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ), m_function( f_ ) { // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect: p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) ); } // test case implementation void do_init() { m_curr_parameter = m_first_parameter; } void do_run() { m_function( *m_curr_parameter++ ); } private: // Data members ParamIterator m_first_parameter; ParamIterator m_last_parameter; ParamIterator m_curr_parameter; function_type m_function; }; // ************************************************************************** // // ************** parametrized_class_test_case ************** // // ************************************************************************** // template <class UserTestCase, class ParamIterator, typename ParameterType> class parametrized_class_test_case : public test_case { public: typedef void (UserTestCase::*function_type)( ParameterType ); // Constructor parametrized_class_test_case( function_type f_, std::string const& name_, boost::shared_ptr<UserTestCase>const & user_test_case_, ParamIterator const& par_begin_, ParamIterator const& par_end_ ) : test_case( name_, true, 0 ), m_first_parameter( par_begin_ ), m_last_parameter( par_end_ ), m_user_test_case( user_test_case_ ), m_function( f_ ) { // the typecasts are here to keep Borland C++ Builder 5 happy, for other compilers they have no effect: p_stages_amount.set( detail::distance( (ParamIterator)par_begin_, (ParamIterator)par_end_ ) ); } // test case implementation void do_init() { m_curr_parameter = m_first_parameter; } void do_run() { ((*m_user_test_case).*m_function)( *m_curr_parameter++ ); } void do_destroy() { m_user_test_case.reset(); } private: // Data members ParamIterator m_first_parameter; ParamIterator m_last_parameter; ParamIterator m_curr_parameter; boost::shared_ptr<UserTestCase> m_user_test_case; function_type m_function; }; // ************************************************************************** // // ************** test_suite ************** // // ************************************************************************** // class test_suite : public test_case { public: // Constructor explicit test_suite( std::string const& name_ = "Master" ); // Destructor virtual ~test_suite(); // test case list management void add( test_case* tc_, unit_test_counter expected_failures_ = 0, int timeout_ = 0 ); // access methods unit_test_counter size() const; // test case implementation void do_init(); void do_run(); private: // Data members struct Impl; boost::shared_ptr<Impl> m_pimpl; }; // ************************************************************************** // // ************** object generators ************** // // ************************************************************************** // namespace detail { std::string const& normalize_test_case_name( std::string& name_ ); } // namespace detail //____________________________________________________________________________// inline test_case* create_test_case( void (*fct_)(), std::string name_ ) { return new function_test_case( fct_, detail::normalize_test_case_name( name_ ) ); } //____________________________________________________________________________// template<class UserTestCase> inline test_case* create_test_case( void (UserTestCase::*fct_)(), std::string name_, boost::shared_ptr<UserTestCase> const& user_test_case_ ) { return new class_test_case<UserTestCase>( fct_, detail::normalize_test_case_name( name_ ), user_test_case_ ); } //____________________________________________________________________________// template<typename ParamIterator, typename ParamType> inline test_case* create_test_case( void (*fct_)( ParamType ), std::string name_, ParamIterator const& par_begin_, ParamIterator const& par_end_ ) { return new parametrized_function_test_case<ParamIterator,ParamType>( fct_, detail::normalize_test_case_name( name_ ), par_begin_, par_end_ ); } //____________________________________________________________________________// template<class UserTestCase, typename ParamIterator, typename ParamType> inline test_case* create_test_case( void (UserTestCase::*fct_)( ParamType ), std::string name_, boost::shared_ptr<UserTestCase> const& user_test_case_, ParamIterator const& par_begin_, ParamIterator const& par_end_ ) { return new parametrized_class_test_case<UserTestCase,ParamIterator,ParamType>( fct_, detail::normalize_test_case_name( name_ ), user_test_case_, par_begin_, par_end_ ); } //____________________________________________________________________________// } // unit_test_framework } // namespace boost // *************************************************************************** // Revision History : // // $Log: unit_test_suite.hpp,v $ // Revision 1.18 2003/12/01 00:41:56 rogeeff // prerelease cleaning // // *************************************************************************** #endif // BOOST_UNIT_TEST_SUITE_HPP