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