From eea5d0bc4166181ecdf24ea1043850976edfc26b Mon Sep 17 00:00:00 2001 From: Gennadiy Rozental Date: Wed, 14 Dec 2005 05:56:56 +0000 Subject: [PATCH] Interraction based / logged expectation testing is introduced [SVN r32048] --- include/boost/test/impl/interaction_based.ipp | 160 +++++++++++ .../boost/test/impl/logged_expectations.ipp | 249 ++++++++++++++++++ 2 files changed, 409 insertions(+) create mode 100644 include/boost/test/impl/interaction_based.ipp create mode 100644 include/boost/test/impl/logged_expectations.ipp diff --git a/include/boost/test/impl/interaction_based.ipp b/include/boost/test/impl/interaction_based.ipp new file mode 100644 index 00000000..70805e85 --- /dev/null +++ b/include/boost/test/impl/interaction_based.ipp @@ -0,0 +1,160 @@ +// (C) Copyright Gennadiy Rozental 2005. +// Use, modification, and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// Version : $Revision$ +// +// Description : +// *************************************************************************** + +#ifndef BOOST_TEST_INTERACTION_BASED_IPP_112105GER +#define BOOST_TEST_INTERACTION_BASED_IPP_112105GER + +// Boost.Test +#include +#include +#include +#include + +#include + +// STL +#include +#include +#include + +# ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::malloc; using ::free; } +# endif + +//____________________________________________________________________________// + +namespace boost { + +namespace itest { // interaction-based testing + +// ************************************************************************** // +// ************** manager ************** // +// ************************************************************************** // + +manager::manager() +{ + instance_ptr( true, this ); +} + +//____________________________________________________________________________// + +manager::~manager() +{ + instance_ptr( true ); +} + +//____________________________________________________________________________// + +manager* +manager::instance_ptr( bool reset, manager* new_ptr ) +{ + static manager dummy( 0 ); + + static manager* ptr = &dummy; + + if( reset ) { + if( new_ptr ) { + if( ptr != &dummy ) + throw std::logic_error( std::string( "Couldn't run two interation based test the same time" ) ); + + ptr = new_ptr; + } + else + ptr = &dummy; + } + + return ptr; +} + +// ************************************************************************** // +// ************** mock_object ************** // +// ************************************************************************** // + +mock_object<> simple_mock; + +} // namespace itest + +} // namespace boost + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** operator new overload ************** // +// ************************************************************************** // + +#if !defined(BOOST_ITEST_NO_NEW_OVERLOADS) && !BOOST_WORKAROUND(BOOST_MSVC, <1300) + +void* +operator new( std::size_t s, ::boost::itest::location const& l ) +{ + void* res = std::malloc( s ); + + if( res ) + ::boost::itest::manager::instance().allocated( l.m_file_name, l.m_line_num, res, s ); + else + throw std::bad_alloc(); + + return res; +} + +//____________________________________________________________________________// + +void* +operator new[]( std::size_t s, ::boost::itest::location const& l ) +{ + void* res = std::malloc( s ); + + if( res ) + ::boost::itest::manager::instance().allocated( l.m_file_name, l.m_line_num, res, s ); + else + throw std::bad_alloc(); + + return res; +} + +//____________________________________________________________________________// + +void operator delete( void* p, ::boost::itest::location const& ) +{ + ::boost::itest::manager::instance().freed( p ); + + std::free( p ); +} + +//____________________________________________________________________________// + +void +operator delete[]( void* p, ::boost::itest::location const& ) +{ + ::boost::itest::manager::instance().freed( p ); + + std::free( p ); +} + +//____________________________________________________________________________// + +#endif + +#include + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/12/14 05:56:56 rogeeff +// Interraction based / logged expectation testing is introduced +// +// *************************************************************************** + +#endif // BOOST_TEST_INTERACTION_BASED_IPP_112105GER diff --git a/include/boost/test/impl/logged_expectations.ipp b/include/boost/test/impl/logged_expectations.ipp new file mode 100644 index 00000000..bb53b278 --- /dev/null +++ b/include/boost/test/impl/logged_expectations.ipp @@ -0,0 +1,249 @@ +// (C) Copyright Gennadiy Rozental 2005. +// Use, modification, and distribution are subject to the +// Boost Software License, ELOG_VER 1.0. (See accompanying file +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/libs/test for the library home page. +// +// File : $RCSfile$ +// +// ELOG_VER : $Revision$ +// +// Description : Facilities to perform interaction based testng of logged expectations +// *************************************************************************** + +#ifndef BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER +#define BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER + +// Boost.Test +#include + +#if !BOOST_WORKAROUND(__GNUC__, < 3) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && !BOOST_WORKAROUND(BOOST_MSVC, <1300) + +#include + +#include +#include + +#include +#include + +#include + +// Boost +#include + +// STL +#include + +//____________________________________________________________________________// + +namespace boost { + +using namespace ::boost::unit_test; + +namespace itest { + +// ************************************************************************** // +// ************** logged expectation test implementation ************** // +// ************************************************************************** // + +struct expectations_logger : itest::manager { + // Constructor + expectations_logger( const_string log_file_name, bool test_or_log ); + + virtual bool decision_point( const_string, std::size_t ); + virtual unsigned enter_scope( const_string, std::size_t, const_string scope_name ); + virtual void allocated( const_string, std::size_t, void*, std::size_t s ); + virtual void data_flow( const_string d ); + virtual std::string return_value( const_string default_value ); + +private: + // Data members + bool m_test_or_log; + std::fstream m_log_file; +}; + +literal_string ELOG_VER = "1.0"; +literal_string CLMN_SEP = "|"; +static const char LINE_SEP = '\n'; + +literal_string FILE_SIG = "ELOG"; +literal_string SCOPE_SIG = "SCOPE"; +literal_string ALLOC_SIG = "ALLOC"; +literal_string DP_SIG = "SWITCH"; +literal_string DATA_SIG = "DATA"; +literal_string RETURN_SIG = "RETURN"; + +//____________________________________________________________________________// + +expectations_logger::expectations_logger( const_string log_file_name, bool test_or_log ) +: m_test_or_log( test_or_log ) +{ + BOOST_REQUIRE_MESSAGE( !log_file_name.is_empty(), "Empty expectations log file name" ); + + m_log_file.open( log_file_name.begin(), test_or_log ? std::ios::in : std::ios::out ); + + BOOST_REQUIRE_MESSAGE( m_log_file.is_open(), + "Couldn't open expectations log file " << log_file_name + << " for " << ( m_test_or_log ? "reading" : "writing") ); + + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, FILE_SIG ); + ++tit; + BOOST_CHECK_EQUAL( *tit, ELOG_VER ); + } + else { + m_log_file << FILE_SIG << CLMN_SEP << ELOG_VER << LINE_SEP; + } +} + +//____________________________________________________________________________// + +bool +expectations_logger::decision_point( const_string, std::size_t ) +{ + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, DP_SIG ); ++tit; + return lexical_cast( *tit ); + } + else { + m_log_file << DP_SIG << CLMN_SEP << std::boolalpha << true << LINE_SEP; + + return true; + } +} + +//____________________________________________________________________________// + +unsigned +expectations_logger::enter_scope( const_string, std::size_t, const_string scope_name ) +{ + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, SCOPE_SIG ); ++tit; + BOOST_CHECK_EQUAL( *tit, scope_name ); + } + else { + m_log_file << SCOPE_SIG << CLMN_SEP << scope_name << LINE_SEP; + } + + return 0; +} + +//____________________________________________________________________________// + +void +expectations_logger::allocated( const_string, std::size_t, void*, std::size_t s ) +{ + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, ALLOC_SIG ); ++tit; + BOOST_CHECK_EQUAL( lexical_cast( *tit ), s ); + } + else { + m_log_file << ALLOC_SIG << CLMN_SEP << s << LINE_SEP; + } +} + +//____________________________________________________________________________// + +void +expectations_logger::data_flow( const_string d ) +{ + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, DATA_SIG ); ++tit; + BOOST_CHECK_EQUAL( *tit, d ); + } + else { + m_log_file << DATA_SIG << CLMN_SEP << d << LINE_SEP; + } +} + +//____________________________________________________________________________// + +std::string +expectations_logger::return_value( const_string default_value ) +{ + if( m_test_or_log ) { + std::string line; + + std::getline( m_log_file, line, LINE_SEP ); + + string_token_iterator tit( const_string( line ), (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); + + BOOST_CHECK_EQUAL( *tit, RETURN_SIG ); ++tit; + + return std::string( tit->begin(), tit->size() ); + } + else { + m_log_file << RETURN_SIG << CLMN_SEP << default_value << LINE_SEP; + + return std::string(); + } +} + +//____________________________________________________________________________// + +// ************************************************************************** // +// ************** logged expectations test ************** // +// ************************************************************************** // + +void BOOST_TEST_DECL +logged_expectations( callback0<> const& F, const_string log_file_name, bool test_or_log ) +{ + expectations_logger el( log_file_name, test_or_log ); + + F(); +} + +//____________________________________________________________________________// + +} // namespace itest + +} // namespace boost + +//____________________________________________________________________________// + +#include + +#endif // not ancient compiler + +// *************************************************************************** +// Revision History : +// +// $Log$ +// Revision 1.1 2005/12/14 05:56:56 rogeeff +// Interraction based / logged expectation testing is introduced +// +// *************************************************************************** + +#endif // BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER