Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:49:40

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 #ifdef BOOST_MSVC
0324 #pragma warning(push)
0325 #pragma warning(disable : 4702) // There is intentionally unreachable code
0326 #endif
0327 
0328 bool
0329 report_assertion( assertion_result const&   ar,
0330                   lazy_ostream const&       assertion_descr,
0331                   const_string              file_name,
0332                   std::size_t               line_num,
0333                   tool_level                tl,
0334                   check_type                ct,
0335                   std::size_t               num_args, ... )
0336 {
0337     using namespace unit_test;
0338 
0339     if( !framework::test_in_progress() ) {
0340         // in case no test is in progress, we do not throw anything:
0341         // raising an exception here may result in raising an exception in a destructor of a global fixture
0342         // which will abort the process
0343         // We flag this as aborted instead
0344 
0345         //BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
0346         //                    std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
0347 
0348         framework::test_aborted();
0349         return false;
0350     }
0351 
0352 
0353     if( !!ar )
0354         tl = PASS;
0355 
0356     log_level    ll;
0357     char const*  prefix;
0358     char const*  suffix;
0359 
0360     switch( tl ) {
0361     case PASS:
0362         ll      = log_successful_tests;
0363         prefix  = "check ";
0364         suffix  = " has passed";
0365         break;
0366     case WARN:
0367         ll      = log_warnings;
0368         prefix  = "condition ";
0369         suffix  = " is not satisfied";
0370         break;
0371     case CHECK:
0372         ll      = log_all_errors;
0373         prefix  = "check ";
0374         suffix  = " has failed";
0375         break;
0376     case REQUIRE:
0377         ll      = log_fatal_errors;
0378         prefix  = "critical check ";
0379         suffix  = " has failed";
0380         break;
0381     default:
0382         return true;
0383     }
0384 
0385     unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
0386     va_list args;
0387     va_start( args, num_args );
0388 
0389     format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
0390 
0391     va_end( args );
0392     unit_test_log << unit_test::log::end();
0393 
0394     switch( tl ) {
0395     case PASS:
0396         framework::assertion_result( AR_PASSED );
0397         return true;
0398 
0399     case WARN:
0400         framework::assertion_result( AR_TRIGGERED );
0401         return false;
0402 
0403     case CHECK:
0404         framework::assertion_result( AR_FAILED );
0405         return false;
0406 
0407     case REQUIRE:
0408         framework::assertion_result( AR_FAILED );
0409         framework::test_unit_aborted( framework::current_test_unit() );
0410         BOOST_TEST_I_THROW( execution_aborted() );
0411         // the previous line either throws or aborts and the return below is not reached
0412         // return false;
0413         BOOST_TEST_UNREACHABLE_RETURN(false);
0414     }
0415 
0416     return true;
0417 }
0418 
0419 #ifdef BOOST_MSVC
0420 #pragma warning(pop)
0421 #endif
0422 
0423 //____________________________________________________________________________//
0424 
0425 assertion_result
0426 format_assertion_result( const_string expr_val, const_string details )
0427 {
0428     assertion_result res(false);
0429 
0430     bool starts_new_line = first_char( expr_val ) == '\n';
0431 
0432     if( !starts_new_line && !expr_val.is_empty() )
0433         res.message().stream() << " [" << expr_val << "]";
0434 
0435     if( !details.is_empty() ) {
0436         if( first_char(details) != '[' )
0437             res.message().stream() << ": ";
0438         else
0439             res.message().stream() << " ";
0440 
0441         res.message().stream() << details;
0442     }
0443 
0444     if( starts_new_line )
0445         res.message().stream() << "." << expr_val;
0446 
0447     return res;
0448 }
0449 
0450 //____________________________________________________________________________//
0451 
0452 BOOST_TEST_DECL std::string
0453 prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
0454 {
0455     std::ostringstream msg_buff;
0456 
0457     va_list args;
0458     va_start( args, num_args );
0459 
0460     format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
0461 
0462     va_end( args );
0463 
0464     return msg_buff.str();
0465 }
0466 
0467 //____________________________________________________________________________//
0468 
0469 assertion_result
0470 equal_impl( char const* left, char const* right )
0471 {
0472     return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
0473 }
0474 
0475 //____________________________________________________________________________//
0476 
0477 #if !defined( BOOST_NO_CWCHAR )
0478 
0479 assertion_result
0480 equal_impl( wchar_t const* left, wchar_t const* right )
0481 {
0482     return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
0483 }
0484 
0485 #endif // !defined( BOOST_NO_CWCHAR )
0486 
0487 //____________________________________________________________________________//
0488 
0489 bool
0490 is_defined_impl( const_string symbol_name, const_string symbol_value )
0491 {
0492     symbol_value.trim_left( 2 );
0493     return symbol_name != symbol_value;
0494 }
0495 
0496 //____________________________________________________________________________//
0497 
0498 // ************************************************************************** //
0499 // **************                 context_frame                ************** //
0500 // ************************************************************************** //
0501 
0502 context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
0503 : m_frame_id( unit_test::framework::add_context( context_descr, true ) )
0504 {
0505 }
0506 
0507 //____________________________________________________________________________//
0508 
0509 context_frame::~context_frame()
0510 {
0511     unit_test::framework::clear_context( m_frame_id );
0512 }
0513 
0514 //____________________________________________________________________________//
0515 
0516 context_frame::operator bool()
0517 {
0518     return true;
0519 }
0520 
0521 //____________________________________________________________________________//
0522 
0523 } // namespace tt_detail
0524 
0525 // ************************************************************************** //
0526 // **************               output_test_stream             ************** //
0527 // ************************************************************************** //
0528 
0529 struct output_test_stream::Impl
0530 {
0531     std::fstream    m_pattern;
0532     bool            m_match_or_save;
0533     bool            m_text_or_binary;
0534     std::string     m_synced_string;
0535 
0536     char            get_char()
0537     {
0538         char res = 0;
0539         do {
0540             m_pattern.get( res );
0541         } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
0542 
0543         return res;
0544     }
0545 
0546     void            check_and_fill( assertion_result& res )
0547     {
0548         if( !res.p_predicate_value )
0549             res.message() << "Output content: \"" << m_synced_string << '\"';
0550     }
0551 };
0552 
0553 //____________________________________________________________________________//
0554 
0555 output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
0556 : m_pimpl( new Impl )
0557 {
0558     if( !pattern_file_name.is_empty() ) {
0559         std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
0560         if( !text_or_binary )
0561             m |= std::ios::binary;
0562 
0563         m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
0564 
0565         if( !m_pimpl->m_pattern.is_open() )
0566             BOOST_TEST_FRAMEWORK_MESSAGE( "Can't open pattern file " << pattern_file_name << " for " << (match_or_save ? "reading" : "writing") );
0567     }
0568 
0569     m_pimpl->m_match_or_save    = match_or_save;
0570     m_pimpl->m_text_or_binary   = text_or_binary;
0571 }
0572 
0573 //____________________________________________________________________________//
0574 
0575 output_test_stream::~output_test_stream()
0576 {
0577     delete m_pimpl;
0578 }
0579 
0580 //____________________________________________________________________________//
0581 
0582 assertion_result
0583 output_test_stream::is_empty( bool flush_stream )
0584 {
0585     sync();
0586 
0587     assertion_result res( m_pimpl->m_synced_string.empty() );
0588 
0589     m_pimpl->check_and_fill( res );
0590 
0591     if( flush_stream )
0592         flush();
0593 
0594     return res;
0595 }
0596 
0597 //____________________________________________________________________________//
0598 
0599 assertion_result
0600 output_test_stream::check_length( std::size_t length_, bool flush_stream )
0601 {
0602     sync();
0603 
0604     assertion_result res( m_pimpl->m_synced_string.length() == length_ );
0605 
0606     m_pimpl->check_and_fill( res );
0607 
0608     if( flush_stream )
0609         flush();
0610 
0611     return res;
0612 }
0613 
0614 //____________________________________________________________________________//
0615 
0616 assertion_result
0617 output_test_stream::is_equal( const_string arg, bool flush_stream )
0618 {
0619     sync();
0620 
0621     assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
0622 
0623     m_pimpl->check_and_fill( res );
0624 
0625     if( flush_stream )
0626         flush();
0627 
0628     return res;
0629 }
0630 
0631 //____________________________________________________________________________//
0632 
0633 std::string pretty_print_log(std::string str) {
0634 
0635     static const std::string to_replace[] = { "\r", "\n" };
0636     static const std::string replacement[] = { "\\r", "\\n" };
0637 
0638     return unit_test::utils::replace_all_occurrences_of(
0639         str,
0640         to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
0641         replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
0642 }
0643 
0644 assertion_result
0645 output_test_stream::match_pattern( bool flush_stream )
0646 {
0647     const std::string::size_type n_chars_presuffix = 10;
0648     sync();
0649 
0650     assertion_result result( true );
0651 
0652     const std::string stream_string_repr = get_stream_string_representation();
0653 
0654     if( !m_pimpl->m_pattern.is_open() ) {
0655         result = false;
0656         result.message() << "Pattern file can't be opened!";
0657     }
0658     else {
0659         if( m_pimpl->m_match_or_save ) {
0660 
0661             int offset = 0;
0662             std::vector<char> last_elements;
0663             for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
0664 
0665                 char c = m_pimpl->get_char();
0666 
0667                 if( last_elements.size() <= n_chars_presuffix ) {
0668                     last_elements.push_back( c );
0669                 }
0670                 else {
0671                     last_elements[ i % last_elements.size() ] = c;
0672                 }
0673 
0674                 bool is_same = !m_pimpl->m_pattern.fail() &&
0675                          !m_pimpl->m_pattern.eof()  &&
0676                          (stream_string_repr[i+offset] == c);
0677 
0678                 if( !is_same ) {
0679 
0680                     result = false;
0681 
0682                     std::string::size_type prefix_size  = (std::min)( i + offset, n_chars_presuffix );
0683 
0684                     std::string::size_type suffix_size  = (std::min)( stream_string_repr.length() - i - offset,
0685                                                                       n_chars_presuffix );
0686 
0687                     // try to log area around the mismatch
0688                     std::string substr = stream_string_repr.substr(0, i+offset);
0689                     std::size_t line = std::count(substr.begin(), substr.end(), '\n');
0690                     std::size_t column = i + offset - substr.rfind('\n');
0691 
0692                     result.message()
0693                         << "Mismatch at position " << i
0694                         << " (line " << line
0695                         << ", column " << column
0696                         << "): '" << pretty_print_log(std::string(1, stream_string_repr[i+offset])) << "' != '" << pretty_print_log(std::string(1, c)) << "' :\n";
0697 
0698                     // we already escape this substring because we need its actual size for the pretty print
0699                     // of the difference location.
0700                     std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
0701 
0702                     // we need this substring as is because we compute the best matching substrings on it.
0703                     std::string sub_str_suffix(stream_string_repr.substr( i + offset, suffix_size));
0704                     result.message() << "... " << sub_str_prefix + pretty_print_log(sub_str_suffix) << " ..." << '\n';
0705 
0706                     result.message() << "... ";
0707                     for( std::size_t j = 0; j < last_elements.size() ; j++ )
0708                         result.message() << pretty_print_log(std::string(1, last_elements[(i + j + 1) % last_elements.size()]));
0709 
0710                     std::vector<char> last_elements_ordered;
0711                     last_elements_ordered.push_back(c);
0712                     for( std::string::size_type counter = 0; counter < suffix_size - 1 ; counter++ ) {
0713                         char c2 = m_pimpl->get_char();
0714 
0715                         if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
0716                             break;
0717 
0718                         result.message() << pretty_print_log(std::string(1, c2));
0719 
0720                         last_elements_ordered.push_back(c2);
0721                     }
0722 
0723                     // tries to find the best substring matching in the remainder of the
0724                     // two strings
0725                     std::size_t max_nb_char_in_common = 0;
0726                     std::size_t best_pattern_start_index = 0;
0727                     std::size_t best_stream_start_index = 0;
0728                     for( std::size_t pattern_start_index = best_pattern_start_index;
0729                          pattern_start_index < last_elements_ordered.size();
0730                          pattern_start_index++ ) {
0731                         for( std::size_t stream_start_index = best_stream_start_index;
0732                              stream_start_index < sub_str_suffix.size();
0733                              stream_start_index++ ) {
0734 
0735                             std::size_t max_size = (std::min)( last_elements_ordered.size() - pattern_start_index, sub_str_suffix.size() - stream_start_index );
0736                             if( max_nb_char_in_common > max_size )
0737                                 break; // safely break to go to the outer loop
0738 
0739                             std::size_t nb_char_in_common = 0;
0740                             for( std::size_t k = 0; k < max_size; k++) {
0741                                 if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
0742                                     nb_char_in_common ++;
0743                                 else
0744                                     break; // we take fully matching substring only
0745                             }
0746 
0747                             if( nb_char_in_common > max_nb_char_in_common ) {
0748                                 max_nb_char_in_common = nb_char_in_common;
0749                                 best_pattern_start_index = pattern_start_index;
0750                                 best_stream_start_index = stream_start_index;
0751                             }
0752                         }
0753                     }
0754 
0755                     // indicates with more precision the location of the mismatchs in "ascii arts" ...
0756                     result.message() << " ...\n... ";
0757                     for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
0758                         result.message() << ' ';
0759                     }
0760 
0761                     result.message() << '~'; // places the first tilde at the current char that mismatches
0762 
0763                     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
0764                         std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
0765                         std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
0766                         for( int h = static_cast<int>((std::max)(s1.size(), s2.size())); h > 0; h--)
0767                             result.message() << "~";
0768                     }
0769 
0770                     if( m_pimpl->m_pattern.eof() ) {
0771                         result.message() << "    (reference string shorter than current stream)";
0772                     }
0773 
0774                     result.message() << "\n";
0775 
0776                     // no need to continue if the EOF is reached
0777                     if( m_pimpl->m_pattern.eof() ) {
0778                         break;
0779                     }
0780 
0781                     // first char is a replicat of c, so we do not copy it.
0782                     for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
0783                         last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
0784 
0785                     i += last_elements_ordered.size()-1;
0786                     offset += best_stream_start_index - best_pattern_start_index;
0787 
0788                 }
0789 
0790             }
0791 
0792             // not needed anymore
0793             /*
0794             if(offset > 0 && false) {
0795                 m_pimpl->m_pattern.ignore(
0796                     static_cast<std::streamsize>( offset ));
0797             }
0798             */
0799         }
0800         else {
0801             m_pimpl->m_pattern.write( stream_string_repr.c_str(),
0802                                       static_cast<std::streamsize>( stream_string_repr.length() ) );
0803             m_pimpl->m_pattern.flush();
0804         }
0805     }
0806 
0807     if( flush_stream )
0808         flush();
0809 
0810     return result;
0811 }
0812 
0813 //____________________________________________________________________________//
0814 
0815 void
0816 output_test_stream::flush()
0817 {
0818     m_pimpl->m_synced_string.erase();
0819 
0820 #ifndef BOOST_NO_STRINGSTREAM
0821     str( std::string() );
0822 #else
0823     seekp( 0, std::ios::beg );
0824 #endif
0825 }
0826 
0827 
0828 std::string
0829 output_test_stream::get_stream_string_representation() const {
0830     return m_pimpl->m_synced_string;
0831 }
0832 
0833 //____________________________________________________________________________//
0834 
0835 std::size_t
0836 output_test_stream::length()
0837 {
0838     sync();
0839 
0840     return m_pimpl->m_synced_string.length();
0841 }
0842 
0843 //____________________________________________________________________________//
0844 
0845 void
0846 output_test_stream::sync()
0847 {
0848 #ifdef BOOST_NO_STRINGSTREAM
0849     m_pimpl->m_synced_string.assign( str(), pcount() );
0850     freeze( false );
0851 #else
0852     m_pimpl->m_synced_string = str();
0853 #endif
0854 }
0855 
0856 //____________________________________________________________________________//
0857 
0858 } // namespace test_tools
0859 } // namespace boost
0860 
0861 #include <boost/test/detail/enable_warnings.hpp>
0862 
0863 #endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER