123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628 |
- // (C) Copyright Gennadiy Rozental 2005-2008.
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // See http://www.boost.org/libs/test for the library home page.
- //
- // File : $RCSfile$
- //
- // Version : $Revision: 54633 $
- //
- // Description : supplies offline implementation for the Test Tools
- // ***************************************************************************
- #ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
- #define BOOST_TEST_TEST_TOOLS_IPP_012205GER
- // Boost.Test
- #include <boost/test/test_tools.hpp>
- #include <boost/test/unit_test_log.hpp>
- #include <boost/test/output_test_stream.hpp>
- #include <boost/test/framework.hpp>
- #include <boost/test/execution_monitor.hpp> // execution_aborted
- #include <boost/test/unit_test_suite_impl.hpp>
- // Boost
- #include <boost/config.hpp>
- // STL
- #include <fstream>
- #include <string>
- #include <cstring>
- #include <cctype>
- #include <cwchar>
- #include <stdexcept>
- #include <ios>
- // !! should we use #include <cstdarg>
- #include <stdarg.h>
- #include <boost/test/detail/suppress_warnings.hpp>
- //____________________________________________________________________________//
- # ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::strcmp; using ::strlen; using ::isprint; }
- #if !defined( BOOST_NO_CWCHAR )
- namespace std { using ::wcscmp; }
- #endif
- # endif
- namespace boost {
- namespace test_tools {
- // ************************************************************************** //
- // ************** print_log_value ************** //
- // ************************************************************************** //
- void
- print_log_value<char>::operator()( std::ostream& ostr, char t )
- {
- if( (std::isprint)( static_cast<unsigned char>(t) ) )
- ostr << '\'' << t << '\'';
- else
- ostr << std::hex
- #if BOOST_TEST_USE_STD_LOCALE
- << std::showbase
- #else
- << "0x"
- #endif
- << static_cast<int>(t);
- }
- //____________________________________________________________________________//
- void
- print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
- {
- ostr << std::hex
- // showbase is only available for new style streams:
- #if BOOST_TEST_USE_STD_LOCALE
- << std::showbase
- #else
- << "0x"
- #endif
- << static_cast<int>(t);
- }
- //____________________________________________________________________________//
- void
- print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
- {
- ostr << ( t ? t : "null string" );
- }
- //____________________________________________________________________________//
- void
- print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
- {
- ostr << ( t ? t : L"null string" );
- }
- //____________________________________________________________________________//
- namespace tt_detail {
- // ************************************************************************** //
- // ************** TOOL BOX Implementation ************** //
- // ************************************************************************** //
- using ::boost::unit_test::lazy_ostream;
- bool
- check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
- const_string file_name, std::size_t line_num,
- tool_level tl, check_type ct,
- std::size_t num_of_args, ... )
- {
- using namespace unit_test;
- if( !framework::is_initialized() )
- throw std::runtime_error( "can't use testing tools before framework is initialized" );
- if( !!pr )
- tl = PASS;
- log_level ll;
- char const* prefix;
- char const* suffix;
-
- switch( tl ) {
- case PASS:
- ll = log_successful_tests;
- prefix = "check ";
- suffix = " passed";
- break;
- case WARN:
- ll = log_warnings;
- prefix = "condition ";
- suffix = " is not satisfied";
- break;
- case CHECK:
- ll = log_all_errors;
- prefix = "check ";
- suffix = " failed";
- break;
- case REQUIRE:
- ll = log_fatal_errors;
- prefix = "critical check ";
- suffix = " failed";
- break;
- default:
- return true;
- }
- switch( ct ) {
- case CHECK_PRED:
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << check_descr << suffix;
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
- break;
- case CHECK_MSG:
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
-
- if( tl == PASS )
- unit_test_log << prefix << "'" << check_descr << "'" << suffix;
- else
- unit_test_log << check_descr;
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- case CHECK_EQUAL:
- case CHECK_NE:
- case CHECK_LT:
- case CHECK_LE:
- case CHECK_GT:
- case CHECK_GE: {
- static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
- static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
- va_list args;
- va_start( args, num_of_args );
- char const* arg1_descr = va_arg( args, char const* );
- lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
- char const* arg2_descr = va_arg( args, char const* );
- lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
- if( tl != PASS )
- unit_test_log << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
- va_end( args );
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- }
- case CHECK_CLOSE:
- case CHECK_CLOSE_FRACTION: {
- va_list args;
- va_start( args, num_of_args );
- char const* arg1_descr = va_arg( args, char const* );
- lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
- char const* arg2_descr = va_arg( args, char const* );
- lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
- /* toler_descr = */ va_arg( args, char const* );
- lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
- unit_test_log << "difference{" << pr.message() << (ct == CHECK_CLOSE ? "%" : "")
- << "} between " << arg1_descr << "{" << *arg1_val
- << "} and " << arg2_descr << "{" << *arg2_val
- << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
- << *toler_val;
- if( ct == CHECK_CLOSE )
- unit_test_log << "%";
- va_end( args );
-
- unit_test_log << unit_test::log::end();
- break;
- }
- case CHECK_SMALL: {
- va_list args;
- va_start( args, num_of_args );
- char const* arg1_descr = va_arg( args, char const* );
- lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
- /* toler_descr = */ va_arg( args, char const* );
- lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
- unit_test_log << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
- << ( tl == PASS ? " doesn't exceed " : " exceeds " )
- << *toler_val;
- va_end( args );
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- }
- case CHECK_PRED_WITH_ARGS: {
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << check_descr;
- // print predicate call description
- {
- va_list args;
- va_start( args, num_of_args );
- unit_test_log << "( ";
- for( std::size_t i = 0; i < num_of_args; ++i ) {
- unit_test_log << va_arg( args, char const* );
- va_arg( args, lazy_ostream const* ); // skip argument value;
-
- if( i != num_of_args-1 )
- unit_test_log << ", ";
- }
- unit_test_log << " )" << suffix;
- va_end( args );
- }
-
- if( tl != PASS ) {
- va_list args;
- va_start( args, num_of_args );
- unit_test_log << " for ( ";
- for( std::size_t i = 0; i < num_of_args; ++i ) {
- va_arg( args, char const* ); // skip argument description;
- unit_test_log << *va_arg( args, lazy_ostream const* );
-
- if( i != num_of_args-1 )
- unit_test_log << ", ";
- }
- unit_test_log << " )";
- va_end( args );
- }
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- }
- case CHECK_EQUAL_COLL: {
- va_list args;
- va_start( args, num_of_args );
- char const* left_begin_descr = va_arg( args, char const* );
- char const* left_end_descr = va_arg( args, char const* );
- char const* right_begin_descr = va_arg( args, char const* );
- char const* right_end_descr = va_arg( args, char const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix
- << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
- << right_begin_descr << ", " << right_end_descr << " }"
- << suffix;
- va_end( args );
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- }
- case CHECK_BITWISE_EQUAL: {
- va_list args;
- va_start( args, num_of_args );
- char const* left_descr = va_arg( args, char const* );
- char const* right_descr = va_arg( args, char const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << left_descr << " =.= " << right_descr << suffix;
- va_end( args );
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
- break;
- }
- }
- switch( tl ) {
- case PASS:
- framework::assertion_result( true );
- return true;
- case WARN:
- return false;
- case CHECK:
- framework::assertion_result( false );
- return false;
-
- case REQUIRE:
- framework::assertion_result( false );
- framework::test_unit_aborted( framework::current_test_case() );
- throw execution_aborted();
- }
- return true;
- }
- //____________________________________________________________________________//
- predicate_result
- equal_impl( char const* left, char const* right )
- {
- return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
- }
- //____________________________________________________________________________//
- #if !defined( BOOST_NO_CWCHAR )
- predicate_result
- equal_impl( wchar_t const* left, wchar_t const* right )
- {
- return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
- }
- #endif // !defined( BOOST_NO_CWCHAR )
- //____________________________________________________________________________//
- bool
- is_defined_impl( const_string symbol_name, const_string symbol_value )
- {
- symbol_value.trim_left( 2 );
- return symbol_name != symbol_value;
- }
- //____________________________________________________________________________//
- } // namespace tt_detail
- // ************************************************************************** //
- // ************** output_test_stream ************** //
- // ************************************************************************** //
- struct output_test_stream::Impl
- {
- std::fstream m_pattern;
- bool m_match_or_save;
- bool m_text_or_binary;
- std::string m_synced_string;
- char get_char()
- {
- char res;
- do {
- m_pattern.get( res );
- } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
- return res;
- }
- void check_and_fill( predicate_result& res )
- {
- if( !res.p_predicate_value )
- res.message() << "Output content: \"" << m_synced_string << '\"';
- }
- };
- //____________________________________________________________________________//
- output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
- : m_pimpl( new Impl )
- {
- if( !pattern_file_name.is_empty() ) {
- std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
- if( !text_or_binary )
- m |= std::ios::binary;
- m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
- BOOST_WARN_MESSAGE( m_pimpl->m_pattern.is_open(),
- "Can't open pattern file " << pattern_file_name
- << " for " << (match_or_save ? "reading" : "writing") );
- }
- m_pimpl->m_match_or_save = match_or_save;
- m_pimpl->m_text_or_binary = text_or_binary;
- }
- //____________________________________________________________________________//
- output_test_stream::~output_test_stream()
- {
- delete m_pimpl;
- }
- //____________________________________________________________________________//
- predicate_result
- output_test_stream::is_empty( bool flush_stream )
- {
- sync();
- result_type res( m_pimpl->m_synced_string.empty() );
- m_pimpl->check_and_fill( res );
- if( flush_stream )
- flush();
- return res;
- }
- //____________________________________________________________________________//
- predicate_result
- output_test_stream::check_length( std::size_t length_, bool flush_stream )
- {
- sync();
- result_type res( m_pimpl->m_synced_string.length() == length_ );
- m_pimpl->check_and_fill( res );
- if( flush_stream )
- flush();
- return res;
- }
- //____________________________________________________________________________//
- predicate_result
- output_test_stream::is_equal( const_string arg, bool flush_stream )
- {
- sync();
- result_type res( const_string( m_pimpl->m_synced_string ) == arg );
- m_pimpl->check_and_fill( res );
- if( flush_stream )
- flush();
- return res;
- }
- //____________________________________________________________________________//
- predicate_result
- output_test_stream::match_pattern( bool flush_stream )
- {
- sync();
- result_type result( true );
- if( !m_pimpl->m_pattern.is_open() ) {
- result = false;
- result.message() << "Pattern file can't be opened!";
- }
- else {
- if( m_pimpl->m_match_or_save ) {
- for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) {
- char c = m_pimpl->get_char();
- result = !m_pimpl->m_pattern.fail() &&
- !m_pimpl->m_pattern.eof() &&
- (m_pimpl->m_synced_string[i] == c);
- if( !result ) {
- std::string::size_type suffix_size = (std::min)( m_pimpl->m_synced_string.length() - i,
- static_cast<std::string::size_type>(5) );
- // try to log area around the mismatch
- result.message() << "Mismatch at position " << i << '\n'
- << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n'
- << "..." << c;
- std::string::size_type counter = suffix_size;
- while( --counter ) {
- char c = m_pimpl->get_char();
- if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
- break;
- result.message() << c;
- }
- result.message() << "...";
- // skip rest of the bytes. May help for further matching
- m_pimpl->m_pattern.ignore(
- static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
- break;
- }
- }
- }
- else {
- m_pimpl->m_pattern.write( m_pimpl->m_synced_string.c_str(),
- static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
- m_pimpl->m_pattern.flush();
- }
- }
- if( flush_stream )
- flush();
- return result;
- }
- //____________________________________________________________________________//
- void
- output_test_stream::flush()
- {
- m_pimpl->m_synced_string.erase();
- #ifndef BOOST_NO_STRINGSTREAM
- str( std::string() );
- #else
- seekp( 0, std::ios::beg );
- #endif
- }
- //____________________________________________________________________________//
- std::size_t
- output_test_stream::length()
- {
- sync();
- return m_pimpl->m_synced_string.length();
- }
- //____________________________________________________________________________//
- void
- output_test_stream::sync()
- {
- #ifdef BOOST_NO_STRINGSTREAM
- m_pimpl->m_synced_string.assign( str(), pcount() );
- freeze( false );
- #else
- m_pimpl->m_synced_string = str();
- #endif
- }
- //____________________________________________________________________________//
- } // namespace test_tools
- } // namespace boost
- //____________________________________________________________________________//
- #include <boost/test/detail/enable_warnings.hpp>
- #endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER
|