test_tools.ipp 27 KB

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