Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:01:00

0001 //  (C) Copyright Gennadiy Rozental 2001.
0002 //  Distributed under the Boost Software License, Version 1.0.
0003 //  (See accompanying file LICENSE_1_0.txt or copy at
0004 //  http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 //  See http://www.boost.org/libs/test for the library home page.
0007 //
0008 //  File        : $RCSfile$
0009 //
0010 //  Version     : $Revision$
0011 //
0012 //  Description : supplies offline implementation for the Test Tools
0013 // ***************************************************************************
0014 
0015 #ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
0016 #define BOOST_TEST_TEST_TOOLS_IPP_012205GER
0017 
0018 // Boost.Test
0019 #include <boost/test/test_tools.hpp>
0020 #include <boost/test/unit_test_log.hpp>
0021 #include <boost/test/tools/context.hpp>
0022 #include <boost/test/tools/output_test_stream.hpp>
0023 
0024 #include <boost/test/tools/detail/fwd.hpp>
0025 #include <boost/test/tools/detail/print_helper.hpp>
0026 
0027 #include <boost/test/framework.hpp>
0028 #include <boost/test/tree/test_unit.hpp>
0029 #include <boost/test/execution_monitor.hpp> // execution_aborted
0030 
0031 #include <boost/test/detail/throw_exception.hpp>
0032 
0033 #include <boost/test/utils/algorithm.hpp>
0034 
0035 // Boost
0036 #include <boost/config.hpp>
0037 
0038 // STL
0039 #include <fstream>
0040 #include <string>
0041 #include <cstring>
0042 #include <cctype>
0043 #include <cwchar>
0044 #include <stdexcept>
0045 #include <vector>
0046 #include <utility>
0047 #include <ios>
0048 
0049 // !! should we use #include <cstdarg>
0050 #include <stdarg.h>
0051 
0052 #include <boost/test/detail/suppress_warnings.hpp>
0053 
0054 //____________________________________________________________________________//
0055 
0056 # ifdef BOOST_NO_STDC_NAMESPACE
0057 namespace std { using ::strcmp; using ::strlen; using ::isprint; }
0058 #if !defined( BOOST_NO_CWCHAR )
0059 namespace std { using ::wcscmp; }
0060 #endif
0061 # endif
0062 
0063 
0064 namespace boost {
0065 namespace unit_test {
0066   // local static variable, needed here for visibility reasons
0067   lazy_ostream lazy_ostream::inst = lazy_ostream();
0068 }}
0069 
0070 namespace boost {
0071 namespace test_tools {
0072 namespace tt_detail {
0073 
0074 // ************************************************************************** //
0075 // **************                print_log_value               ************** //
0076 // ************************************************************************** //
0077 
0078 void
0079 print_log_value<bool>::operator()( std::ostream& ostr, bool t )
0080 {
0081      ostr << std::boolalpha << t;
0082 }
0083 
0084 void
0085 print_log_value<char>::operator()( std::ostream& ostr, char t )
0086 {
0087     if( (std::isprint)( static_cast<unsigned char>(t) ) )
0088         ostr << '\'' << t << '\'';
0089     else
0090         ostr << std::hex
0091 #if BOOST_TEST_USE_STD_LOCALE
0092         << std::showbase
0093 #else
0094         << "0x"
0095 #endif
0096         << static_cast<int>(t);
0097 }
0098 
0099 //____________________________________________________________________________//
0100 
0101 void
0102 print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
0103 {
0104     ostr << std::hex
0105         // showbase is only available for new style streams:
0106 #if BOOST_TEST_USE_STD_LOCALE
0107         << std::showbase
0108 #else
0109         << "0x"
0110 #endif
0111         << static_cast<int>(t);
0112 }
0113 
0114 //____________________________________________________________________________//
0115 
0116 void
0117 print_log_value<wchar_t>::operator()( std::ostream& ostr, wchar_t r )
0118 {
0119     std::mbstate_t state;
0120     std::string mb(MB_CUR_MAX, '\0');
0121     std::size_t ret = std::wcrtomb(&mb[0], r, &state);
0122     if( ret > 0) {
0123         ostr << mb;
0124     }
0125     else {
0126         ostr << "(wchar_t unable to convert)";
0127     }
0128 }
0129 
0130 //____________________________________________________________________________//
0131 
0132 void
0133 print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
0134 {
0135     ostr << ( t ? t : "null string" );
0136 }
0137 
0138 //____________________________________________________________________________//
0139 
0140 void
0141 print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
0142 {
0143     if(t) {
0144       ostr << static_cast<const void*>(t);
0145     }
0146     else {
0147       ostr << "null w-string";
0148     }
0149 }
0150 
0151 //____________________________________________________________________________//
0152 
0153 // ************************************************************************** //
0154 // **************            TOOL BOX Implementation           ************** //
0155 // ************************************************************************** //
0156 
0157 using ::boost::unit_test::lazy_ostream;
0158 
0159 static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
0160 static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < "  };
0161 
0162 template<typename OutStream>
0163 void
0164 format_report( OutStream& os, assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
0165                tool_level tl, check_type ct,
0166                std::size_t num_args, va_list args,
0167                char const*  prefix, char const*  suffix )
0168 {
0169     using namespace unit_test;
0170 
0171     switch( ct ) {
0172     case CHECK_PRED:
0173         os << prefix << assertion_descr << suffix;
0174 
0175         if( !pr.has_empty_message() )
0176             os << ". " << pr.message();
0177         break;
0178 
0179     case CHECK_BUILT_ASSERTION: {
0180         os << prefix << assertion_descr << suffix;
0181 
0182         if( tl != PASS ) {
0183             const_string details_message = pr.message();
0184 
0185             if( !details_message.is_empty() ) {
0186                 os << details_message;
0187             }
0188         }
0189         break;
0190     }
0191 
0192     case CHECK_MSG:
0193         if( tl == PASS )
0194             os << prefix << "'" << assertion_descr << "'" << suffix;
0195         else
0196             os << assertion_descr;
0197 
0198         if( !pr.has_empty_message() )
0199             os << ". " << pr.message();
0200         break;
0201 
0202     case CHECK_EQUAL:
0203     case CHECK_NE:
0204     case CHECK_LT:
0205     case CHECK_LE:
0206     case CHECK_GT:
0207     case CHECK_GE: {
0208         char const*         arg1_descr  = va_arg( args, char const* );
0209         lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
0210         char const*         arg2_descr  = va_arg( args, char const* );
0211         lazy_ostream const* arg2_val    = va_arg( args, lazy_ostream const* );
0212 
0213         os << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
0214 
0215         if( tl != PASS )
0216             os << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
0217 
0218         if( !pr.has_empty_message() )
0219             os << ". " << pr.message();
0220         break;
0221     }
0222 
0223     case CHECK_CLOSE:
0224     case CHECK_CLOSE_FRACTION: {
0225         char const*         arg1_descr  = va_arg( args, char const* );
0226         lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
0227         char const*         arg2_descr  = va_arg( args, char const* );
0228         lazy_ostream const* arg2_val    = va_arg( args, lazy_ostream const* );
0229         /* toler_descr = */               va_arg( args, char const* );
0230         lazy_ostream const* toler_val   = va_arg( args, lazy_ostream const* );
0231 
0232         os << "difference{" << pr.message()
0233                             << "} between " << arg1_descr << "{" << *arg1_val
0234                             << "} and "               << arg2_descr << "{" << *arg2_val
0235                             << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
0236                             << *toler_val;
0237         if( ct == CHECK_CLOSE )
0238             os << "%";
0239         break;
0240     }
0241     case CHECK_SMALL: {
0242         char const*         arg1_descr  = va_arg( args, char const* );
0243         lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
0244         /* toler_descr = */               va_arg( args, char const* );
0245         lazy_ostream const* toler_val   = va_arg( args, lazy_ostream const* );
0246 
0247         os << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
0248                                    << ( tl == PASS ? " doesn't exceed " : " exceeds " )
0249                                    << *toler_val;
0250 
0251         if( !pr.has_empty_message() )
0252             os << ". " << pr.message();
0253         break;
0254     }
0255 
0256     case CHECK_PRED_WITH_ARGS: {
0257         std::vector< std::pair<char const*, lazy_ostream const*> > args_copy;
0258         args_copy.reserve( num_args );
0259         for( std::size_t i = 0; i < num_args; ++i ) {
0260             char const* desc = va_arg( args, char const* );
0261             lazy_ostream const* value = va_arg( args, lazy_ostream const* );
0262             args_copy.push_back( std::make_pair( desc, value ) );
0263         }
0264 
0265         os << prefix << assertion_descr;
0266 
0267         // print predicate call description
0268         os << "( ";
0269         for( std::size_t i = 0; i < num_args; ++i ) {
0270             os << args_copy[i].first;
0271 
0272             if( i != num_args-1 )
0273                 os << ", ";
0274         }
0275         os << " )" << suffix;
0276 
0277         if( tl != PASS ) {
0278             os << " for ( ";
0279             for( std::size_t i = 0; i < num_args; ++i ) {
0280                 os << *args_copy[i].second;
0281 
0282                 if( i != num_args-1 )
0283                     os << ", ";
0284             }
0285             os << " )";
0286         }
0287 
0288         if( !pr.has_empty_message() )
0289             os << ". " << pr.message();
0290         break;
0291     }
0292 
0293     case CHECK_EQUAL_COLL: {
0294         char const* left_begin_descr    = va_arg( args, char const* );
0295         char const* left_end_descr      = va_arg( args, char const* );
0296         char const* right_begin_descr   = va_arg( args, char const* );
0297         char const* right_end_descr     = va_arg( args, char const* );
0298 
0299         os << prefix << "{ " << left_begin_descr  << ", " << left_end_descr  << " } == { "
0300                              << right_begin_descr << ", " << right_end_descr << " }"
0301            << suffix;
0302 
0303         if( !pr.has_empty_message() )
0304             os << ". " << pr.message();
0305         break;
0306     }
0307 
0308     case CHECK_BITWISE_EQUAL: {
0309         char const* left_descr    = va_arg( args, char const* );
0310         char const* right_descr   = va_arg( args, char const* );
0311 
0312         os << prefix << left_descr  << " =.= " << right_descr << suffix;
0313 
0314         if( !pr.has_empty_message() )
0315             os << ". " << pr.message();
0316         break;
0317     }
0318     }
0319 }
0320 
0321 //____________________________________________________________________________//
0322 
0323 bool
0324 report_assertion( assertion_result const&   ar,
0325                   lazy_ostream const&       assertion_descr,
0326                   const_string              file_name,
0327                   std::size_t               line_num,
0328                   tool_level                tl,
0329                   check_type                ct,
0330                   std::size_t               num_args, ... )
0331 {
0332     using namespace unit_test;
0333 
0334     if( !framework::test_in_progress() ) {
0335         // in case no test is in progress, we do not throw anything:
0336         // raising an exception here may result in raising an exception in a destructor of a global fixture
0337         // which will abort the process
0338         // We flag this as aborted instead
0339 
0340         //BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
0341         //                    std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
0342 
0343         framework::test_aborted();
0344         return false;
0345     }
0346 
0347 
0348     if( !!ar )
0349         tl = PASS;
0350 
0351     log_level    ll;
0352     char const*  prefix;
0353     char const*  suffix;
0354 
0355     switch( tl ) {
0356     case PASS:
0357         ll      = log_successful_tests;
0358         prefix  = "check ";
0359         suffix  = " has passed";
0360         break;
0361     case WARN:
0362         ll      = log_warnings;
0363         prefix  = "condition ";
0364         suffix  = " is not satisfied";
0365         break;
0366     case CHECK:
0367         ll      = log_all_errors;
0368         prefix  = "check ";
0369         suffix  = " has failed";
0370         break;
0371     case REQUIRE:
0372         ll      = log_fatal_errors;
0373         prefix  = "critical check ";
0374         suffix  = " has failed";
0375         break;
0376     default:
0377         return true;
0378     }
0379 
0380     unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
0381     va_list args;
0382     va_start( args, num_args );
0383 
0384     format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
0385 
0386     va_end( args );
0387     unit_test_log << unit_test::log::end();
0388 
0389     switch( tl ) {
0390     case PASS:
0391         framework::assertion_result( AR_PASSED );
0392         return true;
0393 
0394     case WARN:
0395         framework::assertion_result( AR_TRIGGERED );
0396         return false;
0397 
0398     case CHECK:
0399         framework::assertion_result( AR_FAILED );
0400         return false;
0401 
0402     case REQUIRE:
0403         framework::assertion_result( AR_FAILED );
0404         framework::test_unit_aborted( framework::current_test_unit() );
0405         BOOST_TEST_I_THROW( execution_aborted() );
0406         // the previous line either throws or aborts and the return below is not reached
0407         // return false;
0408         BOOST_TEST_UNREACHABLE_RETURN(false);
0409     }
0410 
0411     return true;
0412 }
0413 
0414 //____________________________________________________________________________//
0415 
0416 assertion_result
0417 format_assertion_result( const_string expr_val, const_string details )
0418 {
0419     assertion_result res(false);
0420 
0421     bool starts_new_line = first_char( expr_val ) == '\n';
0422 
0423     if( !starts_new_line && !expr_val.is_empty() )
0424         res.message().stream() << " [" << expr_val << "]";
0425 
0426     if( !details.is_empty() ) {
0427         if( first_char(details) != '[' )
0428             res.message().stream() << ": ";
0429         else
0430             res.message().stream() << " ";
0431 
0432         res.message().stream() << details;
0433     }
0434 
0435     if( starts_new_line )
0436         res.message().stream() << "." << expr_val;
0437 
0438     return res;
0439 }
0440 
0441 //____________________________________________________________________________//
0442 
0443 BOOST_TEST_DECL std::string
0444 prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
0445 {
0446     std::ostringstream msg_buff;
0447 
0448     va_list args;
0449     va_start( args, num_args );
0450 
0451     format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
0452 
0453     va_end( args );
0454 
0455     return msg_buff.str();
0456 }
0457 
0458 //____________________________________________________________________________//
0459 
0460 assertion_result
0461 equal_impl( char const* left, char const* right )
0462 {
0463     return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
0464 }
0465 
0466 //____________________________________________________________________________//
0467 
0468 #if !defined( BOOST_NO_CWCHAR )
0469 
0470 assertion_result
0471 equal_impl( wchar_t const* left, wchar_t const* right )
0472 {
0473     return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
0474 }
0475 
0476 #endif // !defined( BOOST_NO_CWCHAR )
0477 
0478 //____________________________________________________________________________//
0479 
0480 bool
0481 is_defined_impl( const_string symbol_name, const_string symbol_value )
0482 {
0483     symbol_value.trim_left( 2 );
0484     return symbol_name != symbol_value;
0485 }
0486 
0487 //____________________________________________________________________________//
0488 
0489 // ************************************************************************** //
0490 // **************                 context_frame                ************** //
0491 // ************************************************************************** //
0492 
0493 context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
0494 : m_frame_id( unit_test::framework::add_context( context_descr, true ) )
0495 {
0496 }
0497 
0498 //____________________________________________________________________________//
0499 
0500 context_frame::~context_frame()
0501 {
0502     unit_test::framework::clear_context( m_frame_id );
0503 }
0504 
0505 //____________________________________________________________________________//
0506 
0507 context_frame::operator bool()
0508 {
0509     return true;
0510 }
0511 
0512 //____________________________________________________________________________//
0513 
0514 } // namespace tt_detail
0515 
0516 // ************************************************************************** //
0517 // **************               output_test_stream             ************** //
0518 // ************************************************************************** //
0519 
0520 struct output_test_stream::Impl
0521 {
0522     std::fstream    m_pattern;
0523     bool            m_match_or_save;
0524     bool            m_text_or_binary;
0525     std::string     m_synced_string;
0526 
0527     char            get_char()
0528     {
0529         char res = 0;
0530         do {
0531             m_pattern.get( res );
0532         } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
0533 
0534         return res;
0535     }
0536 
0537     void            check_and_fill( assertion_result& res )
0538     {
0539         if( !res.p_predicate_value )
0540             res.message() << "Output content: \"" << m_synced_string << '\"';
0541     }
0542 };
0543 
0544 //____________________________________________________________________________//
0545 
0546 output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
0547 : m_pimpl( new Impl )
0548 {
0549     if( !pattern_file_name.is_empty() ) {
0550         std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
0551         if( !text_or_binary )
0552             m |= std::ios::binary;
0553 
0554         m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
0555 
0556         if( !m_pimpl->m_pattern.is_open() )
0557             BOOST_TEST_FRAMEWORK_MESSAGE( "Can't open pattern file " << pattern_file_name << " for " << (match_or_save ? "reading" : "writing") );
0558     }
0559 
0560     m_pimpl->m_match_or_save    = match_or_save;
0561     m_pimpl->m_text_or_binary   = text_or_binary;
0562 }
0563 
0564 //____________________________________________________________________________//
0565 
0566 output_test_stream::~output_test_stream()
0567 {
0568     delete m_pimpl;
0569 }
0570 
0571 //____________________________________________________________________________//
0572 
0573 assertion_result
0574 output_test_stream::is_empty( bool flush_stream )
0575 {
0576     sync();
0577 
0578     assertion_result res( m_pimpl->m_synced_string.empty() );
0579 
0580     m_pimpl->check_and_fill( res );
0581 
0582     if( flush_stream )
0583         flush();
0584 
0585     return res;
0586 }
0587 
0588 //____________________________________________________________________________//
0589 
0590 assertion_result
0591 output_test_stream::check_length( std::size_t length_, bool flush_stream )
0592 {
0593     sync();
0594 
0595     assertion_result res( m_pimpl->m_synced_string.length() == length_ );
0596 
0597     m_pimpl->check_and_fill( res );
0598 
0599     if( flush_stream )
0600         flush();
0601 
0602     return res;
0603 }
0604 
0605 //____________________________________________________________________________//
0606 
0607 assertion_result
0608 output_test_stream::is_equal( const_string arg, bool flush_stream )
0609 {
0610     sync();
0611 
0612     assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
0613 
0614     m_pimpl->check_and_fill( res );
0615 
0616     if( flush_stream )
0617         flush();
0618 
0619     return res;
0620 }
0621 
0622 //____________________________________________________________________________//
0623 
0624 std::string pretty_print_log(std::string str) {
0625 
0626     static const std::string to_replace[] = { "\r", "\n" };
0627     static const std::string replacement[] = { "\\r", "\\n" };
0628 
0629     return unit_test::utils::replace_all_occurrences_of(
0630         str,
0631         to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
0632         replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
0633 }
0634 
0635 assertion_result
0636 output_test_stream::match_pattern( bool flush_stream )
0637 {
0638     const std::string::size_type n_chars_presuffix = 10;
0639     sync();
0640 
0641     assertion_result result( true );
0642 
0643     const std::string stream_string_repr = get_stream_string_representation();
0644 
0645     if( !m_pimpl->m_pattern.is_open() ) {
0646         result = false;
0647         result.message() << "Pattern file can't be opened!";
0648     }
0649     else {
0650         if( m_pimpl->m_match_or_save ) {
0651 
0652             int offset = 0;
0653             std::vector<char> last_elements;
0654             for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
0655 
0656                 char c = m_pimpl->get_char();
0657 
0658                 if( last_elements.size() <= n_chars_presuffix ) {
0659                     last_elements.push_back( c );
0660                 }
0661                 else {
0662                     last_elements[ i % last_elements.size() ] = c;
0663                 }
0664 
0665                 bool is_same = !m_pimpl->m_pattern.fail() &&
0666                          !m_pimpl->m_pattern.eof()  &&
0667                          (stream_string_repr[i+offset] == c);
0668 
0669                 if( !is_same ) {
0670 
0671                     result = false;
0672 
0673                     std::string::size_type prefix_size  = (std::min)( i + offset, n_chars_presuffix );
0674 
0675                     std::string::size_type suffix_size  = (std::min)( stream_string_repr.length() - i - offset,
0676                                                                       n_chars_presuffix );
0677 
0678                     // try to log area around the mismatch
0679                     std::string substr = stream_string_repr.substr(0, i+offset);
0680                     std::size_t line = std::count(substr.begin(), substr.end(), '\n');
0681                     std::size_t column = i + offset - substr.rfind('\n');
0682 
0683                     result.message()
0684                         << "Mismatch at position " << i
0685                         << " (line " << line
0686                         << ", column " << column
0687                         << "): '" << pretty_print_log(std::string(1, stream_string_repr[i+offset])) << "' != '" << pretty_print_log(std::string(1, c)) << "' :\n";
0688 
0689                     // we already escape this substring because we need its actual size for the pretty print
0690                     // of the difference location.
0691                     std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
0692 
0693                     // we need this substring as is because we compute the best matching substrings on it.
0694                     std::string sub_str_suffix(stream_string_repr.substr( i + offset, suffix_size));
0695                     result.message() << "... " << sub_str_prefix + pretty_print_log(sub_str_suffix) << " ..." << '\n';
0696 
0697                     result.message() << "... ";
0698                     for( std::size_t j = 0; j < last_elements.size() ; j++ )
0699                         result.message() << pretty_print_log(std::string(1, last_elements[(i + j + 1) % last_elements.size()]));
0700 
0701                     std::vector<char> last_elements_ordered;
0702                     last_elements_ordered.push_back(c);
0703                     for( std::string::size_type counter = 0; counter < suffix_size - 1 ; counter++ ) {
0704                         char c2 = m_pimpl->get_char();
0705 
0706                         if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
0707                             break;
0708 
0709                         result.message() << pretty_print_log(std::string(1, c2));
0710 
0711                         last_elements_ordered.push_back(c2);
0712                     }
0713 
0714                     // tries to find the best substring matching in the remainder of the
0715                     // two strings
0716                     std::size_t max_nb_char_in_common = 0;
0717                     std::size_t best_pattern_start_index = 0;
0718                     std::size_t best_stream_start_index = 0;
0719                     for( std::size_t pattern_start_index = best_pattern_start_index;
0720                          pattern_start_index < last_elements_ordered.size();
0721                          pattern_start_index++ ) {
0722                         for( std::size_t stream_start_index = best_stream_start_index;
0723                              stream_start_index < sub_str_suffix.size();
0724                              stream_start_index++ ) {
0725 
0726                             std::size_t max_size = (std::min)( last_elements_ordered.size() - pattern_start_index, sub_str_suffix.size() - stream_start_index );
0727                             if( max_nb_char_in_common > max_size )
0728                                 break; // safely break to go to the outer loop
0729 
0730                             std::size_t nb_char_in_common = 0;
0731                             for( std::size_t k = 0; k < max_size; k++) {
0732                                 if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
0733                                     nb_char_in_common ++;
0734                                 else
0735                                     break; // we take fully matching substring only
0736                             }
0737 
0738                             if( nb_char_in_common > max_nb_char_in_common ) {
0739                                 max_nb_char_in_common = nb_char_in_common;
0740                                 best_pattern_start_index = pattern_start_index;
0741                                 best_stream_start_index = stream_start_index;
0742                             }
0743                         }
0744                     }
0745 
0746                     // indicates with more precision the location of the mismatchs in "ascii arts" ...
0747                     result.message() << " ...\n... ";
0748                     for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
0749                         result.message() << ' ';
0750                     }
0751 
0752                     result.message() << '~'; // places the first tilde at the current char that mismatches
0753 
0754                     for( std::size_t k = 1; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) { // 1 is for the current char c
0755                         std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
0756                         std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
0757                         for( int h = static_cast<int>((std::max)(s1.size(), s2.size())); h > 0; h--)
0758                             result.message() << "~";
0759                     }
0760 
0761                     if( m_pimpl->m_pattern.eof() ) {
0762                         result.message() << "    (reference string shorter than current stream)";
0763                     }
0764 
0765                     result.message() << "\n";
0766 
0767                     // no need to continue if the EOF is reached
0768                     if( m_pimpl->m_pattern.eof() ) {
0769                         break;
0770                     }
0771 
0772                     // first char is a replicat of c, so we do not copy it.
0773                     for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
0774                         last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
0775 
0776                     i += last_elements_ordered.size()-1;
0777                     offset += best_stream_start_index - best_pattern_start_index;
0778 
0779                 }
0780 
0781             }
0782 
0783             // not needed anymore
0784             /*
0785             if(offset > 0 && false) {
0786                 m_pimpl->m_pattern.ignore(
0787                     static_cast<std::streamsize>( offset ));
0788             }
0789             */
0790         }
0791         else {
0792             m_pimpl->m_pattern.write( stream_string_repr.c_str(),
0793                                       static_cast<std::streamsize>( stream_string_repr.length() ) );
0794             m_pimpl->m_pattern.flush();
0795         }
0796     }
0797 
0798     if( flush_stream )
0799         flush();
0800 
0801     return result;
0802 }
0803 
0804 //____________________________________________________________________________//
0805 
0806 void
0807 output_test_stream::flush()
0808 {
0809     m_pimpl->m_synced_string.erase();
0810 
0811 #ifndef BOOST_NO_STRINGSTREAM
0812     str( std::string() );
0813 #else
0814     seekp( 0, std::ios::beg );
0815 #endif
0816 }
0817 
0818 
0819 std::string
0820 output_test_stream::get_stream_string_representation() const {
0821     return m_pimpl->m_synced_string;
0822 }
0823 
0824 //____________________________________________________________________________//
0825 
0826 std::size_t
0827 output_test_stream::length()
0828 {
0829     sync();
0830 
0831     return m_pimpl->m_synced_string.length();
0832 }
0833 
0834 //____________________________________________________________________________//
0835 
0836 void
0837 output_test_stream::sync()
0838 {
0839 #ifdef BOOST_NO_STRINGSTREAM
0840     m_pimpl->m_synced_string.assign( str(), pcount() );
0841     freeze( false );
0842 #else
0843     m_pimpl->m_synced_string = str();
0844 #endif
0845 }
0846 
0847 //____________________________________________________________________________//
0848 
0849 } // namespace test_tools
0850 } // namespace boost
0851 
0852 #include <boost/test/detail/enable_warnings.hpp>
0853 
0854 #endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER