Home | History | Annotate | Download | only in test
      1 //  (C) Copyright Gennadiy Rozental 2005-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: 49312 $
     11 //
     12 //  Description : Facilities to perform interaction-based testing
     13 // ***************************************************************************
     14 
     15 #ifndef BOOST_TEST_INTERACTION_BASED_HPP_112105GER
     16 #define BOOST_TEST_INTERACTION_BASED_HPP_112105GER
     17 
     18 // Boost.Test
     19 #include <boost/test/detail/config.hpp>
     20 #include <boost/test/detail/global_typedef.hpp>
     21 
     22 #include <boost/test/utils/wrap_stringstream.hpp>
     23 
     24 #include <boost/test/detail/suppress_warnings.hpp>
     25 
     26 // Boost
     27 #include <boost/lexical_cast.hpp>
     28 
     29 //____________________________________________________________________________//
     30 
     31 // ************************************************************************** //
     32 // **************               BOOST_ITEST_EPOINT             ************** //
     33 // ************************************************************************** //
     34 
     35 #define BOOST_ITEST_EPOINT( description ) \
     36     ::boost::itest::manager::instance().exception_point( BOOST_TEST_L(__FILE__), __LINE__, description )
     37 /**/
     38 
     39 // ************************************************************************** //
     40 // **************               BOOST_ITEST_DPOINT             ************** //
     41 // ************************************************************************** //
     42 
     43 #define BOOST_ITEST_DPOINT() \
     44     ::boost::itest::manager::instance().decision_point( BOOST_TEST_L(__FILE__), __LINE__ )
     45 /**/
     46 
     47 // ************************************************************************** //
     48 // **************                BOOST_ITEST_SCOPE             ************** //
     49 // ************************************************************************** //
     50 
     51 #define BOOST_ITEST_SCOPE( scope_name ) \
     52     ::boost::itest::scope_guard itest_scope_guard ## __LINE__( BOOST_TEST_L(__FILE__), __LINE__, BOOST_STRINGIZE(scope_name) )
     53 /**/
     54 
     55 // ************************************************************************** //
     56 // **************                 BOOST_ITEST_NEW              ************** //
     57 // ************************************************************************** //
     58 
     59 #define BOOST_ITEST_NEW( type_name ) \
     60     new ( ::boost::itest::location( BOOST_TEST_L(__FILE__), __LINE__ ) ) type_name
     61 /**/
     62 
     63 // ************************************************************************** //
     64 // **************              BOOST_ITEST_DATA_FLOW           ************** //
     65 // ************************************************************************** //
     66 
     67 #define BOOST_ITEST_DATA_FLOW( v ) \
     68     ::boost::itest::manager::instance().generic_data_flow( v )
     69 /**/
     70 
     71 // ************************************************************************** //
     72 // **************               BOOST_ITEST_RETURN             ************** //
     73 // ************************************************************************** //
     74 
     75 #define BOOST_ITEST_RETURN( type, default_value ) \
     76     ::boost::itest::manager::instance().generic_return<type>( default_value )
     77 /**/
     78 
     79 // ************************************************************************** //
     80 // **************              BOOST_ITEST_MOCK_FUNC           ************** //
     81 // ************************************************************************** //
     82 
     83 #define BOOST_ITEST_MOCK_FUNC( function_name )          \
     84     BOOST_ITEST_SCOPE( function_name );                 \
     85     BOOST_ITEST_EPOINT( 0 );                            \
     86     return ::boost::itest::mock_object<>::prototype();  \
     87 /**/
     88 
     89 namespace boost {
     90 
     91 namespace itest { // interaction-based testing
     92 
     93 using unit_test::const_string;
     94 
     95 // ************************************************************************** //
     96 // **************                    manager                   ************** //
     97 // ************************************************************************** //
     98 
     99 class BOOST_TEST_DECL manager {
    100 public:
    101     // instance access
    102     static manager&     instance() { return *instance_ptr(); }
    103 
    104     // Mock objects interface hooks
    105     virtual void        exception_point( const_string /*file*/,
    106                                          std::size_t /*line_num*/,
    107                                          const_string /*descr*/ ){}
    108     virtual bool        decision_point( const_string /*file*/,
    109                                         std::size_t /*line_num*/ )          { return true; }
    110     virtual unsigned    enter_scope( const_string /*file*/,
    111                                      std::size_t /*line_num*/,
    112                                      const_string /*scope_name*/){ return 0; }
    113     virtual void        leave_scope( unsigned )                             {}
    114     virtual void        allocated( const_string /*file*/,
    115                                    std::size_t /*line_num*/,
    116                                    void* /*p*/, std::size_t /*s*/ )         {}
    117     virtual void        freed( void* /*p*/ )                                {}
    118     virtual void        data_flow( const_string /*d*/ )                     {}
    119     virtual std::string return_value( const_string /*default_value */ )     { return ""; }
    120 
    121     template<typename T>
    122     void                generic_data_flow( T const& t )
    123     {
    124         wrap_stringstream ws;
    125 
    126         data_flow( (ws << t).str() );
    127     }
    128     template<typename T, typename DefaultValueType>
    129     T                   generic_return( DefaultValueType const& dv )
    130     {
    131         wrap_stringstream ws;
    132 
    133         std::string const& res = return_value( (ws << dv).str() );
    134 
    135         if( res.empty() )
    136             return dv;
    137 
    138         return lexical_cast<T>( res );
    139     }
    140 
    141 protected:
    142     manager();
    143 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
    144 public:
    145 #endif
    146     BOOST_TEST_PROTECTED_VIRTUAL ~manager();
    147 
    148 private:
    149     struct dummy_constr{};
    150     explicit manager( dummy_constr* ) {}
    151 
    152     static manager*     instance_ptr( bool reset = false, manager* ptr = 0 );
    153 }; // manager
    154 
    155 // ************************************************************************** //
    156 // **************                  scope_guard                 ************** //
    157 // ************************************************************************** //
    158 
    159 class scope_guard {
    160 public:
    161     // Constructor
    162     scope_guard( const_string file, std::size_t line_num, const_string scope_name )
    163     {
    164         m_scope_index = manager::instance().enter_scope( file, line_num, scope_name );
    165     }
    166     ~scope_guard()
    167     {
    168         manager::instance().leave_scope( m_scope_index );
    169     }
    170 
    171     unsigned m_scope_index;
    172 };
    173 
    174 // ************************************************************************** //
    175 // **************                    location                  ************** //
    176 // ************************************************************************** //
    177 
    178 struct location {
    179     location( const_string file, std::size_t line )
    180     : m_file_name( file )
    181     , m_line_num( line )
    182     {}
    183 
    184     const_string    m_file_name;
    185     std::size_t     m_line_num;
    186 };
    187 
    188 }  // namespace itest
    189 
    190 } // namespace boost
    191 
    192 // ************************************************************************** //
    193 // **************              operator new overload           ************** //
    194 // ************************************************************************** //
    195 
    196 #if !defined(BOOST_ITEST_NO_NEW_OVERLOADS)
    197 
    198 // STL
    199 #include <cstdlib>
    200 
    201 # ifdef BOOST_NO_STDC_NAMESPACE
    202 namespace std { using ::malloc; using ::free; }
    203 # endif
    204 # ifdef _CRTDBG_MAP_ALLOC
    205 namespace std { using ::_malloc_dbg; using ::_free_dbg; }
    206 # endif
    207 
    208 inline void*
    209 operator new( std::size_t s, ::boost::itest::location const& l )
    210 {
    211     void* res = std::malloc(s ? s : 1);
    212 
    213     if( res )
    214         ::boost::itest::manager::instance().allocated( l.m_file_name, l.m_line_num, res, s );
    215     else
    216         throw std::bad_alloc();
    217 
    218     return res;
    219 }
    220 
    221 //____________________________________________________________________________//
    222 
    223 inline void*
    224 operator new[]( std::size_t s, ::boost::itest::location const& l )
    225 {
    226     void* res = std::malloc(s ? s : 1);
    227 
    228     if( res )
    229         ::boost::itest::manager::instance().allocated( l.m_file_name, l.m_line_num, res, s );
    230     else
    231         throw std::bad_alloc();
    232 
    233     return res;
    234 }
    235 
    236 //____________________________________________________________________________//
    237 
    238 inline void
    239 operator delete( void* p, ::boost::itest::location const& )
    240 {
    241     ::boost::itest::manager::instance().freed( p );
    242 
    243     std::free( p );
    244 }
    245 
    246 //____________________________________________________________________________//
    247 
    248 inline void
    249 operator delete[]( void* p, ::boost::itest::location const& )
    250 {
    251     ::boost::itest::manager::instance().freed( p );
    252 
    253     std::free( p );
    254 }
    255 
    256 //____________________________________________________________________________//
    257 
    258 #endif
    259 
    260 #include <boost/test/detail/enable_warnings.hpp>
    261 
    262 #endif // BOOST_TEST_INTERACTION_BASED_HPP_112105GER
    263