Home | History | Annotate | Download | only in test
      1 //  (C) Copyright Gennadiy Rozental 2001-2008.
      2 //  Distributed under the Boost Software License, Version 1.0.
      3 //  (See accompanying file LICENSE_1_0.txt or copy at
      4 //  http://www.boost.org/LICENSE_1_0.txt)
      5 
      6 //  See http://www.boost.org/libs/test for the library home page.
      7 //
      8 //  File        : $RCSfile$
      9 //
     10 //  Version     : $Revision: 54633 $
     11 //
     12 //  Description : defines test_unit, test_case, test_case_results, test_suite and test_tree_visitor
     13 // ***************************************************************************
     14 
     15 #ifndef BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
     16 #define BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
     17 
     18 // Boost.Test
     19 #include <boost/test/detail/config.hpp>
     20 #include <boost/test/detail/global_typedef.hpp>
     21 #include <boost/test/utils/class_properties.hpp>
     22 #include <boost/test/utils/callback.hpp>
     23 #include <boost/test/detail/fwd_decl.hpp>
     24 #include <boost/test/detail/workaround.hpp>
     25 #include <boost/test/test_observer.hpp>
     26 
     27 // Boost
     28 #include <boost/shared_ptr.hpp>
     29 #include <boost/mpl/for_each.hpp>
     30 #include <boost/mpl/identity.hpp>
     31 #include <boost/type.hpp>
     32 #include <boost/type_traits/is_const.hpp>
     33 
     34 // STL
     35 #include <typeinfo> // for typeid
     36 #include <string>   // for std::string
     37 #include <list>     // for std::list
     38 #include <vector>   // for std::vector
     39 
     40 #include <boost/test/detail/suppress_warnings.hpp>
     41 
     42 //____________________________________________________________________________//
     43 
     44 namespace boost {
     45 
     46 namespace unit_test {
     47 
     48 // ************************************************************************** //
     49 // **************                   test_unit                  ************** //
     50 // ************************************************************************** //
     51 
     52 class BOOST_TEST_DECL test_unit {
     53 public:
     54     enum { type = tut_any };
     55 
     56     // Constructor
     57     test_unit( const_string tu_name, test_unit_type t );
     58 
     59     // dependencies management
     60     void    depends_on( test_unit* tu );
     61     bool    check_dependencies() const;
     62 
     63     // Public r/o properties
     64     typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl))  id_t;
     65     typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite))      parent_id_t;
     66     readonly_property<test_unit_type>   p_type;                 // type for this test unit
     67     readonly_property<const_string>     p_type_name;            // "case"/"suite"
     68     id_t                                p_id;                   // unique id for this test unit
     69     parent_id_t                         p_parent_id;            // parent test suite id
     70 
     71     // Public r/w properties
     72     readwrite_property<std::string>     p_name;                 // name for this test unit
     73     readwrite_property<unsigned>        p_timeout;              // timeout for the test unit execution
     74     readwrite_property<counter_t>       p_expected_failures;    // number of expected failures in this test unit
     75     mutable readwrite_property<bool>    p_enabled;              // enabled status for this unit
     76 
     77     void                                increase_exp_fail( unsigned num );
     78 
     79 protected:
     80     ~test_unit();
     81 
     82 private:
     83     // Data members
     84     std::list<test_unit_id>             m_dependencies;
     85 };
     86 
     87 // ************************************************************************** //
     88 // **************              test_case_generator             ************** //
     89 // ************************************************************************** //
     90 
     91 class BOOST_TEST_DECL test_unit_generator {
     92 public:
     93     virtual test_unit*  next() const = 0;
     94 
     95 protected:
     96     BOOST_TEST_PROTECTED_VIRTUAL ~test_unit_generator() {}
     97 };
     98 
     99 // ************************************************************************** //
    100 // **************                   test_case                  ************** //
    101 // ************************************************************************** //
    102 
    103 class BOOST_TEST_DECL test_case : public test_unit {
    104 public:
    105     enum { type = tut_case };
    106 
    107     // Constructor
    108     test_case( const_string tc_name, callback0<> const& test_func );
    109 
    110     // Access methods
    111     callback0<> const&  test_func() const { return m_test_func; }
    112 
    113 private:
    114     friend class framework_impl;
    115     ~test_case() {}
    116 
    117     // BOOST_MSVC <= 1200 have problems with callback as property
    118     // Data members
    119     callback0<> m_test_func;
    120 };
    121 
    122 // ************************************************************************** //
    123 // **************                  test_suite                  ************** //
    124 // ************************************************************************** //
    125 
    126 class BOOST_TEST_DECL test_suite : public test_unit {
    127 public:
    128     enum { type = tut_suite };
    129 
    130     // Constructor
    131     explicit        test_suite( const_string ts_name );
    132 
    133     // test unit list management
    134     void            add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 );
    135     void            add( test_unit_generator const& gen, unsigned timeout = 0 );
    136     void            remove( test_unit_id id );
    137 
    138     // access methods
    139     test_unit_id    get( const_string tu_name ) const;
    140     std::size_t     size() const { return m_members.size(); }
    141 
    142 protected:
    143     friend BOOST_TEST_DECL
    144     void        traverse_test_tree( test_suite const&, test_tree_visitor& );
    145     friend class framework_impl;
    146     virtual     ~test_suite() {}
    147 
    148     // Data members
    149     std::vector<test_unit_id> m_members;
    150 };
    151 
    152 // ************************************************************************** //
    153 // **************               master_test_suite              ************** //
    154 // ************************************************************************** //
    155 
    156 class BOOST_TEST_DECL master_test_suite_t : public test_suite {
    157 public:
    158     master_test_suite_t() : test_suite( "Master Test Suite" )
    159     , argc( 0 )
    160     , argv( 0 )
    161     {}
    162 
    163     // Data members
    164     int      argc;
    165     char**   argv;
    166 };
    167 
    168 
    169 // ************************************************************************** //
    170 // **************               test_tree_visitor              ************** //
    171 // ************************************************************************** //
    172 
    173 class BOOST_TEST_DECL test_tree_visitor {
    174 public:
    175     // test tree visitor interface
    176     virtual void    visit( test_case const& )               {}
    177     virtual bool    test_suite_start( test_suite const& )   { return true; }
    178     virtual void    test_suite_finish( test_suite const& )  {}
    179 
    180 protected:
    181     BOOST_TEST_PROTECTED_VIRTUAL ~test_tree_visitor() {}
    182 };
    183 
    184 // ************************************************************************** //
    185 // **************               traverse_test_tree             ************** //
    186 // ************************************************************************** //
    187 
    188 BOOST_TEST_DECL void    traverse_test_tree( test_case const&, test_tree_visitor& );
    189 BOOST_TEST_DECL void    traverse_test_tree( test_suite const&, test_tree_visitor& );
    190 BOOST_TEST_DECL void    traverse_test_tree( test_unit_id     , test_tree_visitor& );
    191 
    192 //____________________________________________________________________________//
    193 
    194 inline void
    195 traverse_test_tree( test_unit const& tu, test_tree_visitor& V )
    196 {
    197     if( tu.p_type == tut_case )
    198         traverse_test_tree( static_cast<test_case const&>( tu ), V );
    199     else
    200         traverse_test_tree( static_cast<test_suite const&>( tu ), V );
    201 }
    202 
    203 //____________________________________________________________________________//
    204 
    205 // ************************************************************************** //
    206 // **************                test_case_counter             ************** //
    207 // ************************************************************************** //
    208 
    209 class test_case_counter : public test_tree_visitor {
    210 public:
    211     // Constructor
    212     test_case_counter() : p_count( 0 ) {}
    213 
    214     BOOST_READONLY_PROPERTY( counter_t, (test_case_counter)) p_count;
    215 private:
    216     // test tree visitor interface
    217     virtual void    visit( test_case const& );
    218     virtual bool    test_suite_start( test_suite const& ts )    { return ts.p_enabled; }
    219 };
    220 
    221 // ************************************************************************** //
    222 // **************               test_being_aborted             ************** //
    223 // ************************************************************************** //
    224 
    225 struct BOOST_TEST_DECL test_being_aborted {};
    226 
    227 // ************************************************************************** //
    228 // **************               object generators              ************** //
    229 // ************************************************************************** //
    230 
    231 namespace ut_detail {
    232 
    233 BOOST_TEST_DECL std::string normalize_test_case_name( const_string tu_name );
    234 
    235 template<typename InstanceType,typename UserTestCase>
    236 struct user_tc_method_invoker {
    237     typedef void (UserTestCase::*TestMethod )();
    238 
    239     user_tc_method_invoker( shared_ptr<InstanceType> inst, TestMethod test_method )
    240     : m_inst( inst ), m_test_method( test_method ) {}
    241 
    242     void operator()() { ((*m_inst).*m_test_method)(); }
    243 
    244     shared_ptr<InstanceType> m_inst;
    245     TestMethod               m_test_method;
    246 };
    247 
    248 } // namespace ut_detail
    249 
    250 //____________________________________________________________________________//
    251 
    252 inline test_case*
    253 make_test_case( callback0<> const& test_func, const_string tc_name )
    254 {
    255     return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func );
    256 }
    257 
    258 //____________________________________________________________________________//
    259 
    260 template<typename UserTestCase, typename InstanceType>
    261 inline test_case*
    262 make_test_case( void (UserTestCase::*           test_method )(),
    263                 const_string                    tc_name,
    264                 boost::shared_ptr<InstanceType> user_test_case )
    265 {
    266     return new test_case( ut_detail::normalize_test_case_name( tc_name ),
    267                           ut_detail::user_tc_method_invoker<InstanceType,UserTestCase>( user_test_case, test_method ) );
    268 }
    269 
    270 //____________________________________________________________________________//
    271 
    272 // ************************************************************************** //
    273 // **************           auto_test_unit_registrar           ************** //
    274 // ************************************************************************** //
    275 
    276 namespace ut_detail {
    277 
    278 struct BOOST_TEST_DECL auto_test_unit_registrar
    279 {
    280     // Constructors
    281                 auto_test_unit_registrar( test_case* tc, counter_t exp_fail );
    282     explicit    auto_test_unit_registrar( const_string ts_name );
    283     explicit    auto_test_unit_registrar( test_unit_generator const& tc_gen );
    284     explicit    auto_test_unit_registrar( int );
    285 
    286 private:
    287     static std::list<test_suite*>& curr_ts_store();
    288 };
    289 
    290 //____________________________________________________________________________//
    291 
    292 template<typename T>
    293 struct auto_tc_exp_fail {
    294     auto_tc_exp_fail() : m_value( 0 ) {}
    295 
    296     explicit    auto_tc_exp_fail( unsigned v )
    297     : m_value( v )
    298     {
    299         instance() = this;
    300     }
    301 
    302     static auto_tc_exp_fail*& instance()
    303     {
    304         static auto_tc_exp_fail     inst;
    305         static auto_tc_exp_fail*    inst_ptr = &inst;
    306 
    307         return inst_ptr;
    308     }
    309 
    310     unsigned    value() const { return m_value; }
    311 
    312 private:
    313     // Data members
    314     unsigned    m_value;
    315 };
    316 
    317 //____________________________________________________________________________//
    318 
    319 } // namespace ut_detail
    320 
    321 // ************************************************************************** //
    322 // **************                global_fixture                ************** //
    323 // ************************************************************************** //
    324 
    325 class BOOST_TEST_DECL global_fixture : public test_observer {
    326 public:
    327     // Constructor
    328     global_fixture();
    329 };
    330 
    331 //____________________________________________________________________________//
    332 
    333 namespace ut_detail {
    334 
    335 template<typename F>
    336 struct global_fixture_impl : public global_fixture {
    337     // Constructor
    338     global_fixture_impl(): m_fixure( 0 )    {}
    339 
    340     // test observer interface
    341     virtual void    test_start( counter_t ) { m_fixure = new F; }
    342     virtual void    test_finish()           { delete m_fixure; m_fixure = 0; }
    343     virtual void    test_aborted()          { delete m_fixure; m_fixure = 0; }
    344 
    345 private:
    346     // Data members
    347     F*  m_fixure;
    348 };
    349 
    350 // ************************************************************************** //
    351 // **************          test_case_template_invoker          ************** //
    352 // ************************************************************************** //
    353 
    354 template<typename TestCaseTemplate,typename TestType>
    355 class test_case_template_invoker {
    356 public:
    357     void    operator()()    { TestCaseTemplate::run( (boost::type<TestType>*)0 ); }
    358 };
    359 
    360 // ************************************************************************** //
    361 // **************           generate_test_case_4_type          ************** //
    362 // ************************************************************************** //
    363 
    364 template<typename Generator,typename TestCaseTemplate>
    365 struct generate_test_case_4_type {
    366     explicit    generate_test_case_4_type( const_string tc_name, Generator& G )
    367     : m_test_case_name( tc_name )
    368     , m_holder( G )
    369     {}
    370 
    371     template<typename TestType>
    372     void        operator()( mpl::identity<TestType> )
    373     {
    374         std::string full_name;
    375         assign_op( full_name, m_test_case_name, 0 );
    376         full_name += '<';
    377         full_name += typeid(TestType).name();
    378         if( boost::is_const<TestType>::value )
    379             full_name += " const";
    380         full_name += '>';
    381 
    382         m_holder.m_test_cases.push_back(
    383             new test_case( full_name, test_case_template_invoker<TestCaseTemplate,TestType>() ) );
    384     }
    385 
    386 private:
    387     // Data members
    388     const_string    m_test_case_name;
    389     Generator&      m_holder;
    390 };
    391 
    392 // ************************************************************************** //
    393 // **************              test_case_template              ************** //
    394 // ************************************************************************** //
    395 
    396 template<typename TestCaseTemplate,typename TestTypesList>
    397 class template_test_case_gen : public test_unit_generator {
    398 public:
    399     // Constructor
    400     template_test_case_gen( const_string tc_name )
    401     {
    402         typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,
    403                                           TestCaseTemplate
    404         > single_test_gen;
    405         mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, *this ) );
    406     }
    407 
    408     virtual test_unit* next() const
    409     {
    410         if( m_test_cases.empty() )
    411             return 0;
    412 
    413         test_unit* res = m_test_cases.front();
    414         m_test_cases.pop_front();
    415 
    416         return res;
    417     }
    418 
    419     // Data members
    420     mutable std::list<test_unit*> m_test_cases;
    421 };
    422 
    423 //____________________________________________________________________________//
    424 
    425 } // namespace ut_detail
    426 
    427 } // unit_test
    428 
    429 } // namespace boost
    430 
    431 #include <boost/test/detail/enable_warnings.hpp>
    432 
    433 #endif // BOOST_TEST_UNIT_TEST_SUITE_IMPL_HPP_071894GER
    434 
    435