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 89namespace boost { 90 91namespace itest { // interaction-based testing 92 93using unit_test::const_string; 94 95// ************************************************************************** // 96// ************** manager ************** // 97// ************************************************************************** // 98 99class BOOST_TEST_DECL manager { 100public: 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 141protected: 142 manager(); 143#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) 144public: 145#endif 146 BOOST_TEST_PROTECTED_VIRTUAL ~manager(); 147 148private: 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 159class scope_guard { 160public: 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 178struct 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 202namespace std { using ::malloc; using ::free; } 203# endif 204# ifdef _CRTDBG_MAP_ALLOC 205namespace std { using ::_malloc_dbg; using ::_free_dbg; } 206# endif 207 208inline void* 209operator 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 223inline void* 224operator 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 238inline void 239operator delete( void* p, ::boost::itest::location const& ) 240{ 241 ::boost::itest::manager::instance().freed( p ); 242 243 std::free( p ); 244} 245 246//____________________________________________________________________________// 247 248inline void 249operator 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