test_tools.ipp 26 KB

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