test_tools.ipp 27 KB

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