summaryrefslogtreecommitdiff
path: root/boost/test/impl
diff options
context:
space:
mode:
Diffstat (limited to 'boost/test/impl')
-rw-r--r--boost/test/impl/compiler_log_formatter.ipp119
-rw-r--r--boost/test/impl/cpp_main.ipp41
-rw-r--r--boost/test/impl/debug.ipp73
-rw-r--r--boost/test/impl/decorator.ipp202
-rw-r--r--boost/test/impl/exception_safety.ipp537
-rw-r--r--boost/test/impl/execution_monitor.ipp635
-rw-r--r--boost/test/impl/framework.ipp1076
-rw-r--r--boost/test/impl/interaction_based.ipp90
-rw-r--r--boost/test/impl/logged_expectations.ipp246
-rw-r--r--boost/test/impl/plain_report_formatter.ipp103
-rw-r--r--boost/test/impl/progress_monitor.ipp89
-rw-r--r--boost/test/impl/results_collector.ipp126
-rw-r--r--boost/test/impl/results_reporter.ipp22
-rw-r--r--boost/test/impl/test_main.ipp21
-rw-r--r--boost/test/impl/test_tools.ipp431
-rw-r--r--boost/test/impl/test_tree.ipp459
-rw-r--r--boost/test/impl/unit_test_log.ipp89
-rw-r--r--boost/test/impl/unit_test_main.ipp288
-rw-r--r--boost/test/impl/unit_test_monitor.ipp42
-rw-r--r--boost/test/impl/unit_test_parameters.ipp379
-rw-r--r--boost/test/impl/unit_test_suite.ipp346
-rw-r--r--boost/test/impl/xml_log_formatter.ipp82
-rw-r--r--boost/test/impl/xml_report_formatter.ipp29
23 files changed, 3091 insertions, 2434 deletions
diff --git a/boost/test/impl/compiler_log_formatter.ipp b/boost/test/impl/compiler_log_formatter.ipp
index 8fc08ccf44..c1ed944ab1 100644
--- a/boost/test/impl/compiler_log_formatter.ipp
+++ b/boost/test/impl/compiler_log_formatter.ipp
@@ -1,6 +1,6 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
@@ -16,11 +16,14 @@
#define BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
// Boost.Test
-#include <boost/test/output/compiler_log_formatter.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/framework.hpp>
+#include <boost/test/execution_monitor.hpp>
+#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/lazy_ostream.hpp>
+#include <boost/test/utils/setcolor.hpp>
+#include <boost/test/output/compiler_log_formatter.hpp>
+#include <boost/test/unit_test_parameters.hpp>
// Boost
#include <boost/version.hpp>
@@ -33,9 +36,7 @@
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-
namespace output {
// ************************************************************************** //
@@ -44,12 +45,10 @@ namespace output {
namespace {
-const_string
+std::string
test_phase_identifier()
{
- return framework::is_initialized()
- ? const_string( framework::current_test_case().p_name.get() )
- : BOOST_TEST_L( "Test setup" );
+ return framework::test_in_progress() ? framework::current_test_case().full_name() : std::string( "Test setup" );
}
} // local namespace
@@ -90,6 +89,10 @@ compiler_log_formatter::log_build_info( std::ostream& output )
void
compiler_log_formatter::test_unit_start( std::ostream& output, test_unit const& tu )
{
+ BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::BLUE );
+
+ print_prefix( output, tu.p_file_name, tu.p_line_num );
+
output << "Entering test " << tu.p_type_name << " \"" << tu.p_name << "\"" << std::endl;
}
@@ -98,6 +101,10 @@ compiler_log_formatter::test_unit_start( std::ostream& output, test_unit const&
void
compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const& tu, unsigned long elapsed )
{
+ BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::BLUE );
+
+ print_prefix( output, tu.p_file_name, tu.p_line_num );
+
output << "Leaving test " << tu.p_type_name << " \"" << tu.p_name << "\"";
if( elapsed > 0 ) {
@@ -105,7 +112,7 @@ compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const&
if( elapsed % 1000 == 0 )
output << elapsed/1000 << "ms";
else
- output << elapsed << "mks";
+ output << elapsed << "us";
}
output << std::endl;
@@ -114,31 +121,48 @@ compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const&
//____________________________________________________________________________//
void
-compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu )
+compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu, const_string reason )
{
- output << "Test " << tu.p_type_name << " \"" << tu.p_name << "\"" << "is skipped" << std::endl;
+ BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::YELLOW );
+
+ print_prefix( output, tu.p_file_name, tu.p_line_num );
+
+ output << "Test " << tu.p_type_name << " \"" << tu.full_name() << "\"" << " is skipped because " << reason << std::endl;
}
-
+
//____________________________________________________________________________//
void
-compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+compiler_log_formatter::log_exception_start( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
+
print_prefix( output, loc.m_file_name, loc.m_line_num );
- output << "fatal error in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": ";
+ {
+ BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BLINK, term_color::RED );
- output << ex.what();
+ output << "fatal error: in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": "
+ << ex.what();
+ }
if( !checkpoint_data.m_file_name.is_empty() ) {
output << '\n';
print_prefix( output, checkpoint_data.m_file_name, checkpoint_data.m_line_num );
+
+ BOOST_TEST_SCOPE_SETCOLOR( output, term_attr::BRIGHT, term_color::CYAN );
+
output << "last checkpoint";
if( !checkpoint_data.m_message.empty() )
output << ": " << checkpoint_data.m_message;
}
-
+}
+
+//____________________________________________________________________________//
+
+void
+compiler_log_formatter::log_exception_finish( std::ostream& output )
+{
output << std::endl;
}
@@ -150,21 +174,31 @@ compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data co
switch( let ) {
case BOOST_UTL_ET_INFO:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
+ if( runtime_config::color_output() )
+ output << setcolor( term_attr::BRIGHT, term_color::GREEN );
output << "info: ";
break;
case BOOST_UTL_ET_MESSAGE:
+ if( runtime_config::color_output() )
+ output << setcolor( term_attr::BRIGHT, term_color::CYAN );
break;
case BOOST_UTL_ET_WARNING:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
- output << "warning in \"" << test_phase_identifier() << "\": ";
+ if( runtime_config::color_output() )
+ output << setcolor( term_attr::BRIGHT, term_color::YELLOW );
+ output << "warning: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
- output << "error in \"" << test_phase_identifier() << "\": ";
+ if( runtime_config::color_output() )
+ output << setcolor( term_attr::BRIGHT, term_color::RED );
+ output << "error: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_FATAL_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
- output << "fatal error in \"" << test_phase_identifier() << "\": ";
+ if( runtime_config::color_output() )
+ output << setcolor( term_attr::BLINK, term_color::RED );
+ output << "fatal error: in \"" << test_phase_identifier() << "\": ";
break;
}
}
@@ -190,33 +224,60 @@ compiler_log_formatter::log_entry_value( std::ostream& output, lazy_ostream cons
void
compiler_log_formatter::log_entry_finish( std::ostream& output )
{
+ if( runtime_config::color_output() )
+ output << setcolor();
+
output << std::endl;
}
+
//____________________________________________________________________________//
void
-compiler_log_formatter::print_prefix( std::ostream& output, const_string file, std::size_t line )
+compiler_log_formatter::print_prefix( std::ostream& output, const_string file_name, std::size_t line_num )
{
+ if( !file_name.empty() )
+ {
#ifdef __APPLE_CC__
- // Xcode-compatible logging format, idea by Richard Dingwall at
- // <http://richarddingwall.name/2008/06/01/using-the-boost-unit-test-framework-with-xcode-3/>.
- output << file << ':' << line << ": ";
+ // Xcode-compatible logging format, idea by Richard Dingwall at
+ // <http://richarddingwall.name/2008/06/01/using-the-boost-unit-test-framework-with-xcode-3/>.
+ output << file_name << ':' << line_num << ": ";
#else
- output << file << '(' << line << "): ";
+ output << file_name << '(' << line_num << "): ";
#endif
+ }
}
//____________________________________________________________________________//
-} // namespace output
+void
+compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
+{
+ output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
+}
-} // namespace unit_test
+//____________________________________________________________________________//
-} // namespace boost
+void
+compiler_log_formatter::entry_context_finish( std::ostream& output )
+{
+ output.flush();
+}
//____________________________________________________________________________//
+void
+compiler_log_formatter::log_entry_context( std::ostream& output, const_string context_descr )
+{
+ output << "\n " << context_descr;
+}
+
+//____________________________________________________________________________//
+
+} // namespace output
+} // namespace unit_test
+} // namespace boost
+
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
diff --git a/boost/test/impl/cpp_main.ipp b/boost/test/impl/cpp_main.ipp
index 23d19e2f31..5cab0f4274 100644
--- a/boost/test/impl/cpp_main.ipp
+++ b/boost/test/impl/cpp_main.ipp
@@ -1,7 +1,7 @@
-// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Gennadiy Rozental 2001-2014.
// (C) Copyright Beman Dawes 1995-2001.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
@@ -41,18 +41,18 @@ namespace std { using ::getenv; using ::strerror; }
namespace {
struct cpp_main_caller {
- cpp_main_caller( int (*cpp_main_func)( int argc, char* argv[] ), int argc, char** argv )
+ cpp_main_caller( int (*cpp_main_func)( int argc, char* argv[] ), int argc, char** argv )
: m_cpp_main_func( cpp_main_func )
, m_argc( argc )
, m_argv( argv ) {}
-
- int operator()() { return (*m_cpp_main_func)( m_argc, m_argv ); }
-
+
+ int operator()() { return (*m_cpp_main_func)( m_argc, m_argv ); }
+
private:
- // Data members
- int (*m_cpp_main_func)( int argc, char* argv[] );
- int m_argc;
- char** m_argv;
+ // Data members
+ int (*m_cpp_main_func)( int argc, char* argv[] );
+ int m_argc;
+ char** m_argv;
};
} // local namespace
@@ -68,15 +68,14 @@ prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char
{
int result = 0;
- try {
+ BOOST_TEST_IMPL_TRY {
boost::unit_test::const_string p( std::getenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS" ) );
::boost::execution_monitor ex_mon;
ex_mon.p_catch_system_errors.value = p != "no";
-
- result = ex_mon.execute(
- ::boost::unit_test::callback0<int>( cpp_main_caller( cpp_main, argc, argv ) ) );
-
+
+ result = ex_mon.execute( cpp_main_caller( cpp_main, argc, argv ) );
+
if( result == 0 )
result = ::boost::exit_success;
else if( result != ::boost::exit_success ) {
@@ -84,13 +83,13 @@ prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char
result = ::boost::exit_failure;
}
}
- catch( ::boost::execution_exception const& exex ) {
+ BOOST_TEST_IMPL_CATCH( ::boost::execution_exception, exex ) {
std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl;
result = ::boost::exit_exception_failure;
}
- catch( ::boost::system_error const& ex ) {
+ BOOST_TEST_IMPL_CATCH( ::boost::system_error, ex ) {
std::cout << "\n**** failed to initialize execution monitor."
- << "\n**** expression at fault: " << ex.p_failed_exp
+ << "\n**** expression at fault: " << ex.p_failed_exp
<< "\n**** error(" << ex.p_errno << "): " << std::strerror( ex.p_errno ) << std::endl;
result = ::boost::exit_exception_failure;
}
@@ -104,8 +103,8 @@ prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char
// line argument modifications; for use in production programs
// that's a no-no in some organizations.
::boost::unit_test::const_string p( std::getenv( "BOOST_PRG_MON_CONFIRM" ) );
- if( p != "no" ) {
- std::cerr << std::flush << "no errors detected" << std::endl;
+ if( p != "no" ) {
+ std::cerr << std::flush << "no errors detected" << std::endl;
}
}
@@ -132,8 +131,6 @@ main( int argc, char* argv[] )
#endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_CPP_MAIN_IPP_012205GER
diff --git a/boost/test/impl/debug.ipp b/boost/test/impl/debug.ipp
index 78c3aa8e38..90e9d7ff2f 100644
--- a/boost/test/impl/debug.ipp
+++ b/boost/test/impl/debug.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2006-2008.
+// (C) Copyright Gennadiy Rozental 2006-2014.
// Use, modification, and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// http://www.boost.org/LICENSE_1_0.txt)
@@ -40,10 +40,6 @@
# endif
-# if BOOST_WORKAROUND( BOOST_MSVC, <1300)
-# define snprintf _snprintf
-# endif
-
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::memset; using ::sprintf; }
# endif
@@ -113,7 +109,6 @@ namespace std { using ::memset; using ::sprintf; }
//____________________________________________________________________________//
namespace boost {
-
namespace debug {
using unit_test::const_string;
@@ -210,10 +205,11 @@ private:
#if defined(BOOST_SUN_BASED_DEBUG)
struct psinfo m_psi;
+ char m_binary_path_buff[500+1]; // !! ??
#elif defined(BOOST_LINUX_BASED_DEBUG)
char m_stat_line[BOOST_TEST_STAT_LINE_MAX+1];
-#endif
char m_binary_path_buff[500+1]; // !! ??
+#endif
};
//____________________________________________________________________________//
@@ -239,12 +235,12 @@ process_info::process_info( int pid )
m_binary_name.assign( m_psi.pr_fname );
//-------------------------- //
-
+
::snprintf( fname_buff, sizeof(fname_buff), "/proc/%d/as", pid );
fd_holder as_fd( ::open( fname_buff, O_RDONLY ) );
uintptr_t binary_name_pos;
-
+
// !! ?? could we avoid reading whole m_binary_path_buff?
if( as_fd == -1 ||
::lseek( as_fd, m_psi.pr_argv, SEEK_SET ) == -1 ||
@@ -252,9 +248,9 @@ process_info::process_info( int pid )
::lseek( as_fd, binary_name_pos, SEEK_SET ) == -1 ||
::read ( as_fd, m_binary_path_buff, sizeof(m_binary_path_buff) ) == -1 )
return;
-
+
m_binary_path.assign( m_binary_path_buff );
-
+
#elif defined(BOOST_LINUX_BASED_DEBUG)
char fname_buff[30];
@@ -377,8 +373,10 @@ safe_execlp( char const* file, ... )
va_start( args, file );
while( !!(arg = va_arg( args, char const* )) ) {
printf( "!! %s\n", arg );
- if( !(*argv_it++ = copy_arg( work_buff, arg )) )
+ if( !(*argv_it++ = copy_arg( work_buff, arg )) ) {
+ va_end( args );
return false;
+ }
}
va_end( args );
@@ -440,7 +438,7 @@ prepare_gdb_cmnd_file( dbg_startup_info const& dsi )
WRITE_CSTR( "\ncont" );
if( dsi.break_or_continue )
WRITE_CSTR( "\nup 4" );
-
+
WRITE_CSTR( "\necho \\n" ); // !! ??
WRITE_CSTR( "\nlist -" );
WRITE_CSTR( "\nlist" );
@@ -513,9 +511,9 @@ prepare_dbx_cmd_line( dbg_startup_info const& dsi, bool list_source = true )
{
static char cmd_line_buff[500]; // !! ??
- ::snprintf( cmd_line_buff, sizeof(cmd_line_buff), "unlink %s;cont;%s%s",
- dsi.init_done_lock.begin(),
- dsi.break_or_continue ? "up 2;": "",
+ ::snprintf( cmd_line_buff, sizeof(cmd_line_buff), "unlink %s;cont;%s%s",
+ dsi.init_done_lock.begin(),
+ dsi.break_or_continue ? "up 2;": "",
list_source ? "echo \" \";list -w3;" : "" );
return cmd_line_buff;
@@ -543,8 +541,8 @@ start_dbx_in_xterm( dbg_startup_info const& dsi )
char pid_buff[16]; // !! ??
::snprintf( pid_buff, sizeof(pid_buff), "%ld", dsi.pid );
-
- safe_execlp( "xterm", "-T", title, "-display", dsi.display.begin(),
+
+ safe_execlp( "xterm", "-T", title, "-display", dsi.display.begin(),
"-bg", "black", "-fg", "white", "-geometry", "88x30+10+10", "-fn", "9x15", "-e",
"dbx", "-q", "-c", prepare_dbx_cmd_line( dsi ), dsi.binary_path.begin(), pid_buff, 0 );
}
@@ -580,7 +578,7 @@ start_dbx_in_ddd( dbg_startup_info const& dsi )
char pid_buff[16]; // !! ??
::snprintf( pid_buff, sizeof(pid_buff), "%ld", dsi.pid );
-
+
safe_execlp( "ddd", "-display", dsi.display.begin(),
"--dbx", "-q", "-c", prepare_dbx_cmd_line( dsi, false ), dsi.binary_path.begin(), pid_buff, 0 );
}
@@ -597,7 +595,7 @@ static struct info_t {
// Public properties
unit_test::readwrite_property<std::string> p_dbg;
-
+
// Data members
std::map<std::string,dbg_starter> m_dbg_starter_reg;
} s_info;
@@ -609,7 +607,7 @@ info_t::info_t()
p_dbg.value = ::getenv( "DISPLAY" )
? std::string( BOOST_STRINGIZE( BOOST_TEST_GUI_DBG ) )
: std::string( BOOST_STRINGIZE( BOOST_TEST_CNL_DBG ) );
-
+
m_dbg_starter_reg[std::string("gdb")] = &start_gdb_in_console;
m_dbg_starter_reg[std::string("gdb-emacs")] = &start_gdb_in_emacs;
m_dbg_starter_reg[std::string("gdb-xterm")] = &start_gdb_in_xterm;
@@ -679,8 +677,7 @@ debugger_break()
#if defined(BOOST_WIN32_BASED_DEBUG) // *********************** WIN32
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1300) || \
- BOOST_WORKAROUND(__GNUC__, >= 3) && !defined(__MINGW32__) || \
+#if defined(__GNUC__) && !defined(__MINGW32__) || \
defined(__INTEL_COMPILER)
# define BOOST_DEBUG_BREAK __debugbreak
#else
@@ -734,7 +731,7 @@ set_debugger( unit_test::const_string dbg_id, dbg_starter s )
assign_op( s_info.p_dbg.value, dbg_id, 0 );
if( !!s )
- s_info.m_dbg_starter_reg[s_info.p_dbg] = s;
+ s_info.m_dbg_starter_reg[s_info.p_dbg.get()] = s;
return old;
}
@@ -864,7 +861,7 @@ attach_debugger( bool break_or_continue )
if( init_done_lock_fd == -1 )
return false;
-
+
pid_t child_pid = fork();
if( child_pid == -1 )
@@ -872,7 +869,7 @@ attach_debugger( bool break_or_continue )
if( child_pid != 0 ) { // parent process - here we will start the debugger
dbg_startup_info dsi;
-
+
process_info pi( child_pid );
if( pi.binary_path().is_empty() )
::exit( -1 );
@@ -882,7 +879,7 @@ attach_debugger( bool break_or_continue )
dsi.binary_path = pi.binary_path();
dsi.display = ::getenv( "DISPLAY" );
dsi.init_done_lock = init_done_lock_fn;
-
+
dbg_starter starter = s_info.m_dbg_starter_reg[s_info.p_dbg];
if( !!starter )
starter( dsi );
@@ -922,7 +919,7 @@ attach_debugger( bool break_or_continue )
// ************************************************************************** //
void
-detect_memory_leaks( bool on_off )
+detect_memory_leaks( bool on_off, unit_test::const_string report_file )
{
unit_test::ut_detail::ignore_unused_variable_warning( on_off );
@@ -934,10 +931,19 @@ detect_memory_leaks( bool on_off )
else {
flags |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
- _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
+
+ if( report_file.is_empty() )
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ else {
+ HANDLE hreport_f = ::CreateFileA( report_file.begin(),
+ GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ _CrtSetReportFile(_CRT_WARN, hreport_f );
+ }
}
_CrtSetDbgFlag ( flags );
+#else
+ unit_test::ut_detail::ignore_unused_variable_warning( report_file );
#endif // BOOST_MS_CRT_BASED_DEBUG
}
@@ -954,16 +960,17 @@ break_memory_alloc( long mem_alloc_order_num )
unit_test::ut_detail::ignore_unused_variable_warning( mem_alloc_order_num );
#ifdef BOOST_MS_CRT_BASED_DEBUG
- _CrtSetBreakAlloc( mem_alloc_order_num );
+ // only set the value if one was supplied (do not use default used by UTF just as a indicator to enable leak detection)
+ if( mem_alloc_order_num > 1 )
+ _CrtSetBreakAlloc( mem_alloc_order_num );
#endif // BOOST_MS_CRT_BASED_DEBUG
}
-} // namespace debug
+//____________________________________________________________________________//
+} // namespace debug
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DEBUG_API_IPP_112006GER
diff --git a/boost/test/impl/decorator.ipp b/boost/test/impl/decorator.ipp
new file mode 100644
index 0000000000..bf17907881
--- /dev/null
+++ b/boost/test/impl/decorator.ipp
@@ -0,0 +1,202 @@
+// (C) Copyright Gennadiy Rozental 2011-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+// File : $RCSfile$
+//
+// Version : $Revision$
+//
+// Description : unit test decorators implementation
+// ***************************************************************************
+
+#ifndef BOOST_TEST_TREE_DECORATOR_IPP_091911GER
+#define BOOST_TEST_TREE_DECORATOR_IPP_091911GER
+
+// Boost.Test
+#include <boost/test/tree/decorator.hpp>
+#include <boost/test/tree/test_unit.hpp>
+
+#include <boost/test/framework.hpp>
+#if BOOST_TEST_SUPPORT_TOKEN_ITERATOR
+#include <boost/test/utils/iterator/token_iterator.hpp>
+#endif
+
+#include <boost/test/detail/throw_exception.hpp>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+namespace decorator {
+
+// ************************************************************************** //
+// ************** decorator::collector ************** //
+// ************************************************************************** //
+
+collector&
+collector::operator*( base const& d )
+{
+ m_tu_decorators.push_back( d.clone() );
+
+ return *this;
+}
+
+//____________________________________________________________________________//
+
+void
+collector::store_in( test_unit& tu )
+{
+ tu.p_decorators.value.insert( tu.p_decorators.value.end(), m_tu_decorators.begin(), m_tu_decorators.end() );
+}
+
+//____________________________________________________________________________//
+
+void
+collector::reset()
+{
+ m_tu_decorators.clear();
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::base ************** //
+// ************************************************************************** //
+
+collector&
+base::operator*() const
+{
+ return collector::instance() * *this;
+}
+
+// ************************************************************************** //
+// ************** decorator::label ************** //
+// ************************************************************************** //
+
+void
+label::apply( test_unit& tu )
+{
+ tu.add_label( m_label );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::expected_failures ************** //
+// ************************************************************************** //
+
+void
+expected_failures::apply( test_unit& tu )
+{
+ tu.increase_exp_fail( m_exp_fail );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::timeout ************** //
+// ************************************************************************** //
+
+void
+timeout::apply( test_unit& tu )
+{
+ tu.p_timeout.value = m_timeout;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::description ************** //
+// ************************************************************************** //
+
+void
+description::apply( test_unit& tu )
+{
+ tu.p_description.value += m_description;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::depends_on ************** //
+// ************************************************************************** //
+
+void
+depends_on::apply( test_unit& tu )
+{
+#if !BOOST_TEST_SUPPORT_TOKEN_ITERATOR
+ BOOST_TEST_SETUP_ASSERT( false, "depends_on decorator is not supported on this platform" );
+#else
+ string_token_iterator tit( m_dependency, (dropped_delimeters = "/", kept_delimeters = dt_none) );
+
+ test_unit* dep = &framework::master_test_suite();
+ while( tit != string_token_iterator() ) {
+ BOOST_TEST_SETUP_ASSERT( dep->p_type == TUT_SUITE, std::string( "incorrect dependency specification " ) + m_dependency );
+
+ test_unit_id next_id = static_cast<test_suite*>(dep)->get( *tit );
+
+ BOOST_TEST_SETUP_ASSERT( next_id != INV_TEST_UNIT_ID,
+ std::string( "incorrect dependency specification " ) + m_dependency );
+
+ dep = &framework::get( next_id, TUT_ANY );
+ ++tit;
+ }
+
+ tu.depends_on( dep );
+#endif
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::enable_if/enabled/disabled ************** //
+// ************************************************************************** //
+
+void
+enable_if_impl::apply_impl( test_unit& tu, bool condition )
+{
+ BOOST_TEST_SETUP_ASSERT(tu.p_default_status == test_unit::RS_INHERIT,
+ "Can't apply multiple enabled/disabled decorators "
+ "to the same test unit " + tu.full_name());
+
+ tu.p_default_status.value = condition ? test_unit::RS_ENABLED : test_unit::RS_DISABLED;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::fixture ************** //
+// ************************************************************************** //
+
+void
+fixture_t::apply( test_unit& tu )
+{
+ tu.p_fixtures.value.push_back( m_impl );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** decorator::depends_on ************** //
+// ************************************************************************** //
+
+void
+precondition::apply( test_unit& tu )
+{
+ tu.add_precondition( m_precondition );
+}
+
+//____________________________________________________________________________//
+
+} // namespace decorator
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_TREE_DECORATOR_IPP_091911GER
diff --git a/boost/test/impl/exception_safety.ipp b/boost/test/impl/exception_safety.ipp
deleted file mode 100644
index 7f0afcb457..0000000000
--- a/boost/test/impl/exception_safety.ipp
+++ /dev/null
@@ -1,537 +0,0 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
-// Use, modification, and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/test for the library home page.
-//
-// File : $RCSfile$
-//
-// Version : $Revision$
-//
-// Description : Facilities to perform exception safety tests
-// ***************************************************************************
-
-#ifndef BOOST_TEST_EXECUTION_SAFETY_IPP_112005GER
-#define BOOST_TEST_EXECUTION_SAFETY_IPP_112005GER
-
-// Boost.Test
-#include <boost/test/detail/config.hpp>
-
-#if BOOST_TEST_SUPPORT_INTERACTION_TESTING
-
-#include <boost/test/detail/global_typedef.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
-
-#include <boost/test/utils/callback.hpp>
-#include <boost/test/utils/wrap_stringstream.hpp>
-#include <boost/test/utils/iterator/token_iterator.hpp>
-
-#include <boost/test/interaction_based.hpp>
-#include <boost/test/test_tools.hpp>
-#include <boost/test/unit_test_log.hpp>
-#include <boost/test/framework.hpp>
-#include <boost/test/test_observer.hpp>
-#include <boost/test/debug.hpp>
-
-#include <boost/test/detail/suppress_warnings.hpp>
-
-// Boost
-#include <boost/lexical_cast.hpp>
-
-// STL
-#include <vector>
-#include <cstdlib>
-#include <map>
-#include <iomanip>
-#include <cctype>
-#include <boost/limits.hpp>
-
-//____________________________________________________________________________//
-
-namespace boost {
-
-using namespace ::boost::unit_test;
-
-namespace itest {
-
-// ************************************************************************** //
-// ************** execution_path_point ************** //
-// ************************************************************************** //
-
-enum exec_path_point_type { EPP_SCOPE, EPP_EXCEPT, EPP_DECISION, EPP_ALLOC };
-
-struct execution_path_point {
- execution_path_point( exec_path_point_type t, const_string file, std::size_t line_num )
- : m_type( t )
- , m_file_name( file )
- , m_line_num( line_num )
- {}
-
- exec_path_point_type m_type;
- const_string m_file_name;
- std::size_t m_line_num;
-
- // Execution path point specific
- struct decision_data {
- bool value;
- unsigned forced_exception_point;
- };
- struct scope_data {
- unsigned size;
- char const* name;
- };
- struct except_data {
- char const* description;
- };
- struct alloc_data {
- void* ptr;
- std::size_t size;
- };
-
- union {
- struct decision_data m_decision;
- struct scope_data m_scope;
- struct except_data m_except;
- struct alloc_data m_alloc;
- };
-};
-
-// ************************************************************************** //
-// ************** exception safety test implementation ************** //
-// ************************************************************************** //
-
-struct exception_safety_tester : itest::manager, test_observer {
- // helpers types
- struct unique_exception {};
-
- // Constructor
- explicit exception_safety_tester( const_string test_name );
- ~exception_safety_tester();
-
- // check last run and prepare for next
- bool next_execution_path();
-
- // memory tracking
-
- // manager interface implementation
- virtual void exception_point( const_string file, std::size_t line_num, const_string description );
- virtual bool decision_point( const_string file, std::size_t line_num );
- virtual unsigned enter_scope( const_string file, std::size_t line_num, const_string scope_name );
- virtual void leave_scope( unsigned enter_scope_point );
- virtual void allocated( const_string file, std::size_t line_num, void* p, std::size_t s );
- virtual void freed( void* p );
-
- // test observer interface
- virtual void assertion_result( bool passed );
- virtual int priority() { return (std::numeric_limits<int>::max)(); } // we want this observer to run the last
-
-private:
- void failure_point();
- void report_error();
-
- typedef std::vector<execution_path_point> exec_path;
- typedef std::map<void*,unsigned> registry;
-
- // Data members
- bool m_internal_activity;
-
- unsigned m_exception_point_counter;
- unsigned m_forced_exception_point;
-
- unsigned m_exec_path_point;
- exec_path m_execution_path;
-
- unsigned m_exec_path_counter;
- unsigned m_break_exec_path;
-
- bool m_invairant_failed;
- registry m_memory_in_use;
-};
-
-//____________________________________________________________________________//
-
-struct activity_guard {
- bool& m_v;
-
- activity_guard( bool& v ) : m_v( v ) { m_v = true; }
- ~activity_guard() { m_v = false; }
-};
-
-//____________________________________________________________________________//
-
-exception_safety_tester::exception_safety_tester( const_string test_name )
-: m_internal_activity( true )
-, m_exception_point_counter( 0 )
-, m_forced_exception_point( 1 )
-, m_exec_path_point( 0 )
-, m_exec_path_counter( 1 )
-, m_break_exec_path( static_cast<unsigned>(-1) )
-, m_invairant_failed( false )
-{
- framework::register_observer( *this );
-
- if( !runtime_config::break_exec_path().is_empty() ) {
- using namespace unit_test;
-
- string_token_iterator tit( runtime_config::break_exec_path(),
- (dropped_delimeters = ":",kept_delimeters = " ") );
-
- const_string test_to_break = *tit;
-
- if( test_to_break == test_name ) {
- ++tit;
-
- m_break_exec_path = lexical_cast<unsigned>( *tit );
- }
- }
-
- m_internal_activity = false;
-}
-
-//____________________________________________________________________________//
-
-exception_safety_tester::~exception_safety_tester()
-{
- m_internal_activity = true;
-
- framework::deregister_observer( *this );
-}
-
-//____________________________________________________________________________//
-
-bool
-exception_safety_tester::next_execution_path()
-{
- activity_guard ag( m_internal_activity );
-
- // check memory usage
- if( m_execution_path.size() > 0 ) {
- bool errors_detected = m_invairant_failed || (m_memory_in_use.size() != 0);
- framework::assertion_result( !errors_detected );
-
- if( errors_detected )
- report_error();
-
- m_memory_in_use.clear();
- }
-
- m_exec_path_point = 0;
- m_exception_point_counter = 0;
- m_invairant_failed = false;
- ++m_exec_path_counter;
-
- while( m_execution_path.size() > 0 ) {
- switch( m_execution_path.back().m_type ) {
- case EPP_SCOPE:
- case EPP_ALLOC:
- m_execution_path.pop_back();
- break;
-
- case EPP_DECISION:
- if( !m_execution_path.back().m_decision.value ) {
- m_execution_path.pop_back();
- break;
- }
-
- m_execution_path.back().m_decision.value = false;
- m_forced_exception_point = m_execution_path.back().m_decision.forced_exception_point;
- return true;
-
- case EPP_EXCEPT:
- m_execution_path.pop_back();
- ++m_forced_exception_point;
- return true;
- }
- }
-
- BOOST_TEST_MESSAGE( "Total tested " << --m_exec_path_counter << " execution path" );
-
- return false;
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::exception_point( const_string file, std::size_t line_num, const_string description )
-{
- activity_guard ag( m_internal_activity );
-
- if( ++m_exception_point_counter == m_forced_exception_point ) {
- m_execution_path.push_back(
- execution_path_point( EPP_EXCEPT, file, line_num ) );
-
- m_execution_path.back().m_except.description = description.begin();
-
- ++m_exec_path_point;
-
- failure_point();
- }
-}
-
-//____________________________________________________________________________//
-
-bool
-exception_safety_tester::decision_point( const_string file, std::size_t line_num )
-{
- activity_guard ag( m_internal_activity );
-
- if( m_exec_path_point < m_execution_path.size() ) {
- BOOST_REQUIRE_MESSAGE( m_execution_path[m_exec_path_point].m_type == EPP_DECISION &&
- m_execution_path[m_exec_path_point].m_file_name == file &&
- m_execution_path[m_exec_path_point].m_line_num == line_num,
- "Function under test exibit non-deterministic behavior" );
- }
- else {
- m_execution_path.push_back(
- execution_path_point( EPP_DECISION, file, line_num ) );
-
- m_execution_path.back().m_decision.value = true;
- m_execution_path.back().m_decision.forced_exception_point = m_forced_exception_point;
- }
-
- return m_execution_path[m_exec_path_point++].m_decision.value;
-}
-
-//____________________________________________________________________________//
-
-unsigned
-exception_safety_tester::enter_scope( const_string file, std::size_t line_num, const_string scope_name )
-{
- activity_guard ag( m_internal_activity );
-
- if( m_exec_path_point < m_execution_path.size() ) {
- BOOST_REQUIRE_MESSAGE( m_execution_path[m_exec_path_point].m_type == EPP_SCOPE &&
- m_execution_path[m_exec_path_point].m_file_name == file &&
- m_execution_path[m_exec_path_point].m_line_num == line_num,
- "Function under test exibit non-deterministic behavior" );
- }
- else {
- m_execution_path.push_back(
- execution_path_point( EPP_SCOPE, file, line_num ) );
- }
-
- m_execution_path[m_exec_path_point].m_scope.size = 0;
- m_execution_path[m_exec_path_point].m_scope.name = scope_name.begin();
-
- return m_exec_path_point++;
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::leave_scope( unsigned enter_scope_point )
-{
- activity_guard ag( m_internal_activity );
-
- BOOST_REQUIRE_MESSAGE( m_execution_path[enter_scope_point].m_type == EPP_SCOPE,
- "Function under test exibit non-deterministic behavior" );
-
- m_execution_path[enter_scope_point].m_scope.size = m_exec_path_point - enter_scope_point;
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::allocated( const_string file, std::size_t line_num, void* p, std::size_t s )
-{
- if( m_internal_activity )
- return;
-
- activity_guard ag( m_internal_activity );
-
- if( m_exec_path_point < m_execution_path.size() )
- BOOST_REQUIRE_MESSAGE( m_execution_path[m_exec_path_point].m_type == EPP_ALLOC,
- "Function under test exibit non-deterministic behavior" );
- else
- m_execution_path.push_back(
- execution_path_point( EPP_ALLOC, file, line_num ) );
-
- m_execution_path[m_exec_path_point].m_alloc.ptr = p;
- m_execution_path[m_exec_path_point].m_alloc.size = s;
-
- m_memory_in_use.insert( std::make_pair( p, m_exec_path_point++ ) );
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::freed( void* p )
-{
- if( m_internal_activity )
- return;
-
- activity_guard ag( m_internal_activity );
-
- registry::iterator it = m_memory_in_use.find( p );
- if( it != m_memory_in_use.end() ) {
- m_execution_path[it->second].m_alloc.ptr = 0;
- m_memory_in_use.erase( it );
- }
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::assertion_result( bool passed )
-{
- if( !m_internal_activity && !passed ) {
- m_invairant_failed = true;
-
- failure_point();
- }
-}
-
-//____________________________________________________________________________//
-
-void
-exception_safety_tester::failure_point()
-{
- if( m_exec_path_counter == m_break_exec_path )
- debug::debugger_break();
-
- throw unique_exception();
-}
-
-//____________________________________________________________________________//
-
-namespace {
-
-inline void
-format_location( wrap_stringstream& formatter, execution_path_point const& /*p*/, unsigned indent )
-{
- if( indent )
- formatter << std::left << std::setw( indent ) << "";
-
-// !! ?? optional if( p.m_file_name )
-// formatter << p.m_file_name << '(' << p.m_line_num << "): ";
-}
-
-//____________________________________________________________________________//
-
-template<typename ExecPathIt>
-inline void
-format_execution_path( wrap_stringstream& formatter, ExecPathIt it, ExecPathIt end, unsigned indent = 0 )
-{
- while( it != end ) {
- switch( it->m_type ) {
- case EPP_SCOPE:
- format_location( formatter, *it, indent );
- formatter << "> \"" << it->m_scope.name << "\"\n";
- format_execution_path( formatter, it+1, it + it->m_scope.size, indent + 2 );
- format_location( formatter, *it, indent );
- formatter << "< \"" << it->m_scope.name << "\"\n";
- it += it->m_scope.size;
- break;
-
- case EPP_DECISION:
- format_location( formatter, *it, indent );
- formatter << "Decision made as " << std::boolalpha << it->m_decision.value << '\n';
- ++it;
- break;
-
- case EPP_EXCEPT:
- format_location( formatter, *it, indent );
- formatter << "Forced failure";
- if( it->m_except.description )
- formatter << ": " << it->m_except.description;
- formatter << "\n";
- ++it;
- break;
-
- case EPP_ALLOC:
- if( it->m_alloc.ptr ) {
- format_location( formatter, *it, indent );
- formatter << "Allocated memory block 0x" << std::uppercase << it->m_alloc.ptr
- << ", " << it->m_alloc.size << " bytes long: <";
-
- unsigned i;
- for( i = 0; i < std::min<std::size_t>( it->m_alloc.size, 8 ); i++ ) {
- unsigned char c = static_cast<unsigned char*>(it->m_alloc.ptr)[i];
- if( (std::isprint)( c ) )
- formatter << c;
- else
- formatter << '.';
- }
-
- formatter << "> ";
-
- for( i = 0; i < std::min<std::size_t>( it->m_alloc.size, 8 ); i++ ) {
- unsigned c = static_cast<unsigned char*>(it->m_alloc.ptr)[i];
- formatter << std::hex << std::uppercase << c << ' ';
- }
-
- formatter << "\n";
- }
- ++it;
- break;
- }
- }
-}
-
-//____________________________________________________________________________//
-
-} // local namespace
-
-void
-exception_safety_tester::report_error()
-{
- activity_guard ag( m_internal_activity );
-
- unit_test_log << unit_test::log::begin( m_execution_path.back().m_file_name,
- m_execution_path.back().m_line_num )
- << log_all_errors;
-
- wrap_stringstream formatter;
-
- if( m_invairant_failed )
- formatter << "Failed invariant";
-
- if( m_memory_in_use.size() != 0 ) {
- if( m_invairant_failed )
- formatter << " and ";
-
- formatter << static_cast<unsigned int>(m_memory_in_use.size()) << " memory leak";
- if( m_memory_in_use.size() > 1 )
- formatter << 's';
- }
- formatter << " detected in the execution path " << m_exec_path_counter << ":\n";
-
- format_execution_path( formatter, m_execution_path.begin(), m_execution_path.end() );
-
- unit_test_log << const_string( formatter.str() ) << unit_test::log::end();
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** exception safety test ************** //
-// ************************************************************************** //
-
-void BOOST_TEST_DECL
-exception_safety( callback0<> const& F, const_string test_name )
-{
- exception_safety_tester est( test_name );
-
- do {
- try {
- F();
- }
- catch( exception_safety_tester::unique_exception const& ) {}
-
- } while( est.next_execution_path() );
-}
-
-//____________________________________________________________________________//
-
-} // namespace itest
-
-} // namespace boost
-
-//____________________________________________________________________________//
-
-#include <boost/test/detail/enable_warnings.hpp>
-
-#endif // non-ancient compiler
-
-#endif // BOOST_TEST_EXECUTION_SAFETY_IPP_112005GER
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index 07484b19d9..9929f74b53 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Gennadiy Rozental 2001-2014.
// (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
// Use, modification, and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -27,14 +27,18 @@
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/workaround.hpp>
+#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/debug.hpp>
// Boost
#include <boost/cstdlib.hpp> // for exit codes
#include <boost/config.hpp> // for workarounds
+#include <boost/core/ignore_unused.hpp> // for ignore_unused
+#ifndef BOOST_NO_EXCEPTION
#include <boost/exception/get_error_info.hpp> // for get_error_info
#include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
+#endif
// STL
#include <string> // for std::string
@@ -48,6 +52,8 @@
#include <cstdio> // for vsnprintf
#include <cstdarg> // for varargs
+#include <iostream> // for varargs
+
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strerror; using ::strlen; using ::strncat; }
#endif
@@ -59,17 +65,12 @@ namespace std { using ::strerror; using ::strlen; using ::strncat; }
using std::va_list;
#endif
-// to use vsnprintf
-#if defined(__QNXNTO__)
-# include <stdio.h>
+// to use vsnprintf
+#if defined(__QNXNTO__)
+# include <stdio.h>
#endif
-#if defined(_WIN32) && !defined(BOOST_DISABLE_WIN32) && \
- (!defined(__COMO__) && !defined(__MWERKS__) && !defined(__GNUC__) || \
- BOOST_WORKAROUND(__MWERKS__, >= 0x3000))
-
-# define BOOST_SEH_BASED_SIGNAL_HANDLING
-
+#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
# include <windows.h>
# if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
@@ -84,37 +85,12 @@ using std::va_list;
typedef unsigned uintptr_t;
# endif
-# if BOOST_WORKAROUND(_MSC_VER, < 1300 ) || defined(UNDER_CE)
-typedef void* uintptr_t;
+# if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER, < 1500 )
+ typedef void* uintptr_t;
+# elif defined(UNDER_CE)
+# include <crtdefs.h>
# endif
-// for the FP control routines
-#include <float.h>
-
-#ifndef EM_INVALID
-#define EM_INVALID _EM_INVALID
-#endif
-
-#ifndef EM_DENORMAL
-#define EM_DENORMAL _EM_DENORMAL
-#endif
-
-#ifndef EM_ZERODIVIDE
-#define EM_ZERODIVIDE _EM_ZERODIVIDE
-#endif
-
-#ifndef EM_OVERFLOW
-#define EM_OVERFLOW _EM_OVERFLOW
-#endif
-
-#ifndef EM_UNDERFLOW
-#define EM_UNDERFLOW _EM_UNDERFLOW
-#endif
-
-#ifndef MCW_EM
-#define MCW_EM _MCW_EM
-#endif
-
# if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
# include <crtdbg.h>
# define BOOST_TEST_CRT_HOOK_TYPE _CRT_REPORT_HOOK
@@ -128,7 +104,8 @@ typedef void* uintptr_t;
# define BOOST_TEST_CRT_SET_HOOK(H) (void*)(H)
# endif
-# if !BOOST_WORKAROUND(_MSC_VER, >= 1400 ) || defined(UNDER_CE)
+# if (!BOOST_WORKAROUND(_MSC_VER, >= 1400 ) && \
+ !defined(BOOST_COMO)) || defined(UNDER_CE)
typedef void* _invalid_parameter_handler;
@@ -154,7 +131,9 @@ namespace { void _set_se_translator( void* ) {} }
# include <signal.h>
# include <setjmp.h>
-# if defined(__FreeBSD__)
+# if defined(__FreeBSD__)
+
+# include <osreldate.h>
# ifndef SIGPOLL
# define SIGPOLL SIGIO
@@ -168,13 +147,17 @@ namespace { void _set_se_translator( void* ) {} }
# define ILL_COPROC ILL_FPOP_FAULT
# define BOOST_TEST_LIMITED_SIGNAL_DETAILS
-# define BOOST_TEST_IGNORE_SIGCHLD
-# endif
-# endif
+# endif
+# endif
+
+# if defined(__ANDROID__)
+# include <android/api-level.h>
+# endif
-# if !defined(__CYGWIN__) && !defined(__QNXNTO__)
-# define BOOST_TEST_USE_ALT_STACK
+# if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
+ (!defined(__ANDROID__) || __ANDROID_API__ >= 8)
+# define BOOST_TEST_USE_ALT_STACK
# endif
# if defined(SIGPOLL) && !defined(__CYGWIN__) && \
@@ -188,6 +171,7 @@ namespace { void _set_se_translator( void* ) {} }
# define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
# endif
+
#else
# define BOOST_NO_SIGNAL_HANDLING
@@ -198,6 +182,10 @@ namespace { void _set_se_translator( void* ) {} }
#include <errno.h>
#endif
+#if defined(__GNUC__) && !defined(BOOST_NO_TYPEID)
+# include <cxxabi.h>
+#endif
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -205,6 +193,14 @@ namespace { void _set_se_translator( void* ) {} }
namespace boost {
// ************************************************************************** //
+// ************** throw_exception ************** //
+// ************************************************************************** //
+
+#ifdef BOOST_NO_EXCEPTION
+void throw_exception( std::exception const & e ) { abort(); }
+#endif
+
+// ************************************************************************** //
// ************** report_error ************** //
// ************************************************************************** //
@@ -220,6 +216,8 @@ namespace detail {
# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
#endif
+#ifndef BOOST_NO_EXCEPTION
+
template <typename ErrorInfo>
typename ErrorInfo::value_type
extract( boost::exception const* ex )
@@ -237,39 +235,41 @@ extract( boost::exception const* ex )
static void
report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
{
- static const int REPORT_ERROR_BUFFER_SIZE = 512;
+ static const int REPORT_ERROR_BUFFER_SIZE = 4096;
static char buf[REPORT_ERROR_BUFFER_SIZE];
- BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
+ BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
buf[sizeof(buf)-1] = 0;
va_end( *args );
- throw execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
- extract<throw_line>( be ),
+ throw execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
+ (size_t)extract<throw_line>( be ),
extract<throw_function>( be ) ) );
}
//____________________________________________________________________________//
static void
-report_error( execution_exception::error_code ec, char const* format, ... )
+report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
{
va_list args;
va_start( args, format );
- report_error( ec, 0, format, &args );
+ report_error( ec, be, format, &args );
}
+#endif
+
//____________________________________________________________________________//
static void
-report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
+report_error( execution_exception::error_code ec, char const* format, ... )
{
va_list args;
va_start( args, format );
- report_error( ec, be, format, &args );
+ report_error( ec, 0, format, &args );
}
//____________________________________________________________________________//
@@ -283,6 +283,47 @@ do_invoke( Tr const& tr, Functor const& F )
//____________________________________________________________________________//
+struct fpe_except_guard {
+ explicit fpe_except_guard( unsigned detect_fpe )
+ : m_detect_fpe( detect_fpe )
+ {
+ // prepare fp exceptions control
+ m_previosly_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
+ if( m_previosly_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
+ fpe::enable( detect_fpe );
+ }
+ ~fpe_except_guard()
+ {
+ if( m_detect_fpe != fpe::BOOST_FPE_OFF )
+ fpe::disable( m_detect_fpe );
+ if( m_previosly_enabled != fpe::BOOST_FPE_INV )
+ fpe::enable( m_previosly_enabled );
+ }
+
+ unsigned m_detect_fpe;
+ unsigned m_previosly_enabled;
+};
+
+#ifndef BOOST_NO_TYPEID
+
+// ************************************************************************** //
+// ************** typeid_name ************** //
+// ************************************************************************** //
+
+template<typename T>
+char const*
+typeid_name( T const& t )
+{
+#ifdef __GNUC__
+ int status;
+
+ return abi::__cxa_demangle( typeid(t).name(), 0, 0, &status );
+#else
+ return typeid(t).name();
+#endif
+}
+#endif
+
} // namespace detail
#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
@@ -398,10 +439,10 @@ system_signal_exception::report() const
"signal: co-processor error; address of failing instruction: 0x%08lx",
m_sig_info->si_addr );
break;
- default:
- report_error( execution_exception::system_fatal_error,
- "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
- m_sig_info->si_addr, m_sig_info->si_code );
+ default:
+ report_error( execution_exception::system_fatal_error,
+ "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
+ m_sig_info->si_addr, m_sig_info->si_code );
break;
}
break;
@@ -505,48 +546,6 @@ system_signal_exception::report() const
}
break;
- case SIGCHLD:
- switch( m_sig_info->si_code ) {
-#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
- case CLD_EXITED:
- report_error( execution_exception::system_error,
- "child has exited; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
- case CLD_KILLED:
- report_error( execution_exception::system_error,
- "child was killed; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
- case CLD_DUMPED:
- report_error( execution_exception::system_error,
- "child terminated abnormally; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
- case CLD_TRAPPED:
- report_error( execution_exception::system_error,
- "traced child has trapped; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
- case CLD_STOPPED:
- report_error( execution_exception::system_error,
- "child has stopped; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
- case CLD_CONTINUED:
- report_error( execution_exception::system_error,
- "stopped child had continued; pid: %d; uid: %d; exit value: %d",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
- break;
-#endif
- default:
- report_error( execution_exception::system_error,
- "signal: SIGCHLD, si_code: %d (child process has terminated; pid: %d; uid: %d; exit value: %d)",
- (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status, m_sig_info->si_code );
- break;
- }
- break;
-
#if defined(BOOST_TEST_CATCH_SIGPOLL)
case SIGPOLL:
@@ -585,11 +584,11 @@ system_signal_exception::report() const
break;
#endif
#endif
- default:
- report_error( execution_exception::system_error,
- "signal: SIGPOLL, si_code: %d (asynchronous I/O event occured; band event %d)",
- (int)m_sig_info->si_band, m_sig_info->si_code );
- break;
+ default:
+ report_error( execution_exception::system_error,
+ "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
+ (int)m_sig_info->si_band, m_sig_info->si_code );
+ break;
}
break;
@@ -606,7 +605,8 @@ system_signal_exception::report() const
break;
default:
- report_error( execution_exception::system_error, "unrecognized signal" );
+ report_error( execution_exception::system_error,
+ "unrecognized signal %d", m_sig_info->si_signo );
}
}
@@ -618,8 +618,8 @@ system_signal_exception::report() const
// Forward declaration
extern "C" {
-static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
-static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
+static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
+static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
}
class signal_action {
@@ -663,8 +663,8 @@ signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_
}
m_new_action.sa_flags |= SA_SIGINFO;
- m_new_action.sa_sigaction = attach_dbg ? &execution_monitor_attaching_signal_handler
- : &execution_monitor_jumping_signal_handler;
+ m_new_action.sa_sigaction = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
+ : &boost_execution_monitor_jumping_signal_handler;
BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
#ifdef BOOST_TEST_USE_ALT_STACK
@@ -692,7 +692,7 @@ signal_action::~signal_action()
class signal_handler {
public:
// Constructor
- explicit signal_handler( bool catch_system_errors, int timeout, bool attach_dbg, char* alt_stack );
+ explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack );
// Destructor
~signal_handler();
@@ -715,8 +715,9 @@ public:
private:
// Data members
signal_handler* m_prev_handler;
- int m_timeout;
+ unsigned m_timeout;
+ // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
signal_action m_ILL_action;
signal_action m_FPE_action;
signal_action m_SEGV_action;
@@ -738,16 +739,13 @@ signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
//____________________________________________________________________________//
-signal_handler::signal_handler( bool catch_system_errors, int timeout, bool attach_dbg, char* alt_stack )
+signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack )
: m_prev_handler( s_active_handler )
, m_timeout( timeout )
, m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
-, m_FPE_action ( SIGFPE , catch_system_errors, attach_dbg, alt_stack )
+, m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
, m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
, m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
-#ifndef BOOST_TEST_IGNORE_SIGCHLD
-, m_CHLD_action( SIGCHLD, catch_system_errors, attach_dbg, alt_stack )
-#endif
#ifdef BOOST_TEST_CATCH_SIGPOLL
, m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
#endif
@@ -799,7 +797,12 @@ signal_handler::~signal_handler()
sigstk.ss_size = MINSIGSTKSZ;
sigstk.ss_flags = SS_DISABLE;
- BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
+ if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
+ int error_n = errno;
+ std::cerr << "******** errors disabling the alternate stack:" << std::endl
+ << "\t#error:" << error_n << std::endl
+ << "\t" << std::strerror( error_n ) << std::endl;
+ }
#endif
s_active_handler = m_prev_handler;
@@ -813,26 +816,8 @@ signal_handler::~signal_handler()
extern "C" {
-static bool ignore_sigchild( siginfo_t* info )
-{
- return info->si_signo == SIGCHLD
-#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
- && info->si_code == CLD_EXITED
-#endif
-#ifdef BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE
- ;
-#else
- && (int)info->si_status == 0;
-#endif
-}
-
-//____________________________________________________________________________//
-
-static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
+static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
{
- if( ignore_sigchild( info ) )
- return;
-
signal_handler::sys_sig()( info, context );
siglongjmp( signal_handler::jump_buffer(), sig );
@@ -840,13 +825,10 @@ static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info,
//____________________________________________________________________________//
-static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
+static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
{
- if( ignore_sigchild( info ) )
- return;
-
if( !debug::attach_debugger( false ) )
- execution_monitor_jumping_signal_handler( sig, info, context );
+ boost_execution_monitor_jumping_signal_handler( sig, info, context );
// debugger attached; it will handle the signal
BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
@@ -863,7 +845,7 @@ static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info
// ************************************************************************** //
int
-execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+execution_monitor::catch_signals( boost::function<int ()> const& F )
{
using namespace detail;
@@ -878,13 +860,16 @@ execution_monitor::catch_signals( unit_test::callback0<int> const& F )
p_use_alt_stack.value = false;
#endif
- signal_handler local_signal_handler( p_catch_system_errors, p_timeout, p_auto_start_dbg,
+ signal_handler local_signal_handler( p_catch_system_errors,
+ p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
+ p_timeout,
+ p_auto_start_dbg,
!p_use_alt_stack ? 0 : m_alt_stack.get() );
if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
return detail::do_invoke( m_custom_translators , F );
else
- throw local_signal_handler.sys_sig();
+ return BOOST_TEST_IMPL_THROW( local_signal_handler.sys_sig() );
}
//____________________________________________________________________________//
@@ -916,37 +901,64 @@ public:
{}
void report() const;
- int operator()( unsigned int id, _EXCEPTION_POINTERS* exps );
+ int operator()( unsigned id, _EXCEPTION_POINTERS* exps );
private:
// Data members
execution_monitor* m_em;
- unsigned int m_se_id;
+ unsigned m_se_id;
void* m_fault_address;
bool m_dir;
};
+//____________________________________________________________________________//
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
static void
-seh_catch_preventer( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ )
+seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
{
throw;
}
+#endif
//____________________________________________________________________________//
int
-system_signal_exception::operator()( unsigned int id, _EXCEPTION_POINTERS* exps )
+system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
{
- const unsigned int MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
+ const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
- if( !m_em->p_catch_system_errors || (id == MSFT_CPP_EXCEPT) )
+ // C++ exception - allow to go through
+ if( id == MSFT_CPP_EXCEPT )
return EXCEPTION_CONTINUE_SEARCH;
+ // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
+ if( !m_em->p_catch_system_errors ) {
+ if( !m_em->p_detect_fp_exceptions )
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ switch( id ) {
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_STACK_CHECK:
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_UNDERFLOW:
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ case STATUS_FLOAT_MULTIPLE_FAULTS:
+ case STATUS_FLOAT_MULTIPLE_TRAPS:
+ break;
+ default:
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ }
+
if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
m_em->p_catch_system_errors.value = false;
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
_set_se_translator( &seh_catch_preventer );
-
+#endif
return EXCEPTION_CONTINUE_EXECUTION;
}
@@ -1031,12 +1043,10 @@ system_signal_exception::report() const
"operand of floating point operation is denormal" );
break;
-# if 0 // !! ??
case EXCEPTION_FLT_INEXACT_RESULT:
detail::report_error( execution_exception::system_error,
"result of a floating-point operation cannot be represented exactly" );
break;
-#endif
case EXCEPTION_FLT_OVERFLOW:
detail::report_error( execution_exception::system_error,
@@ -1052,6 +1062,14 @@ system_signal_exception::report() const
detail::report_error( execution_exception::system_error, "floating point error" );
break;
+ case STATUS_FLOAT_MULTIPLE_FAULTS:
+ detail::report_error( execution_exception::system_error, "multiple floating point errors" );
+ break;
+
+ case STATUS_FLOAT_MULTIPLE_TRAPS:
+ detail::report_error( execution_exception::system_error, "multiple floating point errors" );
+ break;
+
case EXCEPTION_BREAKPOINT:
detail::report_error( execution_exception::system_error, "breakpoint encountered" );
break;
@@ -1071,59 +1089,28 @@ system_signal_exception::report() const
int BOOST_TEST_CALL_DECL
assert_reporting_function( int reportType, char* userMessage, int* )
{
- switch( reportType ) {
- case BOOST_TEST_CRT_ASSERT:
- detail::report_error( execution_exception::user_error, userMessage );
+ // write this way instead of switch to avoid unreachable statements
+ if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
+ detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
- return 1; // return value and retVal are not important since we never reach this line
- case BOOST_TEST_CRT_ERROR:
- detail::report_error( execution_exception::system_error, userMessage );
-
- return 1; // return value and retVal are not important since we never reach this line
- default:
- return 0; // use usual reporting method
- }
+ return 0;
} // assert_reporting_function
//____________________________________________________________________________//
void BOOST_TEST_CALL_DECL
-invalid_param_handler( wchar_t const* /* expr */,
- wchar_t const* /* func */,
- wchar_t const* /* file */,
- unsigned int /* line */,
+invalid_param_handler( wchar_t const* /* expr */,
+ wchar_t const* /* func */,
+ wchar_t const* /* file */,
+ unsigned /* line */,
uintptr_t /* reserved */)
{
- detail::report_error( execution_exception::user_error,
+ detail::report_error( execution_exception::user_error,
"Invalid parameter detected by C runtime library" );
}
//____________________________________________________________________________//
-void BOOST_TEST_CALL_DECL
-switch_fp_exceptions( bool on_off )
-{
- if( !on_off )
- _clearfp();
-
- int cw = ::_controlfp( 0, 0 );
-
- int exceptions_mask = EM_INVALID|EM_DENORMAL|EM_ZERODIVIDE|EM_OVERFLOW|EM_UNDERFLOW;
-
- if( on_off )
- cw &= ~exceptions_mask; // Set the exception masks on, turn exceptions off
- else
- cw |= exceptions_mask; // Set the exception masks off, turn exceptions on
-
- if( on_off )
- _clearfp();
-
- // Set the control word
- ::_controlfp( cw, MCW_EM );
-}
-
-//____________________________________________________________________________//
-
} // namespace detail
// ************************************************************************** //
@@ -1131,25 +1118,24 @@ switch_fp_exceptions( bool on_off )
// ************************************************************************** //
int
-execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+execution_monitor::catch_signals( boost::function<int ()> const& F )
{
_invalid_parameter_handler old_iph = _invalid_parameter_handler();
BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
- if( !p_catch_system_errors )
- _set_se_translator( &detail::seh_catch_preventer );
- else {
- if( !!p_detect_fp_exceptions )
- detail::switch_fp_exceptions( true );
-
- old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
+ if( p_catch_system_errors ) {
+ old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
- old_iph = _set_invalid_parameter_handler(
- reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
+ old_iph = _set_invalid_parameter_handler(
+ reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
+ } else if( !p_detect_fp_exceptions ) {
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
+ _set_se_translator( &detail::seh_catch_preventer );
+#endif
}
detail::system_signal_exception SSE( this );
-
+
int ret_val = 0;
__try {
@@ -1161,10 +1147,7 @@ execution_monitor::catch_signals( unit_test::callback0<int> const& F )
}
}
__finally {
- if( !!p_catch_system_errors ) {
- if( !!p_detect_fp_exceptions )
- detail::switch_fp_exceptions( false );
-
+ if( p_catch_system_errors ) {
BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
_set_invalid_parameter_handler( old_iph );
@@ -1188,7 +1171,7 @@ public:
} // namespace detail
int
-execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+execution_monitor::catch_signals( boost::function<int ()> const& F )
{
return detail::do_invoke( m_custom_translators , F );
}
@@ -1198,19 +1181,34 @@ execution_monitor::catch_signals( unit_test::callback0<int> const& F )
#endif // choose signal handler
// ************************************************************************** //
-// ************** execution_monitor::execute ************** //
+// ************** execution_monitor ************** //
// ************************************************************************** //
+execution_monitor::execution_monitor()
+: p_catch_system_errors( true )
+, p_auto_start_dbg( false )
+, p_timeout( 0 )
+, p_use_alt_stack( true )
+, p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
+{}
+
+//____________________________________________________________________________//
+
int
-execution_monitor::execute( unit_test::callback0<int> const& F )
+execution_monitor::execute( boost::function<int ()> const& F )
{
if( debug::under_debugger() )
p_catch_system_errors.value = false;
- try {
+ BOOST_TEST_IMPL_TRY {
+ detail::fpe_except_guard G( p_detect_fp_exceptions );
+ unit_test::ut_detail::ignore_unused_variable_warning( G );
+
return catch_signals( F );
}
+#ifndef BOOST_NO_EXCEPTION
+
// Catch-clause reference arguments are a bit different from function
// arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't
// required. Programmers ask for const anyhow, so we supply it. That's
@@ -1220,89 +1218,61 @@ execution_monitor::execute( unit_test::callback0<int> const& F )
{ detail::report_error( execution_exception::cpp_exception_error,
"C string: %s", ex ); }
catch( std::string const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
+ { detail::report_error( execution_exception::cpp_exception_error,
"std::string: %s", ex.c_str() ); }
// std:: exceptions
+#ifdef BOOST_NO_TYPEID
+#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
+ catch( ex_name const& ex ) \
+ { detail::report_error( execution_exception::cpp_exception_error, \
+ current_exception_cast<boost::exception const>(), \
+ #ex_name ": %s", ex.what() ); } \
+/**/
+#else
+#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
+ catch( ex_name const& ex ) \
+ { detail::report_error( execution_exception::cpp_exception_error, \
+ current_exception_cast<boost::exception const>(), \
+ "%s: %s", detail::typeid_name(ex), ex.what() ); } \
+/**/
+#endif
- catch( std::bad_alloc const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_alloc: %s", ex.what() ); }
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
- catch( std::bad_cast const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_cast" ); }
- catch( std::bad_typeid const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_typeid" ); }
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
#else
- catch( std::bad_cast const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_cast: %s", ex.what() ); }
- catch( std::bad_typeid const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_typeid: %s", ex.what() ); }
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
#endif
- catch( std::bad_exception const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::bad_exception: %s", ex.what() ); }
- catch( std::domain_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::domain_error: %s", ex.what() ); }
- catch( std::invalid_argument const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::invalid_argument: %s", ex.what() ); }
- catch( std::length_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::length_error: %s", ex.what() ); }
- catch( std::out_of_range const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::out_of_range: %s", ex.what() ); }
- catch( std::range_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::range_error: %s", ex.what() ); }
- catch( std::overflow_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::overflow_error: %s", ex.what() ); }
- catch( std::underflow_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::underflow_error: %s", ex.what() ); }
- catch( std::logic_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::logic_error: %s", ex.what() ); }
- catch( std::runtime_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::runtime_error: %s", ex.what() ); }
- catch( std::exception const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- current_exception_cast<boost::exception const>(),
- "std::exception: %s", ex.what() ); }
+ CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
+ CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
+#undef CATCH_AND_REPORT_STD_EXCEPTION
catch( boost::exception const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
- &ex,
- "unknown boost::exception" ); }
+ { detail::report_error( execution_exception::cpp_exception_error,
+ &ex,
+#ifdef BOOST_NO_TYPEID
+ "unknown boost::exception" ); }
+#else
+ typeid(ex).name() ); }
+#endif
// system errors
catch( system_error const& ex )
- { detail::report_error( execution_exception::cpp_exception_error,
+ { detail::report_error( execution_exception::cpp_exception_error,
"system_error produced by: %s: %s", ex.p_failed_exp.get(), std::strerror( ex.p_errno ) ); }
catch( detail::system_signal_exception const& ex )
{ ex.report(); }
@@ -1319,11 +1289,30 @@ execution_monitor::execute( unit_test::callback0<int> const& F )
catch( ... )
{ detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
+#endif // !BOOST_NO_EXCEPTION
+
return 0; // never reached; supplied to quiet compiler warnings
} // execute
//____________________________________________________________________________//
+namespace detail {
+
+struct forward {
+ explicit forward( boost::function<void ()> const& F ) : m_F( F ) {}
+
+ int operator()() { m_F(); return 0; }
+
+ boost::function<void ()> const& m_F;
+};
+
+} // namespace detail
+void
+execution_monitor::vexecute( boost::function<void ()> const& F )
+{
+ execute( detail::forward( F ) );
+}
+
// ************************************************************************** //
// ************** system_error ************** //
// ************************************************************************** //
@@ -1359,6 +1348,88 @@ execution_exception::location::location( char const* file_name, size_t line_num,
//____________________________________________________________________________//
+// ************************************************************************** //
+// **************Floating point exception management interface ************** //
+// ************************************************************************** //
+
+namespace fpe {
+
+unsigned
+enable( unsigned mask )
+{
+ boost::ignore_unused(mask);
+
+#if defined(UNDER_CE)
+ /* Not Implemented in Windows CE */
+ return 0;
+#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
+ _clearfp();
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
+ unsigned old_cw = ::_controlfp( 0, 0 );
+ ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
+#else
+ unsigned old_cw;
+ if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
+ return BOOST_FPE_INV;
+
+ // Set the control word
+ if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
+ return BOOST_FPE_INV;
+#endif
+
+ return ~old_cw & BOOST_FPE_ALL;
+#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
+ ::feclearexcept(BOOST_FPE_ALL);
+ int res = ::feenableexcept( mask );
+ return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
+#else
+ /* Not Implemented */
+ return 0;
+#endif
+}
+
+//____________________________________________________________________________//
+
+unsigned
+disable( unsigned mask )
+{
+ boost::ignore_unused(mask);
+
+#if defined(UNDER_CE)
+ /* Not Implemented in Windows CE */
+ return 0;
+#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
+ _clearfp();
+
+#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
+ unsigned old_cw = ::_controlfp( 0, 0 );
+ ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
+#else
+ unsigned old_cw;
+ if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
+ return BOOST_FPE_INV;
+
+ // Set the control word
+ if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
+ return BOOST_FPE_INV;
+#endif
+
+ return ~old_cw & BOOST_FPE_ALL;
+#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
+ ::feclearexcept(BOOST_FPE_ALL);
+ int res = ::fedisableexcept( mask );
+ return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
+#else
+ /* Not Implemented */
+ return BOOST_FPE_INV;
+#endif
+}
+
+//____________________________________________________________________________//
+
+} // namespace fpe
+
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index a1e98b3771..a69d95cd2d 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,24 +19,36 @@
#include <boost/test/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/debug.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
+#include <boost/test/unit_test_parameters.hpp>
+
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_monitor.hpp>
-#include <boost/test/test_observer.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/progress_monitor.hpp>
#include <boost/test/results_reporter.hpp>
-#include <boost/test/test_tools.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
-#include <boost/test/detail/global_typedef.hpp>
+#include <boost/test/tree/observer.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/visitor.hpp>
+#include <boost/test/tree/traverse.hpp>
+#include <boost/test/tree/test_case_counter.hpp>
+
+#if BOOST_TEST_SUPPORT_TOKEN_ITERATOR
+#include <boost/test/utils/iterator/token_iterator.hpp>
+#endif
#include <boost/test/utils/foreach.hpp>
+#include <boost/test/utils/basic_cstring/io.hpp>
+
+#include <boost/test/detail/global_typedef.hpp>
+#include <boost/test/detail/throw_exception.hpp>
// Boost
#include <boost/timer.hpp>
+#include <boost/bind.hpp>
// STL
+#include <limits>
#include <map>
#include <set>
#include <cstdlib>
@@ -51,148 +63,672 @@ namespace std { using ::time; using ::srand; }
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
+namespace framework {
+namespace impl {
// ************************************************************************** //
-// ************** test_start calls wrapper ************** //
+// ************** order detection helpers ************** //
// ************************************************************************** //
-namespace ut_detail {
+struct order_info {
+ order_info() : depth(-1) {}
-struct test_start_caller {
- test_start_caller( test_observer* to, counter_t tc_amount )
- : m_to( to )
- , m_tc_amount( tc_amount )
- {}
+ int depth;
+ std::vector<test_unit_id> dependant_siblings;
+};
- int operator()()
- {
- m_to->test_start( m_tc_amount );
+typedef std::set<test_unit_id> tu_id_set;
+typedef std::map<test_unit_id,order_info> order_info_per_tu; // !! ?? unordered map
+
+//____________________________________________________________________________//
+
+static test_unit_id
+get_tu_parent( test_unit_id tu_id )
+{
+ return framework::get( tu_id, TUT_ANY ).p_parent_id;
+}
+
+//____________________________________________________________________________//
+
+static int
+tu_depth( test_unit_id tu_id, test_unit_id master_tu_id, order_info_per_tu& tuoi )
+{
+ if( tu_id == master_tu_id )
return 0;
+
+ order_info& info = tuoi[tu_id];
+
+ if( info.depth == -1 )
+ info.depth = tu_depth( get_tu_parent( tu_id ), master_tu_id, tuoi ) + 1;
+
+ return info.depth;
+}
+
+//____________________________________________________________________________//
+
+static void
+collect_dependant_siblings( test_unit_id from, test_unit_id to, test_unit_id master_tu_id, order_info_per_tu& tuoi )
+{
+ int from_depth = tu_depth( from, master_tu_id, tuoi );
+ int to_depth = tu_depth( to, master_tu_id, tuoi );
+
+ while(from_depth > to_depth) {
+ from = get_tu_parent( from );
+ --from_depth;
+ }
+
+ while(from_depth < to_depth) {
+ to = get_tu_parent( to );
+ --to_depth;
+ }
+
+ while(true) {
+ test_unit_id from_parent = get_tu_parent( from );
+ test_unit_id to_parent = get_tu_parent( to );
+ if( from_parent == to_parent )
+ break;
+ from = from_parent;
+ to = to_parent;
+ }
+
+ tuoi[from].dependant_siblings.push_back( to );
+}
+
+//____________________________________________________________________________//
+
+static counter_t
+assign_sibling_rank( test_unit_id tu_id, order_info_per_tu& tuoi )
+{
+ test_unit& tu = framework::get( tu_id, TUT_ANY );
+
+ BOOST_TEST_SETUP_ASSERT( tu.p_sibling_rank != (std::numeric_limits<counter_t>::max)(),
+ "Cyclic dependency detected involving test unit \"" + tu.full_name() + "\"" );
+
+ if( tu.p_sibling_rank != 0 )
+ return tu.p_sibling_rank;
+
+ order_info const& info = tuoi[tu_id];
+
+ // indicate in progress
+ tu.p_sibling_rank.value = (std::numeric_limits<counter_t>::max)();
+
+ counter_t new_rank = 1;
+ BOOST_TEST_FOREACH( test_unit_id, sibling_id, info.dependant_siblings )
+ new_rank = (std::max)(new_rank, assign_sibling_rank( sibling_id, tuoi ) + 1);
+
+ return tu.p_sibling_rank.value = new_rank;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** test_init call wrapper ************** //
+// ************************************************************************** //
+
+static void
+invoke_init_func( init_unit_test_func init_func )
+{
+#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
+ if( !(*init_func)() )
+ BOOST_TEST_IMPL_THROW( std::runtime_error( "test module initialization failed" ) );
+#else
+ test_suite* manual_test_units = (*init_func)( framework::master_test_suite().argc, framework::master_test_suite().argv );
+
+ if( manual_test_units )
+ framework::master_test_suite().add( manual_test_units );
+#endif
+}
+
+// ************************************************************************** //
+// ************** name_filter ************** //
+// ************************************************************************** //
+
+class name_filter : public test_tree_visitor {
+ struct component {
+ component( const_string name ) // has to be implicit
+ {
+ if( name == "*" )
+ m_kind = SFK_ALL;
+ else if( first_char( name ) == '*' && last_char( name ) == '*' ) {
+ m_kind = SFK_SUBSTR;
+ m_name = name.substr( 1, name.size()-1 );
+ }
+ else if( first_char( name ) == '*' ) {
+ m_kind = SFK_TRAILING;
+ m_name = name.substr( 1 );
+ }
+ else if( last_char( name ) == '*' ) {
+ m_kind = SFK_LEADING;
+ m_name = name.substr( 0, name.size()-1 );
+ }
+ else {
+ m_kind = SFK_MATCH;
+ m_name = name;
+ }
+ }
+
+ bool pass( test_unit const& tu ) const
+ {
+ const_string name( tu.p_name );
+
+ switch( m_kind ) {
+ default:
+ case SFK_ALL:
+ return true;
+ case SFK_LEADING:
+ return name.substr( 0, m_name.size() ) == m_name;
+ case SFK_TRAILING:
+ return name.size() >= m_name.size() && name.substr( name.size() - m_name.size() ) == m_name;
+ case SFK_SUBSTR:
+ return name.find( m_name ) != const_string::npos;
+ case SFK_MATCH:
+ return m_name == tu.p_name.get();
+ }
+ }
+ enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
+
+ kind m_kind;
+ const_string m_name;
+ };
+
+public:
+ // Constructor
+ name_filter( test_unit_id_list& targ_list, const_string filter_expr ) : m_targ_list( targ_list ), m_depth( 0 )
+ {
+#ifdef BOOST_TEST_SUPPORT_TOKEN_ITERATOR
+ string_token_iterator tit( filter_expr, (dropped_delimeters = "/", kept_delimeters = dt_none) );
+
+ while( tit != string_token_iterator() ) {
+ m_components.push_back( std::vector<component>( string_token_iterator( *tit, (dropped_delimeters = ",", kept_delimeters = dt_none) ),
+ string_token_iterator() ) );
+
+ ++tit;
+ }
+#endif
}
private:
+ bool filter_unit( test_unit const& tu )
+ {
+ // skip master test suite
+ if( m_depth == 0 )
+ return true;
+
+ // corresponding name filters are at level m_depth-1
+ std::vector<component> const& filters = m_components[m_depth-1];
+
+ // look for match
+ return std::find_if( filters.begin(), filters.end(), bind( &component::pass, _1, boost::ref(tu) ) ) != filters.end();
+ }
+
+ // test_tree_visitor interface
+ virtual void visit( test_case const& tc )
+ {
+ // make sure we only accept test cases if we match last component of the filter
+ if( m_depth == m_components.size() && filter_unit( tc ) )
+ m_targ_list.push_back( tc.p_id ); // found a test case
+ }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( !filter_unit( ts ) )
+ return false;
+
+ if( m_depth < m_components.size() ) {
+ ++m_depth;
+ return true;
+ }
+
+ m_targ_list.push_back( ts.p_id ); // found a test suite
+
+ return false;
+ }
+ virtual void test_suite_finish( test_suite const& /*ts*/ )
+ {
+ --m_depth;
+ }
+
// Data members
- test_observer* m_to;
- counter_t m_tc_amount;
+ typedef std::vector<std::vector<component> > components_per_level;
+
+ components_per_level m_components;
+ test_unit_id_list& m_targ_list;
+ unsigned m_depth;
};
-//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** label_filter ************** //
+// ************************************************************************** //
-struct test_init_caller {
- explicit test_init_caller( init_unit_test_func init_func )
- : m_init_func( init_func )
+class label_filter : public test_tree_visitor {
+public:
+ label_filter( test_unit_id_list& targ_list, const_string label )
+ : m_targ_list( targ_list )
+ , m_label( label )
{}
- int operator()()
+
+private:
+ // test_tree_visitor interface
+ virtual bool visit( test_unit const& tu )
{
-#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
- if( !(*m_init_func)() )
- throw std::runtime_error( "test module initialization failed" );
-#else
- test_suite* manual_test_units = (*m_init_func)( framework::master_test_suite().argc, framework::master_test_suite().argv );
+ if( tu.has_label( m_label ) ) {
+ // found a test unit; add it to list of tu to enable with children and stop recursion in case of suites
+ m_targ_list.push_back( tu.p_id );
+ return false;
+ }
- if( manual_test_units )
- framework::master_test_suite().add( manual_test_units );
-#endif
- return 0;
+ return true;
+ }
+
+ // Data members
+ test_unit_id_list& m_targ_list;
+ const_string m_label;
+};
+
+// ************************************************************************** //
+// ************** set_run_status ************** //
+// ************************************************************************** //
+
+class set_run_status : public test_tree_visitor {
+public:
+ explicit set_run_status( test_unit::run_status rs, test_unit_id_list* dep_collector = 0 )
+ : m_new_status( rs )
+ , m_dep_collector( dep_collector )
+ {}
+
+private:
+ // test_tree_visitor interface
+ virtual bool visit( test_unit const& tu )
+ {
+ const_cast<test_unit&>(tu).p_run_status.value = m_new_status == test_unit::RS_INVALID ? tu.p_default_status : m_new_status;
+
+ if( m_dep_collector ) {
+ BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
+ test_unit const& dep = framework::get( dep_id, TUT_ANY );
+
+ if( dep.p_run_status == tu.p_run_status )
+ continue;
+
+ BOOST_TEST_MESSAGE( "Including test " << dep.p_type_name << ' ' << dep.full_name() <<
+ " as a dependency of test " << tu.p_type_name << ' ' << tu.full_name() );
+
+ m_dep_collector->push_back( dep_id );
+ }
+ }
+ return true;
}
// Data members
- init_unit_test_func m_init_func;
+ test_unit::run_status m_new_status;
+ test_unit_id_list* m_dep_collector;
};
+// ************************************************************************** //
+// ************** parse_filters ************** //
+// ************************************************************************** //
+
+static void
+add_filtered_test_units( test_unit_id master_tu_id, const_string filter, test_unit_id_list& targ )
+{
+ // Choose between two kinds of filters
+ if( filter[0] == '@' ) {
+ filter.trim_left( 1 );
+ label_filter lf( targ, filter );
+ traverse_test_tree( master_tu_id, lf, true );
+ }
+ else {
+ name_filter nf( targ, filter );
+ traverse_test_tree( master_tu_id, nf, true );
+ }
}
+//____________________________________________________________________________//
+
+static bool
+parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_unit_id_list& tu_to_disable )
+{
+ // 10. collect tu to enable and disable based on filters
+ bool had_selector_filter = false;
+
+ BOOST_TEST_FOREACH( const_string, filter, runtime_config::test_to_run() ) {
+ BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" );
+
+ enum { SELECTOR, ENABLER, DISABLER } filter_type = SELECTOR;
+
+ // 11. Deduce filter type
+ if( filter[0] == '!' || filter[0] == '+' ) {
+ filter_type = filter[0] == '+' ? ENABLER : DISABLER;
+ filter.trim_left( 1 );
+ BOOST_TEST_SETUP_ASSERT( !filter.is_empty(), "Invalid filter specification" );
+ }
+
+ had_selector_filter |= filter_type == SELECTOR;
+
+ // 12. Add test units to corresponding list
+ switch( filter_type ) {
+ case SELECTOR:
+ case ENABLER: add_filtered_test_units( master_tu_id, filter, tu_to_enable ); break;
+ case DISABLER: add_filtered_test_units( master_tu_id, filter, tu_to_disable ); break;
+ }
+ }
+
+ return had_selector_filter;
+}
+
+//____________________________________________________________________________//
+
+} // namespace impl
+
// ************************************************************************** //
-// ************** framework ************** //
+// ************** framework::state ************** //
// ************************************************************************** //
-class framework_impl : public test_tree_visitor {
+unsigned const TIMEOUT_EXCEEDED = static_cast<unsigned>( -1 );
+
+class state {
public:
- framework_impl()
- : m_master_test_suite( 0 )
- , m_curr_test_case( INV_TEST_UNIT_ID )
+ state()
+ : m_curr_test_case( INV_TEST_UNIT_ID )
, m_next_test_case_id( MIN_TEST_CASE_ID )
, m_next_test_suite_id( MIN_TEST_SUITE_ID )
- , m_is_initialized( false )
, m_test_in_progress( false )
- {}
+ , m_context_idx( 0 )
+ {
+ }
- ~framework_impl() { clear(); }
+ ~state() { clear(); }
void clear()
{
while( !m_test_units.empty() ) {
test_unit_store::value_type const& tu = *m_test_units.begin();
- test_unit* tu_ptr = tu.second;
+ test_unit const* tu_ptr = tu.second;
// the delete will erase this element from map
- if( ut_detail::test_id_2_unit_type( tu.second->p_id ) == tut_suite )
- delete (test_suite const*)tu_ptr;
+ if( ut_detail::test_id_2_unit_type( tu.second->p_id ) == TUT_SUITE )
+ delete static_cast<test_suite const*>(tu_ptr);
else
- delete (test_case const*)tu_ptr;
+ delete static_cast<test_case const*>(tu_ptr);
}
}
void set_tu_id( test_unit& tu, test_unit_id id ) { tu.p_id.value = id; }
- // test_tree_visitor interface implementation
- void visit( test_case const& tc )
+ //////////////////////////////////////////////////////////////////
+
+ // Validates the dependency graph and deduces the sibling dependency rank for each child
+ void deduce_siblings_order( test_unit_id tu_id, test_unit_id master_tu_id, impl::order_info_per_tu& tuoi )
{
- if( !tc.check_dependencies() ) {
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_skipped( tc );
+ test_unit& tu = framework::get( tu_id, TUT_ANY );
+
+ // collect all sibling dependancy from tu own list
+ BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() )
+ collect_dependant_siblings( tu_id, dep_id, master_tu_id, tuoi );
+ if( tu.p_type != TUT_SUITE )
return;
+
+ test_suite& ts = static_cast<test_suite&>(tu);
+
+ // recursive call to children first
+ BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children )
+ deduce_siblings_order( chld_id, master_tu_id, tuoi );
+
+ BOOST_TEST_FOREACH( test_unit_id, chld_id, ts.m_children ) {
+ counter_t rank = assign_sibling_rank( chld_id, tuoi );
+ ts.m_ranked_children.insert( std::make_pair( rank, chld_id ) );
}
+ }
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_start( tc );
+ //////////////////////////////////////////////////////////////////
- boost::timer tc_timer;
- test_unit_id bkup = m_curr_test_case;
- m_curr_test_case = tc.p_id;
- unit_test_monitor_t::error_level run_result = unit_test_monitor.execute_and_translate( tc );
+ // Finalize default run status:
+ // 1) inherit run status from parent where applicable
+ // 2) if any of test units in test suite enabled enable it as well
+ bool finalize_default_run_status( test_unit_id tu_id, test_unit::run_status parent_status )
+ {
+ test_unit& tu = framework::get( tu_id, TUT_ANY );
- unsigned long elapsed = static_cast<unsigned long>( tc_timer.elapsed() * 1e6 );
+ if( tu.p_default_status == test_suite::RS_INHERIT )
+ tu.p_default_status.value = parent_status;
- if( unit_test_monitor.is_critical_error( run_result ) ) {
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_aborted();
+ // go through list of children
+ if( tu.p_type == TUT_SUITE ) {
+ bool has_enabled_child = false;
+ BOOST_TEST_FOREACH( test_unit_id, chld_id, static_cast<test_suite const&>(tu).m_children )
+ has_enabled_child |= finalize_default_run_status( chld_id, tu.p_default_status );
+
+ tu.p_default_status.value = has_enabled_child ? test_suite::RS_ENABLED : test_suite::RS_DISABLED;
}
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_finish( tc, elapsed );
+ return tu.p_default_status == test_suite::RS_ENABLED;
+ }
- m_curr_test_case = bkup;
+ //////////////////////////////////////////////////////////////////
+
+ bool finalize_run_status( test_unit_id tu_id )
+ {
+ test_unit& tu = framework::get( tu_id, TUT_ANY );
+
+ // go through list of children
+ if( tu.p_type == TUT_SUITE ) {
+ bool has_enabled_child = false;
+ BOOST_TEST_FOREACH( test_unit_id, chld_id, static_cast<test_suite const&>(tu).m_children)
+ has_enabled_child |= finalize_run_status( chld_id );
+
+ tu.p_run_status.value = has_enabled_child ? test_suite::RS_ENABLED : test_suite::RS_DISABLED;
+ }
- if( unit_test_monitor.is_critical_error( run_result ) )
- throw test_being_aborted();
+ return tu.is_enabled();
}
- bool test_suite_start( test_suite const& ts )
+ //////////////////////////////////////////////////////////////////
+
+ void deduce_run_status( test_unit_id master_tu_id )
{
- if( !ts.check_dependencies() ) {
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_skipped( ts );
+ using namespace framework::impl;
+ test_unit_id_list tu_to_enable;
+ test_unit_id_list tu_to_disable;
- return false;
+ // 10. If there are any filters supplied, figure out lists of test units to enable/disable
+ bool had_selector_filter = !runtime_config::test_to_run().empty() &&
+ parse_filters( master_tu_id, tu_to_enable, tu_to_disable );
+
+ // 20. Set the stage: either use default run status or disable all test units
+ set_run_status setter( had_selector_filter ? test_unit::RS_DISABLED : test_unit::RS_INVALID );
+ traverse_test_tree( master_tu_id, setter, true );
+
+ // 30. Apply all selectors and enablers.
+ while( !tu_to_enable.empty() ) {
+ test_unit& tu = framework::get( tu_to_enable.back(), TUT_ANY );
+
+ tu_to_enable.pop_back();
+
+ // 35. Ignore test units which already enabled
+ if( tu.is_enabled() )
+ continue;
+
+ // set new status and add all dependencies into tu_to_enable
+ set_run_status setter( test_unit::RS_ENABLED, &tu_to_enable );
+ traverse_test_tree( tu.p_id, setter, true );
}
- BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_start( ts );
+ // 40. Apply all disablers
+ while( !tu_to_disable.empty() ) {
+ test_unit const& tu = framework::get( tu_to_disable.back(), TUT_ANY );
- return true;
+ tu_to_disable.pop_back();
+
+ // 35. Ignore test units which already disabled
+ if( !tu.is_enabled() )
+ continue;
+
+ set_run_status setter( test_unit::RS_DISABLED );
+ traverse_test_tree( tu.p_id, setter, true );
+ }
+
+ // 50. Make sure parents of enabled test units are also enabled
+ finalize_run_status( master_tu_id );
}
- void test_suite_finish( test_suite const& ts )
+ //////////////////////////////////////////////////////////////////
+
+ typedef unit_test_monitor_t::error_level execution_result;
+
+ // Executed the test tree with the root at specified test unit
+ execution_result execute_test_tree( test_unit_id tu_id, unsigned timeout = 0 )
{
+ test_unit const& tu = framework::get( tu_id, TUT_ANY );
+
+ execution_result result = unit_test_monitor_t::test_ok;
+
+ if( !tu.is_enabled() )
+ return result;
+
+ // 10. Check preconditions, including zero time left for execution and
+ // successful execution of all dependencies
+ if( timeout == TIMEOUT_EXCEEDED ) {
+ // notify all observers about skipped test unit
+ BOOST_TEST_FOREACH( test_observer*, to, m_observers )
+ to->test_unit_skipped( tu, "timeout for the test unit is exceeded" );
+
+ return unit_test_monitor_t::os_timeout;
+ }
+ else if( timeout == 0 || timeout > tu.p_timeout ) // deduce timeout for this test unit
+ timeout = tu.p_timeout;
+
+ test_tools::assertion_result const precondition_res = tu.check_preconditions();
+ if( !precondition_res ) {
+ // notify all observers about skipped test unit
+ BOOST_TEST_FOREACH( test_observer*, to, m_observers )
+ to->test_unit_skipped( tu, precondition_res.message() );
+
+ return unit_test_monitor_t::precondition_failure;
+ }
+
+ // 20. Notify all observers about the start of the test unit
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
- to->test_unit_finish( ts, 0 );
+ to->test_unit_start( tu );
+
+ // 30. Execute setup fixtures if any; any failure here leads to test unit abortion
+ BOOST_TEST_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ result = unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::setup, F ) );
+ if( result != unit_test_monitor_t::test_ok )
+ break;
+ }
+
+ // This is the time we are going to spend executing the test unit
+ unsigned long elapsed = 0;
+
+ if( result == unit_test_monitor_t::test_ok ) {
+ // 40. We are going to time the execution
+ boost::timer tu_timer;
+
+ if( tu.p_type == TUT_SUITE ) {
+ test_suite const& ts = static_cast<test_suite const&>( tu );
+
+ if( runtime_config::random_seed() == 0 ) {
+ typedef std::pair<counter_t,test_unit_id> value_type;
+
+ BOOST_TEST_FOREACH( value_type, chld, ts.m_ranked_children ) {
+ unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
+
+ result = (std::min)( result, execute_test_tree( chld.second, chld_timeout ) );
+
+ if( unit_test_monitor.is_critical_error( result ) )
+ break;
+ }
+ }
+ else {
+ // Go through ranges of chldren with the same dependency rank and shuffle them
+ // independently. Execute each subtree in this order
+ test_unit_id_list children_with_the_same_rank;
+
+ typedef test_suite::children_per_rank::const_iterator it_type;
+ it_type it = ts.m_ranked_children.begin();
+ while( it != ts.m_ranked_children.end() ) {
+ children_with_the_same_rank.clear();
+
+ std::pair<it_type,it_type> range = ts.m_ranked_children.equal_range( it->first );
+ it = range.first;
+ while( it != range.second ) {
+ children_with_the_same_rank.push_back( it->second );
+ it++;
+ }
+
+ std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end() );
+
+ BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
+ unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
+
+ result = (std::min)( result, execute_test_tree( chld, chld_timeout ) );
+
+ if( unit_test_monitor.is_critical_error( result ) )
+ break;
+ }
+ }
+ }
+
+ elapsed = static_cast<unsigned long>( tu_timer.elapsed() * 1e6 );
+ }
+ else { // TUT_CASE
+ test_case const& tc = static_cast<test_case const&>( tu );
+
+ // setup contexts
+ m_context_idx = 0;
+
+ // setup current test case
+ test_unit_id bkup = m_curr_test_case;
+ m_curr_test_case = tc.p_id;
+
+ // execute the test case body
+ result = unit_test_monitor.execute_and_translate( tc.p_test_func, timeout );
+ elapsed = static_cast<unsigned long>( tu_timer.elapsed() * 1e6 );
+
+ // cleanup leftover context
+ m_context.clear();
+
+ // restore state and abort if necessary
+ m_curr_test_case = bkup;
+ }
+ }
+
+ // if run error is critical skip teardown, who knows what the state of the program at this point
+ if( !unit_test_monitor.is_critical_error( result ) ) {
+ // execute teardown fixtures if any in reverse order
+ BOOST_TEST_REVERSE_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ result = (std::min)( result, unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::teardown, F ), 0 ) );
+
+ if( unit_test_monitor.is_critical_error( result ) )
+ break;
+ }
+ }
+
+ // notify all observers about abortion
+ if( unit_test_monitor.is_critical_error( result ) ) {
+ BOOST_TEST_FOREACH( test_observer*, to, m_observers )
+ to->test_aborted();
+ }
+
+ // notify all observers about completion
+ BOOST_TEST_REVERSE_FOREACH( test_observer*, to, m_observers )
+ to->test_unit_finish( tu, elapsed );
+
+ return result;
}
//////////////////////////////////////////////////////////////////
+
+ unsigned child_timeout( unsigned tu_timeout, double elapsed )
+ {
+ if( tu_timeout == 0U )
+ return 0U;
+
+ unsigned elpsed_sec = static_cast<unsigned>(elapsed); // rounding to number of whole seconds
+
+ return tu_timeout > elpsed_sec ? tu_timeout - elpsed_sec : TIMEOUT_EXCEEDED;
+ }
+
struct priority_order {
bool operator()( test_observer* lhs, test_observer* rhs ) const
{
@@ -200,226 +736,467 @@ public:
}
};
+ // Data members
typedef std::map<test_unit_id,test_unit*> test_unit_store;
typedef std::set<test_observer*,priority_order> observer_store;
+ struct context_frame {
+ context_frame( std::string const& d, int id, bool sticky )
+ : descr( d )
+ , frame_id( id )
+ , is_sticky( sticky )
+ {}
+
+ std::string descr;
+ int frame_id;
+ bool is_sticky;
+ };
+ typedef std::vector<context_frame> context_data;
master_test_suite_t* m_master_test_suite;
+ std::vector<test_suite*> m_auto_test_suites;
+
test_unit_id m_curr_test_case;
test_unit_store m_test_units;
test_unit_id m_next_test_case_id;
test_unit_id m_next_test_suite_id;
- bool m_is_initialized;
bool m_test_in_progress;
observer_store m_observers;
+ context_data m_context;
+ int m_context_idx;
+
+ boost::execution_monitor m_aux_em;
};
//____________________________________________________________________________//
+namespace impl {
namespace {
#if defined(__CYGWIN__)
-framework_impl& s_frk_impl() { static framework_impl* the_inst = 0; if(!the_inst) the_inst = new framework_impl; return *the_inst; }
+framework::state& s_frk_state() { static framework::state* the_inst = 0; if(!the_inst) the_inst = new framework::state; return *the_inst; }
#else
-framework_impl& s_frk_impl() { static framework_impl the_inst; return the_inst; }
+framework::state& s_frk_state() { static framework::state the_inst; return the_inst; }
#endif
} // local namespace
+void
+setup_for_execution( test_unit const& tu )
+{
+ s_frk_state().deduce_run_status( tu.p_id );
+}
+
//____________________________________________________________________________//
-namespace framework {
+} // namespace impl
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** framework::init ************** //
+// ************************************************************************** //
void
init( init_unit_test_func init_func, int argc, char* argv[] )
{
+ // 10. Set up runtime parameters
runtime_config::init( argc, argv );
- // set the log level and format
+ // 20. Set the desired log level and format
unit_test_log.set_threshold_level( runtime_config::log_level() );
unit_test_log.set_format( runtime_config::log_format() );
- // set the report level and format
+ // 30. Set the desired report level and format
results_reporter::set_level( runtime_config::report_level() );
results_reporter::set_format( runtime_config::report_format() );
+ // 40. Register default test observers
register_observer( results_collector );
register_observer( unit_test_log );
if( runtime_config::show_progress() )
register_observer( progress_monitor );
+ // 50. Set up memory leak detection
if( runtime_config::detect_memory_leaks() > 0 ) {
- debug::detect_memory_leaks( true );
+ debug::detect_memory_leaks( true, runtime_config::memory_leaks_report_file() );
debug::break_memory_alloc( runtime_config::detect_memory_leaks() );
}
- // init master unit test suite
+ // 60. Initialize master unit test suite
master_test_suite().argc = argc;
master_test_suite().argv = argv;
- try {
- boost::execution_monitor em;
-
- ut_detail::test_init_caller tic( init_func );
+ using namespace impl;
- em.execute( tic );
+ // 70. Invoke test module initialization routine
+ BOOST_TEST_IMPL_TRY {
+ s_frk_state().m_aux_em.vexecute( boost::bind( &impl::invoke_init_func, init_func ) );
}
- catch( execution_exception const& ex ) {
- throw setup_error( ex.what() );
+ BOOST_TEST_IMPL_CATCH( execution_exception, ex ) {
+ BOOST_TEST_SETUP_ASSERT( false, ex.what() );
}
-
- s_frk_impl().m_is_initialized = true;
}
//____________________________________________________________________________//
+void
+finalize_setup_phase( test_unit_id master_tu_id )
+{
+ if( master_tu_id == INV_TEST_UNIT_ID )
+ master_tu_id = master_test_suite().p_id;
+
+ // 10. Apply all decorators to the auto test units
+ class apply_decorators : public test_tree_visitor {
+ private:
+ // test_tree_visitor interface
+ virtual bool visit( test_unit const& tu )
+ {
+ BOOST_TEST_FOREACH( decorator::base_ptr, d, tu.p_decorators.get() )
+ d->apply( const_cast<test_unit&>(tu) );
+
+ return true;
+ }
+ } ad;
+ traverse_test_tree( master_tu_id, ad, true );
+
+ // 20. Finalize setup phase
+ impl::order_info_per_tu tuoi;
+ impl::s_frk_state().deduce_siblings_order( master_tu_id, master_tu_id, tuoi );
+ impl::s_frk_state().finalize_default_run_status( master_tu_id, test_unit::RS_INVALID );
+}
+
+// ************************************************************************** //
+// ************** test_in_progress ************** //
+// ************************************************************************** //
+
bool
-is_initialized()
+test_in_progress()
+{
+ return impl::s_frk_state().m_test_in_progress;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** framework::shutdown ************** //
+// ************************************************************************** //
+
+void
+shutdown()
{
- return s_frk_impl().m_is_initialized;
+ // eliminating some fake memory leak reports. See for more details:
+ // http://connect.microsoft.com/VisualStudio/feedback/details/106937/memory-leaks-reported-by-debug-crt-inside-typeinfo-name
+
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1600 ) && !defined(_DLL) && defined(_DEBUG)
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1600 )
+#define _Next next
+#define _MemPtr memPtr
+#endif
+ __type_info_node* pNode = __type_info_root_node._Next;
+ __type_info_node* tmpNode = &__type_info_root_node;
+
+ for( ; pNode!=NULL; pNode = tmpNode ) {
+ tmpNode = pNode->_Next;
+ delete pNode->_MemPtr;
+ delete pNode;
+ }
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1600 )
+#undef _Next
+#undef _MemPtr
+#endif
+# endif
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** register_test_unit ************** //
+// ************************************************************************** //
+
void
register_test_unit( test_case* tc )
{
BOOST_TEST_SETUP_ASSERT( tc->p_id == INV_TEST_UNIT_ID, BOOST_TEST_L( "test case already registered" ) );
- test_unit_id new_id = s_frk_impl().m_next_test_case_id;
+ test_unit_id new_id = impl::s_frk_state().m_next_test_case_id;
BOOST_TEST_SETUP_ASSERT( new_id != MAX_TEST_CASE_ID, BOOST_TEST_L( "too many test cases" ) );
- typedef framework_impl::test_unit_store::value_type map_value_type;
+ typedef state::test_unit_store::value_type map_value_type;
- s_frk_impl().m_test_units.insert( map_value_type( new_id, tc ) );
- s_frk_impl().m_next_test_case_id++;
+ impl::s_frk_state().m_test_units.insert( map_value_type( new_id, tc ) );
+ impl::s_frk_state().m_next_test_case_id++;
- s_frk_impl().set_tu_id( *tc, new_id );
+ impl::s_frk_state().set_tu_id( *tc, new_id );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** register_test_unit ************** //
+// ************************************************************************** //
+
void
register_test_unit( test_suite* ts )
{
BOOST_TEST_SETUP_ASSERT( ts->p_id == INV_TEST_UNIT_ID, BOOST_TEST_L( "test suite already registered" ) );
- test_unit_id new_id = s_frk_impl().m_next_test_suite_id;
+ test_unit_id new_id = impl::s_frk_state().m_next_test_suite_id;
BOOST_TEST_SETUP_ASSERT( new_id != MAX_TEST_SUITE_ID, BOOST_TEST_L( "too many test suites" ) );
- typedef framework_impl::test_unit_store::value_type map_value_type;
- s_frk_impl().m_test_units.insert( map_value_type( new_id, ts ) );
- s_frk_impl().m_next_test_suite_id++;
+ typedef state::test_unit_store::value_type map_value_type;
+
+ impl::s_frk_state().m_test_units.insert( map_value_type( new_id, ts ) );
+ impl::s_frk_state().m_next_test_suite_id++;
- s_frk_impl().set_tu_id( *ts, new_id );
+ impl::s_frk_state().set_tu_id( *ts, new_id );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** deregister_test_unit ************** //
+// ************************************************************************** //
+
void
deregister_test_unit( test_unit* tu )
{
- s_frk_impl().m_test_units.erase( tu->p_id );
+ impl::s_frk_state().m_test_units.erase( tu->p_id );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** clear ************** //
+// ************************************************************************** //
+
void
clear()
{
- s_frk_impl().clear();
+ impl::s_frk_state().clear();
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** register_observer ************** //
+// ************************************************************************** //
+
void
register_observer( test_observer& to )
{
- s_frk_impl().m_observers.insert( &to );
+ impl::s_frk_state().m_observers.insert( &to );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** deregister_observer ************** //
+// ************************************************************************** //
+
void
deregister_observer( test_observer& to )
{
- s_frk_impl().m_observers.erase( &to );
+ impl::s_frk_state().m_observers.erase( &to );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** add_context ************** //
+// ************************************************************************** //
+
+int
+add_context( ::boost::unit_test::lazy_ostream const& context_descr, bool sticky )
+{
+ std::stringstream buffer;
+ context_descr( buffer );
+ int res_idx = impl::s_frk_state().m_context_idx++;
+
+ impl::s_frk_state().m_context.push_back( state::context_frame( buffer.str(), res_idx, sticky ) );
+
+ return res_idx;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** clear_context ************** //
+// ************************************************************************** //
+
+struct frame_with_id {
+ explicit frame_with_id( int id ) : m_id( id ) {}
+
+ bool operator()( state::context_frame const& f )
+ {
+ return f.frame_id == m_id;
+ }
+ int m_id;
+};
+
+//____________________________________________________________________________//
+
void
-reset_observers()
+clear_context( int frame_id )
+{
+ if( frame_id == -1 ) { // clear all non sticky frames
+ for( int i=static_cast<int>(impl::s_frk_state().m_context.size())-1; i>=0; i-- )
+ if( !impl::s_frk_state().m_context[i].is_sticky )
+ impl::s_frk_state().m_context.erase( impl::s_frk_state().m_context.begin()+i );
+ }
+
+ else { // clear specific frame
+ state::context_data::iterator it =
+ std::find_if( impl::s_frk_state().m_context.begin(), impl::s_frk_state().m_context.end(), frame_with_id( frame_id ) );
+
+ if( it != impl::s_frk_state().m_context.end() ) // really an internal error if this is not true
+ impl::s_frk_state().m_context.erase( it );
+ }
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** get_context ************** //
+// ************************************************************************** //
+
+context_generator
+get_context()
+{
+ return context_generator();
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** context_generator ************** //
+// ************************************************************************** //
+
+bool
+context_generator::is_empty() const
{
- s_frk_impl().m_observers.clear();
+ return impl::s_frk_state().m_context.empty();
}
//____________________________________________________________________________//
+const_string
+context_generator::next() const
+{
+ return m_curr_frame < impl::s_frk_state().m_context.size() ? impl::s_frk_state().m_context[m_curr_frame++].descr : const_string();
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** master_test_suite ************** //
+// ************************************************************************** //
+
master_test_suite_t&
master_test_suite()
{
- if( !s_frk_impl().m_master_test_suite )
- s_frk_impl().m_master_test_suite = new master_test_suite_t;
+ if( !impl::s_frk_state().m_master_test_suite )
+ impl::s_frk_state().m_master_test_suite = new master_test_suite_t;
- return *s_frk_impl().m_master_test_suite;
+ return *impl::s_frk_state().m_master_test_suite;
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** current_auto_test_suite ************** //
+// ************************************************************************** //
+
+test_suite&
+current_auto_test_suite( test_suite* ts, bool push_or_pop )
+{
+ if( impl::s_frk_state().m_auto_test_suites.empty() )
+ impl::s_frk_state().m_auto_test_suites.push_back( &framework::master_test_suite() );
+
+ if( !push_or_pop )
+ impl::s_frk_state().m_auto_test_suites.pop_back();
+ else if( ts )
+ impl::s_frk_state().m_auto_test_suites.push_back( ts );
+
+ return *impl::s_frk_state().m_auto_test_suites.back();
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** current_test_case ************** //
+// ************************************************************************** //
+
test_case const&
current_test_case()
{
- return get<test_case>( s_frk_impl().m_curr_test_case );
+ return get<test_case>( impl::s_frk_state().m_curr_test_case );
}
//____________________________________________________________________________//
+test_unit_id
+current_test_case_id()
+{
+ return impl::s_frk_state().m_curr_test_case;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** framework::get ************** //
+// ************************************************************************** //
+
test_unit&
get( test_unit_id id, test_unit_type t )
{
- test_unit* res = s_frk_impl().m_test_units[id];
+ test_unit* res = impl::s_frk_state().m_test_units[id];
if( (res->p_type & t) == 0 )
- throw internal_error( "Invalid test unit type" );
+ BOOST_TEST_IMPL_THROW( internal_error( "Invalid test unit type" ) );
return *res;
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** framework::run ************** //
+// ************************************************************************** //
+
void
run( test_unit_id id, bool continue_test )
{
if( id == INV_TEST_UNIT_ID )
id = master_test_suite().p_id;
+ // Figure out run status for execution phase
+ impl::s_frk_state().deduce_run_status( id );
+
test_case_counter tcc;
traverse_test_tree( id, tcc );
- BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::test_to_run().is_empty()
- ? BOOST_TEST_L( "test tree is empty" )
- : BOOST_TEST_L( "no test cases matching filter" ) );
+ BOOST_TEST_SETUP_ASSERT( tcc.p_count != 0 , runtime_config::test_to_run().empty()
+ ? BOOST_TEST_L( "test tree is empty" )
+ : BOOST_TEST_L( "no test cases matching filter or all test cases were disabled" ) );
- bool call_start_finish = !continue_test || !s_frk_impl().m_test_in_progress;
- bool was_in_progress = s_frk_impl().m_test_in_progress;
+ bool was_in_progress = framework::test_in_progress();
+ bool call_start_finish = !continue_test || !was_in_progress;
- s_frk_impl().m_test_in_progress = true;
+ impl::s_frk_state().m_test_in_progress = true;
if( call_start_finish ) {
- BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers ) {
- boost::execution_monitor em;
-
- try {
- em.execute( ut_detail::test_start_caller( to, tcc.p_count ) );
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
+ BOOST_TEST_IMPL_TRY {
+ impl::s_frk_state().m_aux_em.vexecute( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
}
- catch( execution_exception const& ex ) {
- throw setup_error( ex.what() );
+ BOOST_TEST_IMPL_CATCH( execution_exception, ex ) {
+ BOOST_TEST_SETUP_ASSERT( false, ex.what() );
}
}
}
@@ -428,7 +1205,7 @@ run( test_unit_id id, bool continue_test )
case 0:
break;
case 1: {
- unsigned int seed = static_cast<unsigned int>( std::time( 0 ) );
+ unsigned seed = static_cast<unsigned>( std::time( 0 ) );
BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << seed );
std::srand( seed );
break;
@@ -438,19 +1215,14 @@ run( test_unit_id id, bool continue_test )
std::srand( runtime_config::random_seed() );
}
- try {
- traverse_test_tree( id, s_frk_impl() );
- }
- catch( test_being_aborted const& ) {
- // abort already reported
- }
+ impl::s_frk_state().execute_test_tree( id );
if( call_start_finish ) {
- BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
+ BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
to->test_finish();
}
- s_frk_impl().m_test_in_progress = was_in_progress;
+ impl::s_frk_state().m_test_in_progress = was_in_progress;
}
//____________________________________________________________________________//
@@ -463,41 +1235,49 @@ run( test_unit const* tu, bool continue_test )
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** assertion_result ************** //
+// ************************************************************************** //
+
void
-assertion_result( bool passed )
+assertion_result( unit_test::assertion_result ar )
{
- BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
- to->assertion_result( passed );
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
+ to->assertion_result( ar );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** exception_caught ************** //
+// ************************************************************************** //
+
void
exception_caught( execution_exception const& ex )
{
- BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
to->exception_caught( ex );
}
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** test_unit_aborted ************** //
+// ************************************************************************** //
+
void
test_unit_aborted( test_unit const& tu )
{
- BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
to->test_unit_aborted( tu );
}
//____________________________________________________________________________//
} // namespace framework
-
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_IPP_021005GER
diff --git a/boost/test/impl/interaction_based.ipp b/boost/test/impl/interaction_based.ipp
deleted file mode 100644
index ce2893364a..0000000000
--- a/boost/test/impl/interaction_based.ipp
+++ /dev/null
@@ -1,90 +0,0 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
-// Use, modification, and distribution are subject to the
-// Boost Software License, Version 1.0. (See accompanying file
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/test for the library home page.
-//
-// File : $RCSfile$
-//
-// Version : $Revision$
-//
-// Description : Facilities to perform interaction-based testing
-// ***************************************************************************
-
-#ifndef BOOST_TEST_INTERACTION_BASED_IPP_112105GER
-#define BOOST_TEST_INTERACTION_BASED_IPP_112105GER
-
-// Boost.Test
-#include <boost/test/detail/config.hpp>
-
-#if BOOST_TEST_SUPPORT_INTERACTION_TESTING
-
-// Boost.Test
-#include <boost/test/detail/config.hpp>
-#include <boost/test/utils/callback.hpp>
-#include <boost/test/interaction_based.hpp>
-#include <boost/test/mock_object.hpp>
-#include <boost/test/framework.hpp> // for setup_error
-
-#include <boost/test/detail/suppress_warnings.hpp>
-
-// STL
-#include <stdexcept>
-#include <string>
-
-//____________________________________________________________________________//
-
-namespace boost {
-
-namespace itest { // interaction-based testing
-
-// ************************************************************************** //
-// ************** manager ************** //
-// ************************************************************************** //
-
-manager::manager()
-{
- instance_ptr( true, this );
-}
-
-//____________________________________________________________________________//
-
-manager::~manager()
-{
- instance_ptr( true );
-}
-
-//____________________________________________________________________________//
-
-manager*
-manager::instance_ptr( bool reset, manager* new_ptr )
-{
- static manager dummy( 0 );
-
- static manager* ptr = &dummy;
-
- if( reset ) {
- if( new_ptr ) {
- BOOST_TEST_SETUP_ASSERT( ptr == &dummy, BOOST_TEST_L( "Can't run two interation based test the same time" ) );
-
- ptr = new_ptr;
- }
- else
- ptr = &dummy;
- }
-
- return ptr;
-}
-
-} // namespace itest
-
-} // namespace boost
-
-//____________________________________________________________________________//
-
-#include <boost/test/detail/enable_warnings.hpp>
-
-#endif // not ancient compiler
-
-#endif // BOOST_TEST_INTERACTION_BASED_IPP_112105GER
diff --git a/boost/test/impl/logged_expectations.ipp b/boost/test/impl/logged_expectations.ipp
deleted file mode 100644
index ff30628b8e..0000000000
--- a/boost/test/impl/logged_expectations.ipp
+++ /dev/null
@@ -1,246 +0,0 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
-// Use, modification, and distribution are subject to the
-// Boost Software License, ELOG_VER 1.0. (See accompanying file
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/test for the library home page.
-//
-// File : $RCSfile$
-//
-// Version : $Revision$
-//
-// Description : Facilities to perform interaction based testng of logged expectations
-// ***************************************************************************
-
-#ifndef BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER
-#define BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER
-
-// Boost.Test
-#include <boost/test/detail/config.hpp>
-
-#if BOOST_TEST_SUPPORT_INTERACTION_TESTING
-
-#include <boost/test/detail/global_typedef.hpp>
-
-#include <boost/test/utils/callback.hpp>
-#include <boost/test/utils/iterator/token_iterator.hpp>
-
-#include <boost/test/interaction_based.hpp>
-#include <boost/test/test_tools.hpp>
-
-#include <boost/test/detail/suppress_warnings.hpp>
-
-// Boost
-#include <boost/lexical_cast.hpp>
-
-// STL
-#include <fstream>
-
-//____________________________________________________________________________//
-
-namespace boost {
-
-using namespace ::boost::unit_test;
-
-namespace itest {
-
-// ************************************************************************** //
-// ************** logged expectation test implementation ************** //
-// ************************************************************************** //
-
-struct expectations_logger : itest::manager {
- // Constructor
- expectations_logger( const_string log_file_name, bool test_or_log );
-
- virtual bool decision_point( const_string, std::size_t );
- virtual unsigned enter_scope( const_string, std::size_t, const_string scope_name );
- virtual void allocated( const_string, std::size_t, void*, std::size_t s );
- virtual void data_flow( const_string d );
- virtual std::string return_value( const_string default_value );
-
-private:
- // Data members
- bool m_test_or_log;
- std::fstream m_log_file;
-};
-
-literal_string ELOG_VER = "1.0";
-literal_string CLMN_SEP = "|";
-static const char LINE_SEP = '\n';
-
-literal_string FILE_SIG = "ELOG";
-literal_string SCOPE_SIG = "SCOPE";
-literal_string ALLOC_SIG = "ALLOC";
-literal_string DP_SIG = "SWITCH";
-literal_string DATA_SIG = "DATA";
-literal_string RETURN_SIG = "RETURN";
-
-//____________________________________________________________________________//
-
-expectations_logger::expectations_logger( const_string log_file_name, bool test_or_log )
-: m_test_or_log( test_or_log )
-{
- BOOST_REQUIRE_MESSAGE( !log_file_name.is_empty(), "Empty expectations log file name" );
-
- m_log_file.open( log_file_name.begin(), test_or_log ? std::ios::in : std::ios::out );
-
- BOOST_REQUIRE_MESSAGE( m_log_file.is_open(),
- "Can't open expectations log file " << log_file_name
- << " for " << ( m_test_or_log ? "reading" : "writing") );
-
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, FILE_SIG );
- ++tit;
- BOOST_CHECK_EQUAL( *tit, ELOG_VER );
- }
- else {
- m_log_file << FILE_SIG << CLMN_SEP << ELOG_VER << LINE_SEP;
- }
-}
-
-//____________________________________________________________________________//
-
-bool
-expectations_logger::decision_point( const_string, std::size_t )
-{
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, DP_SIG ); ++tit;
- return lexical_cast<bool>( *tit );
- }
- else {
- m_log_file << DP_SIG << CLMN_SEP << std::boolalpha << true << LINE_SEP;
-
- return true;
- }
-}
-
-//____________________________________________________________________________//
-
-unsigned
-expectations_logger::enter_scope( const_string, std::size_t, const_string scope_name )
-{
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, SCOPE_SIG ); ++tit;
- BOOST_CHECK_EQUAL( *tit, scope_name );
- }
- else {
- m_log_file << SCOPE_SIG << CLMN_SEP << scope_name << LINE_SEP;
- }
-
- return 0;
-}
-
-//____________________________________________________________________________//
-
-void
-expectations_logger::allocated( const_string, std::size_t, void*, std::size_t s )
-{
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, ALLOC_SIG ); ++tit;
- BOOST_CHECK_EQUAL( lexical_cast<std::size_t>( *tit ), s );
- }
- else {
- m_log_file << ALLOC_SIG << CLMN_SEP << s << LINE_SEP;
- }
-}
-
-//____________________________________________________________________________//
-
-void
-expectations_logger::data_flow( const_string d )
-{
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, DATA_SIG ); ++tit;
- BOOST_CHECK_EQUAL( *tit, d );
- }
- else {
- m_log_file << DATA_SIG << CLMN_SEP << d << LINE_SEP;
- }
-}
-
-//____________________________________________________________________________//
-
-std::string
-expectations_logger::return_value( const_string default_value )
-{
- if( m_test_or_log ) {
- std::string line;
-
- std::getline( m_log_file, line, LINE_SEP );
-
- const_string cline( line );
- string_token_iterator tit( cline, (dropped_delimeters = CLMN_SEP, kept_delimeters = dt_none));
-
- BOOST_CHECK_EQUAL( *tit, RETURN_SIG ); ++tit;
-
- return std::string( tit->begin(), tit->size() );
- }
- else {
- m_log_file << RETURN_SIG << CLMN_SEP << default_value << LINE_SEP;
-
- return std::string();
- }
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** logged expectations test ************** //
-// ************************************************************************** //
-
-void BOOST_TEST_DECL
-logged_expectations( callback0<> const& F, const_string log_file_name, bool test_or_log )
-{
- expectations_logger el( log_file_name, test_or_log );
-
- F();
-}
-
-//____________________________________________________________________________//
-
-} // namespace itest
-
-} // namespace boost
-
-//____________________________________________________________________________//
-
-#include <boost/test/detail/enable_warnings.hpp>
-
-#endif // not ancient compiler
-
-#endif // BOOST_TEST_LOGGED_EXPECTATIONS_IPP_120905GER
diff --git a/boost/test/impl/plain_report_formatter.ipp b/boost/test/impl/plain_report_formatter.ipp
index 95b662135d..f9e7db772a 100644
--- a/boost/test/impl/plain_report_formatter.ipp
+++ b/boost/test/impl/plain_report_formatter.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,9 +19,13 @@
#include <boost/test/output/plain_report_formatter.hpp>
#include <boost/test/utils/custom_manip.hpp>
#include <boost/test/results_collector.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
+
+#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
+#include <boost/test/utils/setcolor.hpp>
+
+#include <boost/test/unit_test_parameters.hpp>
// STL
#include <iomanip>
@@ -37,9 +41,7 @@ namespace std { using ::log10; }
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-
namespace output {
namespace {
@@ -58,17 +60,16 @@ operator<<( custom_printer<quote> const& p, T const& value )
//____________________________________________________________________________//
void
-print_stat_value( std::ostream& ostr, counter_t v, counter_t indent, counter_t total,
- const_string name, const_string res )
+print_stat_value( std::ostream& ostr, counter_t v, counter_t indent, counter_t total, const_string name, const_string res )
{
- if( v > 0 ) {
- ostr << std::setw( indent ) << ""
- << v << ' ' << name << ( v != 1 ? "s" : "" );
- if( total > 0 )
- ostr << " out of " << total;
+ if( v == 0 )
+ return;
- ostr << ' ' << res << '\n';
- }
+ if( total > 0 )
+ ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << name << ( v != 1 ? "s" : "" )
+ << " out of " << total << ' ' << res << '\n';
+ else
+ ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << res << ' ' << name << ( v != 1 ? "s" : "" ) << '\n';
}
//____________________________________________________________________________//
@@ -104,40 +105,42 @@ plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostrea
const_string descr;
if( tr.passed() )
- descr = "passed";
+ descr = "has passed";
else if( tr.p_skipped )
- descr = "skipped";
+ descr = "was skipped";
else if( tr.p_aborted )
- descr = "aborted";
+ descr = "was aborted";
else
- descr = "failed";
+ descr = "has failed";
- ostr << std::setw( m_indent ) << ""
- << "Test " << (tu.p_type == tut_case ? "case " : "suite " ) << quote() << tu.p_name << ' ' << descr;
+ ostr << std::setw( static_cast<int>(m_indent) ) << ""
+ << "Test " << tu.p_type_name << ' ' << quote() << tu.full_name() << ' ' << descr;
if( tr.p_skipped ) {
- ostr << " due to " << (tu.check_dependencies() ? "test aborting\n" : "failed dependancy\n" );
+ ostr << "\n";
m_indent += 2;
return;
}
-
+
counter_t total_assertions = tr.p_assertions_passed + tr.p_assertions_failed;
- counter_t total_tc = tr.p_test_cases_passed + tr.p_test_cases_failed + tr.p_test_cases_skipped;
+ counter_t total_tc = tr.p_test_cases_passed + tr.p_test_cases_warned + tr.p_test_cases_failed + tr.p_test_cases_skipped;
- if( total_assertions > 0 || total_tc > 0 )
+ if( total_assertions > 0 || total_tc > 0 || tr.p_warnings_failed > 0)
ostr << " with:";
ostr << '\n';
m_indent += 2;
- print_stat_value( ostr, tr.p_assertions_passed, m_indent, total_assertions, "assertion", "passed" );
- print_stat_value( ostr, tr.p_assertions_failed, m_indent, total_assertions, "assertion", "failed" );
- print_stat_value( ostr, tr.p_expected_failures, m_indent, 0 , "failure" , "expected" );
- print_stat_value( ostr, tr.p_test_cases_passed, m_indent, total_tc , "test case", "passed" );
- print_stat_value( ostr, tr.p_test_cases_failed, m_indent, total_tc , "test case", "failed" );
- print_stat_value( ostr, tr.p_test_cases_skipped, m_indent, total_tc , "test case", "skipped" );
- print_stat_value( ostr, tr.p_test_cases_aborted, m_indent, total_tc , "test case", "aborted" );
-
+ print_stat_value( ostr, tr.p_test_cases_passed , m_indent, total_tc , "test case", "passed" );
+ print_stat_value( ostr, tr.p_test_cases_warned , m_indent, total_tc , "test case", "passed with warnings" );
+ print_stat_value( ostr, tr.p_test_cases_failed , m_indent, total_tc , "test case", "failed" );
+ print_stat_value( ostr, tr.p_test_cases_skipped, m_indent, total_tc , "test case", "skipped" );
+ print_stat_value( ostr, tr.p_test_cases_aborted, m_indent, total_tc , "test case", "aborted" );
+ print_stat_value( ostr, tr.p_assertions_passed , m_indent, total_assertions, "assertion", "passed" );
+ print_stat_value( ostr, tr.p_assertions_failed , m_indent, total_assertions, "assertion", "failed" );
+ print_stat_value( ostr, tr.p_warnings_failed , m_indent, 0 , "warning" , "failed" );
+ print_stat_value( ostr, tr.p_expected_failures , m_indent, 0 , "failure" , "expected" );
+
ostr << '\n';
}
@@ -155,44 +158,50 @@ void
plain_report_formatter::do_confirmation_report( test_unit const& tu, std::ostream& ostr )
{
test_results const& tr = results_collector.results( tu.p_id );
-
+
if( tr.passed() ) {
+ BOOST_TEST_SCOPE_SETCOLOR( ostr, term_attr::BRIGHT, term_color::GREEN );
+
ostr << "*** No errors detected\n";
return;
}
-
+
+ BOOST_TEST_SCOPE_SETCOLOR( ostr, term_attr::BRIGHT, term_color::RED );
+
if( tr.p_skipped ) {
- ostr << "*** Test " << tu.p_type_name << " skipped due to "
- << (tu.check_dependencies() ? "test aborting\n" : "failed dependancy\n" );
+ ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was skipped"
+ << "; see standard output for details\n";
return;
}
- if( tr.p_assertions_failed == 0 ) {
- ostr << "*** errors detected in test " << tu.p_type_name << " " << quote() << tu.p_name
+ if( tr.p_aborted ) {
+ ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was aborted"
<< "; see standard output for details\n";
+ }
+
+ if( tr.p_assertions_failed == 0 ) {
+ if( !tr.p_aborted )
+ ostr << "*** Errors were detected in the test " << tu.p_type_name << ' ' << quote() << tu.full_name()
+ << "; see standard output for details\n";
return;
}
counter_t num_failures = tr.p_assertions_failed;
-
- ostr << "*** " << num_failures << " failure" << ( num_failures != 1 ? "s" : "" ) << " detected";
-
+
+ ostr << "*** " << num_failures << " failure" << ( num_failures != 1 ? "s are" : " is" ) << " detected";
+
if( tr.p_expected_failures > 0 )
- ostr << " (" << tr.p_expected_failures << " failure" << ( tr.p_expected_failures != 1 ? "s" : "" ) << " expected)";
-
- ostr << " in test " << tu.p_type_name << " " << quote() << tu.p_name << "\n";
+ ostr << " (" << tr.p_expected_failures << " failure" << ( tr.p_expected_failures != 1 ? "s are" : " is" ) << " expected)";
+
+ ostr << " in the test " << tu.p_type_name << " " << quote() << tu.full_name() << "\n";
}
//____________________________________________________________________________//
} // namespace output
-
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
diff --git a/boost/test/impl/progress_monitor.ipp b/boost/test/impl/progress_monitor.ipp
index 5175755c3a..ebdd7e9320 100644
--- a/boost/test/impl/progress_monitor.ipp
+++ b/boost/test/impl/progress_monitor.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -17,12 +17,15 @@
// Boost.Test
#include <boost/test/progress_monitor.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/unit_test_parameters.hpp>
+#include <boost/test/utils/setcolor.hpp>
+
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/test_case_counter.hpp>
+#include <boost/test/tree/traverse.hpp>
// Boost
-#include <boost/progress.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -30,13 +33,70 @@
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
// ************************************************************************** //
// ************** progress_monitor ************** //
// ************************************************************************** //
+struct progress_display {
+ progress_display( counter_t expected_count, std::ostream& os )
+ : m_os(os)
+ , m_count( 0 )
+ , m_expected_count( expected_count )
+ , m_next_tic_count( 0 )
+ , m_tic( 0 )
+ {
+
+ m_os << "\n0% 10 20 30 40 50 60 70 80 90 100%"
+ << "\n|----|----|----|----|----|----|----|----|----|----|"
+ << std::endl;
+
+ if( !m_expected_count )
+ m_expected_count = 1; // prevent divide by zero
+ }
+
+ unsigned long operator+=( unsigned long increment )
+ {
+ if( (m_count += increment) < m_next_tic_count )
+ return m_count;
+
+ // use of floating point ensures that both large and small counts
+ // work correctly. static_cast<>() is also used several places
+ // to suppress spurious compiler warnings.
+ unsigned int tics_needed = static_cast<unsigned int>(
+ (static_cast<double>(m_count)/m_expected_count)*50.0 );
+
+ do {
+ m_os << '*' << std::flush;
+ } while( ++m_tic < tics_needed );
+
+ m_next_tic_count = static_cast<unsigned long>((m_tic/50.0) * m_expected_count);
+
+ if( m_count == m_expected_count ) {
+ if( m_tic < 51 )
+ m_os << '*';
+
+ m_os << std::endl;
+ }
+
+ return m_count;
+ }
+ unsigned long operator++() { return operator+=( 1 ); }
+ unsigned long count() const { return m_count; }
+
+private:
+ BOOST_DELETED_FUNCTION(progress_display(progress_display const&))
+ BOOST_DELETED_FUNCTION(progress_display& operator=(progress_display const&))
+
+ std::ostream& m_os; // may not be present in all imps
+
+ unsigned long m_count;
+ unsigned long m_expected_count;
+ unsigned long m_next_tic_count;
+ unsigned int m_tic;
+};
+
namespace {
struct progress_monitor_impl {
@@ -58,6 +118,8 @@ progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; retu
void
progress_monitor_t::test_start( counter_t test_cases_amount )
{
+ BOOST_TEST_SCOPE_SETCOLOR( *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA );
+
s_pm_impl().m_progress_display.reset( new progress_display( test_cases_amount, *s_pm_impl().m_stream ) );
}
@@ -66,6 +128,8 @@ progress_monitor_t::test_start( counter_t test_cases_amount )
void
progress_monitor_t::test_aborted()
{
+ BOOST_TEST_SCOPE_SETCOLOR( *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA );
+
(*s_pm_impl().m_progress_display) += s_pm_impl().m_progress_display->count();
}
@@ -74,18 +138,22 @@ progress_monitor_t::test_aborted()
void
progress_monitor_t::test_unit_finish( test_unit const& tu, unsigned long )
{
- if( tu.p_type == tut_case )
+ BOOST_TEST_SCOPE_SETCOLOR( *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA );
+
+ if( tu.p_type == TUT_CASE )
++(*s_pm_impl().m_progress_display);
}
//____________________________________________________________________________//
void
-progress_monitor_t::test_unit_skipped( test_unit const& tu )
+progress_monitor_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
+ BOOST_TEST_SCOPE_SETCOLOR( *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA );
+
test_case_counter tcc;
traverse_test_tree( tu, tcc );
-
+
(*s_pm_impl().m_progress_display) += tcc.p_count;
}
@@ -98,13 +166,10 @@ progress_monitor_t::set_stream( std::ostream& ostr )
}
//____________________________________________________________________________//
-
-} // namespace unit_test
+} // namespace unit_test
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
diff --git a/boost/test/impl/results_collector.ipp b/boost/test/impl/results_collector.ipp
index 0d5691aab6..d04d64fd6d 100644
--- a/boost/test/impl/results_collector.ipp
+++ b/boost/test/impl/results_collector.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -16,11 +16,15 @@
#define BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
// Boost.Test
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/visitor.hpp>
+#include <boost/test/tree/test_case_counter.hpp>
+#include <boost/test/tree/traverse.hpp>
+
// Boost
#include <boost/cstdlib.hpp>
@@ -32,7 +36,6 @@
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
// ************************************************************************** //
@@ -52,6 +55,7 @@ test_results::passed() const
return !p_skipped &&
p_test_cases_failed == 0 &&
p_assertions_failed <= p_expected_failures &&
+ p_test_cases_skipped == 0 &&
!p_aborted;
}
@@ -73,7 +77,9 @@ test_results::operator+=( test_results const& tr )
{
p_assertions_passed.value += tr.p_assertions_passed;
p_assertions_failed.value += tr.p_assertions_failed;
+ p_warnings_failed.value += tr.p_warnings_failed;
p_test_cases_passed.value += tr.p_test_cases_passed;
+ p_test_cases_warned.value += tr.p_test_cases_warned;
p_test_cases_failed.value += tr.p_test_cases_failed;
p_test_cases_skipped.value += tr.p_test_cases_skipped;
p_test_cases_aborted.value += tr.p_test_cases_aborted;
@@ -84,25 +90,25 @@ test_results::operator+=( test_results const& tr )
void
test_results::clear()
{
- p_assertions_passed.value = 0;
- p_assertions_failed.value = 0;
- p_expected_failures.value = 0;
- p_test_cases_passed.value = 0;
- p_test_cases_failed.value = 0;
- p_test_cases_skipped.value = 0;
- p_test_cases_aborted.value = 0;
- p_aborted.value = false;
- p_skipped.value = true;
+ p_assertions_passed.value = 0;
+ p_assertions_failed.value = 0;
+ p_warnings_failed.value = 0;
+ p_expected_failures.value = 0;
+ p_test_cases_passed.value = 0;
+ p_test_cases_warned.value = 0;
+ p_test_cases_failed.value = 0;
+ p_test_cases_skipped.value = 0;
+ p_test_cases_aborted.value = 0;
+ p_aborted.value = false;
+ p_skipped.value = false;
}
//____________________________________________________________________________//
-
+
// ************************************************************************** //
// ************** results_collector ************** //
// ************************************************************************** //
-#if !BOOST_WORKAROUND(BOOST_MSVC, <1300)
-
namespace {
struct results_collector_impl {
@@ -113,16 +119,6 @@ results_collector_impl& s_rc_impl() { static results_collector_impl the_inst; re
} // local namespace
-#else
-
-struct results_collector_impl {
- std::map<test_unit_id,test_results> m_results_store;
-};
-
-static results_collector_impl& s_rc_impl() { static results_collector_impl the_inst; return the_inst; }
-
-#endif
-
//____________________________________________________________________________//
void
@@ -134,31 +130,14 @@ results_collector_t::test_start( counter_t )
//____________________________________________________________________________//
void
-results_collector_t::test_finish()
-{
- // do nothing
-}
-
-//____________________________________________________________________________//
-
-void
-results_collector_t::test_aborted()
-{
- // do nothing
-}
-
-//____________________________________________________________________________//
-
-void
results_collector_t::test_unit_start( test_unit const& tu )
{
// init test_results entry
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.clear();
-
- tr.p_expected_failures.value = tu.p_expected_failures;
- tr.p_skipped.value = false;
+
+ tr.p_expected_failures.value = tu.p_expected_failures;
}
//____________________________________________________________________________//
@@ -172,13 +151,18 @@ public:
test_results const& tr = results_collector.results( tc.p_id );
m_tr += tr;
- if( tr.passed() )
- m_tr.p_test_cases_passed.value++;
+ if( tr.passed() ) {
+ if( tr.p_warnings_failed )
+ m_tr.p_test_cases_warned.value++;
+ else
+ m_tr.p_test_cases_passed.value++;
+ }
else if( tr.p_skipped )
m_tr.p_test_cases_skipped.value++;
else {
if( tr.p_aborted )
m_tr.p_test_cases_aborted.value++;
+
m_tr.p_test_cases_failed.value++;
}
}
@@ -186,10 +170,9 @@ public:
{
if( m_ts.p_id == ts.p_id )
return true;
- else {
- m_tr += results_collector.results( ts.p_id );
- return false;
- }
+
+ m_tr += results_collector.results( ts.p_id );
+ return false;
}
private:
@@ -203,53 +186,55 @@ private:
void
results_collector_t::test_unit_finish( test_unit const& tu, unsigned long )
{
- if( tu.p_type == tut_suite ) {
+ if( tu.p_type == TUT_SUITE ) {
results_collect_helper ch( s_rc_impl().m_results_store[tu.p_id], tu );
traverse_test_tree( tu, ch );
}
else {
test_results const& tr = s_rc_impl().m_results_store[tu.p_id];
-
+
bool num_failures_match = tr.p_aborted || tr.p_assertions_failed >= tr.p_expected_failures;
if( !num_failures_match )
- BOOST_TEST_MESSAGE( "Test case " << tu.p_name << " has fewer failures than expected" );
+ BOOST_TEST_MESSAGE( "Test case " << tu.full_name() << " has fewer failures than expected" );
bool check_any_assertions = tr.p_aborted || (tr.p_assertions_failed != 0) || (tr.p_assertions_passed != 0);
if( !check_any_assertions )
- BOOST_TEST_MESSAGE( "Test case " << tu.p_name << " did not check any assertions" );
+ BOOST_TEST_MESSAGE( "Test case " << tu.full_name() << " did not check any assertions" );
}
}
//____________________________________________________________________________//
void
-results_collector_t::test_unit_skipped( test_unit const& tu )
+results_collector_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
- if( tu.p_type == tut_suite ) {
+ test_results& tr = s_rc_impl().m_results_store[tu.p_id];
+
+ tr.clear();
+
+ tr.p_skipped.value = true;
+
+ if( tu.p_type == TUT_SUITE ) {
test_case_counter tcc;
traverse_test_tree( tu, tcc );
- test_results& tr = s_rc_impl().m_results_store[tu.p_id];
-
- tr.clear();
-
- tr.p_skipped.value = true;
- tr.p_test_cases_skipped.value = tcc.p_count;
+ tr.p_test_cases_skipped.value = tcc.p_count;
}
}
//____________________________________________________________________________//
void
-results_collector_t::assertion_result( bool passed )
+results_collector_t::assertion_result( unit_test::assertion_result ar )
{
- test_results& tr = s_rc_impl().m_results_store[framework::current_test_case().p_id];
+ test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
- if( passed )
- tr.p_assertions_passed.value++;
- else
- tr.p_assertions_failed.value++;
+ switch( ar ) {
+ case AR_PASSED: tr.p_assertions_passed.value++; break;
+ case AR_FAILED: tr.p_assertions_failed.value++; break;
+ case AR_TRIGGERED: tr.p_warnings_failed.value++; break;
+ }
if( tr.p_assertions_failed == 1 )
first_failed_assertion();
@@ -260,7 +245,7 @@ results_collector_t::assertion_result( bool passed )
void
results_collector_t::exception_caught( execution_exception const& )
{
- test_results& tr = s_rc_impl().m_results_store[framework::current_test_case().p_id];
+ test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
tr.p_assertions_failed.value++;
}
@@ -284,11 +269,8 @@ results_collector_t::results( test_unit_id id ) const
//____________________________________________________________________________//
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
diff --git a/boost/test/impl/results_reporter.ipp b/boost/test/impl/results_reporter.ipp
index 54447c3932..885295c928 100644
--- a/boost/test/impl/results_reporter.ipp
+++ b/boost/test/impl/results_reporter.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -17,13 +17,16 @@
// Boost.Test
#include <boost/test/results_reporter.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/output/plain_report_formatter.hpp>
#include <boost/test/output/xml_report_formatter.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/tree/visitor.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/traverse.hpp>
+
+#include <boost/test/unit_test_parameters.hpp>
// Boost
#include <boost/scoped_ptr.hpp>
@@ -38,9 +41,7 @@ typedef ::boost::io::ios_base_all_saver io_saver_type;
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-
namespace results_reporter {
// ************************************************************************** //
@@ -126,14 +127,13 @@ void
set_format( output_format rf )
{
switch( rf ) {
- case CLF:
+ default:
+ case OF_CLF:
set_format( new output::plain_report_formatter );
break;
- case XML:
+ case OF_XML:
set_format( new output::xml_report_formatter );
break;
- default:
- break;
}
}
@@ -190,13 +190,9 @@ make_report( report_level l, test_unit_id id )
//____________________________________________________________________________//
} // namespace results_reporter
-
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
diff --git a/boost/test/impl/test_main.ipp b/boost/test/impl/test_main.ipp
index b08f5e16c7..c95c91e88b 100644
--- a/boost/test/impl/test_main.ipp
+++ b/boost/test/impl/test_main.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Gennadiy Rozental 2001-2014.
// (C) Copyright Beman Dawes 1995-2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -6,11 +6,8 @@
// See http://www.boost.org/libs/test for the library home page.
//
-// File : $RCSfile$
-//
-// Version : $$Revision$
-//
-// Description : implements main function for Test Execution Monitor.
+/// @file
+/// @brief Implements main function for Test Execution Monitor.
// ***************************************************************************
#ifndef BOOST_TEST_TEST_MAIN_IPP_012205GER
@@ -32,16 +29,16 @@ extern int test_main( int argc, char* argv[] ); // prototype for user's test_
struct test_main_caller {
test_main_caller( int argc, char** argv ) : m_argc( argc ), m_argv( argv ) {}
-
+
void operator()() {
int test_main_result = test_main( m_argc, m_argv );
// translate a test_main non-success return into a test error
BOOST_CHECK( test_main_result == 0 || test_main_result == boost::exit_success );
}
-
+
private:
- // Data members
+ // Data members
int m_argc;
char** m_argv;
};
@@ -53,11 +50,11 @@ private:
::boost::unit_test::test_suite*
init_unit_test_suite( int argc, char* argv[] ) {
using namespace ::boost::unit_test;
-
+
framework::master_test_suite().p_name.value = "Test Program";
-
+
framework::master_test_suite().add( BOOST_TEST_CASE( test_main_caller( argc, argv ) ) );
-
+
return 0;
}
diff --git a/boost/test/impl/test_tools.ipp b/boost/test/impl/test_tools.ipp
index 6f5d7e9edf..03fea91605 100644
--- a/boost/test/impl/test_tools.ipp
+++ b/boost/test/impl/test_tools.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -16,12 +16,18 @@
#define BOOST_TEST_TEST_TOOLS_IPP_012205GER
// Boost.Test
-#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_log.hpp>
-#include <boost/test/output_test_stream.hpp>
+#include <boost/test/tools/context.hpp>
+#include <boost/test/tools/output_test_stream.hpp>
+
+#include <boost/test/tools/detail/fwd.hpp>
+#include <boost/test/tools/detail/print_helper.hpp>
+
#include <boost/test/framework.hpp>
+#include <boost/test/tree/test_unit.hpp>
#include <boost/test/execution_monitor.hpp> // execution_aborted
-#include <boost/test/unit_test_suite_impl.hpp>
+
+#include <boost/test/detail/throw_exception.hpp>
// Boost
#include <boost/config.hpp>
@@ -33,6 +39,8 @@
#include <cctype>
#include <cwchar>
#include <stdexcept>
+#include <vector>
+#include <utility>
#include <ios>
// !! should we use #include <cstdarg>
@@ -50,8 +58,8 @@ namespace std { using ::wcscmp; }
# endif
namespace boost {
-
namespace test_tools {
+namespace tt_detail {
// ************************************************************************** //
// ************** print_log_value ************** //
@@ -105,119 +113,78 @@ print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const*
//____________________________________________________________________________//
-namespace tt_detail {
-
// ************************************************************************** //
// ************** TOOL BOX Implementation ************** //
// ************************************************************************** //
using ::boost::unit_test::lazy_ostream;
-bool
-check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
- const_string file_name, std::size_t line_num,
- tool_level tl, check_type ct,
- std::size_t num_of_args, ... )
+static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
+static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
+
+template<typename OutStream>
+void
+format_report( OutStream& os, assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
+ tool_level tl, check_type ct,
+ std::size_t num_args, va_list args,
+ char const* prefix, char const* suffix )
{
using namespace unit_test;
- if( !framework::is_initialized() )
- throw std::runtime_error( "can't use testing tools before framework is initialized" );
-
- if( !!pr )
- tl = PASS;
-
- log_level ll;
- char const* prefix;
- char const* suffix;
-
- switch( tl ) {
- case PASS:
- ll = log_successful_tests;
- prefix = "check ";
- suffix = " passed";
- break;
- case WARN:
- ll = log_warnings;
- prefix = "condition ";
- suffix = " is not satisfied";
- break;
- case CHECK:
- ll = log_all_errors;
- prefix = "check ";
- suffix = " failed";
- break;
- case REQUIRE:
- ll = log_fatal_errors;
- prefix = "critical check ";
- suffix = " failed";
- break;
- default:
- return true;
- }
-
switch( ct ) {
case CHECK_PRED:
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << check_descr << suffix;
-
+ os << prefix << assertion_descr << suffix;
+
if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
+ os << ". " << pr.message();
break;
+ case CHECK_BUILT_ASSERTION: {
+ os << prefix << assertion_descr << suffix;
+
+ if( tl != PASS ) {
+ const_string details_message = pr.message();
+
+ if( !details_message.is_empty() ) {
+ os << details_message;
+ }
+ }
+ break;
+ }
+
case CHECK_MSG:
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
-
if( tl == PASS )
- unit_test_log << prefix << "'" << check_descr << "'" << suffix;
+ os << prefix << "'" << assertion_descr << "'" << suffix;
else
- unit_test_log << check_descr;
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
+ os << assertion_descr;
- unit_test_log << unit_test::log::end();
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
break;
- case CHECK_EQUAL:
- case CHECK_NE:
- case CHECK_LT:
- case CHECK_LE:
- case CHECK_GT:
+ case CHECK_EQUAL:
+ case CHECK_NE:
+ case CHECK_LT:
+ case CHECK_LE:
+ case CHECK_GT:
case CHECK_GE: {
- static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
- static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
-
- va_list args;
-
- va_start( args, num_of_args );
char const* arg1_descr = va_arg( args, char const* );
lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
char const* arg2_descr = va_arg( args, char const* );
lazy_ostream const* arg2_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
+ os << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
if( tl != PASS )
- unit_test_log << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
+ os << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
- va_end( args );
-
if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
+ os << ". " << pr.message();
break;
}
case CHECK_CLOSE:
case CHECK_CLOSE_FRACTION: {
- va_list args;
-
- va_start( args, num_of_args );
char const* arg1_descr = va_arg( args, char const* );
lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
char const* arg2_descr = va_arg( args, char const* );
@@ -225,151 +192,172 @@ check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
/* toler_descr = */ va_arg( args, char const* );
lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
-
- unit_test_log << "difference{" << pr.message() << (ct == CHECK_CLOSE ? "%" : "")
- << "} between " << arg1_descr << "{" << *arg1_val
- << "} and " << arg2_descr << "{" << *arg2_val
- << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
- << *toler_val;
+ os << "difference{" << pr.message()
+ << "} between " << arg1_descr << "{" << *arg1_val
+ << "} and " << arg2_descr << "{" << *arg2_val
+ << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
+ << *toler_val;
if( ct == CHECK_CLOSE )
- unit_test_log << "%";
-
- va_end( args );
-
- unit_test_log << unit_test::log::end();
+ os << "%";
break;
}
case CHECK_SMALL: {
- va_list args;
-
- va_start( args, num_of_args );
char const* arg1_descr = va_arg( args, char const* );
lazy_ostream const* arg1_val = va_arg( args, lazy_ostream const* );
/* toler_descr = */ va_arg( args, char const* );
lazy_ostream const* toler_val = va_arg( args, lazy_ostream const* );
- unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
-
- unit_test_log << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
- << ( tl == PASS ? " doesn't exceed " : " exceeds " )
- << *toler_val;
+ os << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
+ << ( tl == PASS ? " doesn't exceed " : " exceeds " )
+ << *toler_val;
- va_end( args );
-
if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
+ os << ". " << pr.message();
break;
}
case CHECK_PRED_WITH_ARGS: {
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << check_descr;
+ std::vector< std::pair<char const*, lazy_ostream const*> > args_copy;
+ args_copy.reserve( num_args );
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ char const* desc = va_arg( args, char const* );
+ lazy_ostream const* value = va_arg( args, lazy_ostream const* );
+ args_copy.push_back( std::make_pair( desc, value ) );
+ }
+
+ os << prefix << assertion_descr;
// print predicate call description
- {
- va_list args;
- va_start( args, num_of_args );
-
- unit_test_log << "( ";
- for( std::size_t i = 0; i < num_of_args; ++i ) {
- unit_test_log << va_arg( args, char const* );
- va_arg( args, lazy_ostream const* ); // skip argument value;
-
- if( i != num_of_args-1 )
- unit_test_log << ", ";
- }
- unit_test_log << " )" << suffix;
- va_end( args );
+ os << "( ";
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ os << args_copy[i].first;
+
+ if( i != num_args-1 )
+ os << ", ";
}
-
+ os << " )" << suffix;
+
if( tl != PASS ) {
- va_list args;
- va_start( args, num_of_args );
-
- unit_test_log << " for ( ";
- for( std::size_t i = 0; i < num_of_args; ++i ) {
- va_arg( args, char const* ); // skip argument description;
- unit_test_log << *va_arg( args, lazy_ostream const* );
-
- if( i != num_of_args-1 )
- unit_test_log << ", ";
+ os << " for ( ";
+ for( std::size_t i = 0; i < num_args; ++i ) {
+ os << *args_copy[i].second;
+
+ if( i != num_args-1 )
+ os << ", ";
}
- unit_test_log << " )";
- va_end( args );
+ os << " )";
}
-
- if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
- unit_test_log << unit_test::log::end();
+ if( !pr.has_empty_message() )
+ os << ". " << pr.message();
break;
}
case CHECK_EQUAL_COLL: {
- va_list args;
-
- va_start( args, num_of_args );
char const* left_begin_descr = va_arg( args, char const* );
char const* left_end_descr = va_arg( args, char const* );
char const* right_begin_descr = va_arg( args, char const* );
char const* right_end_descr = va_arg( args, char const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix
- << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
- << right_begin_descr << ", " << right_end_descr << " }"
- << suffix;
+ os << prefix << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
+ << right_begin_descr << ", " << right_end_descr << " }"
+ << suffix;
- va_end( args );
-
if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
+ os << ". " << pr.message();
break;
}
case CHECK_BITWISE_EQUAL: {
- va_list args;
-
- va_start( args, num_of_args );
char const* left_descr = va_arg( args, char const* );
char const* right_descr = va_arg( args, char const* );
- unit_test_log << unit_test::log::begin( file_name, line_num )
- << ll << prefix << left_descr << " =.= " << right_descr << suffix;
+ os << prefix << left_descr << " =.= " << right_descr << suffix;
- va_end( args );
-
if( !pr.has_empty_message() )
- unit_test_log << ". " << pr.message();
-
- unit_test_log << unit_test::log::end();
+ os << ". " << pr.message();
break;
}
}
+}
+
+//____________________________________________________________________________//
+
+bool
+report_assertion( assertion_result const& ar,
+ lazy_ostream const& assertion_descr,
+ const_string file_name,
+ std::size_t line_num,
+ tool_level tl,
+ check_type ct,
+ std::size_t num_args, ... )
+{
+ using namespace unit_test;
+
+ if( framework::current_test_case_id() == INV_TEST_UNIT_ID )
+ BOOST_TEST_IMPL_THROW(
+ std::runtime_error( "can't use testing tools outside of test case implementation" ) );
+
+ if( !!ar )
+ tl = PASS;
+
+ log_level ll;
+ char const* prefix;
+ char const* suffix;
switch( tl ) {
case PASS:
- framework::assertion_result( true );
+ ll = log_successful_tests;
+ prefix = "check ";
+ suffix = " has passed";
+ break;
+ case WARN:
+ ll = log_warnings;
+ prefix = "condition ";
+ suffix = " is not satisfied";
+ break;
+ case CHECK:
+ ll = log_all_errors;
+ prefix = "check ";
+ suffix = " has failed";
+ break;
+ case REQUIRE:
+ ll = log_fatal_errors;
+ prefix = "critical check ";
+ suffix = " has failed";
+ break;
+ default:
+ return true;
+ }
+
+ unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
+ va_list args;
+ va_start( args, num_args );
+
+ format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
+
+ va_end( args );
+ unit_test_log << unit_test::log::end();
+
+ switch( tl ) {
+ case PASS:
+ framework::assertion_result( AR_PASSED );
return true;
case WARN:
+ framework::assertion_result( AR_TRIGGERED );
return false;
case CHECK:
- framework::assertion_result( false );
+ framework::assertion_result( AR_FAILED );
return false;
-
+
case REQUIRE:
- framework::assertion_result( false );
+ framework::assertion_result( AR_FAILED );
framework::test_unit_aborted( framework::current_test_case() );
- throw execution_aborted();
+ BOOST_TEST_IMPL_THROW( execution_aborted() );
}
return true;
@@ -377,7 +365,51 @@ check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
//____________________________________________________________________________//
-predicate_result
+assertion_result
+format_assertion_result( const_string expr_val, const_string details )
+{
+ assertion_result res(false);
+
+ bool starts_new_line = first_char( expr_val ) == '\n';
+
+ if( !starts_new_line && !expr_val.is_empty() )
+ res.message().stream() << " [" << expr_val << "]";
+
+ if( !details.is_empty() ) {
+ if( first_char(details) != '[' )
+ res.message().stream() << ". ";
+ else
+ res.message().stream() << " ";
+
+ res.message().stream() << details;
+ }
+
+ if( starts_new_line )
+ res.message().stream() << "." << expr_val;
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+BOOST_TEST_DECL std::string
+prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
+{
+ std::ostringstream msg_buff;
+
+ va_list args;
+ va_start( args, num_args );
+
+ format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
+
+ va_end( args );
+
+ return msg_buff.str();
+}
+
+//____________________________________________________________________________//
+
+assertion_result
equal_impl( char const* left, char const* right )
{
return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
@@ -387,7 +419,7 @@ equal_impl( char const* left, char const* right )
#if !defined( BOOST_NO_CWCHAR )
-predicate_result
+assertion_result
equal_impl( wchar_t const* left, wchar_t const* right )
{
return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
@@ -406,6 +438,31 @@ is_defined_impl( const_string symbol_name, const_string symbol_value )
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** context_frame ************** //
+// ************************************************************************** //
+
+context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
+: m_frame_id( unit_test::framework::add_context( context_descr, true ) )
+{
+}
+
+//____________________________________________________________________________//
+
+context_frame::~context_frame()
+{
+ unit_test::framework::clear_context( m_frame_id );
+}
+
+//____________________________________________________________________________//
+
+context_frame::operator bool()
+{
+ return true;
+}
+
+//____________________________________________________________________________//
+
} // namespace tt_detail
// ************************************************************************** //
@@ -429,7 +486,7 @@ struct output_test_stream::Impl
return res;
}
- void check_and_fill( predicate_result& res )
+ void check_and_fill( assertion_result& res )
{
if( !res.p_predicate_value )
res.message() << "Output content: \"" << m_synced_string << '\"';
@@ -448,9 +505,8 @@ output_test_stream::output_test_stream( const_string pattern_file_name, bool mat
m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
- BOOST_WARN_MESSAGE( m_pimpl->m_pattern.is_open(),
- "Can't open pattern file " << pattern_file_name
- << " for " << (match_or_save ? "reading" : "writing") );
+ if( !m_pimpl->m_pattern.is_open() )
+ BOOST_TEST_MESSAGE( "Can't open pattern file " << pattern_file_name << " for " << (match_or_save ? "reading" : "writing") );
}
m_pimpl->m_match_or_save = match_or_save;
@@ -466,12 +522,12 @@ output_test_stream::~output_test_stream()
//____________________________________________________________________________//
-predicate_result
+assertion_result
output_test_stream::is_empty( bool flush_stream )
{
sync();
- result_type res( m_pimpl->m_synced_string.empty() );
+ assertion_result res( m_pimpl->m_synced_string.empty() );
m_pimpl->check_and_fill( res );
@@ -483,12 +539,12 @@ output_test_stream::is_empty( bool flush_stream )
//____________________________________________________________________________//
-predicate_result
+assertion_result
output_test_stream::check_length( std::size_t length_, bool flush_stream )
{
sync();
- result_type res( m_pimpl->m_synced_string.length() == length_ );
+ assertion_result res( m_pimpl->m_synced_string.length() == length_ );
m_pimpl->check_and_fill( res );
@@ -500,12 +556,12 @@ output_test_stream::check_length( std::size_t length_, bool flush_stream )
//____________________________________________________________________________//
-predicate_result
+assertion_result
output_test_stream::is_equal( const_string arg, bool flush_stream )
{
sync();
- result_type res( const_string( m_pimpl->m_synced_string ) == arg );
+ assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
m_pimpl->check_and_fill( res );
@@ -517,12 +573,12 @@ output_test_stream::is_equal( const_string arg, bool flush_stream )
//____________________________________________________________________________//
-predicate_result
+assertion_result
output_test_stream::match_pattern( bool flush_stream )
{
sync();
- result_type result( true );
+ assertion_result result( true );
if( !m_pimpl->m_pattern.is_open() ) {
result = false;
@@ -548,18 +604,18 @@ output_test_stream::match_pattern( bool flush_stream )
std::string::size_type counter = suffix_size;
while( --counter ) {
- char c = m_pimpl->get_char();
+ char c2 = m_pimpl->get_char();
if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
break;
- result.message() << c;
+ result.message() << c2;
}
result.message() << "...";
// skip rest of the bytes. May help for further matching
- m_pimpl->m_pattern.ignore(
+ m_pimpl->m_pattern.ignore(
static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
break;
}
@@ -618,11 +674,8 @@ output_test_stream::sync()
//____________________________________________________________________________//
} // namespace test_tools
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER
diff --git a/boost/test/impl/test_tree.ipp b/boost/test/impl/test_tree.ipp
new file mode 100644
index 0000000000..712cb9ee42
--- /dev/null
+++ b/boost/test/impl/test_tree.ipp
@@ -0,0 +1,459 @@
+// (C) Copyright Gennadiy Rozental 2005-2014.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+/// @file
+/// Provides core implementation for Unit Test Framework.
+/// Extensions can be provided in separate files
+// ***************************************************************************
+
+#ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
+#define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
+
+// Boost.Test
+#include <boost/detail/workaround.hpp>
+
+#include <boost/test/framework.hpp>
+#include <boost/test/results_collector.hpp>
+
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/visitor.hpp>
+#include <boost/test/tree/traverse.hpp>
+#include <boost/test/tree/auto_registration.hpp>
+#include <boost/test/tree/global_fixture.hpp>
+
+#include <boost/test/utils/foreach.hpp>
+#include <boost/test/utils/basic_cstring/io.hpp>
+
+#include <boost/test/unit_test_parameters.hpp>
+
+// Boost
+#include <boost/timer.hpp>
+
+// STL
+#include <algorithm>
+#include <vector>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) && BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450)
+ using std::rand; // rand is in std and random_shuffle is in _STL
+#endif
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+
+// ************************************************************************** //
+// ************** test_unit ************** //
+// ************************************************************************** //
+
+test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
+: p_type( t )
+, p_type_name( t == TUT_CASE ? "case" : "suite" )
+, p_file_name( file_name )
+, p_line_num( line_num )
+, p_id( INV_TEST_UNIT_ID )
+, p_parent_id( INV_TEST_UNIT_ID )
+, p_name( std::string( name.begin(), name.size() ) )
+, p_timeout( 0 )
+, p_expected_failures( 0 )
+, p_default_status( RS_INHERIT )
+, p_run_status( RS_INVALID )
+, p_sibling_rank(0)
+{
+}
+
+//____________________________________________________________________________//
+
+test_unit::test_unit( const_string module_name )
+: p_type( TUT_SUITE )
+, p_type_name( "module" )
+, p_line_num( 0 )
+, p_id( INV_TEST_UNIT_ID )
+, p_parent_id( INV_TEST_UNIT_ID )
+, p_name( std::string( module_name.begin(), module_name.size() ) )
+, p_timeout( 0 )
+, p_expected_failures( 0 )
+, p_default_status( RS_INHERIT )
+, p_run_status( RS_INVALID )
+, p_sibling_rank(0)
+{
+}
+
+//____________________________________________________________________________//
+
+test_unit::~test_unit()
+{
+ framework::deregister_test_unit( this );
+}
+
+//____________________________________________________________________________//
+
+void
+test_unit::depends_on( test_unit* tu )
+{
+ BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
+ "Can't add dependency to the master test suite" );
+
+ p_dependencies.value.push_back( tu->p_id );
+}
+
+//____________________________________________________________________________//
+
+void
+test_unit::add_precondition( precondition_t const& pc )
+{
+ p_preconditions.value.push_back( pc );
+}
+
+//____________________________________________________________________________//
+
+test_tools::assertion_result
+test_unit::check_preconditions() const
+{
+ BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
+ test_unit const& dep = framework::get( dep_id, TUT_ANY );
+
+ if( !dep.is_enabled() ) {
+ test_tools::assertion_result res(false);
+ res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
+ return res;
+ }
+
+ test_results const& test_rslt = unit_test::results_collector.results( dep_id );
+ if( !test_rslt.passed() ) {
+ test_tools::assertion_result res(false);
+ res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has failed";
+ return res;
+ }
+
+ if( test_rslt.p_test_cases_skipped > 0 ) {
+ test_tools::assertion_result res(false);
+ res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
+ return res;
+ }
+ }
+
+ BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
+ test_tools::assertion_result res = precondition( p_id );
+ if( !res )
+ return res;
+ }
+
+ return true;
+}
+
+//____________________________________________________________________________//
+
+void
+test_unit::increase_exp_fail( counter_t num )
+{
+ p_expected_failures.value += num;
+
+ if( p_parent_id != INV_TEST_UNIT_ID )
+ framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
+}
+
+//____________________________________________________________________________//
+
+std::string
+test_unit::full_name() const
+{
+ if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
+ return p_name;
+
+ std::string res = framework::get<test_suite>( p_parent_id ).full_name();
+ res.append("/");
+
+ res.append( p_name );
+
+ return res;
+}
+
+//____________________________________________________________________________//
+
+void
+test_unit::add_label( const_string l )
+{
+ p_labels.value.push_back( std::string() + l );
+}
+
+//____________________________________________________________________________//
+
+bool
+test_unit::has_label( const_string l ) const
+{
+ return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** test_case ************** //
+// ************************************************************************** //
+
+test_case::test_case( const_string name, boost::function<void ()> const& test_func )
+: test_unit( name, "", 0, static_cast<test_unit_type>(type) )
+, p_test_func( test_func )
+{
+ framework::register_test_unit( this );
+}
+
+//____________________________________________________________________________//
+
+test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
+: test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
+, p_test_func( test_func )
+{
+ framework::register_test_unit( this );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** test_suite ************** //
+// ************************************************************************** //
+
+//____________________________________________________________________________//
+
+test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
+: test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
+{
+ framework::register_test_unit( this );
+}
+
+//____________________________________________________________________________//
+
+test_suite::test_suite( const_string module_name )
+: test_unit( module_name )
+{
+ framework::register_test_unit( this );
+}
+
+//____________________________________________________________________________//
+
+void
+test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
+{
+ tu->p_timeout.value = timeout;
+
+ m_children.push_back( tu->p_id );
+ tu->p_parent_id.value = p_id;
+
+ if( tu->p_expected_failures != 0 )
+ increase_exp_fail( tu->p_expected_failures );
+
+ if( expected_failures )
+ tu->increase_exp_fail( expected_failures );
+}
+
+//____________________________________________________________________________//
+
+void
+test_suite::add( test_unit_generator const& gen, unsigned timeout )
+{
+ test_unit* tu;
+ while((tu = gen.next()) != 0)
+ add( tu, 0, timeout );
+}
+
+//____________________________________________________________________________//
+
+void
+test_suite::add( test_unit_generator const& gen, decorator::collector& decorators )
+{
+ test_unit* tu;
+ while((tu = gen.next()) != 0) {
+ decorators.store_in( *tu );
+ add( tu, 0 );
+ }
+
+ decorators.reset();
+}
+
+//____________________________________________________________________________//
+
+void
+test_suite::remove( test_unit_id id )
+{
+ test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
+
+ if( it != m_children.end() )
+ m_children.erase( it );
+}
+
+//____________________________________________________________________________//
+
+test_unit_id
+test_suite::get( const_string tu_name ) const
+{
+ BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
+ if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
+ return id;
+ }
+
+ return INV_TEST_UNIT_ID;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** master_test_suite ************** //
+// ************************************************************************** //
+
+master_test_suite_t::master_test_suite_t()
+: test_suite( "Master Test Suite" )
+, argc( 0 )
+, argv( 0 )
+{
+ p_default_status.value = RS_ENABLED;
+}
+
+// ************************************************************************** //
+// ************** traverse_test_tree ************** //
+// ************************************************************************** //
+
+void
+traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
+{
+ if( tc.is_enabled() || ignore_status )
+ V.visit( tc );
+}
+
+//____________________________________________________________________________//
+
+void
+traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
+{
+ // skip disabled test suite unless we asked to ignore this condition
+ if( !ignore_status && !suite.is_enabled() )
+ return;
+
+ // Invoke test_suite_start callback
+ if( !V.test_suite_start( suite ) )
+ return;
+
+ // Recurse into children
+ std::size_t total_children = suite.m_children.size();
+ for( std::size_t i=0; i < total_children; ) {
+ // this statement can remove the test unit from this list
+ traverse_test_tree( suite.m_children[i], V, ignore_status );
+ if( total_children > suite.m_children.size() )
+ total_children = suite.m_children.size();
+ else
+ ++i;
+ }
+
+ // Invoke test_suite_finish callback
+ V.test_suite_finish( suite );
+}
+
+//____________________________________________________________________________//
+
+void
+traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
+{
+ if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
+ traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
+ else
+ traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** object generators ************** //
+// ************************************************************************** //
+
+namespace ut_detail {
+
+std::string
+normalize_test_case_name( const_string name )
+{
+ std::string norm_name( name.begin(), name.size() );
+
+ if( name[0] == '&' )
+ norm_name = norm_name.substr( 1 );
+
+ std::replace(norm_name.begin(), norm_name.end(), ' ', '_');
+
+ return norm_name;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** auto_test_unit_registrar ************** //
+// ************************************************************************** //
+
+auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector& decorators, counter_t exp_fail )
+{
+ framework::current_auto_test_suite().add( tc, exp_fail );
+
+ decorators.store_in( *tc );
+ decorators.reset();
+}
+
+//____________________________________________________________________________//
+
+auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector& decorators )
+{
+ test_unit_id id = framework::current_auto_test_suite().get( ts_name );
+
+ test_suite* ts;
+
+ if( id != INV_TEST_UNIT_ID ) {
+ ts = &framework::get<test_suite>( id );
+ BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
+ }
+ else {
+ ts = new test_suite( ts_name, ts_file, ts_line );
+ framework::current_auto_test_suite().add( ts );
+ }
+
+ decorators.store_in( *ts );
+ decorators.reset();
+
+ framework::current_auto_test_suite( ts );
+}
+
+//____________________________________________________________________________//
+
+auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector& decorators )
+{
+ framework::current_auto_test_suite().add( tc_gen, decorators );
+}
+
+//____________________________________________________________________________//
+
+auto_test_unit_registrar::auto_test_unit_registrar( int )
+{
+ framework::current_auto_test_suite( 0, false );
+}
+
+//____________________________________________________________________________//
+
+} // namespace ut_detail
+
+// ************************************************************************** //
+// ************** global_fixture ************** //
+// ************************************************************************** //
+
+global_fixture::global_fixture()
+{
+ framework::register_observer( *this );
+}
+
+//____________________________________________________________________________//
+
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
diff --git a/boost/test/impl/unit_test_log.ipp b/boost/test/impl/unit_test_log.ipp
index 7cb4f4b4a8..f202f5027d 100644
--- a/boost/test/impl/unit_test_log.ipp
+++ b/boost/test/impl/unit_test_log.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,10 +18,10 @@
// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/execution_monitor.hpp>
+#include <boost/test/framework.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
@@ -38,7 +38,6 @@ typedef ::boost::io::ios_base_all_saver io_saver_type;
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
// ************************************************************************** //
@@ -57,7 +56,7 @@ entry_value_collector::operator<<( lazy_ostream const& v ) const
//____________________________________________________________________________//
-entry_value_collector const&
+entry_value_collector const&
entry_value_collector::operator<<( const_string v ) const
{
unit_test_log << v;
@@ -194,7 +193,7 @@ unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
//____________________________________________________________________________//
void
-unit_test_log_t::test_unit_skipped( test_unit const& tu )
+unit_test_log_t::test_unit_skipped( test_unit const& tu, const_string reason )
{
if( s_log_impl().m_threshold_level > log_test_units )
return;
@@ -202,23 +201,7 @@ unit_test_log_t::test_unit_skipped( test_unit const& tu )
if( s_log_impl().m_entry_in_progress )
*this << log::end();
- s_log_impl().m_log_formatter->test_unit_skipped( s_log_impl().stream(), tu );
-}
-
-//____________________________________________________________________________//
-
-void
-unit_test_log_t::test_unit_aborted( test_unit const& )
-{
- // do nothing
-}
-
-//____________________________________________________________________________//
-
-void
-unit_test_log_t::assertion_result( bool )
-{
- // do nothing
+ s_log_impl().m_log_formatter->test_unit_skipped( s_log_impl().stream(), tu, reason );
}
//____________________________________________________________________________//
@@ -235,8 +218,14 @@ unit_test_log_t::exception_caught( execution_exception const& ex )
if( s_log_impl().m_entry_in_progress )
*this << log::end();
- s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex );
+ s_log_impl().m_log_formatter->log_exception_start( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex );
+
+ log_entry_context( l );
+
+ s_log_impl().m_log_formatter->log_exception_finish( s_log_impl().stream() );
}
+
+ clear_entry_context();
}
//____________________________________________________________________________//
@@ -254,7 +243,7 @@ set_unix_slash( char in )
{
return in == '\\' ? '/' : in;
}
-
+
unit_test_log_t&
unit_test_log_t::operator<<( log::begin const& b )
{
@@ -282,10 +271,15 @@ unit_test_log_t::operator<<( log::begin const& b )
unit_test_log_t&
unit_test_log_t::operator<<( log::end const& )
{
- if( s_log_impl().m_entry_in_progress )
+ if( s_log_impl().m_entry_in_progress ) {
+ log_entry_context( s_log_impl().m_entry_data.m_level );
+
s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() );
- s_log_impl().m_entry_in_progress = false;
+ s_log_impl().m_entry_in_progress = false;
+ }
+
+ clear_entry_context();
return *this;
}
@@ -315,7 +309,7 @@ unit_test_log_t::operator()( log_level l )
bool
unit_test_log_t::log_entry_start()
{
- if( s_log_impl().m_entry_in_progress )
+ if( s_log_impl().m_entry_in_progress )
return true;
switch( s_log_impl().m_entry_data.m_level ) {
@@ -377,6 +371,33 @@ unit_test_log_t::operator<<( lazy_ostream const& value )
//____________________________________________________________________________//
void
+unit_test_log_t::log_entry_context( log_level l )
+{
+ framework::context_generator const& context = framework::get_context();
+ if( context.is_empty() )
+ return;
+
+ const_string frame;
+
+ s_log_impl().m_log_formatter->entry_context_start( s_log_impl().stream(), l );
+
+ while( !(frame=context.next()).is_empty() )
+ s_log_impl().m_log_formatter->log_entry_context( s_log_impl().stream(), frame );
+
+ s_log_impl().m_log_formatter->entry_context_finish( s_log_impl().stream() );
+}
+
+//____________________________________________________________________________//
+
+void
+unit_test_log_t::clear_entry_context()
+{
+ framework::clear_context();
+}
+
+//____________________________________________________________________________//
+
+void
unit_test_log_t::set_stream( std::ostream& str )
{
if( s_log_impl().m_entry_in_progress )
@@ -405,10 +426,15 @@ unit_test_log_t::set_format( output_format log_format )
if( s_log_impl().m_entry_in_progress )
return;
- if( log_format == CLF )
+ switch( log_format ) {
+ default:
+ case OF_CLF:
set_formatter( new output::compiler_log_formatter );
- else
+ break;
+ case OF_XML:
set_formatter( new output::xml_log_formatter );
+ break;
+ }
}
//____________________________________________________________________________//
@@ -434,11 +460,8 @@ unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const
//____________________________________________________________________________//
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
diff --git a/boost/test/impl/unit_test_main.ipp b/boost/test/impl/unit_test_main.ipp
index adedf35180..327e14de30 100644
--- a/boost/test/impl/unit_test_main.ipp
+++ b/boost/test/impl/unit_test_main.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Gennadiy Rozental 2001-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,154 +18,164 @@
// Boost.Test
#include <boost/test/framework.hpp>
#include <boost/test/results_collector.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/results_reporter.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/tree/visitor.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/tree/traverse.hpp>
-#if !defined(__BORLANDC__) && !BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
-#define BOOST_TEST_SUPPORT_RUN_BY_NAME
-#include <boost/test/utils/iterator/token_iterator.hpp>
-#endif
+#include <boost/test/unit_test_parameters.hpp>
+
+#include <boost/test/utils/foreach.hpp>
+#include <boost/test/utils/basic_cstring/io.hpp>
// Boost
#include <boost/cstdlib.hpp>
-#include <boost/bind.hpp>
// STL
+#include <cstdio>
#include <stdexcept>
#include <iostream>
+#include <iomanip>
+#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
+namespace ut_detail {
+
// ************************************************************************** //
-// ************** test_case_filter ************** //
+// ************** hrf_content_reporter ************** //
// ************************************************************************** //
-class test_case_filter : public test_tree_visitor {
-public:
- struct single_filter {
- single_filter( const_string in )
- {
- if( in == "*" )
- m_kind = SFK_ALL;
- else if( first_char( in ) == '*' && last_char( in ) == '*' ) {
- m_kind = SFK_SUBSTR;
- m_value = in.substr( 1, in.size()-1 );
- }
- else if( first_char( in ) == '*' ) {
- m_kind = SFK_TRAILING;
- m_value = in.substr( 1 );
- }
- else if( last_char( in ) == '*' ) {
- m_kind = SFK_LEADING;
- m_value = in.substr( 0, in.size()-1 );
- }
- else {
- m_kind = SFK_MATCH;
- m_value = in;
- }
- };
+struct hrf_content_reporter : test_tree_visitor {
+ explicit hrf_content_reporter( std::ostream& os ) : m_os( os ), m_indent( -4 ) {} // skip master test suite
- bool pass( test_unit const& tu ) const
- {
- const_string name( tu.p_name );
-
- switch( m_kind ) {
- default:
- case SFK_ALL:
- return true;
+private:
+ void report_test_unit( test_unit const& tu )
+ {
+ m_os << std::setw( m_indent ) << "" << tu.p_name;
+ m_os << (tu.p_default_status == test_unit::RS_ENABLED ? "*" : " ");
+ //m_os << '[' << tu.p_sibling_rank << ']';
+ if( !tu.p_description->empty() )
+ m_os << ": " << tu.p_description;
- case SFK_LEADING:
- return name.substr( 0, m_value.size() ) == m_value;
+ m_os << "\n";
+ }
+ virtual void visit( test_case const& tc ) { report_test_unit( tc ); }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( m_indent >= 0 )
+ report_test_unit( ts );
+ m_indent += 4;
+ return true;
+ }
+ virtual void test_suite_finish( test_suite const& )
+ {
+ m_indent -= 4;
+ }
- case SFK_TRAILING:
- return name.size() >= m_value.size() && name.substr( name.size() - m_value.size() ) == m_value;
+ // Data members
+ std::ostream& m_os;
+ int m_indent;
+};
- case SFK_SUBSTR:
- return name.find( m_value ) != const_string::npos;
+// ************************************************************************** //
+// ************** dot_content_reporter ************** //
+// ************************************************************************** //
- case SFK_MATCH:
- return m_value == tu.p_name.get();
- }
- }
- enum kind { SFK_ALL, SFK_LEADING, SFK_TRAILING, SFK_SUBSTR, SFK_MATCH };
-
- kind m_kind;
- const_string m_value;
- };
- // Constructor
-#ifndef BOOST_TEST_SUPPORT_RUN_BY_NAME
- explicit test_case_filter( const_string ) : m_depth( 0 ) {}
-#else
- explicit test_case_filter( const_string tc_to_run )
- : m_depth( 0 )
+struct dot_content_reporter : test_tree_visitor {
+ explicit dot_content_reporter( std::ostream& os ) : m_os( os ) {}
+
+private:
+ void report_test_unit( test_unit const& tu )
{
- string_token_iterator tit( tc_to_run, (dropped_delimeters = "/", kept_delimeters = dt_none) );
+ bool master_ts = tu.p_parent_id == INV_TEST_UNIT_ID;
- while( tit != string_token_iterator() ) {
- m_filters.push_back(
- std::vector<single_filter>( string_token_iterator( *tit, (dropped_delimeters = ",", kept_delimeters = dt_none) ),
- string_token_iterator() ) );
+ m_os << "tu" << tu.p_id;
- ++tit;
- }
- }
-#endif
-
- void filter_unit( test_unit const& tu )
- {
- if( (++m_depth - 1) > m_filters.size() ) {
- tu.p_enabled.value = true;
- return;
- }
+ m_os << (master_ts ? "[shape=ellipse,peripheries=2" : "[shape=Mrecord" );
- if( m_depth == 1 )
- return;
+ m_os << ",fontname=Helvetica";
- std::vector<single_filter> const& filters = m_filters[m_depth-2];
+ m_os << (tu.is_enabled() ? ",color=green" : ",color=yellow");
- tu.p_enabled.value =
- std::find_if( filters.begin(), filters.end(), bind( &single_filter::pass, _1, boost::ref(tu) ) ) != filters.end();
- }
+ if( master_ts )
+ m_os << ",label=\"" << tu.p_name << "\"];\n";
+ else {
+ m_os << ",label=\"" << tu.p_name << "|" << tu.p_file_name << "(" << tu.p_line_num << ")";
+ if( tu.p_timeout > 0 )
+ m_os << "|timeout=" << tu.p_timeout;
+ if( tu.p_expected_failures != 0 )
+ m_os << "|expected failures=" << tu.p_expected_failures;
+ if( !tu.p_labels->empty() ) {
+ m_os << "|labels:";
- // test tree visitor interface
- virtual void visit( test_case const& tc )
- {
- if( m_depth < m_filters.size() ) {
- tc.p_enabled.value = false;
- return;
+ BOOST_TEST_FOREACH( std::string const&, l, tu.p_labels.get() )
+ m_os << " @" << l;
+ }
+ m_os << "\"];\n";
}
- filter_unit( tc );
+ if( !master_ts )
+ m_os << "tu" << tu.p_parent_id << " -> " << "tu" << tu.p_id << ";\n";
- --m_depth;
- }
+ BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
+ test_unit const& dep = framework::get( dep_id, TUT_ANY );
- virtual bool test_suite_start( test_suite const& ts )
+ m_os << "tu" << tu.p_id << " -> " << "tu" << dep.p_id << "[color=red,style=dotted,constraint=false];\n";
+ }
+
+ }
+ virtual void visit( test_case const& tc )
{
- filter_unit( ts );
+ report_test_unit( tc );
+ }
+ virtual bool test_suite_start( test_suite const& ts )
+ {
+ if( ts.p_parent_id == INV_TEST_UNIT_ID )
+ m_os << "digraph G {rankdir=LR;\n";
- if( !ts.p_enabled )
- --m_depth;
+ report_test_unit( ts );
- return ts.p_enabled;
+ m_os << "{\n";
+
+ return true;
+ }
+ virtual void test_suite_finish( test_suite const& ts )
+ {
+ m_os << "}\n";
+ if( ts.p_parent_id == INV_TEST_UNIT_ID )
+ m_os << "}\n";
}
- virtual void test_suite_finish( test_suite const& ) { --m_depth; }
+ std::ostream& m_os;
+};
+
+// ************************************************************************** //
+// ************** labels_collector ************** //
+// ************************************************************************** //
+
+struct labels_collector : test_tree_visitor {
+ std::set<std::string> const& labels() const { return m_labels; }
private:
+ virtual bool visit( test_unit const& tu )
+ {
+ m_labels.insert( tu.p_labels->begin(), tu.p_labels->end() );
+ return true;
+ }
+
// Data members
- std::vector<std::vector<single_filter> > m_filters;
- unsigned m_depth;
+ std::set<std::string> m_labels;
};
+} // namespace ut_detail
+
// ************************************************************************** //
// ************** unit_test_main ************** //
// ************************************************************************** //
@@ -173,45 +183,81 @@ private:
int BOOST_TEST_DECL
unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
{
- try {
+ int result_code = 0;
+
+ BOOST_TEST_IMPL_TRY {
framework::init( init_func, argc, argv );
- if( !runtime_config::test_to_run().is_empty() ) {
- test_case_filter filter( runtime_config::test_to_run() );
+ if( runtime_config::wait_for_debugger() ) {
+ results_reporter::get_stream() << "Press any key to continue..." << std::endl;
+
+ std::getchar();
+ results_reporter::get_stream() << "Continuing..." << std::endl;
+ }
+
+ framework::finalize_setup_phase();
+
+ if( runtime_config::list_content() != unit_test::OF_INVALID ) {
+ if( runtime_config::list_content() == unit_test::OF_DOT ) {
+ ut_detail::dot_content_reporter reporter( results_reporter::get_stream() );
+
+ traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
+ }
+ else {
+ ut_detail::hrf_content_reporter reporter( results_reporter::get_stream() );
+
+ traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
+ }
- traverse_test_tree( framework::master_test_suite().p_id, filter );
+ return boost::exit_success;
+ }
+
+ if( runtime_config::list_labels() ) {
+ ut_detail::labels_collector collector;
+
+ traverse_test_tree( framework::master_test_suite().p_id, collector, true );
+
+ results_reporter::get_stream() << "Available labels:\n ";
+ std::copy( collector.labels().begin(), collector.labels().end(),
+ std::ostream_iterator<std::string>( results_reporter::get_stream(), "\n " ) );
+ results_reporter::get_stream() << "\n";
+
+ return boost::exit_success;
}
framework::run();
results_reporter::make_report();
- return runtime_config::no_result_code()
- ? boost::exit_success
- : results_collector.results( framework::master_test_suite().p_id ).result_code();
+ result_code = runtime_config::no_result_code()
+ ? boost::exit_success
+ : results_collector.results( framework::master_test_suite().p_id ).result_code();
}
- catch( framework::nothing_to_test const& ) {
- return boost::exit_success;
+ BOOST_TEST_IMPL_CATCH0( framework::nothing_to_test ) {
+ result_code = boost::exit_success;
}
- catch( framework::internal_error const& ex ) {
+ BOOST_TEST_IMPL_CATCH( framework::internal_error, ex ) {
results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
-
- return boost::exit_exception_failure;
+
+ result_code = boost::exit_exception_failure;
}
- catch( framework::setup_error const& ex ) {
+ BOOST_TEST_IMPL_CATCH( framework::setup_error, ex ) {
results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
-
- return boost::exit_exception_failure;
+
+ result_code = boost::exit_exception_failure;
}
- catch( ... ) {
+ BOOST_TEST_IMPL_CATCHALL() {
results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
-
- return boost::exit_exception_failure;
+
+ result_code = boost::exit_exception_failure;
}
+
+ framework::shutdown();
+
+ return result_code;
}
} // namespace unit_test
-
} // namespace boost
#if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
diff --git a/boost/test/impl/unit_test_monitor.ipp b/boost/test/impl/unit_test_monitor.ipp
index dc912f544e..8c931f203f 100644
--- a/boost/test/impl/unit_test_monitor.ipp
+++ b/boost/test/impl/unit_test_monitor.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,57 +18,34 @@
// Boost.Test
#include <boost/test/unit_test_monitor.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
-#include <boost/test/test_tools.hpp>
#include <boost/test/framework.hpp>
-
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/tree/test_unit.hpp>
+#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-namespace {
-
-template<typename F>
-struct zero_return_wrapper_t {
- explicit zero_return_wrapper_t( F const& f ) : m_f( f ) {}
-
- int operator()() { m_f(); return 0; }
-
- F const& m_f;
-};
-
-template<typename F>
-zero_return_wrapper_t<F>
-zero_return_wrapper( F const& f )
-{
- return zero_return_wrapper_t<F>( f );
-}
-
-}
-
// ************************************************************************** //
// ************** unit_test_monitor ************** //
// ************************************************************************** //
unit_test_monitor_t::error_level
-unit_test_monitor_t::execute_and_translate( test_case const& tc )
+unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned timeout )
{
- try {
+ BOOST_TEST_IMPL_TRY {
p_catch_system_errors.value = runtime_config::catch_sys_errors();
- p_timeout.value = tc.p_timeout.get();
+ p_timeout.value = timeout;
p_auto_start_dbg.value = runtime_config::auto_start_dbg();
p_use_alt_stack.value = runtime_config::use_alt_stack();
p_detect_fp_exceptions.value = runtime_config::detect_fp_exceptions();
- execute( callback0<int>( zero_return_wrapper( tc.test_func() ) ) );
+ vexecute( func );
}
- catch( execution_exception const& ex ) {
+ BOOST_TEST_IMPL_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
framework::test_unit_aborted( framework::current_test_case() );
@@ -91,11 +68,8 @@ unit_test_monitor_t::execute_and_translate( test_case const& tc )
//____________________________________________________________________________//
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
diff --git a/boost/test/impl/unit_test_parameters.ipp b/boost/test/impl/unit_test_parameters.ipp
index f220792b34..2ffa495e67 100644
--- a/boost/test/impl/unit_test_parameters.ipp
+++ b/boost/test/impl/unit_test_parameters.ipp
@@ -1,4 +1,4 @@
-// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Gennadiy Rozental 2001-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -19,7 +19,7 @@
#define BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
// Boost.Test
-#include <boost/test/detail/unit_test_parameters.hpp>
+#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
@@ -27,6 +27,8 @@
#include <boost/test/debug.hpp>
#include <boost/test/framework.hpp>
+#include <boost/test/detail/throw_exception.hpp>
+
// Boost.Runtime.Param
#include <boost/test/utils/runtime/cla/dual_name_parameter.hpp>
#include <boost/test/utils/runtime/cla/parser.hpp>
@@ -34,14 +36,12 @@
namespace rt = boost::runtime;
namespace cla = rt::cla;
-
#ifndef UNDER_CE
#include <boost/test/utils/runtime/env/variable.hpp>
namespace env = rt::env;
#endif
-
// Boost
#include <boost/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -63,7 +63,6 @@ namespace std { using ::getenv; using ::strncmp; using ::strcmp; }
# endif
namespace boost {
-
namespace unit_test {
// ************************************************************************** //
@@ -127,18 +126,19 @@ std::istream&
operator>>( std::istream& in, unit_test::output_format& of )
{
fixed_mapping<const_string,unit_test::output_format,case_ins_less<char const> > output_format_name (
- "HRF", unit_test::CLF,
- "CLF", unit_test::CLF,
- "XML", unit_test::XML,
+ "HRF", unit_test::OF_CLF,
+ "CLF", unit_test::OF_CLF,
+ "XML", unit_test::OF_XML,
+ "DOT", unit_test::OF_DOT,
- unit_test::INV_OF
+ unit_test::OF_INVALID
);
std::string val;
in >> val;
of = output_format_name[val];
- BOOST_TEST_SETUP_ASSERT( of != unit_test::INV_OF, "invalid output format " + val );
+ BOOST_TEST_SETUP_ASSERT( of != unit_test::OF_INVALID, "invalid output format " + val );
return in;
}
@@ -158,8 +158,11 @@ std::string AUTO_START_DBG = "auto_start_dbg";
std::string BREAK_EXEC_PATH = "break_exec_path";
std::string BUILD_INFO = "build_info";
std::string CATCH_SYS_ERRORS = "catch_system_errors";
+std::string COLOR_OUTPUT = "color_output";
std::string DETECT_FP_EXCEPT = "detect_fp_exceptions";
std::string DETECT_MEM_LEAKS = "detect_memory_leaks";
+std::string LIST_CONTENT = "list_content";
+std::string LIST_LABELS = "list_labels";
std::string LOG_FORMAT = "log_format";
std::string LOG_LEVEL = "log_level";
std::string LOG_SINK = "log_sink";
@@ -173,39 +176,55 @@ std::string TESTS_TO_RUN = "run_test";
std::string SAVE_TEST_PATTERN = "save_pattern";
std::string SHOW_PROGRESS = "show_progress";
std::string USE_ALT_STACK = "use_alt_stack";
+std::string WAIT_FOR_DEBUGGER = "wait_for_debugger";
+
+static const_string
+parameter_2_env_var( const_string param_name )
+{
+ typedef std::map<const_string,const_string> mtype;
+ static mtype s_mapping;
+
+ if( s_mapping.empty() ) {
+ s_mapping[AUTO_START_DBG] = "BOOST_TEST_AUTO_START_DBG";
+ s_mapping[BREAK_EXEC_PATH] = "BOOST_TEST_BREAK_EXEC_PATH";
+ s_mapping[BUILD_INFO] = "BOOST_TEST_BUILD_INFO";
+ s_mapping[CATCH_SYS_ERRORS] = "BOOST_TEST_CATCH_SYSTEM_ERRORS";
+ s_mapping[COLOR_OUTPUT] = "BOOST_TEST_COLOR_OUTPUT";
+ s_mapping[DETECT_FP_EXCEPT] = "BOOST_TEST_DETECT_FP_EXCEPTIONS";
+ s_mapping[DETECT_MEM_LEAKS] = "BOOST_TEST_DETECT_MEMORY_LEAK";
+ s_mapping[LIST_CONTENT] = "BOOST_TEST_LIST_CONTENT";
+ s_mapping[LIST_CONTENT] = "BOOST_TEST_LIST_LABELS";
+ s_mapping[LOG_FORMAT] = "BOOST_TEST_LOG_FORMAT";
+ s_mapping[LOG_LEVEL] = "BOOST_TEST_LOG_LEVEL";
+ s_mapping[LOG_SINK] = "BOOST_TEST_LOG_SINK";
+ s_mapping[OUTPUT_FORMAT] = "BOOST_TEST_OUTPUT_FORMAT";
+ s_mapping[RANDOM_SEED] = "BOOST_TEST_RANDOM";
+ s_mapping[REPORT_FORMAT] = "BOOST_TEST_REPORT_FORMAT";
+ s_mapping[REPORT_LEVEL] = "BOOST_TEST_REPORT_LEVEL";
+ s_mapping[REPORT_SINK] = "BOOST_TEST_REPORT_SINK";
+ s_mapping[RESULT_CODE] = "BOOST_TEST_RESULT_CODE";
+ s_mapping[TESTS_TO_RUN] = "BOOST_TESTS_TO_RUN";
+ s_mapping[SAVE_TEST_PATTERN] = "BOOST_TEST_SAVE_PATTERN";
+ s_mapping[SHOW_PROGRESS] = "BOOST_TEST_SHOW_PROGRESS";
+ s_mapping[USE_ALT_STACK] = "BOOST_TEST_USE_ALT_STACK";
+ s_mapping[WAIT_FOR_DEBUGGER] = "BOOST_TEST_WAIT_FOR_DEBUGGER";
+ }
-fixed_mapping<const_string,const_string> parameter_2_env_var(
- AUTO_START_DBG , "BOOST_TEST_AUTO_START_DBG",
- BREAK_EXEC_PATH , "BOOST_TEST_BREAK_EXEC_PATH",
- BUILD_INFO , "BOOST_TEST_BUILD_INFO",
- CATCH_SYS_ERRORS , "BOOST_TEST_CATCH_SYSTEM_ERRORS",
- DETECT_FP_EXCEPT , "BOOST_TEST_DETECT_FP_EXCEPTIONS",
- DETECT_MEM_LEAKS , "BOOST_TEST_DETECT_MEMORY_LEAK",
- LOG_FORMAT , "BOOST_TEST_LOG_FORMAT",
- LOG_LEVEL , "BOOST_TEST_LOG_LEVEL",
- LOG_SINK , "BOOST_TEST_LOG_SINK",
- OUTPUT_FORMAT , "BOOST_TEST_OUTPUT_FORMAT",
- RANDOM_SEED , "BOOST_TEST_RANDOM",
- REPORT_FORMAT , "BOOST_TEST_REPORT_FORMAT",
- REPORT_LEVEL , "BOOST_TEST_REPORT_LEVEL",
- REPORT_SINK , "BOOST_TEST_REPORT_SINK",
- RESULT_CODE , "BOOST_TEST_RESULT_CODE",
- TESTS_TO_RUN , "BOOST_TESTS_TO_RUN",
- SAVE_TEST_PATTERN , "BOOST_TEST_SAVE_PATTERN",
- SHOW_PROGRESS , "BOOST_TEST_SHOW_PROGRESS",
- USE_ALT_STACK , "BOOST_TEST_USE_ALT_STACK",
-
- ""
-);
+ mtype::const_iterator it = s_mapping.find( param_name );
+
+ return it == s_mapping.end() ? const_string() : it->second;
+}
//____________________________________________________________________________//
// storage for the CLAs
-cla::parser s_cla_parser;
-std::string s_empty;
+cla::parser s_cla_parser;
+std::string s_empty;
+
+output_format s_report_format;
+output_format s_log_format;
-output_format s_report_format;
-output_format s_log_format;
+std::list<std::string> s_test_to_run;
//____________________________________________________________________________//
@@ -229,7 +248,7 @@ retrieve_parameter( const_string parameter_name, cla::parser const& s_cla_parser
boost::optional<T> v;
#ifndef UNDER_CE
- env::get( parameter_2_env_var[parameter_name], v );
+ env::get( parameter_2_env_var(parameter_name), v );
#endif
if( v )
@@ -240,101 +259,127 @@ retrieve_parameter( const_string parameter_name, cla::parser const& s_cla_parser
//____________________________________________________________________________//
-} // local namespace
+void
+disable_use( cla::parameter const&, std::string const& )
+{
+ BOOST_TEST_SETUP_ASSERT( false, "parameter break_exec_path is disabled in this release" );
+}
+
+//____________________________________________________________________________//
+
+} // local namespace
void
init( int& argc, char** argv )
{
using namespace cla;
- try {
- s_cla_parser - cla::ignore_mismatch
- << cla::dual_name_parameter<bool>( AUTO_START_DBG + "|d" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Automatically starts debugger if system level error (signal) occurs")
- << cla::named_parameter<std::string>( BREAK_EXEC_PATH )
- - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "For the exception safety testing allows to break at specific execution path")
- << cla::dual_name_parameter<bool>( BUILD_INFO + "|i" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Shows library build information" )
- << cla::dual_name_parameter<bool>( CATCH_SYS_ERRORS + "|s" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Allows to switch between catching and ignoring system errors (signals)")
- << cla::named_parameter<bool>( DETECT_FP_EXCEPT )
- - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "Allows to switch between catching and ignoring floating point exceptions")
- << cla::named_parameter<long>( DETECT_MEM_LEAKS )
- - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "Allows to switch between catching and ignoring memory leaks")
- << cla::dual_name_parameter<unit_test::output_format>( LOG_FORMAT + "|f" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies log format")
- << cla::dual_name_parameter<unit_test::log_level>( LOG_LEVEL + "|l" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies log level")
- << cla::dual_name_parameter<std::string>( LOG_SINK + "|k" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies log sink:stdout(default),stderr or file name")
- << cla::dual_name_parameter<unit_test::output_format>( OUTPUT_FORMAT + "|o" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies output format (both log and report)")
- << cla::dual_name_parameter<int>( RANDOM_SEED + "|a" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,cla::optional_value,
- cla::description = "Allows to switch between sequential and random order of test units execution.\n"
- "Optionally allows to specify concrete seed for random number generator")
- << cla::dual_name_parameter<unit_test::output_format>( REPORT_FORMAT + "|m" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies report format")
- << cla::dual_name_parameter<unit_test::report_level>(REPORT_LEVEL + "|r")
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies report level")
- << cla::dual_name_parameter<std::string>( REPORT_SINK + "|e" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Specifies report sink:stderr(default),stdout or file name")
- << cla::dual_name_parameter<bool>( RESULT_CODE + "|c" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Allows to disable test modules's result code generation")
- << cla::dual_name_parameter<std::string>( TESTS_TO_RUN + "|t" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Allows to filter which test units to run")
- << cla::named_parameter<bool>( SAVE_TEST_PATTERN )
- - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "Allows to switch between saving and matching against test pattern file")
- << cla::dual_name_parameter<bool>( SHOW_PROGRESS + "|p" )
- - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
- cla::description = "Turns on progress display")
- << cla::named_parameter<bool>( USE_ALT_STACK )
- - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "Turns on/off usage of an alternative stack for signal handling")
-
- << cla::dual_name_parameter<bool>( "help|?" )
- - (cla::prefix = "--|-",cla::separator = "=",cla::guess_name,cla::optional,
- cla::description = "this help message")
- ;
+ BOOST_TEST_IMPL_TRY {
+ if( s_cla_parser.num_params() != 0 )
+ s_cla_parser.reset();
+ else
+ s_cla_parser - cla::ignore_mismatch
+ << cla::dual_name_parameter<bool>( AUTO_START_DBG + "|d" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Automatically starts debugger if system level error (signal) occurs")
+ << cla::named_parameter<std::string>( BREAK_EXEC_PATH )
+ - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
+ cla::description = "For the exception safety testing allows to break at specific execution path",
+ cla::handler = &disable_use)
+ << cla::dual_name_parameter<bool>( BUILD_INFO + "|i" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Shows library build information" )
+ << cla::dual_name_parameter<bool>( CATCH_SYS_ERRORS + "|s" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Allows to switch between catching and ignoring system errors (signals)")
+ << cla::dual_name_parameter<bool>( COLOR_OUTPUT + "|x" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Allows to switch between catching and ignoring system errors (signals)")
+ << cla::named_parameter<bool>( DETECT_FP_EXCEPT )
+ - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
+ cla::description = "Allows to switch between catching and ignoring floating point exceptions")
+ << cla::named_parameter<std::string>( DETECT_MEM_LEAKS )
+ - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,cla::optional_value,
+ cla::description = "Allows to switch between catching and ignoring memory leaks")
+ << cla::dual_name_parameter<unit_test::output_format>( LOG_FORMAT + "|f" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies log format")
+ << cla::dual_name_parameter<unit_test::log_level>( LOG_LEVEL + "|l" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies log level")
+ << cla::dual_name_parameter<std::string>( LOG_SINK + "|k" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies log sink:stdout(default),stderr or file name")
+ << cla::dual_name_parameter<unit_test::output_format>( OUTPUT_FORMAT + "|o" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies output format (both log and report)")
+ << cla::dual_name_parameter<unsigned>( RANDOM_SEED + "|a" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,cla::optional_value,
+ cla::description = "Allows to switch between sequential and random order of test units execution.\n"
+ "Optionally allows to specify concrete seed for random number generator")
+ << cla::dual_name_parameter<unit_test::output_format>( REPORT_FORMAT + "|m" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies report format")
+ << cla::dual_name_parameter<unit_test::report_level>(REPORT_LEVEL + "|r")
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies report level")
+ << cla::dual_name_parameter<std::string>( REPORT_SINK + "|e" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Specifies report sink:stderr(default),stdout or file name")
+ << cla::dual_name_parameter<bool>( RESULT_CODE + "|c" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Allows to disable test modules's result code generation")
+ << cla::dual_name_parameter<std::string>( TESTS_TO_RUN + "|t" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,cla::multiplicable,
+ cla::description = "Allows to filter which test units to run")
+ << cla::named_parameter<bool>( SAVE_TEST_PATTERN )
+ - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
+ cla::description = "Allows to switch between saving and matching against test pattern file")
+ << cla::dual_name_parameter<bool>( SHOW_PROGRESS + "|p" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,
+ cla::description = "Turns on progress display")
+ << cla::dual_name_parameter<unit_test::output_format>( LIST_CONTENT + "|j" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,cla::optional_value,
+ cla::description = "Lists the content of test tree - names of all test suites and test cases")
+ << cla::named_parameter<bool>( LIST_LABELS )
+ - (cla::prefix = "--",cla::separator = "= ",cla::guess_name,cla::optional,
+ cla::description = "Lists all available labels")
+ << cla::named_parameter<bool>( USE_ALT_STACK )
+ - (cla::prefix = "--",cla::separator = "=",cla::guess_name,cla::optional,
+ cla::description = "Turns on/off usage of an alternative stack for signal handling")
+ << cla::dual_name_parameter<bool>( WAIT_FOR_DEBUGGER + "|w" )
+ - (cla::prefix = "--|-",cla::separator = "=| ",cla::guess_name,cla::optional,cla::optional_value,
+ cla::description = "Forces test module to wait for button to be pressed before starting test run")
+
+ << cla::dual_name_parameter<bool>( "help|?" )
+ - (cla::prefix = "--|-",cla::separator = "=",cla::guess_name,cla::optional,
+ cla::description = "this help message")
+ ;
s_cla_parser.parse( argc, argv );
if( s_cla_parser["help"] ) {
s_cla_parser.help( std::cout );
- throw framework::nothing_to_test();
+ BOOST_TEST_IMPL_THROW( framework::nothing_to_test() );
}
- s_report_format = retrieve_parameter( REPORT_FORMAT, s_cla_parser, unit_test::CLF );
- s_log_format = retrieve_parameter( LOG_FORMAT, s_cla_parser, unit_test::CLF );
+ s_report_format = retrieve_parameter( REPORT_FORMAT, s_cla_parser, unit_test::OF_CLF );
+ s_log_format = retrieve_parameter( LOG_FORMAT, s_cla_parser, unit_test::OF_CLF );
- unit_test::output_format of = retrieve_parameter( OUTPUT_FORMAT, s_cla_parser, unit_test::INV_OF );
+ unit_test::output_format of = retrieve_parameter( OUTPUT_FORMAT, s_cla_parser, unit_test::OF_INVALID );
- if( of != unit_test::INV_OF )
+ if( of != unit_test::OF_INVALID )
s_report_format = s_log_format = of;
+
+ s_test_to_run = retrieve_parameter<std::list<std::string> >( TESTS_TO_RUN, s_cla_parser );
}
- catch( rt::logic_error const& ex ) {
+ BOOST_TEST_IMPL_CATCH( rt::logic_error, ex ) {
std::ostringstream err;
-
+
err << "Fail to process runtime parameters: " << ex.msg() << std::endl;
s_cla_parser.usage( err );
- throw framework::setup_error( err.str() );
+ BOOST_TEST_SETUP_ASSERT( false, err.str() );
}
}
@@ -364,11 +409,9 @@ report_level()
//____________________________________________________________________________//
-const_string
+std::list<std::string> const&
test_to_run()
{
- static std::string s_test_to_run = retrieve_parameter( TESTS_TO_RUN, s_cla_parser, s_empty );
-
return s_test_to_run;
}
@@ -408,14 +451,30 @@ show_build_info()
//____________________________________________________________________________//
+output_format
+list_content()
+{
+ return retrieve_parameter( LIST_CONTENT, s_cla_parser, unit_test::OF_INVALID, unit_test::OF_CLF );
+}
+
+//____________________________________________________________________________//
+
+bool
+list_labels()
+{
+ return retrieve_parameter( LIST_LABELS, s_cla_parser, false );
+}
+
+//____________________________________________________________________________//
+
bool
catch_sys_errors()
{
- return retrieve_parameter( CATCH_SYS_ERRORS, s_cla_parser,
+ return retrieve_parameter( CATCH_SYS_ERRORS, s_cla_parser,
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
false
#else
- true
+ true
#endif
);
}
@@ -423,9 +482,17 @@ catch_sys_errors()
//____________________________________________________________________________//
bool
+color_output()
+{
+ return retrieve_parameter( COLOR_OUTPUT, s_cla_parser, false );
+}
+
+//____________________________________________________________________________//
+
+bool
auto_start_dbg()
{
- // !! set debugger as an option
+ // !! ?? set debugger as an option
return retrieve_parameter( AUTO_START_DBG, s_cla_parser, false );
;
}
@@ -433,6 +500,14 @@ auto_start_dbg()
//____________________________________________________________________________//
bool
+wait_for_debugger()
+{
+ return retrieve_parameter( WAIT_FOR_DEBUGGER, s_cla_parser, false );
+}
+
+//____________________________________________________________________________//
+
+bool
use_alt_stack()
{
return retrieve_parameter( USE_ALT_STACK, s_cla_parser, true );
@@ -470,13 +545,13 @@ report_sink()
std::string sink_name = retrieve_parameter( REPORT_SINK, s_cla_parser, s_empty );
if( sink_name.empty() || sink_name == "stderr" )
- return &std::cerr;
-
+ return &std::cerr;
+
if( sink_name == "stdout" )
return &std::cout;
- static std::ofstream log_file( sink_name.c_str() );
- return &log_file;
+ static std::ofstream report_file( sink_name.c_str() );
+ return &report_file;
}
//____________________________________________________________________________//
@@ -487,13 +562,13 @@ log_sink()
std::string sink_name = retrieve_parameter( LOG_SINK, s_cla_parser, s_empty );
if( sink_name.empty() || sink_name == "stdout" )
- return &std::cout;
+ return &std::cout;
if( sink_name == "stderr" )
- return &std::cerr;
+ return &std::cerr;
- static std::ofstream report_file( sink_name.c_str() );
- return &report_file;
+ static std::ofstream log_file( sink_name.c_str() );
+ return &log_file;
}
//____________________________________________________________________________//
@@ -501,27 +576,65 @@ log_sink()
long
detect_memory_leaks()
{
- return retrieve_parameter( DETECT_MEM_LEAKS, s_cla_parser, static_cast<long>(1) );
+ static long s_value = -1;
+
+ if( s_value >= 0 )
+ return s_value;
+
+ std::string value = retrieve_parameter( DETECT_MEM_LEAKS, s_cla_parser, s_empty );
+
+ optional<bool> bool_val;
+ if( runtime::interpret_argument_value_impl<bool>::_( value, bool_val ) )
+ s_value = *bool_val ? 1L : 0L;
+ else {
+ BOOST_TEST_IMPL_TRY {
+ // if representable as long - this is leak number
+ s_value = boost::lexical_cast<long>( value );
+ }
+ BOOST_TEST_IMPL_CATCH0( boost::bad_lexical_cast ) {
+ // value is leak report file and detection is enabled
+ s_value = 1L;
+ }
+ }
+
+ return s_value;
+}
+
+//____________________________________________________________________________//
+
+const_string
+memory_leaks_report_file()
+{
+ if( detect_memory_leaks() != 1 )
+ return const_string();
+
+ static std::string s_value;
+
+ if( s_value.empty() ) {
+ s_value = retrieve_parameter<std::string>( DETECT_MEM_LEAKS, s_cla_parser );
+
+ optional<bool> bool_val;
+ if( runtime::interpret_argument_value_impl<bool>::_( s_value, bool_val ) )
+ s_value.clear();
+ }
+
+ return s_value;
}
//____________________________________________________________________________//
-int
+unsigned
random_seed()
{
- return retrieve_parameter( RANDOM_SEED, s_cla_parser, 0, 1 );
+ return retrieve_parameter( RANDOM_SEED, s_cla_parser, 0U, 1U );
}
//____________________________________________________________________________//
} // namespace runtime_config
-
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
diff --git a/boost/test/impl/unit_test_suite.ipp b/boost/test/impl/unit_test_suite.ipp
deleted file mode 100644
index 32efc6059e..0000000000
--- a/boost/test/impl/unit_test_suite.ipp
+++ /dev/null
@@ -1,346 +0,0 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-// See http://www.boost.org/libs/test for the library home page.
-//
-// File : $RCSfile$
-//
-// Version : $Revision$
-//
-// Description : privides core implementation for Unit Test Framework.
-// Extensions can be provided in separate files
-// ***************************************************************************
-
-#ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
-#define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
-
-// Boost.Test
-#include <boost/detail/workaround.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
-#include <boost/test/framework.hpp>
-#include <boost/test/utils/foreach.hpp>
-#include <boost/test/results_collector.hpp>
-#include <boost/test/detail/unit_test_parameters.hpp>
-
-// Boost
-#include <boost/timer.hpp>
-
-// STL
-#include <algorithm>
-#include <vector>
-
-#include <boost/test/detail/suppress_warnings.hpp>
-
-#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \
- BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450) \
- /**/
- using std::rand; // rand is in std and random_shuffle is in _STL
-#endif
-
-//____________________________________________________________________________//
-
-namespace boost {
-
-namespace unit_test {
-
-// ************************************************************************** //
-// ************** test_unit ************** //
-// ************************************************************************** //
-
-test_unit::test_unit( const_string name, test_unit_type t )
-: p_type( t )
-, p_type_name( t == tut_case ? "case" : "suite" )
-, p_id( INV_TEST_UNIT_ID )
-, p_name( std::string( name.begin(), name.size() ) )
-, p_enabled( true )
-{
-}
-
-//____________________________________________________________________________//
-
-test_unit::~test_unit()
-{
- framework::deregister_test_unit( this );
-}
-
-//____________________________________________________________________________//
-
-void
-test_unit::depends_on( test_unit* tu )
-{
- m_dependencies.push_back( tu->p_id );
-}
-
-//____________________________________________________________________________//
-
-bool
-test_unit::check_dependencies() const
-{
- BOOST_TEST_FOREACH( test_unit_id, tu_id, m_dependencies ) {
- if( !unit_test::results_collector.results( tu_id ).passed() )
- return false;
- }
-
- return true;
-}
-
-//____________________________________________________________________________//
-
-void
-test_unit::increase_exp_fail( unsigned num )
-{
- p_expected_failures.value += num;
-
- if( p_parent_id != 0 )
- framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** test_case ************** //
-// ************************************************************************** //
-
-test_case::test_case( const_string name, callback0<> const& test_func )
-: test_unit( name, static_cast<test_unit_type>(type) )
-, m_test_func( test_func )
-{
- // !! weirdest MSVC BUG; try to remove this statement; looks like it eats first token of next statement
-#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
- 0;
-#endif
- framework::register_test_unit( this );
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** test_suite ************** //
-// ************************************************************************** //
-
-//____________________________________________________________________________//
-
-test_suite::test_suite( const_string name )
-: test_unit( name, static_cast<test_unit_type>(type) )
-{
- framework::register_test_unit( this );
-}
-
-//____________________________________________________________________________//
-
-void
-test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
-{
- if( timeout != 0 )
- tu->p_timeout.value = timeout;
-
- m_members.push_back( tu->p_id );
- tu->p_parent_id.value = p_id;
-
- if( tu->p_expected_failures )
- increase_exp_fail( tu->p_expected_failures );
-
- if( expected_failures )
- tu->increase_exp_fail( expected_failures );
-}
-
-//____________________________________________________________________________//
-
-void
-test_suite::add( test_unit_generator const& gen, unsigned timeout )
-{
- test_unit* tu;
- while((tu = gen.next(), tu))
- add( tu, 0, timeout );
-}
-
-//____________________________________________________________________________//
-
-void
-test_suite::remove( test_unit_id id )
-{
- std::vector<test_unit_id>::iterator it = std::find( m_members.begin(), m_members.end(), id );
-
- if( it != m_members.end() )
- m_members.erase( it );
-}
-
-//____________________________________________________________________________//
-
-test_unit_id
-test_suite::get( const_string tu_name ) const
-{
- BOOST_TEST_FOREACH( test_unit_id, id, m_members ) {
- if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
- return id;
- }
-
- return INV_TEST_UNIT_ID;
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** traverse_test_tree ************** //
-// ************************************************************************** //
-
-void
-traverse_test_tree( test_case const& tc, test_tree_visitor& V )
-{
- if( tc.p_enabled )
- V.visit( tc );
-}
-
-//____________________________________________________________________________//
-
-void
-traverse_test_tree( test_suite const& suite, test_tree_visitor& V )
-{
- if( !suite.p_enabled || !V.test_suite_start( suite ) )
- return;
-
- try {
- if( runtime_config::random_seed() == 0 ) {
- BOOST_TEST_FOREACH( test_unit_id, id, suite.m_members )
- traverse_test_tree( id, V );
- }
- else {
- std::vector<test_unit_id> members( suite.m_members );
- std::random_shuffle( members.begin(), members.end() );
- BOOST_TEST_FOREACH( test_unit_id, id, members )
- traverse_test_tree( id, V );
- }
-
- } catch( test_being_aborted const& ) {
- V.test_suite_finish( suite );
- framework::test_unit_aborted( suite );
-
- throw;
- }
-
- V.test_suite_finish( suite );
-}
-
-//____________________________________________________________________________//
-
-void
-traverse_test_tree( test_unit_id id, test_tree_visitor& V )
-{
- if( ut_detail::test_id_2_unit_type( id ) == tut_case )
- traverse_test_tree( framework::get<test_case>( id ), V );
- else
- traverse_test_tree( framework::get<test_suite>( id ), V );
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** test_case_counter ************** //
-// ************************************************************************** //
-
-void
-test_case_counter::visit( test_case const& tc )
-{
- if( tc.p_enabled )
- ++p_count.value;
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** object generators ************** //
-// ************************************************************************** //
-
-namespace ut_detail {
-
-std::string
-normalize_test_case_name( const_string name )
-{
- return ( name[0] == '&'
- ? std::string( name.begin()+1, name.size()-1 )
- : std::string( name.begin(), name.size() ) );
-}
-
-//____________________________________________________________________________//
-
-// ************************************************************************** //
-// ************** auto_test_unit_registrar ************** //
-// ************************************************************************** //
-
-auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, counter_t exp_fail )
-{
- curr_ts_store().back()->add( tc, exp_fail );
-}
-
-//____________________________________________________________________________//
-
-auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name )
-{
- test_unit_id id = curr_ts_store().back()->get( ts_name );
-
- test_suite* ts;
-
- if( id != INV_TEST_UNIT_ID ) {
- ts = &framework::get<test_suite>( id ); // !! test for invalid tu type
- BOOST_ASSERT( ts->p_parent_id == curr_ts_store().back()->p_id );
- }
- else {
- ts = new test_suite( ts_name );
- curr_ts_store().back()->add( ts );
- }
-
- curr_ts_store().push_back( ts );
-}
-
-//____________________________________________________________________________//
-
-auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen )
-{
- curr_ts_store().back()->add( tc_gen );
-}
-
-//____________________________________________________________________________//
-
-auto_test_unit_registrar::auto_test_unit_registrar( int )
-{
- if( curr_ts_store().size() == 0 )
- return; // report error?
-
- curr_ts_store().pop_back();
-}
-
-//____________________________________________________________________________//
-
-std::list<test_suite*>&
-auto_test_unit_registrar::curr_ts_store()
-{
- static std::list<test_suite*> inst( 1, &framework::master_test_suite() );
- return inst;
-}
-
-//____________________________________________________________________________//
-
-} // namespace ut_detail
-
-// ************************************************************************** //
-// ************** global_fixture ************** //
-// ************************************************************************** //
-
-global_fixture::global_fixture()
-{
- framework::register_observer( *this );
-}
-
-//____________________________________________________________________________//
-
-} // namespace unit_test
-
-} // namespace boost
-
-//____________________________________________________________________________//
-
-#include <boost/test/detail/enable_warnings.hpp>
-
-#endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
diff --git a/boost/test/impl/xml_log_formatter.ipp b/boost/test/impl/xml_log_formatter.ipp
index 6c0127bb57..286cd60005 100644
--- a/boost/test/impl/xml_log_formatter.ipp
+++ b/boost/test/impl/xml_log_formatter.ipp
@@ -1,6 +1,6 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
@@ -9,7 +9,7 @@
//
// Version : $Revision$
//
-// Description : implements XML Log formatter
+// Description : implements OF_XML Log formatter
// ***************************************************************************
#ifndef BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
@@ -17,10 +17,10 @@
// Boost.Test
#include <boost/test/output/xml_log_formatter.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
+#include <boost/test/execution_monitor.hpp>
#include <boost/test/framework.hpp>
+#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
-
#include <boost/test/utils/xml_printer.hpp>
// Boost
@@ -34,14 +34,12 @@
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-
namespace output {
static const_string tu_type_name( test_unit const& tu )
{
- return tu.p_type == tut_case ? "TestCase" : "TestSuite";
+ return tu.p_type == TUT_CASE ? "TestCase" : "TestSuite";
}
// ************************************************************************** //
@@ -82,7 +80,13 @@ xml_log_formatter::log_build_info( std::ostream& ostr )
void
xml_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
{
- ostr << "<" << tu_type_name( tu ) << " name" << attr_value() << tu.p_name.get() << ">";
+ ostr << "<" << tu_type_name( tu ) << " name" << attr_value() << tu.p_name.get();
+
+ if( !tu.p_file_name.get().empty() )
+ ostr << BOOST_TEST_L( " file" ) << attr_value() << tu.p_file_name
+ << BOOST_TEST_L( " line" ) << attr_value() << tu.p_line_num;
+
+ ostr << ">";
}
//____________________________________________________________________________//
@@ -90,27 +94,28 @@ xml_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
void
xml_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
{
- if( tu.p_type == tut_case )
+ if( tu.p_type == TUT_CASE )
ostr << "<TestingTime>" << elapsed << "</TestingTime>";
-
+
ostr << "</" << tu_type_name( tu ) << ">";
}
//____________________________________________________________________________//
void
-xml_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu )
+xml_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu, const_string reason )
{
ostr << "<" << tu_type_name( tu )
<< " name" << attr_value() << tu.p_name.get()
<< " skipped" << attr_value() << "yes"
+ << " reason" << attr_value() << reason
<< "/>";
}
-
+
//____________________________________________________________________________//
void
-xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+xml_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
@@ -129,7 +134,13 @@ xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const&
<< cdata() << checkpoint_data.m_message
<< "</LastCheckpoint>";
}
+}
+
+//____________________________________________________________________________//
+void
+xml_log_formatter::log_exception_finish( std::ostream& ostr )
+{
ostr << "</Exception>";
}
@@ -145,6 +156,8 @@ xml_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& en
<< BOOST_TEST_L( " file" ) << attr_value() << entry_data.m_file_name
<< BOOST_TEST_L( " line" ) << attr_value() << entry_data.m_line_num
<< BOOST_TEST_L( "><![CDATA[" );
+
+ m_value_closed = false;
}
//____________________________________________________________________________//
@@ -152,7 +165,7 @@ xml_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& en
void
xml_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
{
- ostr << value;
+ print_escaped_cdata( ostr, value );
}
//____________________________________________________________________________//
@@ -160,21 +173,52 @@ xml_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
void
xml_log_formatter::log_entry_finish( std::ostream& ostr )
{
- ostr << BOOST_TEST_L( "]]></" ) << m_curr_tag << BOOST_TEST_L( ">" );
+ if( !m_value_closed ) {
+ ostr << BOOST_TEST_L( "]]>" );
+ m_value_closed = true;
+ }
+
+ ostr << BOOST_TEST_L( "</" ) << m_curr_tag << BOOST_TEST_L( ">" );
m_curr_tag.clear();
}
//____________________________________________________________________________//
-} // namespace output
+void
+xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
+{
+ if( !m_value_closed ) {
+ ostr << BOOST_TEST_L( "]]>" );
+ m_value_closed = true;
+ }
-} // namespace unit_test
+ ostr << BOOST_TEST_L( "<Context>" );
-} // namespace boost
+}
+
+//____________________________________________________________________________//
+
+void
+xml_log_formatter::entry_context_finish( std::ostream& ostr )
+{
+ ostr << BOOST_TEST_L( "</Context>" );
+}
//____________________________________________________________________________//
+void
+xml_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+{
+ ostr << BOOST_TEST_L( "<Frame>" ) << cdata() << context_descr << BOOST_TEST_L( "</Frame>" );
+}
+
+//____________________________________________________________________________//
+
+} // namespace output
+} // namespace unit_test
+} // namespace boost
+
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
diff --git a/boost/test/impl/xml_report_formatter.ipp b/boost/test/impl/xml_report_formatter.ipp
index 261db788b3..5606fdc0b1 100644
--- a/boost/test/impl/xml_report_formatter.ipp
+++ b/boost/test/impl/xml_report_formatter.ipp
@@ -1,6 +1,6 @@
-// (C) Copyright Gennadiy Rozental 2005-2008.
+// (C) Copyright Gennadiy Rozental 2005-2014.
// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
+// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
@@ -9,7 +9,7 @@
//
// Version : $Revision$
//
-// Description : XML report formatter
+// Description : OF_XML report formatter
// ***************************************************************************
#ifndef BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
@@ -17,9 +17,9 @@
// Boost.Test
#include <boost/test/results_collector.hpp>
-#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/output/xml_report_formatter.hpp>
+#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/xml_printer.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
@@ -28,9 +28,7 @@
//____________________________________________________________________________//
namespace boost {
-
namespace unit_test {
-
namespace output {
void
@@ -66,20 +64,23 @@ xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream&
else
descr = "failed";
- ostr << '<' << ( tu.p_type == tut_case ? "TestCase" : "TestSuite" )
+ ostr << '<' << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" )
<< " name" << attr_value() << tu.p_name.get()
<< " result" << attr_value() << descr
<< " assertions_passed" << attr_value() << tr.p_assertions_passed
<< " assertions_failed" << attr_value() << tr.p_assertions_failed
+ << " warnings_failed" << attr_value() << tr.p_warnings_failed
<< " expected_failures" << attr_value() << tr.p_expected_failures;
- if( tu.p_type == tut_suite )
+ if( tu.p_type == TUT_SUITE ) {
ostr << " test_cases_passed" << attr_value() << tr.p_test_cases_passed
+ << " test_cases_passed_with_warnings" << attr_value() << tr.p_test_cases_warned
<< " test_cases_failed" << attr_value() << tr.p_test_cases_failed
<< " test_cases_skipped" << attr_value() << tr.p_test_cases_skipped
<< " test_cases_aborted" << attr_value() << tr.p_test_cases_aborted;
-
-
+ }
+
+
ostr << '>';
}
@@ -88,7 +89,7 @@ xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream&
void
xml_report_formatter::test_unit_report_finish( test_unit const& tu, std::ostream& ostr )
{
- ostr << "</" << ( tu.p_type == tut_case ? "TestCase" : "TestSuite" ) << '>';
+ ostr << "</" << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" ) << '>';
}
//____________________________________________________________________________//
@@ -97,19 +98,15 @@ void
xml_report_formatter::do_confirmation_report( test_unit const& tu, std::ostream& ostr )
{
test_unit_report_start( tu, ostr );
- test_unit_report_finish( tu, ostr );
+ test_unit_report_finish( tu, ostr );
}
//____________________________________________________________________________//
} // namespace output
-
} // namespace unit_test
-
} // namespace boost
-//____________________________________________________________________________//
-
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER