1 // (C) Copyright Gennadiy Rozental 2005-2008.
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)
6 // See http://www.boost.org/libs/test for the library home page.
10 // Version : $Revision$
12 // Description : supplies offline implementation for the Test Tools
13 // ***************************************************************************
15 #ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
16 #define BOOST_TEST_TEST_TOOLS_IPP_012205GER
19 #include <boost/test/test_tools.hpp>
20 #include <boost/test/unit_test_log.hpp>
21 #include <boost/test/output_test_stream.hpp>
22 #include <boost/test/framework.hpp>
23 #include <boost/test/execution_monitor.hpp> // execution_aborted
24 #include <boost/test/unit_test_suite_impl.hpp>
27 #include <boost/config.hpp>
38 // !! should we use #include <cstdarg>
41 #include <boost/test/detail/suppress_warnings.hpp>
43 //____________________________________________________________________________//
45 # ifdef BOOST_NO_STDC_NAMESPACE
46 namespace std { using ::strcmp; using ::strlen; using ::isprint; }
47 #if !defined( BOOST_NO_CWCHAR )
48 namespace std { using ::wcscmp; }
54 namespace test_tools {
56 // ************************************************************************** //
57 // ************** print_log_value ************** //
58 // ************************************************************************** //
61 print_log_value<char>::operator()( std::ostream& ostr, char t )
63 if( (std::isprint)( static_cast<unsigned char>(t) ) )
64 ostr << '\'' << t << '\'';
67 #if BOOST_TEST_USE_STD_LOCALE
72 << static_cast<int>(t);
75 //____________________________________________________________________________//
78 print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
81 // showbase is only available for new style streams:
82 #if BOOST_TEST_USE_STD_LOCALE
87 << static_cast<int>(t);
90 //____________________________________________________________________________//
93 print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
95 ostr << ( t ? t : "null string" );
98 //____________________________________________________________________________//
101 print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
103 ostr << ( t ? t : L"null string" );
106 //____________________________________________________________________________//
108 namespace tt_detail {
110 // ************************************************************************** //
111 // ************** TOOL BOX Implementation ************** //
112 // ************************************************************************** //
114 using ::boost::unit_test::lazy_ostream;
117 check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
118 const_string file_name, std::size_t line_num,
119 tool_level tl, check_type ct,
120 std::size_t num_of_args, ... )
122 using namespace unit_test;
124 if( !framework::is_initialized() )
125 throw std::runtime_error( "can't use testing tools before framework is initialized" );
136 ll = log_successful_tests;
142 prefix = "condition ";
143 suffix = " is not satisfied";
151 ll = log_fatal_errors;
152 prefix = "critical check ";
161 unit_test_log << unit_test::log::begin( file_name, line_num )
162 << ll << prefix << check_descr << suffix;
164 if( !pr.has_empty_message() )
165 unit_test_log << ". " << pr.message();
167 unit_test_log << unit_test::log::end();
171 unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
174 unit_test_log << prefix << "'" << check_descr << "'" << suffix;
176 unit_test_log << check_descr;
178 if( !pr.has_empty_message() )
179 unit_test_log << ". " << pr.message();
181 unit_test_log << unit_test::log::end();
190 static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
191 static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
195 va_start( args, num_of_args );
196 char const* arg1_descr = va_arg( args, char const* );
197 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
198 char const* arg2_descr = va_arg( args, char const* );
199 lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
201 unit_test_log << unit_test::log::begin( file_name, line_num )
202 << ll << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
205 unit_test_log << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
209 if( !pr.has_empty_message() )
210 unit_test_log << ". " << pr.message();
212 unit_test_log << unit_test::log::end();
217 case CHECK_CLOSE_FRACTION: {
220 va_start( args, num_of_args );
221 char const* arg1_descr = va_arg( args, char const* );
222 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
223 char const* arg2_descr = va_arg( args, char const* );
224 lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
225 /* toler_descr = */ va_arg( args, char const* );
226 lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
228 unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
230 unit_test_log << "difference{" << pr.message() << (ct == CHECK_CLOSE ? "%" : "")
231 << "} between " << arg1_descr << "{" << *arg1_val
232 << "} and " << arg2_descr << "{" << *arg2_val
233 << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
235 if( ct == CHECK_CLOSE )
236 unit_test_log << "%";
240 unit_test_log << unit_test::log::end();
246 va_start( args, num_of_args );
247 char const* arg1_descr = va_arg( args, char const* );
248 lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
249 /* toler_descr = */ va_arg( args, char const* );
250 lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
252 unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
254 unit_test_log << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
255 << ( tl == PASS ? " doesn't exceed " : " exceeds " )
260 if( !pr.has_empty_message() )
261 unit_test_log << ". " << pr.message();
263 unit_test_log << unit_test::log::end();
267 case CHECK_PRED_WITH_ARGS: {
268 unit_test_log << unit_test::log::begin( file_name, line_num )
269 << ll << prefix << check_descr;
271 // print predicate call description
274 va_start( args, num_of_args );
276 unit_test_log << "( ";
277 for( std::size_t i = 0; i < num_of_args; ++i ) {
278 unit_test_log << va_arg( args, char const* );
279 va_arg( args, lazy_ostream const* ); // skip argument value;
281 if( i != num_of_args-1 )
282 unit_test_log << ", ";
284 unit_test_log << " )" << suffix;
290 va_start( args, num_of_args );
292 unit_test_log << " for ( ";
293 for( std::size_t i = 0; i < num_of_args; ++i ) {
294 va_arg( args, char const* ); // skip argument description;
295 unit_test_log << *va_arg( args, lazy_ostream const* );
297 if( i != num_of_args-1 )
298 unit_test_log << ", ";
300 unit_test_log << " )";
304 if( !pr.has_empty_message() )
305 unit_test_log << ". " << pr.message();
307 unit_test_log << unit_test::log::end();
311 case CHECK_EQUAL_COLL: {
314 va_start( args, num_of_args );
315 char const* left_begin_descr = va_arg( args, char const* );
316 char const* left_end_descr = va_arg( args, char const* );
317 char const* right_begin_descr = va_arg( args, char const* );
318 char const* right_end_descr = va_arg( args, char const* );
320 unit_test_log << unit_test::log::begin( file_name, line_num )
322 << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
323 << right_begin_descr << ", " << right_end_descr << " }"
328 if( !pr.has_empty_message() )
329 unit_test_log << ". " << pr.message();
331 unit_test_log << unit_test::log::end();
335 case CHECK_BITWISE_EQUAL: {
338 va_start( args, num_of_args );
339 char const* left_descr = va_arg( args, char const* );
340 char const* right_descr = va_arg( args, char const* );
342 unit_test_log << unit_test::log::begin( file_name, line_num )
343 << ll << prefix << left_descr << " =.= " << right_descr << suffix;
347 if( !pr.has_empty_message() )
348 unit_test_log << ". " << pr.message();
350 unit_test_log << unit_test::log::end();
357 framework::assertion_result( true );
364 framework::assertion_result( false );
368 framework::assertion_result( false );
370 framework::test_unit_aborted( framework::current_test_case() );
372 throw execution_aborted();
378 //____________________________________________________________________________//
381 equal_impl( char const* left, char const* right )
383 return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
386 //____________________________________________________________________________//
388 #if !defined( BOOST_NO_CWCHAR )
391 equal_impl( wchar_t const* left, wchar_t const* right )
393 return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
396 #endif // !defined( BOOST_NO_CWCHAR )
398 //____________________________________________________________________________//
401 is_defined_impl( const_string symbol_name, const_string symbol_value )
403 symbol_value.trim_left( 2 );
404 return symbol_name != symbol_value;
407 //____________________________________________________________________________//
409 } // namespace tt_detail
411 // ************************************************************************** //
412 // ************** output_test_stream ************** //
413 // ************************************************************************** //
415 struct output_test_stream::Impl
417 std::fstream m_pattern;
418 bool m_match_or_save;
419 bool m_text_or_binary;
420 std::string m_synced_string;
426 m_pattern.get( res );
427 } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
432 void check_and_fill( predicate_result& res )
434 if( !res.p_predicate_value )
435 res.message() << "Output content: \"" << m_synced_string << '\"';
439 //____________________________________________________________________________//
441 output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
442 : m_pimpl( new Impl )
444 if( !pattern_file_name.is_empty() ) {
445 std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
446 if( !text_or_binary )
447 m |= std::ios::binary;
449 m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
451 BOOST_WARN_MESSAGE( m_pimpl->m_pattern.is_open(),
452 "Can't open pattern file " << pattern_file_name
453 << " for " << (match_or_save ? "reading" : "writing") );
456 m_pimpl->m_match_or_save = match_or_save;
457 m_pimpl->m_text_or_binary = text_or_binary;
460 //____________________________________________________________________________//
462 output_test_stream::~output_test_stream()
467 //____________________________________________________________________________//
470 output_test_stream::is_empty( bool flush_stream )
474 result_type res( m_pimpl->m_synced_string.empty() );
476 m_pimpl->check_and_fill( res );
484 //____________________________________________________________________________//
487 output_test_stream::check_length( std::size_t length_, bool flush_stream )
491 result_type res( m_pimpl->m_synced_string.length() == length_ );
493 m_pimpl->check_and_fill( res );
501 //____________________________________________________________________________//
504 output_test_stream::is_equal( const_string arg, bool flush_stream )
508 result_type res( const_string( m_pimpl->m_synced_string ) == arg );
510 m_pimpl->check_and_fill( res );
518 //____________________________________________________________________________//
521 output_test_stream::match_pattern( bool flush_stream )
525 result_type result( true );
527 if( !m_pimpl->m_pattern.is_open() ) {
529 result.message() << "Pattern file can't be opened!";
532 if( m_pimpl->m_match_or_save ) {
533 for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) {
534 char c = m_pimpl->get_char();
536 result = !m_pimpl->m_pattern.fail() &&
537 !m_pimpl->m_pattern.eof() &&
538 (m_pimpl->m_synced_string[i] == c);
541 std::string::size_type suffix_size = (std::min)( m_pimpl->m_synced_string.length() - i,
542 static_cast<std::string::size_type>(5) );
544 // try to log area around the mismatch
545 result.message() << "Mismatch at position " << i << '\n'
546 << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n'
549 std::string::size_type counter = suffix_size;
551 char c = m_pimpl->get_char();
553 if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
556 result.message() << c;
559 result.message() << "...";
561 // skip rest of the bytes. May help for further matching
562 m_pimpl->m_pattern.ignore(
563 static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
569 m_pimpl->m_pattern.write( m_pimpl->m_synced_string.c_str(),
570 static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
571 m_pimpl->m_pattern.flush();
581 //____________________________________________________________________________//
584 output_test_stream::flush()
586 m_pimpl->m_synced_string.erase();
588 #ifndef BOOST_NO_STRINGSTREAM
589 str( std::string() );
591 seekp( 0, std::ios::beg );
595 //____________________________________________________________________________//
598 output_test_stream::length()
602 return m_pimpl->m_synced_string.length();
605 //____________________________________________________________________________//
608 output_test_stream::sync()
610 #ifdef BOOST_NO_STRINGSTREAM
611 m_pimpl->m_synced_string.assign( str(), pcount() );
614 m_pimpl->m_synced_string = str();
618 //____________________________________________________________________________//
620 } // namespace test_tools
624 //____________________________________________________________________________//
626 #include <boost/test/detail/enable_warnings.hpp>
628 #endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER