]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/test/impl/test_tools.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / test / impl / test_tools.ipp
1 // (C) Copyright Gennadiy Rozental 2001.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // See http://www.boost.org/libs/test for the library home page.
7 //
8 // File : $RCSfile$
9 //
10 // Version : $Revision$
11 //
12 // Description : supplies offline implementation for the Test Tools
13 // ***************************************************************************
14
15 #ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
16 #define BOOST_TEST_TEST_TOOLS_IPP_012205GER
17
18 // Boost.Test
19 #include <boost/test/unit_test_log.hpp>
20 #include <boost/test/tools/context.hpp>
21 #include <boost/test/tools/output_test_stream.hpp>
22
23 #include <boost/test/tools/detail/fwd.hpp>
24 #include <boost/test/tools/detail/print_helper.hpp>
25
26 #include <boost/test/framework.hpp>
27 #include <boost/test/tree/test_unit.hpp>
28 #include <boost/test/execution_monitor.hpp> // execution_aborted
29
30 #include <boost/test/detail/throw_exception.hpp>
31
32 #include <boost/test/utils/algorithm.hpp>
33
34 // Boost
35 #include <boost/config.hpp>
36
37 // STL
38 #include <fstream>
39 #include <string>
40 #include <cstring>
41 #include <cctype>
42 #include <cwchar>
43 #include <stdexcept>
44 #include <vector>
45 #include <utility>
46 #include <ios>
47
48 // !! should we use #include <cstdarg>
49 #include <stdarg.h>
50
51 #include <boost/test/detail/suppress_warnings.hpp>
52
53 //____________________________________________________________________________//
54
55 # ifdef BOOST_NO_STDC_NAMESPACE
56 namespace std { using ::strcmp; using ::strlen; using ::isprint; }
57 #if !defined( BOOST_NO_CWCHAR )
58 namespace std { using ::wcscmp; }
59 #endif
60 # endif
61
62 namespace boost {
63 namespace test_tools {
64 namespace tt_detail {
65
66 // ************************************************************************** //
67 // ************** print_log_value ************** //
68 // ************************************************************************** //
69
70 void
71 print_log_value<bool>::operator()( std::ostream& ostr, bool t )
72 {
73 ostr << std::boolalpha << t;
74 }
75
76 void
77 print_log_value<char>::operator()( std::ostream& ostr, char t )
78 {
79 if( (std::isprint)( static_cast<unsigned char>(t) ) )
80 ostr << '\'' << t << '\'';
81 else
82 ostr << std::hex
83 #if BOOST_TEST_USE_STD_LOCALE
84 << std::showbase
85 #else
86 << "0x"
87 #endif
88 << static_cast<int>(t);
89 }
90
91 //____________________________________________________________________________//
92
93 void
94 print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
95 {
96 ostr << std::hex
97 // showbase is only available for new style streams:
98 #if BOOST_TEST_USE_STD_LOCALE
99 << std::showbase
100 #else
101 << "0x"
102 #endif
103 << static_cast<int>(t);
104 }
105
106 //____________________________________________________________________________//
107
108 void
109 print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
110 {
111 ostr << ( t ? t : "null string" );
112 }
113
114 //____________________________________________________________________________//
115
116 void
117 print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
118 {
119 ostr << ( t ? t : L"null string" );
120 }
121
122 #if !defined(BOOST_NO_CXX11_NULLPTR)
123 void
124 print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t )
125 {
126 ostr << "nullptr";
127 }
128 #endif
129
130 //____________________________________________________________________________//
131
132 // ************************************************************************** //
133 // ************** TOOL BOX Implementation ************** //
134 // ************************************************************************** //
135
136 using ::boost::unit_test::lazy_ostream;
137
138 static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
139 static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
140
141 template<typename OutStream>
142 void
143 format_report( OutStream& os, assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
144 tool_level tl, check_type ct,
145 std::size_t num_args, va_list args,
146 char const* prefix, char const* suffix )
147 {
148 using namespace unit_test;
149
150 switch( ct ) {
151 case CHECK_PRED:
152 os << prefix << assertion_descr << suffix;
153
154 if( !pr.has_empty_message() )
155 os << ". " << pr.message();
156 break;
157
158 case CHECK_BUILT_ASSERTION: {
159 os << prefix << assertion_descr << suffix;
160
161 if( tl != PASS ) {
162 const_string details_message = pr.message();
163
164 if( !details_message.is_empty() ) {
165 os << details_message;
166 }
167 }
168 break;
169 }
170
171 case CHECK_MSG:
172 if( tl == PASS )
173 os << prefix << "'" << assertion_descr << "'" << suffix;
174 else
175 os << assertion_descr;
176
177 if( !pr.has_empty_message() )
178 os << ". " << pr.message();
179 break;
180
181 case CHECK_EQUAL:
182 case CHECK_NE:
183 case CHECK_LT:
184 case CHECK_LE:
185 case CHECK_GT:
186 case CHECK_GE: {
187 char const* arg1_descr = va_arg( args, char const* );
188 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
189 char const* arg2_descr = va_arg( args, char const* );
190 lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
191
192 os << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
193
194 if( tl != PASS )
195 os << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
196
197 if( !pr.has_empty_message() )
198 os << ". " << pr.message();
199 break;
200 }
201
202 case CHECK_CLOSE:
203 case CHECK_CLOSE_FRACTION: {
204 char const* arg1_descr = va_arg( args, char const* );
205 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
206 char const* arg2_descr = va_arg( args, char const* );
207 lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
208 /* toler_descr = */ va_arg( args, char const* );
209 lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
210
211 os << "difference{" << pr.message()
212 << "} between " << arg1_descr << "{" << *arg1_val
213 << "} and " << arg2_descr << "{" << *arg2_val
214 << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
215 << *toler_val;
216 if( ct == CHECK_CLOSE )
217 os << "%";
218 break;
219 }
220 case CHECK_SMALL: {
221 char const* arg1_descr = va_arg( args, char const* );
222 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
223 /* toler_descr = */ va_arg( args, char const* );
224 lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
225
226 os << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
227 << ( tl == PASS ? " doesn't exceed " : " exceeds " )
228 << *toler_val;
229
230 if( !pr.has_empty_message() )
231 os << ". " << pr.message();
232 break;
233 }
234
235 case CHECK_PRED_WITH_ARGS: {
236 std::vector< std::pair<char const*, lazy_ostream const*> > args_copy;
237 args_copy.reserve( num_args );
238 for( std::size_t i = 0; i < num_args; ++i ) {
239 char const* desc = va_arg( args, char const* );
240 lazy_ostream const* value = va_arg( args, lazy_ostream const* );
241 args_copy.push_back( std::make_pair( desc, value ) );
242 }
243
244 os << prefix << assertion_descr;
245
246 // print predicate call description
247 os << "( ";
248 for( std::size_t i = 0; i < num_args; ++i ) {
249 os << args_copy[i].first;
250
251 if( i != num_args-1 )
252 os << ", ";
253 }
254 os << " )" << suffix;
255
256 if( tl != PASS ) {
257 os << " for ( ";
258 for( std::size_t i = 0; i < num_args; ++i ) {
259 os << *args_copy[i].second;
260
261 if( i != num_args-1 )
262 os << ", ";
263 }
264 os << " )";
265 }
266
267 if( !pr.has_empty_message() )
268 os << ". " << pr.message();
269 break;
270 }
271
272 case CHECK_EQUAL_COLL: {
273 char const* left_begin_descr = va_arg( args, char const* );
274 char const* left_end_descr = va_arg( args, char const* );
275 char const* right_begin_descr = va_arg( args, char const* );
276 char const* right_end_descr = va_arg( args, char const* );
277
278 os << prefix << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
279 << right_begin_descr << ", " << right_end_descr << " }"
280 << suffix;
281
282 if( !pr.has_empty_message() )
283 os << ". " << pr.message();
284 break;
285 }
286
287 case CHECK_BITWISE_EQUAL: {
288 char const* left_descr = va_arg( args, char const* );
289 char const* right_descr = va_arg( args, char const* );
290
291 os << prefix << left_descr << " =.= " << right_descr << suffix;
292
293 if( !pr.has_empty_message() )
294 os << ". " << pr.message();
295 break;
296 }
297 }
298 }
299
300 //____________________________________________________________________________//
301
302 bool
303 report_assertion( assertion_result const& ar,
304 lazy_ostream const& assertion_descr,
305 const_string file_name,
306 std::size_t line_num,
307 tool_level tl,
308 check_type ct,
309 std::size_t num_args, ... )
310 {
311 using namespace unit_test;
312
313 if( !framework::test_in_progress() ) {
314 // in case no test is in progress, we do not throw anything:
315 // raising an exception here may result in raising an exception in a destructor of a global fixture
316 // which will abort the process
317 // We flag this as aborted instead
318
319 //BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
320 // std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
321
322 framework::test_aborted();
323 return false;
324 }
325
326
327 if( !!ar )
328 tl = PASS;
329
330 log_level ll;
331 char const* prefix;
332 char const* suffix;
333
334 switch( tl ) {
335 case PASS:
336 ll = log_successful_tests;
337 prefix = "check ";
338 suffix = " has passed";
339 break;
340 case WARN:
341 ll = log_warnings;
342 prefix = "condition ";
343 suffix = " is not satisfied";
344 break;
345 case CHECK:
346 ll = log_all_errors;
347 prefix = "check ";
348 suffix = " has failed";
349 break;
350 case REQUIRE:
351 ll = log_fatal_errors;
352 prefix = "critical check ";
353 suffix = " has failed";
354 break;
355 default:
356 return true;
357 }
358
359 unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
360 va_list args;
361 va_start( args, num_args );
362
363 format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
364
365 va_end( args );
366 unit_test_log << unit_test::log::end();
367
368 switch( tl ) {
369 case PASS:
370 framework::assertion_result( AR_PASSED );
371 return true;
372
373 case WARN:
374 framework::assertion_result( AR_TRIGGERED );
375 return false;
376
377 case CHECK:
378 framework::assertion_result( AR_FAILED );
379 return false;
380
381 case REQUIRE:
382 framework::assertion_result( AR_FAILED );
383 framework::test_unit_aborted( framework::current_test_unit() );
384 BOOST_TEST_I_THROW( execution_aborted() );
385 return false;
386 }
387
388 return true;
389 }
390
391 //____________________________________________________________________________//
392
393 assertion_result
394 format_assertion_result( const_string expr_val, const_string details )
395 {
396 assertion_result res(false);
397
398 bool starts_new_line = first_char( expr_val ) == '\n';
399
400 if( !starts_new_line && !expr_val.is_empty() )
401 res.message().stream() << " [" << expr_val << "]";
402
403 if( !details.is_empty() ) {
404 if( first_char(details) != '[' )
405 res.message().stream() << ". ";
406 else
407 res.message().stream() << " ";
408
409 res.message().stream() << details;
410 }
411
412 if( starts_new_line )
413 res.message().stream() << "." << expr_val;
414
415 return res;
416 }
417
418 //____________________________________________________________________________//
419
420 BOOST_TEST_DECL std::string
421 prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
422 {
423 std::ostringstream msg_buff;
424
425 va_list args;
426 va_start( args, num_args );
427
428 format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
429
430 va_end( args );
431
432 return msg_buff.str();
433 }
434
435 //____________________________________________________________________________//
436
437 assertion_result
438 equal_impl( char const* left, char const* right )
439 {
440 return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
441 }
442
443 //____________________________________________________________________________//
444
445 #if !defined( BOOST_NO_CWCHAR )
446
447 assertion_result
448 equal_impl( wchar_t const* left, wchar_t const* right )
449 {
450 return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
451 }
452
453 #endif // !defined( BOOST_NO_CWCHAR )
454
455 //____________________________________________________________________________//
456
457 bool
458 is_defined_impl( const_string symbol_name, const_string symbol_value )
459 {
460 symbol_value.trim_left( 2 );
461 return symbol_name != symbol_value;
462 }
463
464 //____________________________________________________________________________//
465
466 // ************************************************************************** //
467 // ************** context_frame ************** //
468 // ************************************************************************** //
469
470 context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
471 : m_frame_id( unit_test::framework::add_context( context_descr, true ) )
472 {
473 }
474
475 //____________________________________________________________________________//
476
477 context_frame::~context_frame()
478 {
479 unit_test::framework::clear_context( m_frame_id );
480 }
481
482 //____________________________________________________________________________//
483
484 context_frame::operator bool()
485 {
486 return true;
487 }
488
489 //____________________________________________________________________________//
490
491 } // namespace tt_detail
492
493 // ************************************************************************** //
494 // ************** output_test_stream ************** //
495 // ************************************************************************** //
496
497 struct output_test_stream::Impl
498 {
499 std::fstream m_pattern;
500 bool m_match_or_save;
501 bool m_text_or_binary;
502 std::string m_synced_string;
503
504 char get_char()
505 {
506 char res = 0;
507 do {
508 m_pattern.get( res );
509 } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
510
511 return res;
512 }
513
514 void check_and_fill( assertion_result& res )
515 {
516 if( !res.p_predicate_value )
517 res.message() << "Output content: \"" << m_synced_string << '\"';
518 }
519 };
520
521 //____________________________________________________________________________//
522
523 output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
524 : m_pimpl( new Impl )
525 {
526 if( !pattern_file_name.is_empty() ) {
527 std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
528 if( !text_or_binary )
529 m |= std::ios::binary;
530
531 m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
532
533 if( !m_pimpl->m_pattern.is_open() )
534 BOOST_TEST_FRAMEWORK_MESSAGE( "Can't open pattern file " << pattern_file_name << " for " << (match_or_save ? "reading" : "writing") );
535 }
536
537 m_pimpl->m_match_or_save = match_or_save;
538 m_pimpl->m_text_or_binary = text_or_binary;
539 }
540
541 //____________________________________________________________________________//
542
543 output_test_stream::~output_test_stream()
544 {
545 delete m_pimpl;
546 }
547
548 //____________________________________________________________________________//
549
550 assertion_result
551 output_test_stream::is_empty( bool flush_stream )
552 {
553 sync();
554
555 assertion_result res( m_pimpl->m_synced_string.empty() );
556
557 m_pimpl->check_and_fill( res );
558
559 if( flush_stream )
560 flush();
561
562 return res;
563 }
564
565 //____________________________________________________________________________//
566
567 assertion_result
568 output_test_stream::check_length( std::size_t length_, bool flush_stream )
569 {
570 sync();
571
572 assertion_result res( m_pimpl->m_synced_string.length() == length_ );
573
574 m_pimpl->check_and_fill( res );
575
576 if( flush_stream )
577 flush();
578
579 return res;
580 }
581
582 //____________________________________________________________________________//
583
584 assertion_result
585 output_test_stream::is_equal( const_string arg, bool flush_stream )
586 {
587 sync();
588
589 assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
590
591 m_pimpl->check_and_fill( res );
592
593 if( flush_stream )
594 flush();
595
596 return res;
597 }
598
599 //____________________________________________________________________________//
600
601 std::string pretty_print_log(std::string str) {
602
603 static const std::string to_replace[] = { "\r", "\n" };
604 static const std::string replacement[] = { "\\r", "\\n" };
605
606 return unit_test::utils::replace_all_occurrences_of(
607 str,
608 to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
609 replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
610 }
611
612 assertion_result
613 output_test_stream::match_pattern( bool flush_stream )
614 {
615 const std::string::size_type n_chars_presuffix = 10;
616 sync();
617
618 assertion_result result( true );
619
620 const std::string stream_string_repr = get_stream_string_representation();
621
622 if( !m_pimpl->m_pattern.is_open() ) {
623 result = false;
624 result.message() << "Pattern file can't be opened!";
625 }
626 else {
627 if( m_pimpl->m_match_or_save ) {
628
629 int offset = 0;
630 std::vector<char> last_elements;
631 for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
632
633 char c = m_pimpl->get_char();
634
635 if( last_elements.size() <= n_chars_presuffix ) {
636 last_elements.push_back( c );
637 }
638 else {
639 last_elements[ i % last_elements.size() ] = c;
640 }
641
642 bool is_same = !m_pimpl->m_pattern.fail() &&
643 !m_pimpl->m_pattern.eof() &&
644 (stream_string_repr[i+offset] == c);
645
646 if( !is_same ) {
647
648 result = false;
649
650 std::string::size_type prefix_size = (std::min)( i + offset, n_chars_presuffix );
651
652 std::string::size_type suffix_size = (std::min)( stream_string_repr.length() - i - offset,
653 n_chars_presuffix );
654
655 // try to log area around the mismatch
656 std::string substr = stream_string_repr.substr(0, i+offset);
657 std::size_t line = std::count(substr.begin(), substr.end(), '\n');
658 std::size_t column = i + offset - substr.rfind('\n');
659
660 result.message()
661 << "Mismatch at position " << i
662 << " (line " << line
663 << ", column " << column
664 << "): '" << pretty_print_log(std::string(1, stream_string_repr[i+offset])) << "' != '" << pretty_print_log(std::string(1, c)) << "' :\n";
665
666 // we already escape this substring because we need its actual size for the pretty print
667 // of the difference location.
668 std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
669
670 // we need this substring as is because we compute the best matching substrings on it.
671 std::string sub_str_suffix(stream_string_repr.substr( i + offset, suffix_size));
672 result.message() << "... " << sub_str_prefix + pretty_print_log(sub_str_suffix) << " ..." << '\n';
673
674 result.message() << "... ";
675 for( std::size_t j = 0; j < last_elements.size() ; j++ )
676 result.message() << pretty_print_log(std::string(1, last_elements[(i + j + 1) % last_elements.size()]));
677
678 std::vector<char> last_elements_ordered;
679 last_elements_ordered.push_back(c);
680 for( std::string::size_type counter = 0; counter < suffix_size - 1 ; counter++ ) {
681 char c2 = m_pimpl->get_char();
682
683 if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
684 break;
685
686 result.message() << pretty_print_log(std::string(1, c2));
687
688 last_elements_ordered.push_back(c2);
689 }
690
691 // tries to find the best substring matching in the remainder of the
692 // two strings
693 std::size_t max_nb_char_in_common = 0;
694 std::size_t best_pattern_start_index = 0;
695 std::size_t best_stream_start_index = 0;
696 for( std::size_t pattern_start_index = best_pattern_start_index;
697 pattern_start_index < last_elements_ordered.size();
698 pattern_start_index++ ) {
699 for( std::size_t stream_start_index = best_stream_start_index;
700 stream_start_index < sub_str_suffix.size();
701 stream_start_index++ ) {
702
703 std::size_t max_size = (std::min)( last_elements_ordered.size() - pattern_start_index, sub_str_suffix.size() - stream_start_index );
704 if( max_nb_char_in_common > max_size )
705 break; // safely break to go to the outer loop
706
707 std::size_t nb_char_in_common = 0;
708 for( std::size_t k = 0; k < max_size; k++) {
709 if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
710 nb_char_in_common ++;
711 else
712 break; // we take fully matching substring only
713 }
714
715 if( nb_char_in_common > max_nb_char_in_common ) {
716 max_nb_char_in_common = nb_char_in_common;
717 best_pattern_start_index = pattern_start_index;
718 best_stream_start_index = stream_start_index;
719 }
720 }
721 }
722
723 // indicates with more precision the location of the mismatchs in "ascii arts" ...
724 result.message() << " ...\n... ";
725 for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
726 result.message() << ' ';
727 }
728
729 result.message() << '~'; // places the first tilde at the current char that mismatches
730
731 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
732 std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
733 std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
734 for( int h = (std::max)(s1.size(), s2.size()); h > 0; h--)
735 result.message() << "~";
736 }
737
738 if( m_pimpl->m_pattern.eof() ) {
739 result.message() << " (reference string shorter than current stream)";
740 }
741
742 result.message() << "\n";
743
744 // no need to continue if the EOF is reached
745 if( m_pimpl->m_pattern.eof() ) {
746 break;
747 }
748
749 // first char is a replicat of c, so we do not copy it.
750 for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
751 last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
752
753 i += last_elements_ordered.size()-1;
754 offset += best_stream_start_index - best_pattern_start_index;
755
756 }
757
758 }
759
760 // not needed anymore
761 /*
762 if(offset > 0 && false) {
763 m_pimpl->m_pattern.ignore(
764 static_cast<std::streamsize>( offset ));
765 }
766 */
767 }
768 else {
769 m_pimpl->m_pattern.write( stream_string_repr.c_str(),
770 static_cast<std::streamsize>( stream_string_repr.length() ) );
771 m_pimpl->m_pattern.flush();
772 }
773 }
774
775 if( flush_stream )
776 flush();
777
778 return result;
779 }
780
781 //____________________________________________________________________________//
782
783 void
784 output_test_stream::flush()
785 {
786 m_pimpl->m_synced_string.erase();
787
788 #ifndef BOOST_NO_STRINGSTREAM
789 str( std::string() );
790 #else
791 seekp( 0, std::ios::beg );
792 #endif
793 }
794
795
796 std::string
797 output_test_stream::get_stream_string_representation() const {
798 return m_pimpl->m_synced_string;
799 }
800
801 //____________________________________________________________________________//
802
803 std::size_t
804 output_test_stream::length()
805 {
806 sync();
807
808 return m_pimpl->m_synced_string.length();
809 }
810
811 //____________________________________________________________________________//
812
813 void
814 output_test_stream::sync()
815 {
816 #ifdef BOOST_NO_STRINGSTREAM
817 m_pimpl->m_synced_string.assign( str(), pcount() );
818 freeze( false );
819 #else
820 m_pimpl->m_synced_string = str();
821 #endif
822 }
823
824 //____________________________________________________________________________//
825
826 } // namespace test_tools
827 } // namespace boost
828
829 #include <boost/test/detail/enable_warnings.hpp>
830
831 #endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER