1// (C) Copyright Gennadiy Rozental 2005-2008. 2// Use, modification, and distribution are subject to the 3// Boost Software License, ELOG_VER 1.0. (See accompanying file 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 : Facilities to perform interaction based testng of logged expectations 13// *************************************************************************** 14 15#ifndef BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER 16#define BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER 17 18// Boost.Test 19#include <boost/test/detail/config.hpp> 20 21#if BOOST_TEST_SUPPORT_INTERACTION_TESTING 22 23#include <boost/test/detail/global_typedef.hpp> 24 25#include <boost/test/utils/callback.hpp> 26#include <boost/test/utils/iterator/token_iterator.hpp> 27 28#include <boost/test/interaction_based.hpp> 29#include <boost/test/test_tools.hpp> 30 31#include <boost/test/detail/suppress_warnings.hpp> 32 33// Boost 34#include <boost/lexical_cast.hpp> 35 36// STL 37#include <fstream> 38 39//____________________________________________________________________________// 40 41namespace boost { 42 43using namespace ::boost::unit_test; 44 45namespace itest { 46 47// ************************************************************************** // 48// ************** logged expectation test implementation ************** // 49// ************************************************************************** // 50 51struct expectations_logger : itest::manager { 52 // Constructor 53 expectations_logger( const_string log_file_name, bool test_or_log ); 54 55 virtual bool decision_point( const_string, std::size_t ); 56 virtual unsigned enter_scope( const_string, std::size_t, const_string scope_name ); 57 virtual void allocated( const_string, std::size_t, void*, std::size_t s ); 58 virtual void data_flow( const_string d ); 59 virtual std::string return_value( const_string default_value ); 60 61private: 62 // Data members 63 bool m_test_or_log; 64 std::fstream m_log_file; 65}; 66 67literal_string ELOG_VER = "1.0"; 68literal_string CLMN_SEP = "|"; 69static const char LINE_SEP = '\n'; 70 71literal_string FILE_SIG = "ELOG"; 72literal_string SCOPE_SIG = "SCOPE"; 73literal_string ALLOC_SIG = "ALLOC"; 74literal_string DP_SIG = "SWITCH"; 75literal_string DATA_SIG = "DATA"; 76literal_string RETURN_SIG = "RETURN"; 77 78//____________________________________________________________________________// 79 80expectations_logger::expectations_logger( const_string log_file_name, bool test_or_log ) 81: m_test_or_log( test_or_log ) 82{ 83 BOOST_REQUIRE_MESSAGE( !log_file_name.is_empty(), "Empty expectations log file name" ); 84 85 m_log_file.open( log_file_name.begin(), test_or_log ? std::ios::in : std::ios::out ); 86 87 BOOST_REQUIRE_MESSAGE( m_log_file.is_open(), 88 "Can't open expectations log file " << log_file_name 89 << " for " << ( m_test_or_log ? "reading" : "writing") ); 90 91 if( m_test_or_log ) { 92 std::string line; 93 94 std::getline( m_log_file, line, LINE_SEP ); 95 96 const_string cline( line ); 97 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 98 99 BOOST_CHECK_EQUAL( *tit, FILE_SIG ); 100 ++tit; 101 BOOST_CHECK_EQUAL( *tit, ELOG_VER ); 102 } 103 else { 104 m_log_file << FILE_SIG << CLMN_SEP << ELOG_VER << LINE_SEP; 105 } 106} 107 108//____________________________________________________________________________// 109 110bool 111expectations_logger::decision_point( const_string, std::size_t ) 112{ 113 if( m_test_or_log ) { 114 std::string line; 115 116 std::getline( m_log_file, line, LINE_SEP ); 117 118 const_string cline( line ); 119 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 120 121 BOOST_CHECK_EQUAL( *tit, DP_SIG ); ++tit; 122 return lexical_cast<bool>( *tit ); 123 } 124 else { 125 m_log_file << DP_SIG << CLMN_SEP << std::boolalpha << true << LINE_SEP; 126 127 return true; 128 } 129} 130 131//____________________________________________________________________________// 132 133unsigned 134expectations_logger::enter_scope( const_string, std::size_t, const_string scope_name ) 135{ 136 if( m_test_or_log ) { 137 std::string line; 138 139 std::getline( m_log_file, line, LINE_SEP ); 140 141 const_string cline( line ); 142 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 143 144 BOOST_CHECK_EQUAL( *tit, SCOPE_SIG ); ++tit; 145 BOOST_CHECK_EQUAL( *tit, scope_name ); 146 } 147 else { 148 m_log_file << SCOPE_SIG << CLMN_SEP << scope_name << LINE_SEP; 149 } 150 151 return 0; 152} 153 154//____________________________________________________________________________// 155 156void 157expectations_logger::allocated( const_string, std::size_t, void*, std::size_t s ) 158{ 159 if( m_test_or_log ) { 160 std::string line; 161 162 std::getline( m_log_file, line, LINE_SEP ); 163 164 const_string cline( line ); 165 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 166 167 BOOST_CHECK_EQUAL( *tit, ALLOC_SIG ); ++tit; 168 BOOST_CHECK_EQUAL( lexical_cast<std::size_t>( *tit ), s ); 169 } 170 else { 171 m_log_file << ALLOC_SIG << CLMN_SEP << s << LINE_SEP; 172 } 173} 174 175//____________________________________________________________________________// 176 177void 178expectations_logger::data_flow( const_string d ) 179{ 180 if( m_test_or_log ) { 181 std::string line; 182 183 std::getline( m_log_file, line, LINE_SEP ); 184 185 const_string cline( line ); 186 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 187 188 BOOST_CHECK_EQUAL( *tit, DATA_SIG ); ++tit; 189 BOOST_CHECK_EQUAL( *tit, d ); 190 } 191 else { 192 m_log_file << DATA_SIG << CLMN_SEP << d << LINE_SEP; 193 } 194} 195 196//____________________________________________________________________________// 197 198std::string 199expectations_logger::return_value( const_string default_value ) 200{ 201 if( m_test_or_log ) { 202 std::string line; 203 204 std::getline( m_log_file, line, LINE_SEP ); 205 206 const_string cline( line ); 207 string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none)); 208 209 BOOST_CHECK_EQUAL( *tit, RETURN_SIG ); ++tit; 210 211 return std::string( tit->begin(), tit->size() ); 212 } 213 else { 214 m_log_file << RETURN_SIG << CLMN_SEP << default_value << LINE_SEP; 215 216 return std::string(); 217 } 218} 219 220//____________________________________________________________________________// 221 222// ************************************************************************** // 223// ************** logged expectations test ************** // 224// ************************************************************************** // 225 226void BOOST_TEST_DECL 227logged_expectations( callback0<> const& F, const_string log_file_name, bool test_or_log ) 228{ 229 expectations_logger el( log_file_name, test_or_log ); 230 231 F(); 232} 233 234//____________________________________________________________________________// 235 236} // namespace itest 237 238} // namespace boost 239 240//____________________________________________________________________________// 241 242#include <boost/test/detail/enable_warnings.hpp> 243 244#endif // not ancient compiler 245 246#endif // BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER 247