mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 00:31:11 -06:00
Initial work for G-code sender and more intensive usage of Boost
This commit is contained in:
parent
43cbad8867
commit
11dd67ab34
1649 changed files with 1860 additions and 1642 deletions
222
xs/include/boost/test/impl/compiler_log_formatter.ipp
Normal file
222
xs/include/boost/test/impl/compiler_log_formatter.ipp
Normal file
|
@ -0,0 +1,222 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : implements compiler like Log formatter
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
|
||||
#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/utils/basic_cstring/io.hpp>
|
||||
#include <boost/test/utils/lazy_ostream.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
namespace output {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** compiler_log_formatter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
|
||||
const_string
|
||||
test_phase_identifier()
|
||||
{
|
||||
return framework::is_initialized()
|
||||
? const_string( framework::current_test_case().p_name.get() )
|
||||
: BOOST_TEST_L( "Test setup" );
|
||||
}
|
||||
|
||||
} // local namespace
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount )
|
||||
{
|
||||
if( test_cases_amount > 0 )
|
||||
output << "Running " << test_cases_amount << " test "
|
||||
<< (test_cases_amount > 1 ? "cases" : "case") << "...\n";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_finish( std::ostream& ostr )
|
||||
{
|
||||
ostr.flush();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_build_info( std::ostream& output )
|
||||
{
|
||||
output << "Platform: " << BOOST_PLATFORM << '\n'
|
||||
<< "Compiler: " << BOOST_COMPILER << '\n'
|
||||
<< "STL : " << BOOST_STDLIB << '\n'
|
||||
<< "Boost : " << BOOST_VERSION/100000 << "."
|
||||
<< BOOST_VERSION/100 % 1000 << "."
|
||||
<< BOOST_VERSION % 100 << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::test_unit_start( std::ostream& output, test_unit const& tu )
|
||||
{
|
||||
output << "Entering test " << tu.p_type_name << " \"" << tu.p_name << "\"" << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const& tu, unsigned long elapsed )
|
||||
{
|
||||
output << "Leaving test " << tu.p_type_name << " \"" << tu.p_name << "\"";
|
||||
|
||||
if( elapsed > 0 ) {
|
||||
output << "; testing time: ";
|
||||
if( elapsed % 1000 == 0 )
|
||||
output << elapsed/1000 << "ms";
|
||||
else
|
||||
output << elapsed << "mks";
|
||||
}
|
||||
|
||||
output << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu )
|
||||
{
|
||||
output << "Test " << tu.p_type_name << " \"" << tu.p_name << "\"" << "is skipped" << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_exception( 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 ) << "\": ";
|
||||
|
||||
output << 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 );
|
||||
output << "last checkpoint";
|
||||
if( !checkpoint_data.m_message.empty() )
|
||||
output << ": " << checkpoint_data.m_message;
|
||||
}
|
||||
|
||||
output << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data const& entry_data, log_entry_types let )
|
||||
{
|
||||
switch( let ) {
|
||||
case BOOST_UTL_ET_INFO:
|
||||
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
|
||||
output << "info: ";
|
||||
break;
|
||||
case BOOST_UTL_ET_MESSAGE:
|
||||
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() << "\": ";
|
||||
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() << "\": ";
|
||||
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() << "\": ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_entry_value( std::ostream& output, const_string value )
|
||||
{
|
||||
output << value;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_entry_value( std::ostream& output, lazy_ostream const& value )
|
||||
{
|
||||
output << value;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::log_entry_finish( std::ostream& output )
|
||||
{
|
||||
output << std::endl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
compiler_log_formatter::print_prefix( std::ostream& output, const_string file, std::size_t line )
|
||||
{
|
||||
#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 << ": ";
|
||||
#else
|
||||
output << file << '(' << line << "): ";
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace output
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
|
139
xs/include/boost/test/impl/cpp_main.ipp
Normal file
139
xs/include/boost/test/impl/cpp_main.ipp
Normal file
|
@ -0,0 +1,139 @@
|
|||
// (C) Copyright Gennadiy Rozental 2001-2008.
|
||||
// (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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision: 49312 $
|
||||
//
|
||||
// Description : main function implementation for Program Executon Monitor
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_CPP_MAIN_IPP_012205GER
|
||||
#define BOOST_TEST_CPP_MAIN_IPP_012205GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/execution_monitor.hpp>
|
||||
#include <boost/test/detail/config.hpp>
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/cstdlib.hpp> // for exit codes
|
||||
#include <boost/config.hpp> // for workarounds
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
#include <cstdlib> // std::getenv
|
||||
#include <cstring> // std::strerror
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::getenv; using ::strerror; }
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
struct cpp_main_caller {
|
||||
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 ); }
|
||||
|
||||
private:
|
||||
// Data members
|
||||
int (*m_cpp_main_func)( int argc, char* argv[] );
|
||||
int m_argc;
|
||||
char** m_argv;
|
||||
};
|
||||
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** prg_exec_monitor_main ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace boost {
|
||||
|
||||
int BOOST_TEST_DECL
|
||||
prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char* argv[] )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
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 ) ) );
|
||||
|
||||
if( result == 0 )
|
||||
result = ::boost::exit_success;
|
||||
else if( result != ::boost::exit_success ) {
|
||||
std::cout << "\n**** error return code: " << result << std::endl;
|
||||
result = ::boost::exit_failure;
|
||||
}
|
||||
}
|
||||
catch( ::boost::execution_exception const& exex ) {
|
||||
std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl;
|
||||
result = ::boost::exit_exception_failure;
|
||||
}
|
||||
catch( ::boost::system_error const& ex ) {
|
||||
std::cout << "\n**** failed to initialize execution monitor."
|
||||
<< "\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;
|
||||
}
|
||||
|
||||
if( result != ::boost::exit_success ) {
|
||||
std::cerr << "******** errors detected; see standard output for details ********" << std::endl;
|
||||
}
|
||||
else {
|
||||
// Some prefer a confirming message when all is well, while others don't
|
||||
// like the clutter. Use an environment variable to avoid command
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** main function for tests using lib ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
int cpp_main( int argc, char* argv[] ); // prototype for user's cpp_main()
|
||||
|
||||
int BOOST_TEST_CALL_DECL
|
||||
main( int argc, char* argv[] )
|
||||
{
|
||||
return ::boost::prg_exec_monitor_main( &cpp_main, argc, argv );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_CPP_MAIN_IPP_012205GER
|
970
xs/include/boost/test/impl/debug.ipp
Normal file
970
xs/include/boost/test/impl/debug.ipp
Normal file
|
@ -0,0 +1,970 @@
|
|||
// (C) Copyright Gennadiy Rozental 2006-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: 57992 $
|
||||
//
|
||||
// Description : debug interfaces implementation
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_DEBUG_API_IPP_112006GER
|
||||
#define BOOST_TEST_DEBUG_API_IPP_112006GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/detail/config.hpp>
|
||||
#include <boost/test/detail/workaround.hpp>
|
||||
#include <boost/test/detail/global_typedef.hpp>
|
||||
|
||||
#include <boost/test/debug.hpp>
|
||||
#include <boost/test/debug_config.hpp>
|
||||
|
||||
// Implementation on Windows
|
||||
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(BOOST_DISABLE_WIN32) // ******* WIN32
|
||||
|
||||
# define BOOST_WIN32_BASED_DEBUG
|
||||
|
||||
// SYSTEM API
|
||||
# include <windows.h>
|
||||
# include <winreg.h>
|
||||
# include <cstdio>
|
||||
# include <cstring>
|
||||
|
||||
# if !defined(NDEBUG) && defined(_MSC_VER)
|
||||
# define BOOST_MS_CRT_BASED_DEBUG
|
||||
# include <crtdbg.h>
|
||||
# endif
|
||||
|
||||
|
||||
# if BOOST_WORKAROUND( BOOST_MSVC, <1300)
|
||||
# define snprintf _snprintf
|
||||
# endif
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::memset; using ::sprintf; }
|
||||
# endif
|
||||
|
||||
#elif defined(unix) || defined(__unix) // ********************* UNIX
|
||||
|
||||
# define BOOST_UNIX_BASED_DEBUG
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/class_properties.hpp>
|
||||
#include <boost/test/utils/algorithm.hpp>
|
||||
|
||||
// STL
|
||||
#include <cstring> // std::memcpy
|
||||
#include <map>
|
||||
#include <cstdio>
|
||||
#include <stdarg.h> // !! ?? cstdarg
|
||||
|
||||
// SYSTEM API
|
||||
# include <unistd.h>
|
||||
# include <signal.h>
|
||||
# include <fcntl.h>
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/time.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
# if defined(sun) || defined(__sun)
|
||||
|
||||
# define BOOST_SUN_BASED_DEBUG
|
||||
|
||||
# ifndef BOOST_TEST_DBG_LIST
|
||||
# define BOOST_TEST_DBG_LIST dbx;gdb
|
||||
# endif
|
||||
|
||||
# define BOOST_TEST_CNL_DBG dbx
|
||||
# define BOOST_TEST_GUI_DBG dbx-ddd
|
||||
|
||||
# include <procfs.h>
|
||||
|
||||
# elif defined(linux) || defined(__linux)
|
||||
|
||||
# define BOOST_LINUX_BASED_DEBUG
|
||||
|
||||
# include <sys/ptrace.h>
|
||||
|
||||
# ifndef BOOST_TEST_STAT_LINE_MAX
|
||||
# define BOOST_TEST_STAT_LINE_MAX 500
|
||||
# endif
|
||||
|
||||
# ifndef BOOST_TEST_DBG_LIST
|
||||
# define BOOST_TEST_DBG_LIST gdb
|
||||
# endif
|
||||
|
||||
# define BOOST_TEST_CNL_DBG gdb
|
||||
# define BOOST_TEST_GUI_DBG gdb-xterm
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace debug {
|
||||
|
||||
using unit_test::const_string;
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** debug::info_t ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(BOOST_WIN32_BASED_DEBUG) // *********************** WIN32
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
dyn_symbol( T& res, char const* module_name, char const* symbol_name )
|
||||
{
|
||||
HMODULE m = ::GetModuleHandleA( module_name );
|
||||
|
||||
if( !m )
|
||||
m = ::LoadLibraryA( module_name );
|
||||
|
||||
res = reinterpret_cast<T>( ::GetProcAddress( m, symbol_name ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static struct info_t {
|
||||
typedef BOOL (WINAPI* IsDebuggerPresentT)();
|
||||
typedef LONG (WINAPI* RegQueryValueExT)( HKEY, char const* /*LPTSTR*/, LPDWORD, LPDWORD, LPBYTE, LPDWORD );
|
||||
typedef LONG (WINAPI* RegOpenKeyT)( HKEY, char const* /*LPCTSTR*/, PHKEY );
|
||||
typedef LONG (WINAPI* RegCloseKeyT)( HKEY );
|
||||
|
||||
info_t();
|
||||
|
||||
IsDebuggerPresentT m_is_debugger_present;
|
||||
RegOpenKeyT m_reg_open_key;
|
||||
RegQueryValueExT m_reg_query_value;
|
||||
RegCloseKeyT m_reg_close_key;
|
||||
|
||||
} s_info;
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
info_t::info_t()
|
||||
{
|
||||
dyn_symbol( m_is_debugger_present, "kernel32", "IsDebuggerPresent" );
|
||||
dyn_symbol( m_reg_open_key, "advapi32", "RegOpenKeyA" );
|
||||
dyn_symbol( m_reg_query_value, "advapi32", "RegQueryValueExA" );
|
||||
dyn_symbol( m_reg_close_key, "advapi32", "RegCloseKey" );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#elif defined(BOOST_UNIX_BASED_DEBUG)
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** fd_holder ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
struct fd_holder {
|
||||
explicit fd_holder( int fd ) : m_fd( fd ) {}
|
||||
~fd_holder()
|
||||
{
|
||||
if( m_fd != -1 )
|
||||
::close( m_fd );
|
||||
}
|
||||
|
||||
operator int() { return m_fd; }
|
||||
|
||||
private:
|
||||
// Data members
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** process_info ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
struct process_info {
|
||||
// Constructor
|
||||
explicit process_info( int pid );
|
||||
|
||||
// access methods
|
||||
int parent_pid() const { return m_parent_pid; }
|
||||
const_string binary_name() const { return m_binary_name; }
|
||||
const_string binary_path() const { return m_binary_path; }
|
||||
|
||||
private:
|
||||
// Data members
|
||||
int m_parent_pid;
|
||||
const_string m_binary_name;
|
||||
const_string m_binary_path;
|
||||
|
||||
#if defined(BOOST_SUN_BASED_DEBUG)
|
||||
struct psinfo m_psi;
|
||||
#elif defined(BOOST_LINUX_BASED_DEBUG)
|
||||
char m_stat_line[BOOST_TEST_STAT_LINE_MAX+1];
|
||||
#endif
|
||||
char m_binary_path_buff[500+1]; // !! ??
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
process_info::process_info( int pid )
|
||||
: m_parent_pid( 0 )
|
||||
{
|
||||
#if defined(BOOST_SUN_BASED_DEBUG)
|
||||
char fname_buff[30];
|
||||
|
||||
::snprintf( fname_buff, sizeof(fname_buff), "/proc/%d/psinfo", pid );
|
||||
|
||||
fd_holder psinfo_fd( ::open( fname_buff, O_RDONLY ) );
|
||||
|
||||
if( psinfo_fd == -1 )
|
||||
return;
|
||||
|
||||
if( ::read( psinfo_fd, &m_psi, sizeof(m_psi) ) == -1 )
|
||||
return;
|
||||
|
||||
m_parent_pid = m_psi.pr_ppid;
|
||||
|
||||
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 ||
|
||||
::read ( as_fd, &binary_name_pos, sizeof(binary_name_pos) ) == -1 ||
|
||||
::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];
|
||||
|
||||
::snprintf( fname_buff, sizeof(fname_buff), "/proc/%d/stat", pid );
|
||||
|
||||
fd_holder psinfo_fd( ::open( fname_buff, O_RDONLY ) );
|
||||
|
||||
if( psinfo_fd == -1 )
|
||||
return;
|
||||
|
||||
ssize_t num_read = ::read( psinfo_fd, m_stat_line, sizeof(m_stat_line)-1 );
|
||||
if( num_read == -1 )
|
||||
return;
|
||||
|
||||
m_stat_line[num_read] = 0;
|
||||
|
||||
char const* name_beg = m_stat_line;
|
||||
while( *name_beg && *name_beg != '(' )
|
||||
++name_beg;
|
||||
|
||||
char const* name_end = name_beg+1;
|
||||
while( *name_end && *name_end != ')' )
|
||||
++name_end;
|
||||
|
||||
std::sscanf( name_end+1, "%*s%d", &m_parent_pid );
|
||||
|
||||
m_binary_name.assign( name_beg+1, name_end );
|
||||
|
||||
::snprintf( fname_buff, sizeof(fname_buff), "/proc/%d/exe", pid );
|
||||
num_read = ::readlink( fname_buff, m_binary_path_buff, sizeof(m_binary_path_buff)-1 );
|
||||
|
||||
if( num_read == -1 )
|
||||
return;
|
||||
|
||||
m_binary_path_buff[num_read] = 0;
|
||||
m_binary_path.assign( m_binary_path_buff, num_read );
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** prepare_window_title ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static char*
|
||||
prepare_window_title( dbg_startup_info const& dsi )
|
||||
{
|
||||
typedef unit_test::const_string str_t;
|
||||
|
||||
static char title_str[50];
|
||||
|
||||
str_t path_sep( "\\/" );
|
||||
|
||||
str_t::iterator it = unit_test::find_last_of( dsi.binary_path.begin(), dsi.binary_path.end(),
|
||||
path_sep.begin(), path_sep.end() );
|
||||
|
||||
if( it == dsi.binary_path.end() )
|
||||
it = dsi.binary_path.begin();
|
||||
else
|
||||
++it;
|
||||
|
||||
::snprintf( title_str, sizeof(title_str), "%*s %ld", (int)(dsi.binary_path.end()-it), it, dsi.pid );
|
||||
|
||||
return title_str;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** save_execlp ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
typedef unit_test::basic_cstring<char> mbuffer;
|
||||
|
||||
inline char*
|
||||
copy_arg( mbuffer& dest, const_string arg )
|
||||
{
|
||||
if( dest.size() < arg.size()+1 )
|
||||
return 0;
|
||||
|
||||
char* res = dest.begin();
|
||||
|
||||
std::memcpy( res, arg.begin(), arg.size()+1 );
|
||||
|
||||
dest.trim_left( arg.size()+1 );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
safe_execlp( char const* file, ... )
|
||||
{
|
||||
static char* argv_buff[200];
|
||||
|
||||
va_list args;
|
||||
char const* arg;
|
||||
|
||||
// first calculate actual number of arguments
|
||||
int num_args = 2; // file name and 0 at least
|
||||
|
||||
va_start( args, file );
|
||||
while( !!(arg = va_arg( args, char const* )) )
|
||||
num_args++;
|
||||
va_end( args );
|
||||
|
||||
// reserve space for the argument pointers array
|
||||
char** argv_it = argv_buff;
|
||||
mbuffer work_buff( reinterpret_cast<char*>(argv_buff), sizeof(argv_buff) );
|
||||
work_buff.trim_left( num_args * sizeof(char*) );
|
||||
|
||||
// copy all the argument values into local storage
|
||||
if( !(*argv_it++ = copy_arg( work_buff, file )) )
|
||||
return false;
|
||||
|
||||
printf( "!! %s\n", file );
|
||||
|
||||
va_start( args, file );
|
||||
while( !!(arg = va_arg( args, char const* )) ) {
|
||||
printf( "!! %s\n", arg );
|
||||
if( !(*argv_it++ = copy_arg( work_buff, arg )) )
|
||||
return false;
|
||||
}
|
||||
va_end( args );
|
||||
|
||||
*argv_it = 0;
|
||||
|
||||
return ::execvp( file, argv_buff ) != -1;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** start_debugger_in_emacs ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static void
|
||||
start_debugger_in_emacs( dbg_startup_info const& dsi, char const* emacs_name, char const* dbg_command )
|
||||
{
|
||||
char const* title = prepare_window_title( dsi );
|
||||
|
||||
if( !title )
|
||||
return;
|
||||
|
||||
dsi.display.is_empty()
|
||||
? safe_execlp( emacs_name, "-title", title, "--eval", dbg_command, 0 )
|
||||
: safe_execlp( emacs_name, "-title", title, "-display", dsi.display.begin(), "--eval", dbg_command, 0 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** gdb starters ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static char const*
|
||||
prepare_gdb_cmnd_file( dbg_startup_info const& dsi )
|
||||
{
|
||||
// prepare pid value
|
||||
char pid_buff[16];
|
||||
::snprintf( pid_buff, sizeof(pid_buff), "%ld", dsi.pid );
|
||||
unit_test::const_string pid_str( pid_buff );
|
||||
|
||||
static char cmd_file_name[] = "/tmp/btl_gdb_cmd_XXXXXX"; // !! ??
|
||||
|
||||
// prepare commands
|
||||
fd_holder cmd_fd( ::mkstemp( cmd_file_name ) );
|
||||
|
||||
if( cmd_fd == -1 )
|
||||
return 0;
|
||||
|
||||
#define WRITE_STR( str ) if( ::write( cmd_fd, str.begin(), str.size() ) == -1 ) return 0;
|
||||
#define WRITE_CSTR( str ) if( ::write( cmd_fd, str, sizeof( str )-1 ) == -1 ) return 0;
|
||||
|
||||
WRITE_CSTR( "file " );
|
||||
WRITE_STR( dsi.binary_path );
|
||||
WRITE_CSTR( "\nattach " );
|
||||
WRITE_STR( pid_str );
|
||||
WRITE_CSTR( "\nshell unlink " );
|
||||
WRITE_STR( dsi.init_done_lock );
|
||||
WRITE_CSTR( "\ncont" );
|
||||
if( dsi.break_or_continue )
|
||||
WRITE_CSTR( "\nup 4" );
|
||||
|
||||
WRITE_CSTR( "\necho \\n" ); // !! ??
|
||||
WRITE_CSTR( "\nlist -" );
|
||||
WRITE_CSTR( "\nlist" );
|
||||
WRITE_CSTR( "\nshell unlink " );
|
||||
WRITE_CSTR( cmd_file_name );
|
||||
|
||||
return cmd_file_name;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_gdb_in_console( dbg_startup_info const& dsi )
|
||||
{
|
||||
char const* cmnd_file_name = prepare_gdb_cmnd_file( dsi );
|
||||
|
||||
if( !cmnd_file_name )
|
||||
return;
|
||||
|
||||
safe_execlp( "gdb", "-q", "-x", cmnd_file_name, 0 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_gdb_in_xterm( dbg_startup_info const& dsi )
|
||||
{
|
||||
char const* title = prepare_window_title( dsi );
|
||||
char const* cmnd_file_name = prepare_gdb_cmnd_file( dsi );
|
||||
|
||||
if( !title || !cmnd_file_name )
|
||||
return;
|
||||
|
||||
safe_execlp( "xterm", "-T", title, "-display", dsi.display.begin(),
|
||||
"-bg", "black", "-fg", "white", "-geometry", "88x30+10+10", "-fn", "9x15", "-e",
|
||||
"gdb", "-q", "-x", cmnd_file_name, 0 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_gdb_in_emacs( dbg_startup_info const& dsi )
|
||||
{
|
||||
char const* cmnd_file_name = prepare_gdb_cmnd_file( dsi );
|
||||
if( !cmnd_file_name )
|
||||
return;
|
||||
|
||||
char dbg_cmd_buff[500]; // !! ??
|
||||
::snprintf( dbg_cmd_buff, sizeof(dbg_cmd_buff), "(progn (gdb \"gdb -q -x %s\"))", cmnd_file_name );
|
||||
|
||||
start_debugger_in_emacs( dsi, "emacs", dbg_cmd_buff );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_gdb_in_xemacs( dbg_startup_info const& )
|
||||
{
|
||||
// !! ??
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** dbx starters ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static char const*
|
||||
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;": "",
|
||||
list_source ? "echo \" \";list -w3;" : "" );
|
||||
|
||||
return cmd_line_buff;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_dbx_in_console( dbg_startup_info const& dsi )
|
||||
{
|
||||
char pid_buff[16];
|
||||
::snprintf( pid_buff, sizeof(pid_buff), "%ld", dsi.pid );
|
||||
|
||||
safe_execlp( "dbx", "-q", "-c", prepare_dbx_cmd_line( dsi ), dsi.binary_path.begin(), pid_buff, 0 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_dbx_in_xterm( dbg_startup_info const& dsi )
|
||||
{
|
||||
char const* title = prepare_window_title( dsi );
|
||||
if( !title )
|
||||
return;
|
||||
|
||||
char pid_buff[16]; // !! ??
|
||||
::snprintf( pid_buff, sizeof(pid_buff), "%ld", dsi.pid );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_dbx_in_emacs( dbg_startup_info const& /*dsi*/ )
|
||||
{
|
||||
// char dbg_cmd_buff[500]; // !! ??
|
||||
//
|
||||
// ::snprintf( dbg_cmd_buff, sizeof(dbg_cmd_buff), "(progn (dbx \"dbx -q -c cont %s %ld\"))", dsi.binary_path.begin(), dsi.pid );
|
||||
|
||||
// start_debugger_in_emacs( dsi, "emacs", dbg_cmd_buff );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_dbx_in_xemacs( dbg_startup_info const& )
|
||||
{
|
||||
// !! ??
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
static void
|
||||
start_dbx_in_ddd( dbg_startup_info const& dsi )
|
||||
{
|
||||
char const* title = prepare_window_title( dsi );
|
||||
if( !title )
|
||||
return;
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** debug::info_t ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static struct info_t {
|
||||
// Constructor
|
||||
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;
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
m_dbg_starter_reg[std::string("gdb-xemacs")] = &start_gdb_in_xemacs;
|
||||
|
||||
m_dbg_starter_reg[std::string("dbx")] = &start_dbx_in_console;
|
||||
m_dbg_starter_reg[std::string("dbx-emacs")] = &start_dbx_in_emacs;
|
||||
m_dbg_starter_reg[std::string("dbx-xterm")] = &start_dbx_in_xterm;
|
||||
m_dbg_starter_reg[std::string("dbx-xemacs")] = &start_dbx_in_xemacs;
|
||||
m_dbg_starter_reg[std::string("dbx-ddd")] = &start_dbx_in_ddd;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#endif
|
||||
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** check if program is running under debugger ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
bool
|
||||
under_debugger()
|
||||
{
|
||||
#if defined(BOOST_WIN32_BASED_DEBUG) // *********************** WIN32
|
||||
|
||||
return !!s_info.m_is_debugger_present && s_info.m_is_debugger_present();
|
||||
|
||||
#elif defined(BOOST_UNIX_BASED_DEBUG) // ********************** UNIX
|
||||
|
||||
// !! ?? could/should we cache the result somehow?
|
||||
const_string dbg_list = BOOST_TEST_STRINGIZE( BOOST_TEST_DBG_LIST );
|
||||
|
||||
pid_t pid = ::getpid();
|
||||
|
||||
while( pid != 0 ) {
|
||||
process_info pi( pid );
|
||||
|
||||
// !! ?? should we use tokenizer here instead?
|
||||
if( dbg_list.find( pi.binary_name() ) != const_string::npos )
|
||||
return true;
|
||||
|
||||
pid = (pi.parent_pid() == pid ? 0 : pi.parent_pid());
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
#else // ****************************************************** default
|
||||
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** cause program to break execution ************** //
|
||||
// ************** in debugger at call point ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
debugger_break()
|
||||
{
|
||||
// !! ?? auto-start debugger?
|
||||
|
||||
#if defined(BOOST_WIN32_BASED_DEBUG) // *********************** WIN32
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1300) || \
|
||||
BOOST_WORKAROUND(__GNUC__, >= 3) && !defined(__MINGW32__) || \
|
||||
defined(__INTEL_COMPILER)
|
||||
# define BOOST_DEBUG_BREAK __debugbreak
|
||||
#else
|
||||
# define BOOST_DEBUG_BREAK DebugBreak
|
||||
#endif
|
||||
|
||||
#ifndef __MINGW32__
|
||||
if( !under_debugger() ) {
|
||||
__try {
|
||||
__try {
|
||||
BOOST_DEBUG_BREAK();
|
||||
}
|
||||
__except( UnhandledExceptionFilter(GetExceptionInformation()) )
|
||||
{
|
||||
// User opted to ignore the breakpoint
|
||||
return;
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
// If we got here, the user has pushed Debug. Debugger is already attached to our process and we
|
||||
// continue to let the another BOOST_DEBUG_BREAK to be called.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_DEBUG_BREAK();
|
||||
|
||||
#elif defined(BOOST_UNIX_BASED_DEBUG) // ********************** UNIX
|
||||
|
||||
::kill( ::getpid(), SIGTRAP );
|
||||
|
||||
#else // ****************************************************** default
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** console debugger setup ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
#if defined(BOOST_UNIX_BASED_DEBUG) // ************************ UNIX
|
||||
|
||||
std::string
|
||||
set_debugger( unit_test::const_string dbg_id, dbg_starter s )
|
||||
{
|
||||
std::string old = s_info.p_dbg;
|
||||
|
||||
assign_op( s_info.p_dbg.value, dbg_id, 0 );
|
||||
|
||||
if( !!s )
|
||||
s_info.m_dbg_starter_reg[s_info.p_dbg] = s;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
#else // ***************************************************** default
|
||||
|
||||
std::string
|
||||
set_debugger( unit_test::const_string, dbg_starter )
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** attach debugger to the current process ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
bool
|
||||
attach_debugger( bool break_or_continue )
|
||||
{
|
||||
if( under_debugger() )
|
||||
return false;
|
||||
|
||||
#if defined(BOOST_WIN32_BASED_DEBUG) // *********************** WIN32
|
||||
|
||||
const int MAX_CMD_LINE = 200;
|
||||
|
||||
// *************************************************** //
|
||||
// Debugger "ready" event
|
||||
|
||||
SECURITY_ATTRIBUTES attr;
|
||||
attr.nLength = sizeof(attr);
|
||||
attr.lpSecurityDescriptor = NULL;
|
||||
attr.bInheritHandle = true;
|
||||
|
||||
// manual resettable, initially non signaled, unnamed event,
|
||||
// that will signal me that debugger initialization is done
|
||||
HANDLE dbg_init_done_ev = ::CreateEvent(
|
||||
&attr, // pointer to security attributes
|
||||
true, // flag for manual-reset event
|
||||
false, // flag for initial state
|
||||
NULL // pointer to event-object name
|
||||
);
|
||||
|
||||
if( !dbg_init_done_ev )
|
||||
return false;
|
||||
|
||||
// *************************************************** //
|
||||
// Debugger command line format
|
||||
|
||||
HKEY reg_key;
|
||||
|
||||
if( !s_info.m_reg_open_key || (*s_info.m_reg_open_key)(
|
||||
HKEY_LOCAL_MACHINE, // handle of open key
|
||||
"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", // name of subkey to open
|
||||
®_key ) != ERROR_SUCCESS ) // address of handle of open key
|
||||
return false;
|
||||
|
||||
char format[MAX_CMD_LINE];
|
||||
DWORD format_size = MAX_CMD_LINE;
|
||||
DWORD type = REG_SZ;
|
||||
|
||||
if( !s_info.m_reg_query_value || (*s_info.m_reg_query_value)(
|
||||
reg_key, // handle of open key
|
||||
"Debugger", // name of subkey to query
|
||||
0, // reserved
|
||||
&type, // value type
|
||||
(LPBYTE)format, // buffer for returned string
|
||||
&format_size ) != ERROR_SUCCESS ) // in: buffer size; out: actual size of returned string
|
||||
return false;
|
||||
|
||||
if( !s_info.m_reg_close_key || (*s_info.m_reg_close_key)( reg_key ) != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
// *************************************************** //
|
||||
// Debugger command line
|
||||
|
||||
char cmd_line[MAX_CMD_LINE];
|
||||
std::sprintf( cmd_line, format, ::GetCurrentProcessId(), dbg_init_done_ev );
|
||||
|
||||
// *************************************************** //
|
||||
// Debugger window parameters
|
||||
|
||||
STARTUPINFOA startup_info;
|
||||
std::memset( &startup_info, 0, sizeof(startup_info) );
|
||||
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
startup_info.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup_info.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
// debugger process s_info
|
||||
PROCESS_INFORMATION debugger_info;
|
||||
|
||||
bool created = !!::CreateProcessA(
|
||||
NULL, // pointer to name of executable module; NULL - use the one in command line
|
||||
cmd_line, // pointer to command line string
|
||||
NULL, // pointer to process security attributes; NULL - debugger's handle can't be inherited
|
||||
NULL, // pointer to thread security attributes; NULL - debugger's handle can't be inherited
|
||||
true, // debugger inherit opened handles
|
||||
0, // priority flags; 0 - normal priority
|
||||
NULL, // pointer to new environment block; NULL - use this process environment
|
||||
NULL, // pointer to current directory name; NULL - use this process correct directory
|
||||
&startup_info, // pointer to STARTUPINFO that specifies main window appearance
|
||||
&debugger_info // pointer to PROCESS_INFORMATION that will contain the new process identification
|
||||
);
|
||||
|
||||
if( created )
|
||||
::WaitForSingleObject( dbg_init_done_ev, INFINITE );
|
||||
|
||||
::CloseHandle( dbg_init_done_ev );
|
||||
|
||||
if( !created )
|
||||
return false;
|
||||
|
||||
if( break_or_continue )
|
||||
debugger_break();
|
||||
|
||||
return true;
|
||||
|
||||
#elif defined(BOOST_UNIX_BASED_DEBUG) // ********************** UNIX
|
||||
|
||||
char init_done_lock_fn[] = "/tmp/btl_dbg_init_done_XXXXXX";
|
||||
fd_holder init_done_lock_fd( ::mkstemp( init_done_lock_fn ) );
|
||||
|
||||
if( init_done_lock_fd == -1 )
|
||||
return false;
|
||||
|
||||
pid_t child_pid = fork();
|
||||
|
||||
if( child_pid == -1 )
|
||||
return false;
|
||||
|
||||
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 );
|
||||
|
||||
dsi.pid = child_pid;
|
||||
dsi.break_or_continue = 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 );
|
||||
|
||||
::perror( "Boost.Test execution monitor failed to start a debugger:" );
|
||||
|
||||
::exit( -1 );
|
||||
}
|
||||
|
||||
// child process - here we will continue our test module execution ; // !! ?? should it be vice versa
|
||||
|
||||
while( ::access( init_done_lock_fn, F_OK ) == 0 ) {
|
||||
struct timeval to = { 0, 100 };
|
||||
|
||||
::select( 0, 0, 0, 0, &to );
|
||||
}
|
||||
|
||||
// char dummy;
|
||||
// while( ::read( init_done_lock_fd, &dummy, sizeof(char) ) == 0 );
|
||||
|
||||
if( break_or_continue )
|
||||
debugger_break();
|
||||
|
||||
return true;
|
||||
|
||||
#else // ****************************************************** default
|
||||
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** switch on/off detect memory leaks feature ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
detect_memory_leaks( bool on_off )
|
||||
{
|
||||
unit_test::ut_detail::ignore_unused_variable_warning( on_off );
|
||||
|
||||
#ifdef BOOST_MS_CRT_BASED_DEBUG
|
||||
int flags = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
||||
|
||||
if( !on_off )
|
||||
flags &= ~_CRTDBG_LEAK_CHECK_DF;
|
||||
else {
|
||||
flags |= _CRTDBG_LEAK_CHECK_DF;
|
||||
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
|
||||
}
|
||||
|
||||
_CrtSetDbgFlag ( flags );
|
||||
#endif // BOOST_MS_CRT_BASED_DEBUG
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** cause program to break execution in ************** //
|
||||
// ************** debugger at specific allocation point ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
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 );
|
||||
#endif // BOOST_MS_CRT_BASED_DEBUG
|
||||
}
|
||||
|
||||
} // namespace debug
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_DEBUG_API_IPP_112006GER
|
||||
|
537
xs/include/boost/test/impl/exception_safety.ipp
Normal file
537
xs/include/boost/test/impl/exception_safety.ipp
Normal file
|
@ -0,0 +1,537 @@
|
|||
// (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: 54633 $
|
||||
//
|
||||
// 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
|
1367
xs/include/boost/test/impl/execution_monitor.ipp
Normal file
1367
xs/include/boost/test/impl/execution_monitor.ipp
Normal file
File diff suppressed because it is too large
Load diff
503
xs/include/boost/test/impl/framework.ipp
Normal file
503
xs/include/boost/test/impl/framework.ipp
Normal file
|
@ -0,0 +1,503 @@
|
|||
// (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: 57991 $
|
||||
//
|
||||
// Description : implements framework API - main driver for the test
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_FRAMEWORK_IPP_021005GER
|
||||
#define BOOST_TEST_FRAMEWORK_IPP_021005GER
|
||||
|
||||
// Boost.Test
|
||||
#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_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/utils/foreach.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/timer.hpp>
|
||||
|
||||
// STL
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::time; using ::srand; }
|
||||
#endif
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** test_start calls wrapper ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace ut_detail {
|
||||
|
||||
struct test_start_caller {
|
||||
test_start_caller( test_observer* to, counter_t tc_amount )
|
||||
: m_to( to )
|
||||
, m_tc_amount( tc_amount )
|
||||
{}
|
||||
|
||||
int operator()()
|
||||
{
|
||||
m_to->test_start( m_tc_amount );
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Data members
|
||||
test_observer* m_to;
|
||||
counter_t m_tc_amount;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
struct test_init_caller {
|
||||
explicit test_init_caller( init_unit_test_func init_func )
|
||||
: m_init_func( init_func )
|
||||
{}
|
||||
int operator()()
|
||||
{
|
||||
#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( manual_test_units )
|
||||
framework::master_test_suite().add( manual_test_units );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Data members
|
||||
init_unit_test_func m_init_func;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** framework ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
class framework_impl : public test_tree_visitor {
|
||||
public:
|
||||
framework_impl()
|
||||
: m_master_test_suite( 0 )
|
||||
, 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 )
|
||||
{}
|
||||
|
||||
~framework_impl() { 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;
|
||||
|
||||
// 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;
|
||||
else
|
||||
delete (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 )
|
||||
{
|
||||
if( !tc.check_dependencies() ) {
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_unit_skipped( tc );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
unsigned long elapsed = static_cast<unsigned long>( tc_timer.elapsed() * 1e6 );
|
||||
|
||||
if( unit_test_monitor.is_critical_error( run_result ) ) {
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_aborted();
|
||||
}
|
||||
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_unit_finish( tc, elapsed );
|
||||
|
||||
m_curr_test_case = bkup;
|
||||
|
||||
if( unit_test_monitor.is_critical_error( run_result ) )
|
||||
throw test_being_aborted();
|
||||
}
|
||||
|
||||
bool test_suite_start( test_suite const& ts )
|
||||
{
|
||||
if( !ts.check_dependencies() ) {
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_unit_skipped( ts );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_unit_start( ts );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void test_suite_finish( test_suite const& ts )
|
||||
{
|
||||
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
|
||||
to->test_unit_finish( ts, 0 );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
struct priority_order {
|
||||
bool operator()( test_observer* lhs, test_observer* rhs ) const
|
||||
{
|
||||
return (lhs->priority() < rhs->priority()) || ((lhs->priority() == rhs->priority()) && (lhs < rhs));
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<test_unit_id,test_unit*> test_unit_store;
|
||||
typedef std::set<test_observer*,priority_order> observer_store;
|
||||
|
||||
master_test_suite_t* m_master_test_suite;
|
||||
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;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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; }
|
||||
#else
|
||||
framework_impl& s_frk_impl() { static framework_impl the_inst; return the_inst; }
|
||||
#endif
|
||||
|
||||
} // local namespace
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace framework {
|
||||
|
||||
void
|
||||
init( init_unit_test_func init_func, int argc, char* argv[] )
|
||||
{
|
||||
runtime_config::init( argc, argv );
|
||||
|
||||
// set the 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
|
||||
results_reporter::set_level( runtime_config::report_level() );
|
||||
results_reporter::set_format( runtime_config::report_format() );
|
||||
|
||||
register_observer( results_collector );
|
||||
register_observer( unit_test_log );
|
||||
|
||||
if( runtime_config::show_progress() )
|
||||
register_observer( progress_monitor );
|
||||
|
||||
if( runtime_config::detect_memory_leaks() > 0 ) {
|
||||
debug::detect_memory_leaks( true );
|
||||
debug::break_memory_alloc( runtime_config::detect_memory_leaks() );
|
||||
}
|
||||
|
||||
// init 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 );
|
||||
|
||||
em.execute( tic );
|
||||
}
|
||||
catch( execution_exception const& ex ) {
|
||||
throw setup_error( ex.what() );
|
||||
}
|
||||
|
||||
s_frk_impl().m_is_initialized = true;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
is_initialized()
|
||||
{
|
||||
return s_frk_impl().m_is_initialized;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
s_frk_impl().m_test_units.insert( map_value_type( new_id, tc ) );
|
||||
s_frk_impl().m_next_test_case_id++;
|
||||
|
||||
s_frk_impl().set_tu_id( *tc, new_id );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
|
||||
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++;
|
||||
|
||||
s_frk_impl().set_tu_id( *ts, new_id );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
deregister_test_unit( test_unit* tu )
|
||||
{
|
||||
s_frk_impl().m_test_units.erase( tu->p_id );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
clear()
|
||||
{
|
||||
s_frk_impl().clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
register_observer( test_observer& to )
|
||||
{
|
||||
s_frk_impl().m_observers.insert( &to );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
deregister_observer( test_observer& to )
|
||||
{
|
||||
s_frk_impl().m_observers.erase( &to );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
reset_observers()
|
||||
{
|
||||
s_frk_impl().m_observers.clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
|
||||
return *s_frk_impl().m_master_test_suite;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
test_case const&
|
||||
current_test_case()
|
||||
{
|
||||
return get<test_case>( s_frk_impl().m_curr_test_case );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
test_unit&
|
||||
get( test_unit_id id, test_unit_type t )
|
||||
{
|
||||
test_unit* res = s_frk_impl().m_test_units[id];
|
||||
|
||||
if( (res->p_type & t) == 0 )
|
||||
throw internal_error( "Invalid test unit type" );
|
||||
|
||||
return *res;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
run( test_unit_id id, bool continue_test )
|
||||
{
|
||||
if( id == INV_TEST_UNIT_ID )
|
||||
id = master_test_suite().p_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" ) );
|
||||
|
||||
bool call_start_finish = !continue_test || !s_frk_impl().m_test_in_progress;
|
||||
bool was_in_progress = s_frk_impl().m_test_in_progress;
|
||||
|
||||
s_frk_impl().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 ) );
|
||||
}
|
||||
catch( execution_exception const& ex ) {
|
||||
throw setup_error( ex.what() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( runtime_config::random_seed() ) {
|
||||
case 0:
|
||||
break;
|
||||
case 1: {
|
||||
unsigned int seed = static_cast<unsigned int>( std::time( 0 ) );
|
||||
BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << seed );
|
||||
std::srand( seed );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BOOST_TEST_MESSAGE( "Test cases order is shuffled using seed: " << runtime_config::random_seed() );
|
||||
std::srand( runtime_config::random_seed() );
|
||||
}
|
||||
|
||||
try {
|
||||
traverse_test_tree( id, s_frk_impl() );
|
||||
}
|
||||
catch( test_being_aborted const& ) {
|
||||
// abort already reported
|
||||
}
|
||||
|
||||
if( call_start_finish ) {
|
||||
BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
|
||||
to->test_finish();
|
||||
}
|
||||
|
||||
s_frk_impl().m_test_in_progress = was_in_progress;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
run( test_unit const* tu, bool continue_test )
|
||||
{
|
||||
run( tu->p_id, continue_test );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
assertion_result( bool passed )
|
||||
{
|
||||
BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
|
||||
to->assertion_result( passed );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
exception_caught( execution_exception const& ex )
|
||||
{
|
||||
BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().m_observers )
|
||||
to->exception_caught( ex );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
test_unit_aborted( test_unit const& tu )
|
||||
{
|
||||
BOOST_TEST_FOREACH( test_observer*, to, s_frk_impl().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
|
90
xs/include/boost/test/impl/interaction_based.ipp
Normal file
90
xs/include/boost/test/impl/interaction_based.ipp
Normal file
|
@ -0,0 +1,90 @@
|
|||
// (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: 54633 $
|
||||
//
|
||||
// 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
|
246
xs/include/boost/test/impl/logged_expectations.ipp
Normal file
246
xs/include/boost/test/impl/logged_expectations.ipp
Normal file
|
@ -0,0 +1,246 @@
|
|||
// (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: 54633 $
|
||||
//
|
||||
// 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
|
198
xs/include/boost/test/impl/plain_report_formatter.ipp
Normal file
198
xs/include/boost/test/impl/plain_report_formatter.ipp
Normal file
|
@ -0,0 +1,198 @@
|
|||
// (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: 49312 $
|
||||
//
|
||||
// Description : plain report formatter definition
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
|
||||
#define BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
|
||||
|
||||
// Boost.Test
|
||||
#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/utils/basic_cstring/io.hpp>
|
||||
|
||||
// STL
|
||||
#include <iomanip>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::log10; }
|
||||
# endif
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
namespace output {
|
||||
|
||||
namespace {
|
||||
|
||||
typedef custom_manip<struct quote_t> quote;
|
||||
|
||||
template<typename T>
|
||||
inline std::ostream&
|
||||
operator<<( custom_printer<quote> const& p, T const& value )
|
||||
{
|
||||
*p << '"' << value << '"';
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
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;
|
||||
|
||||
ostr << ' ' << res << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** plain_report_formatter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
plain_report_formatter::results_report_start( std::ostream& ostr )
|
||||
{
|
||||
m_indent = 0;
|
||||
ostr << '\n';
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
plain_report_formatter::results_report_finish( std::ostream& ostr )
|
||||
{
|
||||
ostr.flush();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream& ostr )
|
||||
{
|
||||
test_results const& tr = results_collector.results( tu.p_id );
|
||||
|
||||
const_string descr;
|
||||
|
||||
if( tr.passed() )
|
||||
descr = "passed";
|
||||
else if( tr.p_skipped )
|
||||
descr = "skipped";
|
||||
else if( tr.p_aborted )
|
||||
descr = "aborted";
|
||||
else
|
||||
descr = "failed";
|
||||
|
||||
ostr << std::setw( m_indent ) << ""
|
||||
<< "Test " << (tu.p_type == tut_case ? "case " : "suite " ) << quote() << tu.p_name << ' ' << descr;
|
||||
|
||||
if( tr.p_skipped ) {
|
||||
ostr << " due to " << (tu.check_dependencies() ? "test aborting\n" : "failed dependancy\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;
|
||||
|
||||
if( total_assertions > 0 || total_tc > 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" );
|
||||
|
||||
ostr << '\n';
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
plain_report_formatter::test_unit_report_finish( test_unit const&, std::ostream& )
|
||||
{
|
||||
m_indent -= 2;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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() ) {
|
||||
ostr << "*** No errors detected\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if( tr.p_skipped ) {
|
||||
ostr << "*** Test " << tu.p_type_name << " skipped due to "
|
||||
<< (tu.check_dependencies() ? "test aborting\n" : "failed dependancy\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( tr.p_assertions_failed == 0 ) {
|
||||
ostr << "*** errors detected in test " << tu.p_type_name << " " << quote() << tu.p_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";
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace output
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
|
110
xs/include/boost/test/impl/progress_monitor.ipp
Normal file
110
xs/include/boost/test/impl/progress_monitor.ipp
Normal file
|
@ -0,0 +1,110 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : implements simple text based progress monitor
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
|
||||
#define BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/progress_monitor.hpp>
|
||||
#include <boost/test/unit_test_suite_impl.hpp>
|
||||
|
||||
#include <boost/test/detail/unit_test_parameters.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/progress.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** progress_monitor ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
|
||||
struct progress_monitor_impl {
|
||||
// Constructor
|
||||
progress_monitor_impl()
|
||||
: m_stream( runtime_config::log_sink() )
|
||||
{}
|
||||
|
||||
std::ostream* m_stream;
|
||||
scoped_ptr<progress_display> m_progress_display;
|
||||
};
|
||||
|
||||
progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; return the_inst; }
|
||||
|
||||
} // local namespace
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
progress_monitor_t::test_start( counter_t test_cases_amount )
|
||||
{
|
||||
s_pm_impl().m_progress_display.reset( new progress_display( test_cases_amount, *s_pm_impl().m_stream ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
progress_monitor_t::test_aborted()
|
||||
{
|
||||
(*s_pm_impl().m_progress_display) += s_pm_impl().m_progress_display->count();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
progress_monitor_t::test_unit_finish( test_unit const& tu, unsigned long )
|
||||
{
|
||||
if( tu.p_type == tut_case )
|
||||
++(*s_pm_impl().m_progress_display);
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
progress_monitor_t::test_unit_skipped( test_unit const& tu )
|
||||
{
|
||||
test_case_counter tcc;
|
||||
traverse_test_tree( tu, tcc );
|
||||
|
||||
(*s_pm_impl().m_progress_display) += tcc.p_count;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
progress_monitor_t::set_stream( std::ostream& ostr )
|
||||
{
|
||||
s_pm_impl().m_stream = &ostr;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
|
294
xs/include/boost/test/impl/results_collector.ipp
Normal file
294
xs/include/boost/test/impl/results_collector.ipp
Normal file
|
@ -0,0 +1,294 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : implements Unit Test results collecting facility.
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
|
||||
#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>
|
||||
|
||||
// Boost
|
||||
#include <boost/cstdlib.hpp>
|
||||
|
||||
// STL
|
||||
#include <map>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** test_results ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
test_results::test_results()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
test_results::passed() const
|
||||
{
|
||||
return !p_skipped &&
|
||||
p_test_cases_failed == 0 &&
|
||||
p_assertions_failed <= p_expected_failures &&
|
||||
!p_aborted;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
int
|
||||
test_results::result_code() const
|
||||
{
|
||||
return passed() ? exit_success
|
||||
: ( (p_assertions_failed > p_expected_failures || p_skipped )
|
||||
? exit_test_failure
|
||||
: exit_exception_failure );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
test_results::operator+=( test_results const& tr )
|
||||
{
|
||||
p_assertions_passed.value += tr.p_assertions_passed;
|
||||
p_assertions_failed.value += tr.p_assertions_failed;
|
||||
p_test_cases_passed.value += tr.p_test_cases_passed;
|
||||
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;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** results_collector ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, <1300)
|
||||
|
||||
namespace {
|
||||
|
||||
struct results_collector_impl {
|
||||
std::map<test_unit_id,test_results> m_results_store;
|
||||
};
|
||||
|
||||
results_collector_impl& s_rc_impl() { static results_collector_impl the_inst; return the_inst; }
|
||||
|
||||
} // 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
|
||||
results_collector_t::test_start( counter_t )
|
||||
{
|
||||
s_rc_impl().m_results_store.clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
class results_collect_helper : public test_tree_visitor {
|
||||
public:
|
||||
explicit results_collect_helper( test_results& tr, test_unit const& ts ) : m_tr( tr ), m_ts( ts ) {}
|
||||
|
||||
void visit( test_case const& tc )
|
||||
{
|
||||
test_results const& tr = results_collector.results( tc.p_id );
|
||||
m_tr += tr;
|
||||
|
||||
if( tr.passed() )
|
||||
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++;
|
||||
}
|
||||
}
|
||||
bool test_suite_start( test_suite const& ts )
|
||||
{
|
||||
if( m_ts.p_id == ts.p_id )
|
||||
return true;
|
||||
else {
|
||||
m_tr += results_collector.results( ts.p_id );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Data members
|
||||
test_results& m_tr;
|
||||
test_unit const& m_ts;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
results_collector_t::test_unit_finish( test_unit const& tu, unsigned long )
|
||||
{
|
||||
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" );
|
||||
|
||||
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" );
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
results_collector_t::test_unit_skipped( test_unit const& tu )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
results_collector_t::assertion_result( bool passed )
|
||||
{
|
||||
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case().p_id];
|
||||
|
||||
if( passed )
|
||||
tr.p_assertions_passed.value++;
|
||||
else
|
||||
tr.p_assertions_failed.value++;
|
||||
|
||||
if( tr.p_assertions_failed == 1 )
|
||||
first_failed_assertion();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
results_collector_t::exception_caught( execution_exception const& )
|
||||
{
|
||||
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case().p_id];
|
||||
|
||||
tr.p_assertions_failed.value++;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
results_collector_t::test_unit_aborted( test_unit const& tu )
|
||||
{
|
||||
s_rc_impl().m_results_store[tu.p_id].p_aborted.value = true;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
test_results const&
|
||||
results_collector_t::results( test_unit_id id ) const
|
||||
{
|
||||
return s_rc_impl().m_results_store[id];
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
|
202
xs/include/boost/test/impl/results_reporter.ipp
Normal file
202
xs/include/boost/test/impl/results_reporter.ipp
Normal file
|
@ -0,0 +1,202 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : result reporting facilties
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
|
||||
#define BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
|
||||
|
||||
// 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>
|
||||
|
||||
// Boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/io/ios_state.hpp>
|
||||
typedef ::boost::io::ios_base_all_saver io_saver_type;
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
namespace results_reporter {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** result reporter implementation ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
|
||||
struct results_reporter_impl : test_tree_visitor {
|
||||
// Constructor
|
||||
results_reporter_impl()
|
||||
: m_output( runtime_config::report_sink() )
|
||||
, m_stream_state_saver( new io_saver_type( *m_output ) )
|
||||
, m_report_level( CONFIRMATION_REPORT )
|
||||
, m_formatter( new output::plain_report_formatter )
|
||||
{}
|
||||
|
||||
// test tree visitor interface implementation
|
||||
void visit( test_case const& tc )
|
||||
{
|
||||
m_formatter->test_unit_report_start( tc, *m_output );
|
||||
m_formatter->test_unit_report_finish( tc, *m_output );
|
||||
}
|
||||
bool test_suite_start( test_suite const& ts )
|
||||
{
|
||||
m_formatter->test_unit_report_start( ts, *m_output );
|
||||
|
||||
if( m_report_level == DETAILED_REPORT && !results_collector.results( ts.p_id ).p_skipped )
|
||||
return true;
|
||||
|
||||
m_formatter->test_unit_report_finish( ts, *m_output );
|
||||
return false;
|
||||
}
|
||||
void test_suite_finish( test_suite const& ts )
|
||||
{
|
||||
m_formatter->test_unit_report_finish( ts, *m_output );
|
||||
}
|
||||
|
||||
typedef scoped_ptr<io_saver_type> saver_ptr;
|
||||
|
||||
// Data members
|
||||
std::ostream* m_output;
|
||||
saver_ptr m_stream_state_saver;
|
||||
report_level m_report_level;
|
||||
scoped_ptr<format> m_formatter;
|
||||
};
|
||||
|
||||
results_reporter_impl& s_rr_impl() { static results_reporter_impl the_inst; return the_inst; }
|
||||
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** report configuration ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
set_level( report_level l )
|
||||
{
|
||||
if( l != INV_REPORT_LEVEL )
|
||||
s_rr_impl().m_report_level = l;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
set_stream( std::ostream& ostr )
|
||||
{
|
||||
s_rr_impl().m_output = &ostr;
|
||||
s_rr_impl().m_stream_state_saver.reset( new io_saver_type( ostr ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::ostream&
|
||||
get_stream()
|
||||
{
|
||||
return *s_rr_impl().m_output;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
set_format( output_format rf )
|
||||
{
|
||||
switch( rf ) {
|
||||
case CLF:
|
||||
set_format( new output::plain_report_formatter );
|
||||
break;
|
||||
case XML:
|
||||
set_format( new output::xml_report_formatter );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
set_format( results_reporter::format* f )
|
||||
{
|
||||
if( f )
|
||||
s_rr_impl().m_formatter.reset( f );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** report initiation ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
make_report( report_level l, test_unit_id id )
|
||||
{
|
||||
if( l == INV_REPORT_LEVEL )
|
||||
l = s_rr_impl().m_report_level;
|
||||
|
||||
if( l == NO_REPORT )
|
||||
return;
|
||||
|
||||
if( id == INV_TEST_UNIT_ID )
|
||||
id = framework::master_test_suite().p_id;
|
||||
|
||||
s_rr_impl().m_stream_state_saver->restore();
|
||||
|
||||
report_level bkup = s_rr_impl().m_report_level;
|
||||
s_rr_impl().m_report_level = l;
|
||||
|
||||
s_rr_impl().m_formatter->results_report_start( *s_rr_impl().m_output );
|
||||
|
||||
switch( l ) {
|
||||
case CONFIRMATION_REPORT:
|
||||
s_rr_impl().m_formatter->do_confirmation_report( framework::get<test_unit>( id ), *s_rr_impl().m_output );
|
||||
break;
|
||||
case SHORT_REPORT:
|
||||
case DETAILED_REPORT:
|
||||
traverse_test_tree( id, s_rr_impl() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s_rr_impl().m_formatter->results_report_finish( *s_rr_impl().m_output );
|
||||
s_rr_impl().m_report_level = bkup;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace results_reporter
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
|
68
xs/include/boost/test/impl/test_main.ipp
Normal file
68
xs/include/boost/test/impl/test_main.ipp
Normal file
|
@ -0,0 +1,68 @@
|
|||
// (C) Copyright Gennadiy Rozental 2001-2008.
|
||||
// (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
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $$Revision: 49312 $
|
||||
//
|
||||
// Description : implements main function for Test Execution Monitor.
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_TEST_MAIN_IPP_012205GER
|
||||
#define BOOST_TEST_TEST_MAIN_IPP_012205GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/framework.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/test/unit_test_suite.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/cstdlib.hpp>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
extern int test_main( int argc, char* argv[] ); // prototype for user's test_main()
|
||||
|
||||
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
|
||||
int m_argc;
|
||||
char** m_argv;
|
||||
};
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** test main ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
::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;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_TEST_MAIN_IPP_012205GER
|
628
xs/include/boost/test/impl/test_tools.ipp
Normal file
628
xs/include/boost/test/impl/test_tools.ipp
Normal file
|
@ -0,0 +1,628 @@
|
|||
// (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: 54633 $
|
||||
//
|
||||
// Description : supplies offline implementation for the Test Tools
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
|
||||
#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/framework.hpp>
|
||||
#include <boost/test/execution_monitor.hpp> // execution_aborted
|
||||
#include <boost/test/unit_test_suite_impl.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// STL
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cwchar>
|
||||
#include <stdexcept>
|
||||
#include <ios>
|
||||
|
||||
// !! should we use #include <cstdarg>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::strcmp; using ::strlen; using ::isprint; }
|
||||
#if !defined( BOOST_NO_CWCHAR )
|
||||
namespace std { using ::wcscmp; }
|
||||
#endif
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace test_tools {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** print_log_value ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
print_log_value<char>::operator()( std::ostream& ostr, char t )
|
||||
{
|
||||
if( (std::isprint)( static_cast<unsigned char>(t) ) )
|
||||
ostr << '\'' << t << '\'';
|
||||
else
|
||||
ostr << std::hex
|
||||
#if BOOST_TEST_USE_STD_LOCALE
|
||||
<< std::showbase
|
||||
#else
|
||||
<< "0x"
|
||||
#endif
|
||||
<< static_cast<int>(t);
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
|
||||
{
|
||||
ostr << std::hex
|
||||
// showbase is only available for new style streams:
|
||||
#if BOOST_TEST_USE_STD_LOCALE
|
||||
<< std::showbase
|
||||
#else
|
||||
<< "0x"
|
||||
#endif
|
||||
<< static_cast<int>(t);
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
|
||||
{
|
||||
ostr << ( t ? t : "null string" );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
|
||||
{
|
||||
ostr << ( t ? t : L"null string" );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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, ... )
|
||||
{
|
||||
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;
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
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;
|
||||
else
|
||||
unit_test_log << check_descr;
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
if( tl != PASS )
|
||||
unit_test_log << " [" << *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();
|
||||
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* );
|
||||
lazy_ostream const* arg2_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 << "difference{" << pr.message() << (ct == CHECK_CLOSE ? "%" : "")
|
||||
<< "} 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();
|
||||
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;
|
||||
|
||||
va_end( args );
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
break;
|
||||
}
|
||||
|
||||
case CHECK_PRED_WITH_ARGS: {
|
||||
unit_test_log << unit_test::log::begin( file_name, line_num )
|
||||
<< ll << prefix << check_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 );
|
||||
}
|
||||
|
||||
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 << ", ";
|
||||
}
|
||||
unit_test_log << " )";
|
||||
va_end( args );
|
||||
}
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
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;
|
||||
|
||||
va_end( args );
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
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;
|
||||
|
||||
va_end( args );
|
||||
|
||||
if( !pr.has_empty_message() )
|
||||
unit_test_log << ". " << pr.message();
|
||||
|
||||
unit_test_log << unit_test::log::end();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch( tl ) {
|
||||
case PASS:
|
||||
framework::assertion_result( true );
|
||||
return true;
|
||||
|
||||
case WARN:
|
||||
return false;
|
||||
|
||||
case CHECK:
|
||||
framework::assertion_result( false );
|
||||
return false;
|
||||
|
||||
case REQUIRE:
|
||||
framework::assertion_result( false );
|
||||
|
||||
framework::test_unit_aborted( framework::current_test_case() );
|
||||
|
||||
throw execution_aborted();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
predicate_result
|
||||
equal_impl( char const* left, char const* right )
|
||||
{
|
||||
return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#if !defined( BOOST_NO_CWCHAR )
|
||||
|
||||
predicate_result
|
||||
equal_impl( wchar_t const* left, wchar_t const* right )
|
||||
{
|
||||
return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
|
||||
}
|
||||
|
||||
#endif // !defined( BOOST_NO_CWCHAR )
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
is_defined_impl( const_string symbol_name, const_string symbol_value )
|
||||
{
|
||||
symbol_value.trim_left( 2 );
|
||||
return symbol_name != symbol_value;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace tt_detail
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** output_test_stream ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
struct output_test_stream::Impl
|
||||
{
|
||||
std::fstream m_pattern;
|
||||
bool m_match_or_save;
|
||||
bool m_text_or_binary;
|
||||
std::string m_synced_string;
|
||||
|
||||
char get_char()
|
||||
{
|
||||
char res;
|
||||
do {
|
||||
m_pattern.get( res );
|
||||
} while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void check_and_fill( predicate_result& res )
|
||||
{
|
||||
if( !res.p_predicate_value )
|
||||
res.message() << "Output content: \"" << m_synced_string << '\"';
|
||||
}
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
|
||||
: m_pimpl( new Impl )
|
||||
{
|
||||
if( !pattern_file_name.is_empty() ) {
|
||||
std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
|
||||
if( !text_or_binary )
|
||||
m |= std::ios::binary;
|
||||
|
||||
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") );
|
||||
}
|
||||
|
||||
m_pimpl->m_match_or_save = match_or_save;
|
||||
m_pimpl->m_text_or_binary = text_or_binary;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
output_test_stream::~output_test_stream()
|
||||
{
|
||||
delete m_pimpl;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
predicate_result
|
||||
output_test_stream::is_empty( bool flush_stream )
|
||||
{
|
||||
sync();
|
||||
|
||||
result_type res( m_pimpl->m_synced_string.empty() );
|
||||
|
||||
m_pimpl->check_and_fill( res );
|
||||
|
||||
if( flush_stream )
|
||||
flush();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
predicate_result
|
||||
output_test_stream::check_length( std::size_t length_, bool flush_stream )
|
||||
{
|
||||
sync();
|
||||
|
||||
result_type res( m_pimpl->m_synced_string.length() == length_ );
|
||||
|
||||
m_pimpl->check_and_fill( res );
|
||||
|
||||
if( flush_stream )
|
||||
flush();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
predicate_result
|
||||
output_test_stream::is_equal( const_string arg, bool flush_stream )
|
||||
{
|
||||
sync();
|
||||
|
||||
result_type res( const_string( m_pimpl->m_synced_string ) == arg );
|
||||
|
||||
m_pimpl->check_and_fill( res );
|
||||
|
||||
if( flush_stream )
|
||||
flush();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
predicate_result
|
||||
output_test_stream::match_pattern( bool flush_stream )
|
||||
{
|
||||
sync();
|
||||
|
||||
result_type result( true );
|
||||
|
||||
if( !m_pimpl->m_pattern.is_open() ) {
|
||||
result = false;
|
||||
result.message() << "Pattern file can't be opened!";
|
||||
}
|
||||
else {
|
||||
if( m_pimpl->m_match_or_save ) {
|
||||
for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) {
|
||||
char c = m_pimpl->get_char();
|
||||
|
||||
result = !m_pimpl->m_pattern.fail() &&
|
||||
!m_pimpl->m_pattern.eof() &&
|
||||
(m_pimpl->m_synced_string[i] == c);
|
||||
|
||||
if( !result ) {
|
||||
std::string::size_type suffix_size = (std::min)( m_pimpl->m_synced_string.length() - i,
|
||||
static_cast<std::string::size_type>(5) );
|
||||
|
||||
// try to log area around the mismatch
|
||||
result.message() << "Mismatch at position " << i << '\n'
|
||||
<< "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n'
|
||||
<< "..." << c;
|
||||
|
||||
std::string::size_type counter = suffix_size;
|
||||
while( --counter ) {
|
||||
char c = m_pimpl->get_char();
|
||||
|
||||
if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
|
||||
break;
|
||||
|
||||
result.message() << c;
|
||||
}
|
||||
|
||||
result.message() << "...";
|
||||
|
||||
// skip rest of the bytes. May help for further matching
|
||||
m_pimpl->m_pattern.ignore(
|
||||
static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_pimpl->m_pattern.write( m_pimpl->m_synced_string.c_str(),
|
||||
static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
|
||||
m_pimpl->m_pattern.flush();
|
||||
}
|
||||
}
|
||||
|
||||
if( flush_stream )
|
||||
flush();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
output_test_stream::flush()
|
||||
{
|
||||
m_pimpl->m_synced_string.erase();
|
||||
|
||||
#ifndef BOOST_NO_STRINGSTREAM
|
||||
str( std::string() );
|
||||
#else
|
||||
seekp( 0, std::ios::beg );
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::size_t
|
||||
output_test_stream::length()
|
||||
{
|
||||
sync();
|
||||
|
||||
return m_pimpl->m_synced_string.length();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
output_test_stream::sync()
|
||||
{
|
||||
#ifdef BOOST_NO_STRINGSTREAM
|
||||
m_pimpl->m_synced_string.assign( str(), pcount() );
|
||||
freeze( false );
|
||||
#else
|
||||
m_pimpl->m_synced_string = str();
|
||||
#endif
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace test_tools
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER
|
444
xs/include/boost/test/impl/unit_test_log.ipp
Normal file
444
xs/include/boost/test/impl/unit_test_log.ipp
Normal file
|
@ -0,0 +1,444 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : implemets Unit Test Log
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
|
||||
#define BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
|
||||
|
||||
// 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/detail/unit_test_parameters.hpp>
|
||||
|
||||
#include <boost/test/utils/basic_cstring/compare.hpp>
|
||||
|
||||
#include <boost/test/output/compiler_log_formatter.hpp>
|
||||
#include <boost/test/output/xml_log_formatter.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/io/ios_state.hpp>
|
||||
typedef ::boost::io::ios_base_all_saver io_saver_type;
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** entry_value_collector ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace ut_detail {
|
||||
|
||||
entry_value_collector const&
|
||||
entry_value_collector::operator<<( lazy_ostream const& v ) const
|
||||
{
|
||||
unit_test_log << v;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
entry_value_collector const&
|
||||
entry_value_collector::operator<<( const_string v ) const
|
||||
{
|
||||
unit_test_log << v;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
entry_value_collector::~entry_value_collector()
|
||||
{
|
||||
if( m_last )
|
||||
unit_test_log << log::end();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace ut_detail
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** unit_test_log ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
|
||||
struct unit_test_log_impl {
|
||||
// Constructor
|
||||
unit_test_log_impl()
|
||||
: m_stream( runtime_config::log_sink() )
|
||||
, m_stream_state_saver( new io_saver_type( *m_stream ) )
|
||||
, m_threshold_level( log_all_errors )
|
||||
, m_log_formatter( new output::compiler_log_formatter )
|
||||
{
|
||||
}
|
||||
|
||||
// log data
|
||||
typedef scoped_ptr<unit_test_log_formatter> formatter_ptr;
|
||||
typedef scoped_ptr<io_saver_type> saver_ptr;
|
||||
|
||||
std::ostream* m_stream;
|
||||
saver_ptr m_stream_state_saver;
|
||||
log_level m_threshold_level;
|
||||
formatter_ptr m_log_formatter;
|
||||
|
||||
// entry data
|
||||
bool m_entry_in_progress;
|
||||
bool m_entry_started;
|
||||
log_entry_data m_entry_data;
|
||||
|
||||
// check point data
|
||||
log_checkpoint_data m_checkpoint_data;
|
||||
|
||||
// helper functions
|
||||
std::ostream& stream() { return *m_stream; }
|
||||
void set_checkpoint( const_string file, std::size_t line_num, const_string msg )
|
||||
{
|
||||
assign_op( m_checkpoint_data.m_message, msg, 0 );
|
||||
m_checkpoint_data.m_file_name = file;
|
||||
m_checkpoint_data.m_line_num = line_num;
|
||||
}
|
||||
};
|
||||
|
||||
unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; }
|
||||
|
||||
} // local namespace
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_start( counter_t test_cases_amount )
|
||||
{
|
||||
if( s_log_impl().m_threshold_level == log_nothing )
|
||||
return;
|
||||
|
||||
s_log_impl().m_log_formatter->log_start( s_log_impl().stream(), test_cases_amount );
|
||||
|
||||
if( runtime_config::show_build_info() )
|
||||
s_log_impl().m_log_formatter->log_build_info( s_log_impl().stream() );
|
||||
|
||||
s_log_impl().m_entry_in_progress = false;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_finish()
|
||||
{
|
||||
if( s_log_impl().m_threshold_level == log_nothing )
|
||||
return;
|
||||
|
||||
s_log_impl().m_log_formatter->log_finish( s_log_impl().stream() );
|
||||
|
||||
s_log_impl().stream().flush();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_aborted()
|
||||
{
|
||||
BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_unit_start( test_unit const& tu )
|
||||
{
|
||||
if( s_log_impl().m_threshold_level > log_test_units )
|
||||
return;
|
||||
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
*this << log::end();
|
||||
|
||||
s_log_impl().m_log_formatter->test_unit_start( s_log_impl().stream(), tu );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
|
||||
{
|
||||
if( s_log_impl().m_threshold_level > log_test_units )
|
||||
return;
|
||||
|
||||
s_log_impl().m_checkpoint_data.clear();
|
||||
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
*this << log::end();
|
||||
|
||||
s_log_impl().m_log_formatter->test_unit_finish( s_log_impl().stream(), tu, elapsed );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::test_unit_skipped( test_unit const& tu )
|
||||
{
|
||||
if( s_log_impl().m_threshold_level > log_test_units )
|
||||
return;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::exception_caught( execution_exception const& ex )
|
||||
{
|
||||
log_level l =
|
||||
ex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors :
|
||||
(ex.code() <= execution_exception::timeout_error ? log_system_errors
|
||||
: log_fatal_errors );
|
||||
|
||||
if( l >= s_log_impl().m_threshold_level ) {
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg )
|
||||
{
|
||||
s_log_impl().set_checkpoint( file, line_num, msg );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
char
|
||||
set_unix_slash( char in )
|
||||
{
|
||||
return in == '\\' ? '/' : in;
|
||||
}
|
||||
|
||||
unit_test_log_t&
|
||||
unit_test_log_t::operator<<( log::begin const& b )
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
*this << log::end();
|
||||
|
||||
s_log_impl().m_stream_state_saver->restore();
|
||||
|
||||
s_log_impl().m_entry_data.clear();
|
||||
|
||||
assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 );
|
||||
|
||||
// normalize file name
|
||||
std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(),
|
||||
s_log_impl().m_entry_data.m_file_name.begin(),
|
||||
&set_unix_slash );
|
||||
|
||||
s_log_impl().m_entry_data.m_line_num = b.m_line_num;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test_log_t&
|
||||
unit_test_log_t::operator<<( log::end const& )
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() );
|
||||
|
||||
s_log_impl().m_entry_in_progress = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test_log_t&
|
||||
unit_test_log_t::operator<<( log_level l )
|
||||
{
|
||||
s_log_impl().m_entry_data.m_level = l;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
ut_detail::entry_value_collector
|
||||
unit_test_log_t::operator()( log_level l )
|
||||
{
|
||||
*this << l;
|
||||
|
||||
return ut_detail::entry_value_collector();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
unit_test_log_t::log_entry_start()
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
return true;
|
||||
|
||||
switch( s_log_impl().m_entry_data.m_level ) {
|
||||
case log_successful_tests:
|
||||
s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
|
||||
unit_test_log_formatter::BOOST_UTL_ET_INFO );
|
||||
break;
|
||||
case log_messages:
|
||||
s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
|
||||
unit_test_log_formatter::BOOST_UTL_ET_MESSAGE );
|
||||
break;
|
||||
case log_warnings:
|
||||
s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
|
||||
unit_test_log_formatter::BOOST_UTL_ET_WARNING );
|
||||
break;
|
||||
case log_all_errors:
|
||||
case log_cpp_exception_errors:
|
||||
case log_system_errors:
|
||||
s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
|
||||
unit_test_log_formatter::BOOST_UTL_ET_ERROR );
|
||||
break;
|
||||
case log_fatal_errors:
|
||||
s_log_impl().m_log_formatter->log_entry_start( s_log_impl().stream(), s_log_impl().m_entry_data,
|
||||
unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR );
|
||||
break;
|
||||
case log_nothing:
|
||||
case log_test_units:
|
||||
case invalid_log_level:
|
||||
return false;
|
||||
}
|
||||
|
||||
s_log_impl().m_entry_in_progress = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test_log_t&
|
||||
unit_test_log_t::operator<<( const_string value )
|
||||
{
|
||||
if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() && log_entry_start() )
|
||||
s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test_log_t&
|
||||
unit_test_log_t::operator<<( lazy_ostream const& value )
|
||||
{
|
||||
if( s_log_impl().m_entry_data.m_level >= s_log_impl().m_threshold_level && !value.empty() && log_entry_start() )
|
||||
s_log_impl().m_log_formatter->log_entry_value( s_log_impl().stream(), value );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::set_stream( std::ostream& str )
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
return;
|
||||
|
||||
s_log_impl().m_stream = &str;
|
||||
s_log_impl().m_stream_state_saver.reset( new io_saver_type( str ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::set_threshold_level( log_level lev )
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress || lev == invalid_log_level )
|
||||
return;
|
||||
|
||||
s_log_impl().m_threshold_level = lev;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::set_format( output_format log_format )
|
||||
{
|
||||
if( s_log_impl().m_entry_in_progress )
|
||||
return;
|
||||
|
||||
if( log_format == CLF )
|
||||
set_formatter( new output::compiler_log_formatter );
|
||||
else
|
||||
set_formatter( new output::xml_log_formatter );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter )
|
||||
{
|
||||
s_log_impl().m_log_formatter.reset( the_formatter );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** unit_test_log_formatter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const& value )
|
||||
{
|
||||
log_entry_value( ostr, (wrap_stringstream().ref() << value).str() );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
|
246
xs/include/boost/test/impl/unit_test_main.ipp
Normal file
246
xs/include/boost/test/impl/unit_test_main.ipp
Normal file
|
@ -0,0 +1,246 @@
|
|||
// (C) Copyright Gennadiy Rozental 2001-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: 54633 $
|
||||
//
|
||||
// Description : main function implementation for Unit Test Framework
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
|
||||
#define BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
|
||||
|
||||
// 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>
|
||||
|
||||
#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
|
||||
|
||||
// Boost
|
||||
#include <boost/cstdlib.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
// STL
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** test_case_filter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
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_value.size() ) == m_value;
|
||||
|
||||
case SFK_TRAILING:
|
||||
return name.size() >= m_value.size() && name.substr( name.size() - m_value.size() ) == m_value;
|
||||
|
||||
case SFK_SUBSTR:
|
||||
return name.find( m_value ) != const_string::npos;
|
||||
|
||||
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 )
|
||||
{
|
||||
string_token_iterator tit( tc_to_run, (dropped_delimeters = "/", kept_delimeters = dt_none) );
|
||||
|
||||
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() ) );
|
||||
|
||||
++tit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void filter_unit( test_unit const& tu )
|
||||
{
|
||||
if( (++m_depth - 1) > m_filters.size() ) {
|
||||
tu.p_enabled.value = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_depth == 1 )
|
||||
return;
|
||||
|
||||
std::vector<single_filter> const& filters = m_filters[m_depth-2];
|
||||
|
||||
tu.p_enabled.value =
|
||||
std::find_if( filters.begin(), filters.end(), bind( &single_filter::pass, _1, boost::ref(tu) ) ) != filters.end();
|
||||
}
|
||||
|
||||
// test tree visitor interface
|
||||
virtual void visit( test_case const& tc )
|
||||
{
|
||||
if( m_depth < m_filters.size() ) {
|
||||
tc.p_enabled.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
filter_unit( tc );
|
||||
|
||||
--m_depth;
|
||||
}
|
||||
|
||||
virtual bool test_suite_start( test_suite const& ts )
|
||||
{
|
||||
filter_unit( ts );
|
||||
|
||||
if( !ts.p_enabled )
|
||||
--m_depth;
|
||||
|
||||
return ts.p_enabled;
|
||||
}
|
||||
|
||||
virtual void test_suite_finish( test_suite const& ) { --m_depth; }
|
||||
|
||||
private:
|
||||
// Data members
|
||||
std::vector<std::vector<single_filter> > m_filters;
|
||||
unsigned m_depth;
|
||||
};
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** unit_test_main ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
int BOOST_TEST_DECL
|
||||
unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
|
||||
{
|
||||
try {
|
||||
framework::init( init_func, argc, argv );
|
||||
|
||||
if( !runtime_config::test_to_run().is_empty() ) {
|
||||
test_case_filter filter( runtime_config::test_to_run() );
|
||||
|
||||
traverse_test_tree( framework::master_test_suite().p_id, filter );
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
catch( framework::nothing_to_test const& ) {
|
||||
return boost::exit_success;
|
||||
}
|
||||
catch( framework::internal_error const& ex ) {
|
||||
results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
|
||||
|
||||
return boost::exit_exception_failure;
|
||||
}
|
||||
catch( framework::setup_error const& ex ) {
|
||||
results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
|
||||
|
||||
return boost::exit_exception_failure;
|
||||
}
|
||||
catch( ... ) {
|
||||
results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
|
||||
|
||||
return boost::exit_exception_failure;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** main function for tests using lib ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
int BOOST_TEST_CALL_DECL
|
||||
main( int argc, char* argv[] )
|
||||
{
|
||||
// prototype for user's unit test init function
|
||||
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
|
||||
extern bool init_unit_test();
|
||||
|
||||
boost::unit_test::init_unit_test_func init_func = &init_unit_test;
|
||||
#else
|
||||
extern ::boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] );
|
||||
|
||||
boost::unit_test::init_unit_test_func init_func = &init_unit_test_suite;
|
||||
#endif
|
||||
|
||||
return ::boost::unit_test::unit_test_main( init_func, argc, argv );
|
||||
}
|
||||
|
||||
#endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_UNIT_TEST_MAIN_IPP_012205GER
|
101
xs/include/boost/test/impl/unit_test_monitor.ipp
Normal file
101
xs/include/boost/test/impl/unit_test_monitor.ipp
Normal file
|
@ -0,0 +1,101 @@
|
|||
// (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: 49312 $
|
||||
//
|
||||
// Description : implements specific subclass of Executon Monitor used by Unit
|
||||
// Test Framework to monitor test cases run.
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
|
||||
#define BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
|
||||
|
||||
// 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/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 )
|
||||
{
|
||||
try {
|
||||
p_catch_system_errors.value = runtime_config::catch_sys_errors();
|
||||
p_timeout.value = tc.p_timeout.get();
|
||||
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() ) ) );
|
||||
}
|
||||
catch( execution_exception const& ex ) {
|
||||
framework::exception_caught( ex );
|
||||
framework::test_unit_aborted( framework::current_test_case() );
|
||||
|
||||
// translate execution_exception::error_code to error_level
|
||||
switch( ex.code() ) {
|
||||
case execution_exception::no_error: return test_ok;
|
||||
case execution_exception::user_error: return unexpected_exception;
|
||||
case execution_exception::cpp_exception_error: return unexpected_exception;
|
||||
case execution_exception::system_error: return os_exception;
|
||||
case execution_exception::timeout_error: return os_timeout;
|
||||
case execution_exception::user_fatal_error:
|
||||
case execution_exception::system_fatal_error: return fatal_error;
|
||||
default: return unexpected_exception;
|
||||
}
|
||||
}
|
||||
|
||||
return test_ok;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
|
527
xs/include/boost/test/impl/unit_test_parameters.ipp
Normal file
527
xs/include/boost/test/impl/unit_test_parameters.ipp
Normal file
|
@ -0,0 +1,527 @@
|
|||
// (C) Copyright Gennadiy Rozental 2001-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: 63640 $
|
||||
//
|
||||
// Description : simple implementation for Unit Test Framework parameter
|
||||
// handling routines. May be rewritten in future to use some kind of
|
||||
// command-line arguments parsing facility and environment variable handling
|
||||
// facility
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
|
||||
#define BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/detail/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>
|
||||
#include <boost/test/utils/fixed_mapping.hpp>
|
||||
#include <boost/test/debug.hpp>
|
||||
#include <boost/test/framework.hpp>
|
||||
|
||||
// Boost.Runtime.Param
|
||||
#include <boost/test/utils/runtime/cla/dual_name_parameter.hpp>
|
||||
#include <boost/test/utils/runtime/cla/parser.hpp>
|
||||
|
||||
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>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
// STL
|
||||
#include <map>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::getenv; using ::strncmp; using ::strcmp; }
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** input operations for unit_test's enums ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
std::istream&
|
||||
operator>>( std::istream& in, unit_test::log_level& ll )
|
||||
{
|
||||
static fixed_mapping<const_string,unit_test::log_level,case_ins_less<char const> > log_level_name(
|
||||
"all" , log_successful_tests,
|
||||
"success" , log_successful_tests,
|
||||
"test_suite" , log_test_units,
|
||||
"unit_scope" , log_test_units,
|
||||
"message" , log_messages,
|
||||
"warning" , log_warnings,
|
||||
"error" , log_all_errors,
|
||||
"cpp_exception" , log_cpp_exception_errors,
|
||||
"system_error" , log_system_errors,
|
||||
"fatal_error" , log_fatal_errors,
|
||||
"nothing" , log_nothing,
|
||||
|
||||
invalid_log_level
|
||||
);
|
||||
|
||||
std::string val;
|
||||
in >> val;
|
||||
|
||||
ll = log_level_name[val];
|
||||
BOOST_TEST_SETUP_ASSERT( ll != unit_test::invalid_log_level, "invalid log level " + val );
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::istream&
|
||||
operator>>( std::istream& in, unit_test::report_level& rl )
|
||||
{
|
||||
fixed_mapping<const_string,unit_test::report_level,case_ins_less<char const> > report_level_name (
|
||||
"confirm", CONFIRMATION_REPORT,
|
||||
"short", SHORT_REPORT,
|
||||
"detailed", DETAILED_REPORT,
|
||||
"no", NO_REPORT,
|
||||
|
||||
INV_REPORT_LEVEL
|
||||
);
|
||||
|
||||
std::string val;
|
||||
in >> val;
|
||||
|
||||
rl = report_level_name[val];
|
||||
BOOST_TEST_SETUP_ASSERT( rl != INV_REPORT_LEVEL, "invalid report level " + val );
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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,
|
||||
|
||||
unit_test::INV_OF
|
||||
);
|
||||
|
||||
std::string val;
|
||||
in >> val;
|
||||
|
||||
of = output_format_name[val];
|
||||
BOOST_TEST_SETUP_ASSERT( of != unit_test::INV_OF, "invalid output format " + val );
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime_config ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace runtime_config {
|
||||
|
||||
namespace {
|
||||
|
||||
// framework parameters and corresponding command-line arguments
|
||||
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 DETECT_FP_EXCEPT = "detect_fp_exceptions";
|
||||
std::string DETECT_MEM_LEAKS = "detect_memory_leaks";
|
||||
std::string LOG_FORMAT = "log_format";
|
||||
std::string LOG_LEVEL = "log_level";
|
||||
std::string LOG_SINK = "log_sink";
|
||||
std::string OUTPUT_FORMAT = "output_format";
|
||||
std::string RANDOM_SEED = "random";
|
||||
std::string REPORT_FORMAT = "report_format";
|
||||
std::string REPORT_LEVEL = "report_level";
|
||||
std::string REPORT_SINK = "report_sink";
|
||||
std::string RESULT_CODE = "result_code";
|
||||
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";
|
||||
|
||||
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",
|
||||
|
||||
""
|
||||
);
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// storage for the CLAs
|
||||
cla::parser s_cla_parser;
|
||||
std::string s_empty;
|
||||
|
||||
output_format s_report_format;
|
||||
output_format s_log_format;
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
retrieve_parameter( const_string parameter_name, cla::parser const& s_cla_parser, T const& default_value = T(), T const& optional_value = T() )
|
||||
{
|
||||
rt::const_argument_ptr arg = s_cla_parser[parameter_name];
|
||||
if( arg ) {
|
||||
if( rtti::type_id<T>() == rtti::type_id<bool>() ||
|
||||
!static_cast<cla::parameter const&>( arg->p_formal_parameter.get() ).p_optional_value )
|
||||
return s_cla_parser.get<T>( parameter_name );
|
||||
|
||||
optional<T> val = s_cla_parser.get<optional<T> >( parameter_name );
|
||||
if( val )
|
||||
return *val;
|
||||
else
|
||||
return optional_value;
|
||||
}
|
||||
|
||||
boost::optional<T> v;
|
||||
|
||||
#ifndef UNDER_CE
|
||||
env::get( parameter_2_env_var[parameter_name], v );
|
||||
#endif
|
||||
|
||||
if( v )
|
||||
return *v;
|
||||
else
|
||||
return default_value;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // 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")
|
||||
;
|
||||
|
||||
s_cla_parser.parse( argc, argv );
|
||||
|
||||
if( s_cla_parser["help"] ) {
|
||||
s_cla_parser.help( std::cout );
|
||||
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 );
|
||||
|
||||
unit_test::output_format of = retrieve_parameter( OUTPUT_FORMAT, s_cla_parser, unit_test::INV_OF );
|
||||
|
||||
if( of != unit_test::INV_OF )
|
||||
s_report_format = s_log_format = of;
|
||||
}
|
||||
catch( rt::logic_error const& 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() );
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test::log_level
|
||||
log_level()
|
||||
{
|
||||
return retrieve_parameter( LOG_LEVEL, s_cla_parser, unit_test::log_all_errors );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
no_result_code()
|
||||
{
|
||||
return !retrieve_parameter( RESULT_CODE, s_cla_parser, true );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
unit_test::report_level
|
||||
report_level()
|
||||
{
|
||||
return retrieve_parameter( REPORT_LEVEL, s_cla_parser, unit_test::CONFIRMATION_REPORT );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
const_string
|
||||
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;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
const_string
|
||||
break_exec_path()
|
||||
{
|
||||
static std::string s_break_exec_path = retrieve_parameter( BREAK_EXEC_PATH, s_cla_parser, s_empty );
|
||||
|
||||
return s_break_exec_path;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
save_pattern()
|
||||
{
|
||||
return retrieve_parameter( SAVE_TEST_PATTERN, s_cla_parser, false );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
show_progress()
|
||||
{
|
||||
return retrieve_parameter( SHOW_PROGRESS, s_cla_parser, false );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
show_build_info()
|
||||
{
|
||||
return retrieve_parameter( BUILD_INFO, s_cla_parser, false );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
catch_sys_errors()
|
||||
{
|
||||
return retrieve_parameter( CATCH_SYS_ERRORS, s_cla_parser,
|
||||
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
auto_start_dbg()
|
||||
{
|
||||
// !! set debugger as an option
|
||||
return retrieve_parameter( AUTO_START_DBG, s_cla_parser, false );
|
||||
;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
use_alt_stack()
|
||||
{
|
||||
return retrieve_parameter( USE_ALT_STACK, s_cla_parser, true );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
detect_fp_exceptions()
|
||||
{
|
||||
return retrieve_parameter( DETECT_FP_EXCEPT, s_cla_parser, false );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
output_format
|
||||
report_format()
|
||||
{
|
||||
return s_report_format;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
output_format
|
||||
log_format()
|
||||
{
|
||||
return s_log_format;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::ostream*
|
||||
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;
|
||||
|
||||
if( sink_name == "stdout" )
|
||||
return &std::cout;
|
||||
|
||||
static std::ofstream log_file( sink_name.c_str() );
|
||||
return &log_file;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::ostream*
|
||||
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;
|
||||
|
||||
if( sink_name == "stderr" )
|
||||
return &std::cerr;
|
||||
|
||||
static std::ofstream report_file( sink_name.c_str() );
|
||||
return &report_file;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
long
|
||||
detect_memory_leaks()
|
||||
{
|
||||
return retrieve_parameter( DETECT_MEM_LEAKS, s_cla_parser, static_cast<long>(1) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
int
|
||||
random_seed()
|
||||
{
|
||||
return retrieve_parameter( RANDOM_SEED, s_cla_parser, 0, 1 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace runtime_config
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER
|
346
xs/include/boost/test/impl/unit_test_suite.ipp
Normal file
346
xs/include/boost/test/impl/unit_test_suite.ipp
Normal file
|
@ -0,0 +1,346 @@
|
|||
// (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: 54633 $
|
||||
//
|
||||
// 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
|
180
xs/include/boost/test/impl/xml_log_formatter.ipp
Normal file
180
xs/include/boost/test/impl/xml_log_formatter.ipp
Normal file
|
@ -0,0 +1,180 @@
|
|||
// (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: 57992 $
|
||||
//
|
||||
// Description : implements XML Log formatter
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
|
||||
#define BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/output/xml_log_formatter.hpp>
|
||||
#include <boost/test/unit_test_suite_impl.hpp>
|
||||
#include <boost/test/framework.hpp>
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
|
||||
#include <boost/test/utils/xml_printer.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/version.hpp>
|
||||
|
||||
// STL
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** xml_log_formatter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
xml_log_formatter::log_start( std::ostream& ostr, counter_t )
|
||||
{
|
||||
ostr << "<TestLog>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_finish( std::ostream& ostr )
|
||||
{
|
||||
ostr << "</TestLog>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_build_info( std::ostream& ostr )
|
||||
{
|
||||
ostr << "<BuildInfo"
|
||||
<< " platform" << attr_value() << BOOST_PLATFORM
|
||||
<< " compiler" << attr_value() << BOOST_COMPILER
|
||||
<< " stl" << attr_value() << BOOST_STDLIB
|
||||
<< " boost=\"" << BOOST_VERSION/100000 << "."
|
||||
<< BOOST_VERSION/100 % 1000 << "."
|
||||
<< BOOST_VERSION % 100 << '\"'
|
||||
<< "/>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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() << ">";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
ostr << "<" << tu_type_name( tu )
|
||||
<< " name" << attr_value() << tu.p_name.get()
|
||||
<< " skipped" << attr_value() << "yes"
|
||||
<< "/>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
|
||||
{
|
||||
execution_exception::location const& loc = ex.where();
|
||||
|
||||
ostr << "<Exception file" << attr_value() << loc.m_file_name
|
||||
<< " line" << attr_value() << loc.m_line_num;
|
||||
|
||||
if( !loc.m_function.is_empty() )
|
||||
ostr << " function" << attr_value() << loc.m_function;
|
||||
|
||||
ostr << ">" << cdata() << ex.what();
|
||||
|
||||
if( !checkpoint_data.m_file_name.is_empty() ) {
|
||||
ostr << "<LastCheckpoint file" << attr_value() << checkpoint_data.m_file_name
|
||||
<< " line" << attr_value() << checkpoint_data.m_line_num
|
||||
<< ">"
|
||||
<< cdata() << checkpoint_data.m_message
|
||||
<< "</LastCheckpoint>";
|
||||
}
|
||||
|
||||
ostr << "</Exception>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& entry_data, log_entry_types let )
|
||||
{
|
||||
static literal_string xml_tags[] = { "Info", "Message", "Warning", "Error", "FatalError" };
|
||||
|
||||
m_curr_tag = xml_tags[let];
|
||||
ostr << '<' << m_curr_tag
|
||||
<< 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[" );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
|
||||
{
|
||||
ostr << value;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_log_formatter::log_entry_finish( std::ostream& ostr )
|
||||
{
|
||||
ostr << BOOST_TEST_L( "]]></" ) << m_curr_tag << BOOST_TEST_L( ">" );
|
||||
|
||||
m_curr_tag.clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace output
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
|
115
xs/include/boost/test/impl/xml_report_formatter.ipp
Normal file
115
xs/include/boost/test/impl/xml_report_formatter.ipp
Normal file
|
@ -0,0 +1,115 @@
|
|||
// (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: 49312 $
|
||||
//
|
||||
// Description : XML report formatter
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
|
||||
#define BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
|
||||
|
||||
// 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/utils/xml_printer.hpp>
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
|
||||
#include <boost/test/detail/suppress_warnings.hpp>
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace unit_test {
|
||||
|
||||
namespace output {
|
||||
|
||||
void
|
||||
xml_report_formatter::results_report_start( std::ostream& ostr )
|
||||
{
|
||||
ostr << "<TestResult>";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_report_formatter::results_report_finish( std::ostream& ostr )
|
||||
{
|
||||
ostr << "</TestResult>";
|
||||
}
|
||||
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream& ostr )
|
||||
{
|
||||
test_results const& tr = results_collector.results( tu.p_id );
|
||||
|
||||
const_string descr;
|
||||
|
||||
if( tr.passed() )
|
||||
descr = "passed";
|
||||
else if( tr.p_skipped )
|
||||
descr = "skipped";
|
||||
else if( tr.p_aborted )
|
||||
descr = "aborted";
|
||||
else
|
||||
descr = "failed";
|
||||
|
||||
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
|
||||
<< " expected_failures" << attr_value() << tr.p_expected_failures;
|
||||
|
||||
if( tu.p_type == tut_suite )
|
||||
ostr << " test_cases_passed" << attr_value() << tr.p_test_cases_passed
|
||||
<< " 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 << '>';
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
xml_report_formatter::test_unit_report_finish( test_unit const& tu, std::ostream& ostr )
|
||||
{
|
||||
ostr << "</" << ( tu.p_type == tut_case ? "TestCase" : "TestSuite" ) << '>';
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace output
|
||||
|
||||
} // namespace unit_test
|
||||
|
||||
} // namespace boost
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
#include <boost/test/detail/enable_warnings.hpp>
|
||||
|
||||
#endif // BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
|
Loading…
Add table
Add a link
Reference in a new issue