File indexing completed on 2025-01-30 10:01:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
0016 #define BOOST_TEST_TEST_TOOLS_IPP_012205GER
0017
0018
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
0036 #include <boost/config.hpp>
0037
0038
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
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
0067 lazy_ostream lazy_ostream::inst = lazy_ostream();
0068 }}
0069
0070 namespace boost {
0071 namespace test_tools {
0072 namespace tt_detail {
0073
0074
0075
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
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
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 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 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
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
0336
0337
0338
0339
0340
0341
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
0407
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
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
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 }
0515
0516
0517
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
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
0690
0691 std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
0692
0693
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
0715
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;
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;
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
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() << '~';
0753
0754 for( std::size_t k = 1; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) {
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
0768 if( m_pimpl->m_pattern.eof() ) {
0769 break;
0770 }
0771
0772
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
0784
0785
0786
0787
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 }
0850 }
0851
0852 #include <boost/test/detail/enable_warnings.hpp>
0853
0854 #endif