Chris@16: // (C) Copyright Gennadiy Rozental 2001-2008. Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // See http://www.boost.org/libs/test for the library home page. Chris@16: // Chris@16: // File : $RCSfile$ Chris@16: // Chris@101: // Version : $Revision$ Chris@16: // Chris@16: // Description : defines test_unit, test_case, test_case_results, test_suite and test_tree_visitor Chris@16: // *************************************************************************** Chris@16: Chris@16: #ifndef BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER Chris@16: #define BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER Chris@16: Chris@16: // Boost.Test Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Boost Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // STL Chris@16: #include // for typeid Chris@16: #include // for std::string Chris@16: #include // for std::list Chris@16: #include // for std::vector Chris@16: Chris@16: #include Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: namespace unit_test { Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_unit ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL test_unit { Chris@16: public: Chris@16: enum { type = tut_any }; Chris@16: Chris@16: // Constructor Chris@16: test_unit( const_string tu_name, test_unit_type t ); Chris@16: Chris@16: // dependencies management Chris@16: void depends_on( test_unit* tu ); Chris@16: bool check_dependencies() const; Chris@16: Chris@16: // Public r/o properties Chris@16: typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl)) id_t; Chris@16: typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite)) parent_id_t; Chris@16: readonly_property p_type; // type for this test unit Chris@16: readonly_property p_type_name; // "case"/"suite" Chris@16: id_t p_id; // unique id for this test unit Chris@16: parent_id_t p_parent_id; // parent test suite id Chris@16: Chris@16: // Public r/w properties Chris@16: readwrite_property p_name; // name for this test unit Chris@16: readwrite_property p_timeout; // timeout for the test unit execution Chris@16: readwrite_property p_expected_failures; // number of expected failures in this test unit Chris@16: mutable readwrite_property p_enabled; // enabled status for this unit Chris@16: Chris@16: void increase_exp_fail( unsigned num ); Chris@16: Chris@16: protected: Chris@16: ~test_unit(); Chris@16: Chris@16: private: Chris@16: // Data members Chris@16: std::list m_dependencies; Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_case_generator ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL test_unit_generator { Chris@16: public: Chris@16: virtual test_unit* next() const = 0; Chris@16: Chris@16: protected: Chris@16: BOOST_TEST_PROTECTED_VIRTUAL ~test_unit_generator() {} Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_case ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL test_case : public test_unit { Chris@16: public: Chris@16: enum { type = tut_case }; Chris@16: Chris@16: // Constructor Chris@16: test_case( const_string tc_name, callback0<> const& test_func ); Chris@16: Chris@16: // Access methods Chris@16: callback0<> const& test_func() const { return m_test_func; } Chris@16: Chris@16: private: Chris@16: friend class framework_impl; Chris@16: ~test_case() {} Chris@16: Chris@16: // BOOST_MSVC <= 1200 have problems with callback as property Chris@16: // Data members Chris@16: callback0<> m_test_func; Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_suite ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL test_suite : public test_unit { Chris@16: public: Chris@16: enum { type = tut_suite }; Chris@16: Chris@16: // Constructor Chris@16: explicit test_suite( const_string ts_name ); Chris@16: Chris@16: // test unit list management Chris@16: void add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 ); Chris@16: void add( test_unit_generator const& gen, unsigned timeout = 0 ); Chris@16: void remove( test_unit_id id ); Chris@16: Chris@16: // access methods Chris@16: test_unit_id get( const_string tu_name ) const; Chris@16: std::size_t size() const { return m_members.size(); } Chris@16: Chris@16: protected: Chris@16: friend BOOST_TEST_DECL Chris@16: void traverse_test_tree( test_suite const&, test_tree_visitor& ); Chris@16: friend class framework_impl; Chris@16: virtual ~test_suite() {} Chris@16: Chris@16: // Data members Chris@16: std::vector m_members; Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** master_test_suite ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL master_test_suite_t : public test_suite { Chris@16: public: Chris@16: master_test_suite_t() : test_suite( "Master Test Suite" ) Chris@16: , argc( 0 ) Chris@16: , argv( 0 ) Chris@16: {} Chris@16: Chris@16: // Data members Chris@16: int argc; Chris@16: char** argv; Chris@16: }; Chris@16: Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_tree_visitor ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL test_tree_visitor { Chris@16: public: Chris@16: // test tree visitor interface Chris@16: virtual void visit( test_case const& ) {} Chris@16: virtual bool test_suite_start( test_suite const& ) { return true; } Chris@16: virtual void test_suite_finish( test_suite const& ) {} Chris@16: Chris@16: protected: Chris@16: BOOST_TEST_PROTECTED_VIRTUAL ~test_tree_visitor() {} Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** traverse_test_tree ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: BOOST_TEST_DECL void traverse_test_tree( test_case const&, test_tree_visitor& ); Chris@16: BOOST_TEST_DECL void traverse_test_tree( test_suite const&, test_tree_visitor& ); Chris@16: BOOST_TEST_DECL void traverse_test_tree( test_unit_id , test_tree_visitor& ); Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: inline void Chris@16: traverse_test_tree( test_unit const& tu, test_tree_visitor& V ) Chris@16: { Chris@16: if( tu.p_type == tut_case ) Chris@16: traverse_test_tree( static_cast( tu ), V ); Chris@16: else Chris@16: traverse_test_tree( static_cast( tu ), V ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_case_counter ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class test_case_counter : public test_tree_visitor { Chris@16: public: Chris@16: // Constructor Chris@16: test_case_counter() : p_count( 0 ) {} Chris@16: Chris@16: BOOST_READONLY_PROPERTY( counter_t, (test_case_counter)) p_count; Chris@16: private: Chris@16: // test tree visitor interface Chris@16: virtual void visit( test_case const& ); Chris@16: virtual bool test_suite_start( test_suite const& ts ) { return ts.p_enabled; } Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_being_aborted ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: struct BOOST_TEST_DECL test_being_aborted {}; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** object generators ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: namespace ut_detail { Chris@16: Chris@16: BOOST_TEST_DECL std::string normalize_test_case_name( const_string tu_name ); Chris@16: Chris@16: template Chris@16: struct user_tc_method_invoker { Chris@16: typedef void (UserTestCase::*TestMethod )(); Chris@16: Chris@16: user_tc_method_invoker( shared_ptr inst, TestMethod test_method ) Chris@16: : m_inst( inst ), m_test_method( test_method ) {} Chris@16: Chris@16: void operator()() { ((*m_inst).*m_test_method)(); } Chris@16: Chris@16: shared_ptr m_inst; Chris@16: TestMethod m_test_method; Chris@16: }; Chris@16: Chris@16: } // namespace ut_detail Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: inline test_case* Chris@16: make_test_case( callback0<> const& test_func, const_string tc_name ) Chris@16: { Chris@16: return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: inline test_case* Chris@16: make_test_case( void (UserTestCase::* test_method )(), Chris@16: const_string tc_name, Chris@16: boost::shared_ptr user_test_case ) Chris@16: { Chris@16: return new test_case( ut_detail::normalize_test_case_name( tc_name ), Chris@16: ut_detail::user_tc_method_invoker( user_test_case, test_method ) ); Chris@16: } Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** auto_test_unit_registrar ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: namespace ut_detail { Chris@16: Chris@16: struct BOOST_TEST_DECL auto_test_unit_registrar Chris@16: { Chris@16: // Constructors Chris@16: auto_test_unit_registrar( test_case* tc, counter_t exp_fail ); Chris@16: explicit auto_test_unit_registrar( const_string ts_name ); Chris@16: explicit auto_test_unit_registrar( test_unit_generator const& tc_gen ); Chris@16: explicit auto_test_unit_registrar( int ); Chris@16: Chris@16: private: Chris@16: static std::list& curr_ts_store(); Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: template Chris@16: struct auto_tc_exp_fail { Chris@16: auto_tc_exp_fail() : m_value( 0 ) {} Chris@16: Chris@16: explicit auto_tc_exp_fail( unsigned v ) Chris@16: : m_value( v ) Chris@16: { Chris@16: instance() = this; Chris@16: } Chris@16: Chris@16: static auto_tc_exp_fail*& instance() Chris@16: { Chris@16: static auto_tc_exp_fail inst; Chris@16: static auto_tc_exp_fail* inst_ptr = &inst; Chris@16: Chris@16: return inst_ptr; Chris@16: } Chris@16: Chris@16: unsigned value() const { return m_value; } Chris@16: Chris@16: private: Chris@16: // Data members Chris@16: unsigned m_value; Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: } // namespace ut_detail Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** global_fixture ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: class BOOST_TEST_DECL global_fixture : public test_observer { Chris@16: public: Chris@16: // Constructor Chris@16: global_fixture(); Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: namespace ut_detail { Chris@16: Chris@16: template Chris@16: struct global_fixture_impl : public global_fixture { Chris@16: // Constructor Chris@16: global_fixture_impl(): m_fixure( 0 ) {} Chris@16: Chris@16: // test observer interface Chris@16: virtual void test_start( counter_t ) { m_fixure = new F; } Chris@16: virtual void test_finish() { delete m_fixure; m_fixure = 0; } Chris@16: virtual void test_aborted() { delete m_fixure; m_fixure = 0; } Chris@16: Chris@16: private: Chris@16: // Data members Chris@16: F* m_fixure; Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_case_template_invoker ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: class test_case_template_invoker { Chris@16: public: Chris@16: void operator()() { TestCaseTemplate::run( (boost::type*)0 ); } Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** generate_test_case_4_type ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: struct generate_test_case_4_type { Chris@16: explicit generate_test_case_4_type( const_string tc_name, Generator& G ) Chris@16: : m_test_case_name( tc_name ) Chris@16: , m_holder( G ) Chris@16: {} Chris@16: Chris@16: template Chris@16: void operator()( mpl::identity ) Chris@16: { Chris@16: std::string full_name; Chris@16: assign_op( full_name, m_test_case_name, 0 ); Chris@16: full_name += '<'; Chris@16: full_name += typeid(TestType).name(); Chris@16: if( boost::is_const::value ) Chris@16: full_name += " const"; Chris@16: full_name += '>'; Chris@16: Chris@16: m_holder.m_test_cases.push_back( Chris@16: new test_case( full_name, test_case_template_invoker() ) ); Chris@16: } Chris@16: Chris@16: private: Chris@16: // Data members Chris@16: const_string m_test_case_name; Chris@16: Generator& m_holder; Chris@16: }; Chris@16: Chris@16: // ************************************************************************** // Chris@16: // ************** test_case_template ************** // Chris@16: // ************************************************************************** // Chris@16: Chris@16: template Chris@16: class template_test_case_gen : public test_unit_generator { Chris@16: public: Chris@16: // Constructor Chris@16: template_test_case_gen( const_string tc_name ) Chris@16: { Chris@16: typedef generate_test_case_4_type, Chris@16: TestCaseTemplate Chris@16: > single_test_gen; Chris@16: mpl::for_each >( single_test_gen( tc_name, *this ) ); Chris@16: } Chris@16: Chris@16: virtual test_unit* next() const Chris@16: { Chris@16: if( m_test_cases.empty() ) Chris@16: return 0; Chris@16: Chris@16: test_unit* res = m_test_cases.front(); Chris@16: m_test_cases.pop_front(); Chris@16: Chris@16: return res; Chris@16: } Chris@16: Chris@16: // Data members Chris@16: mutable std::list m_test_cases; Chris@16: }; Chris@16: Chris@16: //____________________________________________________________________________// Chris@16: Chris@16: } // namespace ut_detail Chris@16: Chris@16: } // unit_test Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER Chris@16: