summaryrefslogtreecommitdiff
path: root/src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp')
-rw-r--r--src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp823
1 files changed, 823 insertions, 0 deletions
diff --git a/src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp b/src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp
new file mode 100644
index 00000000000..2956879326b
--- /dev/null
+++ b/src/third_party/boost-1.69.0/boost/test/impl/test_tools.ipp
@@ -0,0 +1,823 @@
+// (C) Copyright Gennadiy Rozental 2001.
+// 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$
+//
+// 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/unit_test_log.hpp>
+#include <boost/test/tools/context.hpp>
+#include <boost/test/tools/output_test_stream.hpp>
+
+#include <boost/test/tools/detail/fwd.hpp>
+#include <boost/test/tools/detail/print_helper.hpp>
+
+#include <boost/test/framework.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/execution_monitor.hpp> // execution_aborted
+
+#include <boost/test/detail/throw_exception.hpp>
+
+#include <boost/test/utils/algorithm.hpp>
+
+// Boost
+#include <boost/config.hpp>
+
+// STL
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <cctype>
+#include <cwchar>
+#include <stdexcept>
+#include <vector>
+#include <utility>
+#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 {
+namespace tt_detail {
+
+// ************************************************************************** //
+// ************** print_log_value ************** //
+// ************************************************************************** //
+
+void
+print_log_value<bool>::operator()( std::ostream& ostr, bool t )
+{
+ ostr << std::boolalpha << t;
+}
+
+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" );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** TOOL BOX Implementation ************** //
+// ************************************************************************** //
+
+using ::boost::unit_test::lazy_ostream;
+
+static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
+static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
+
+template<typename OutStream>
+void
+format_report( OutStream& os, assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
+ tool_level tl, check_type ct,
+ std::size_t num_args, va_list args,
+ char const* prefix, char const* suffix )
+{
+ using namespace unit_test;
+
+ switch( ct ) {
+ case CHECK_PRED:
+ os << prefix << assertion_descr << suffix;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+
+ case CHECK_BUILT_ASSERTION: {
+ os << prefix << assertion_descr << suffix;
+
+ if( tl != PASS ) {
+ const_string details_message = pr.message();
+
+ if( !details_message.is_empty() ) {
+ os << details_message;
+ }
+ }
+ break;
+ }
+
+ case CHECK_MSG:
+ if( tl == PASS )
+ os << prefix << "'" << assertion_descr << "'" << suffix;
+ else
+ os << assertion_descr;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+
+ case CHECK_EQUAL:
+ case CHECK_NE:
+ case CHECK_LT:
+ case CHECK_LE:
+ case CHECK_GT:
+ case CHECK_GE: {
+ 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* );
+
+ os << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
+
+ if( tl != PASS )
+ os << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+ }
+
+ case CHECK_CLOSE:
+ case CHECK_CLOSE_FRACTION: {
+ 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* );
+
+ os << "difference{" << pr.message()
+ << "} between " << arg1_descr << "{" << *arg1_val
+ << "} and " << arg2_descr << "{" << *arg2_val
+ << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
+ << *toler_val;
+ if( ct == CHECK_CLOSE )
+ os << "%";
+ break;
+ }
+ case CHECK_SMALL: {
+ 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* );
+
+ os << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
+ << ( tl == PASS ? " doesn't exceed " : " exceeds " )
+ << *toler_val;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+ }
+
+ case CHECK_PRED_WITH_ARGS: {
+ std::vector< std::pair<char const*, lazy_ostream const*> > args_copy;
+ args_copy.reserve( num_args );
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ char const* desc = va_arg( args, char const* );
+ lazy_ostream const* value = va_arg( args, lazy_ostream const* );
+ args_copy.push_back( std::make_pair( desc, value ) );
+ }
+
+ os << prefix << assertion_descr;
+
+ // print predicate call description
+ os << "( ";
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ os << args_copy[i].first;
+
+ if( i != num_args-1 )
+ os << ", ";
+ }
+ os << " )" << suffix;
+
+ if( tl != PASS ) {
+ os << " for ( ";
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ os << *args_copy[i].second;
+
+ if( i != num_args-1 )
+ os << ", ";
+ }
+ os << " )";
+ }
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+ }
+
+ case CHECK_EQUAL_COLL: {
+ 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* );
+
+ os << prefix << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
+ << right_begin_descr << ", " << right_end_descr << " }"
+ << suffix;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+ }
+
+ case CHECK_BITWISE_EQUAL: {
+ char const* left_descr = va_arg( args, char const* );
+ char const* right_descr = va_arg( args, char const* );
+
+ os << prefix << left_descr << " =.= " << right_descr << suffix;
+
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
+ break;
+ }
+ }
+}
+
+//____________________________________________________________________________//
+
+bool
+report_assertion( assertion_result const& ar,
+ lazy_ostream const& assertion_descr,
+ const_string file_name,
+ std::size_t line_num,
+ tool_level tl,
+ check_type ct,
+ std::size_t num_args, ... )
+{
+ using namespace unit_test;
+
+ if( !framework::test_in_progress() ) {
+ // in case no test is in progress, we do not throw anything:
+ // raising an exception here may result in raising an exception in a destructor of a global fixture
+ // which will abort the process
+ // We flag this as aborted instead
+
+ //BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
+ // std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
+
+ framework::test_aborted();
+ return false;
+ }
+
+
+ if( !!ar )
+ tl = PASS;
+
+ log_level ll;
+ char const* prefix;
+ char const* suffix;
+
+ switch( tl ) {
+ case PASS:
+ ll = log_successful_tests;
+ prefix = "check ";
+ suffix = " has passed";
+ break;
+ case WARN:
+ ll = log_warnings;
+ prefix = "condition ";
+ suffix = " is not satisfied";
+ break;
+ case CHECK:
+ ll = log_all_errors;
+ prefix = "check ";
+ suffix = " has failed";
+ break;
+ case REQUIRE:
+ ll = log_fatal_errors;
+ prefix = "critical check ";
+ suffix = " has failed";
+ break;
+ default:
+ return true;
+ }
+
+ unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
+ va_list args;
+ va_start( args, num_args );
+
+ format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
+
+ va_end( args );
+ unit_test_log << unit_test::log::end();
+
+ switch( tl ) {
+ case PASS:
+ framework::assertion_result( AR_PASSED );
+ return true;
+
+ case WARN:
+ framework::assertion_result( AR_TRIGGERED );
+ return false;
+
+ case CHECK:
+ framework::assertion_result( AR_FAILED );
+ return false;
+
+ case REQUIRE:
+ framework::assertion_result( AR_FAILED );
+ framework::test_unit_aborted( framework::current_test_unit() );
+ BOOST_TEST_I_THROW( execution_aborted() );
+ return false;
+ }
+
+ return true;
+}
+
+//____________________________________________________________________________//
+
+assertion_result
+format_assertion_result( const_string expr_val, const_string details )
+{
+ assertion_result res(false);
+
+ bool starts_new_line = first_char( expr_val ) == '\n';
+
+ if( !starts_new_line && !expr_val.is_empty() )
+ res.message().stream() << " [" << expr_val << "]";
+
+ if( !details.is_empty() ) {
+ if( first_char(details) != '[' )
+ res.message().stream() << ". ";
+ else
+ res.message().stream() << " ";
+
+ res.message().stream() << details;
+ }
+
+ if( starts_new_line )
+ res.message().stream() << "." << expr_val;
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+BOOST_TEST_DECL std::string
+prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
+{
+ std::ostringstream msg_buff;
+
+ va_list args;
+ va_start( args, num_args );
+
+ format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
+
+ va_end( args );
+
+ return msg_buff.str();
+}
+
+//____________________________________________________________________________//
+
+assertion_result
+equal_impl( char const* left, char const* right )
+{
+ return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
+}
+
+//____________________________________________________________________________//
+
+#if !defined( BOOST_NO_CWCHAR )
+
+assertion_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;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** context_frame ************** //
+// ************************************************************************** //
+
+context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
+: m_frame_id( unit_test::framework::add_context( context_descr, true ) )
+{
+}
+
+//____________________________________________________________________________//
+
+context_frame::~context_frame()
+{
+ unit_test::framework::clear_context( m_frame_id );
+}
+
+//____________________________________________________________________________//
+
+context_frame::operator bool()
+{
+ return true;
+}
+
+//____________________________________________________________________________//
+
+} // 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 = 0;
+ do {
+ m_pattern.get( res );
+ } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
+
+ return res;
+ }
+
+ void check_and_fill( assertion_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 );
+
+ if( !m_pimpl->m_pattern.is_open() )
+ BOOST_TEST_FRAMEWORK_MESSAGE( "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;
+}
+
+//____________________________________________________________________________//
+
+assertion_result
+output_test_stream::is_empty( bool flush_stream )
+{
+ sync();
+
+ assertion_result res( m_pimpl->m_synced_string.empty() );
+
+ m_pimpl->check_and_fill( res );
+
+ if( flush_stream )
+ flush();
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+assertion_result
+output_test_stream::check_length( std::size_t length_, bool flush_stream )
+{
+ sync();
+
+ assertion_result res( m_pimpl->m_synced_string.length() == length_ );
+
+ m_pimpl->check_and_fill( res );
+
+ if( flush_stream )
+ flush();
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+assertion_result
+output_test_stream::is_equal( const_string arg, bool flush_stream )
+{
+ sync();
+
+ assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
+
+ m_pimpl->check_and_fill( res );
+
+ if( flush_stream )
+ flush();
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+std::string pretty_print_log(std::string str) {
+
+ static const std::string to_replace[] = { "\r", "\n" };
+ static const std::string replacement[] = { "\\r", "\\n" };
+
+ return unit_test::utils::replace_all_occurrences_of(
+ str,
+ to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
+ replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
+}
+
+assertion_result
+output_test_stream::match_pattern( bool flush_stream )
+{
+ const std::string::size_type n_chars_presuffix = 10;
+ sync();
+
+ assertion_result result( true );
+
+ const std::string stream_string_repr = get_stream_string_representation();
+
+ 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 ) {
+
+ int offset = 0;
+ std::vector<char> last_elements;
+ for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
+
+ char c = m_pimpl->get_char();
+
+ if( last_elements.size() <= n_chars_presuffix ) {
+ last_elements.push_back( c );
+ }
+ else {
+ last_elements[ i % last_elements.size() ] = c;
+ }
+
+ bool is_same = !m_pimpl->m_pattern.fail() &&
+ !m_pimpl->m_pattern.eof() &&
+ (stream_string_repr[i+offset] == c);
+
+ if( !is_same ) {
+
+ result = false;
+
+ std::string::size_type prefix_size = (std::min)( i + offset, n_chars_presuffix );
+
+ std::string::size_type suffix_size = (std::min)( stream_string_repr.length() - i - offset,
+ n_chars_presuffix );
+
+ // try to log area around the mismatch
+ std::string substr = stream_string_repr.substr(0, i+offset);
+ std::size_t line = std::count(substr.begin(), substr.end(), '\n');
+ std::size_t column = i + offset - substr.rfind('\n');
+
+ result.message()
+ << "Mismatch at position " << i
+ << " (line " << line
+ << ", column " << column
+ << "): '" << pretty_print_log(std::string(1, stream_string_repr[i+offset])) << "' != '" << pretty_print_log(std::string(1, c)) << "' :\n";
+
+ // we already escape this substring because we need its actual size for the pretty print
+ // of the difference location.
+ std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
+
+ // we need this substring as is because we compute the best matching substrings on it.
+ std::string sub_str_suffix(stream_string_repr.substr( i + offset, suffix_size));
+ result.message() << "... " << sub_str_prefix + pretty_print_log(sub_str_suffix) << " ..." << '\n';
+
+ result.message() << "... ";
+ for( std::size_t j = 0; j < last_elements.size() ; j++ )
+ result.message() << pretty_print_log(std::string(1, last_elements[(i + j + 1) % last_elements.size()]));
+
+ std::vector<char> last_elements_ordered;
+ last_elements_ordered.push_back(c);
+ for( std::string::size_type counter = 0; counter < suffix_size - 1 ; counter++ ) {
+ char c2 = m_pimpl->get_char();
+
+ if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
+ break;
+
+ result.message() << pretty_print_log(std::string(1, c2));
+
+ last_elements_ordered.push_back(c2);
+ }
+
+ // tries to find the best substring matching in the remainder of the
+ // two strings
+ std::size_t max_nb_char_in_common = 0;
+ std::size_t best_pattern_start_index = 0;
+ std::size_t best_stream_start_index = 0;
+ for( std::size_t pattern_start_index = best_pattern_start_index;
+ pattern_start_index < last_elements_ordered.size();
+ pattern_start_index++ ) {
+ for( std::size_t stream_start_index = best_stream_start_index;
+ stream_start_index < sub_str_suffix.size();
+ stream_start_index++ ) {
+
+ std::size_t max_size = (std::min)( last_elements_ordered.size() - pattern_start_index, sub_str_suffix.size() - stream_start_index );
+ if( max_nb_char_in_common > max_size )
+ break; // safely break to go to the outer loop
+
+ std::size_t nb_char_in_common = 0;
+ for( std::size_t k = 0; k < max_size; k++) {
+ if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
+ nb_char_in_common ++;
+ else
+ break; // we take fully matching substring only
+ }
+
+ if( nb_char_in_common > max_nb_char_in_common ) {
+ max_nb_char_in_common = nb_char_in_common;
+ best_pattern_start_index = pattern_start_index;
+ best_stream_start_index = stream_start_index;
+ }
+ }
+ }
+
+ // indicates with more precision the location of the mismatchs in "ascii arts" ...
+ result.message() << " ...\n... ";
+ for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
+ result.message() << ' ';
+ }
+
+ result.message() << '~'; // places the first tilde at the current char that mismatches
+
+ 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
+ std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
+ std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
+ for( int h = (std::max)(s1.size(), s2.size()); h > 0; h--)
+ result.message() << "~";
+ }
+
+ if( m_pimpl->m_pattern.eof() ) {
+ result.message() << " (reference string shorter than current stream)";
+ }
+
+ result.message() << "\n";
+
+ // no need to continue if the EOF is reached
+ if( m_pimpl->m_pattern.eof() ) {
+ break;
+ }
+
+ // first char is a replicat of c, so we do not copy it.
+ for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
+ last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
+
+ i += last_elements_ordered.size()-1;
+ offset += best_stream_start_index - best_pattern_start_index;
+
+ }
+
+ }
+
+ // not needed anymore
+ /*
+ if(offset > 0 && false) {
+ m_pimpl->m_pattern.ignore(
+ static_cast<std::streamsize>( offset ));
+ }
+ */
+ }
+ else {
+ m_pimpl->m_pattern.write( stream_string_repr.c_str(),
+ static_cast<std::streamsize>( stream_string_repr.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::string
+output_test_stream::get_stream_string_representation() const {
+ return m_pimpl->m_synced_string;
+}
+
+//____________________________________________________________________________//
+
+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