early-access version 3088

This commit is contained in:
pineappleEA
2022-11-05 15:35:56 +01:00
parent 4e4fc25ce3
commit b601909c6d
35519 changed files with 5996896 additions and 860 deletions

View File

@@ -0,0 +1,293 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/tree/test_unit.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 {
std::string
test_phase_identifier()
{
return framework::test_in_progress() ? framework::current_test_unit().full_name() : std::string( "Test setup" );
}
} // local namespace
//____________________________________________________________________________//
void
compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount )
{
m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
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, bool log_build_info )
{
if(log_build_info) {
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 )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::BLUE );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Entering test " << tu.p_type_name << " \"" << tu.p_name << "\"" << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const& tu, unsigned long elapsed )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::BLUE );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Leaving test " << tu.p_type_name << " \"" << tu.p_name << "\"";
if( elapsed > 0 ) {
output << "; testing time: ";
if( elapsed % 1000 == 0 )
output << elapsed/1000 << "ms";
else
output << elapsed << "us";
}
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu, const_string reason )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::YELLOW );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Test " << tu.p_type_name << " \"" << tu.full_name() << "\"" << " is skipped because " << reason << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_exception_start( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
print_prefix( output, loc.m_file_name, loc.m_line_num );
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::UNDERLINE, term_color::RED );
output << "fatal error: in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": "
<< ex.what();
}
if( !checkpoint_data.m_file_name.is_empty() ) {
output << '\n';
print_prefix( output, checkpoint_data.m_file_name, checkpoint_data.m_line_num );
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::CYAN );
output << "last checkpoint";
if( !checkpoint_data.m_message.empty() )
output << ": " << checkpoint_data.m_message;
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_exception_finish( std::ostream& output )
{
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data const& entry_data, log_entry_types let )
{
using namespace utils;
switch( let ) {
case BOOST_UTL_ET_INFO:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::GREEN, term_color::ORIGINAL, &m_color_state);
output << "info: ";
break;
case BOOST_UTL_ET_MESSAGE:
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::CYAN, term_color::ORIGINAL, &m_color_state);
break;
case BOOST_UTL_ET_WARNING:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::YELLOW, term_color::ORIGINAL, &m_color_state);
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 << setcolor( m_color_output, term_attr::BRIGHT, term_color::RED, term_color::ORIGINAL, &m_color_state);
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 << setcolor( m_color_output, term_attr::UNDERLINE, term_color::RED, term_color::ORIGINAL, &m_color_state);
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 )
{
if( m_color_output )
output << utils::setcolor(m_color_output, &m_color_state);
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::print_prefix( std::ostream& output, const_string file_name, std::size_t line_num )
{
if( !file_name.empty() ) {
#ifdef __APPLE_CC__
// Xcode-compatible logging format, idea by Richard Dingwall at
// <http://richarddingwall.name/2008/06/01/using-the-boost-unit-test-framework-with-xcode-3/>.
output << file_name << ':' << line_num << ": ";
#else
output << file_name << '(' << line_num << "): ";
#endif
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
{
if( l == log_messages ) {
output << "\n[context:";
}
else {
output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::entry_context_finish( std::ostream& output, log_level l )
{
if( l == log_messages ) {
output << "]";
}
output.flush();
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_context( std::ostream& output, log_level /*l*/, const_string context_descr )
{
output << "\n " << context_descr;
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,136 @@
// (C) Copyright Gennadiy Rozental 2001.
// (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$
//
// 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;
BOOST_TEST_I_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( 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;
}
}
BOOST_TEST_I_CATCH( ::boost::execution_exception, exex ) {
std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl;
result = ::boost::exit_exception_failure;
}
BOOST_TEST_I_CATCH( ::boost::system_error, 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
// (C) Copyright Gennadiy Rozental 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.
//
// Description : unit test decorators implementation
// ***************************************************************************
#ifndef BOOST_TEST_TREE_DECORATOR_IPP_091911GER
#define BOOST_TEST_TREE_DECORATOR_IPP_091911GER
// Boost.Test
#include <boost/test/tree/decorator.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/framework.hpp>
#if BOOST_TEST_SUPPORT_TOKEN_ITERATOR
#include <boost/test/utils/iterator/token_iterator.hpp>
#endif
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace decorator {
// ************************************************************************** //
// ************** decorator::collector_t ************** //
// ************************************************************************** //
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(collector_t)
collector_t&
collector_t::operator*( base const& d )
{
m_tu_decorators_stack.begin()->push_back( d.clone() );
return *this;
}
//____________________________________________________________________________//
void
collector_t::store_in( test_unit& tu )
{
tu.p_decorators.value.insert(
tu.p_decorators.value.end(),
m_tu_decorators_stack.begin()->begin(),
m_tu_decorators_stack.begin()->end() );
}
//____________________________________________________________________________//
void
collector_t::reset()
{
if(m_tu_decorators_stack.size() > 1) {
m_tu_decorators_stack.erase(m_tu_decorators_stack.begin());
}
else {
assert(m_tu_decorators_stack.size() == 1);
m_tu_decorators_stack.begin()->clear();
}
}
void
collector_t::stack()
{
assert(m_tu_decorators_stack.size() >= 1);
m_tu_decorators_stack.insert(m_tu_decorators_stack.begin(), std::vector<base_ptr>());
}
//____________________________________________________________________________//
std::vector<base_ptr>
collector_t::get_lazy_decorators() const
{
return *m_tu_decorators_stack.begin();
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::base ************** //
// ************************************************************************** //
collector_t&
base::operator*() const
{
return collector_t::instance() * *this;
}
// ************************************************************************** //
// ************** decorator::stack_decorator ************** //
// ************************************************************************** //
collector_t&
stack_decorator::operator*() const
{
collector_t& instance = collector_t::instance();
instance.stack();
return instance * *this;
}
void
stack_decorator::apply( test_unit& /*tu*/ )
{
// does nothing by definition
}
// ************************************************************************** //
// ************** decorator::label ************** //
// ************************************************************************** //
void
label::apply( test_unit& tu )
{
tu.add_label( m_label );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::expected_failures ************** //
// ************************************************************************** //
void
expected_failures::apply( test_unit& tu )
{
tu.increase_exp_fail( m_exp_fail );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::timeout ************** //
// ************************************************************************** //
void
timeout::apply( test_unit& tu )
{
tu.p_timeout.value = m_timeout;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::description ************** //
// ************************************************************************** //
void
description::apply( test_unit& tu )
{
tu.p_description.value += m_description;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::depends_on ************** //
// ************************************************************************** //
void
depends_on::apply( test_unit& tu )
{
#if !BOOST_TEST_SUPPORT_TOKEN_ITERATOR
BOOST_TEST_SETUP_ASSERT( false, "depends_on decorator is not supported on this platform" );
#else
utils::string_token_iterator tit( m_dependency, (utils::dropped_delimeters = "/", utils::kept_delimeters = utils::dt_none) );
test_unit* dep = &framework::master_test_suite();
while( tit != utils::string_token_iterator() ) {
BOOST_TEST_SETUP_ASSERT( dep->p_type == TUT_SUITE, std::string( "incorrect dependency specification " ) + m_dependency );
test_unit_id next_id = static_cast<test_suite*>(dep)->get( *tit );
BOOST_TEST_SETUP_ASSERT( next_id != INV_TEST_UNIT_ID,
std::string( "incorrect dependency specification " ) + m_dependency );
dep = &framework::get( next_id, TUT_ANY );
++tit;
}
tu.depends_on( dep );
#endif
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::enable_if/enabled/disabled ************** //
// ************************************************************************** //
void
enable_if_impl::apply_impl( test_unit& tu, bool condition )
{
BOOST_TEST_SETUP_ASSERT(tu.p_default_status == test_unit::RS_INHERIT,
"Can't apply multiple enabled/disabled decorators "
"to the same test unit " + tu.full_name());
tu.p_default_status.value = condition ? test_unit::RS_ENABLED : test_unit::RS_DISABLED;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::fixture ************** //
// ************************************************************************** //
void
fixture_t::apply( test_unit& tu )
{
tu.p_fixtures.value.push_back( m_impl );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** decorator::depends_on ************** //
// ************************************************************************** //
void
precondition::apply( test_unit& tu )
{
tu.add_precondition( m_precondition );
}
//____________________________________________________________________________//
} // namespace decorator
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TREE_DECORATOR_IPP_091911GER

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,878 @@
// (C) Copyright 2016 Raffi Enficiaud.
// 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
///@brief Contains the implementatoin of the Junit log formatter (OF_JUNIT)
// ***************************************************************************
#ifndef BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
#define BOOST_TEST_JUNIT_LOG_FORMATTER_IPP__
// Boost.Test
#include <boost/test/output/junit_log_formatter.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/xml_printer.hpp>
#include <boost/test/utils/string_cast.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/traverse.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/utils/algorithm.hpp>
#include <boost/test/utils/string_cast.hpp>
//#include <boost/test/results_reporter.hpp>
// Boost
#include <boost/version.hpp>
#include <boost/core/ignore_unused.hpp>
// STL
#include <iostream>
#include <fstream>
#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
struct s_replace_chars {
template <class T>
void operator()(T& to_replace)
{
if(to_replace == '/')
to_replace = '.';
else if(to_replace == ' ')
to_replace = '_';
}
};
inline std::string tu_name_normalize(std::string full_name)
{
// maybe directly using normalize_test_case_name instead?
std::for_each(full_name.begin(), full_name.end(), s_replace_chars());
return full_name;
}
inline std::string tu_name_remove_newlines(std::string full_name)
{
full_name.erase(std::remove(full_name.begin(), full_name.end(), '\n'), full_name.end());
return full_name;
}
const_string file_basename(const_string filename) {
const_string path_sep( "\\/" );
const_string::iterator it = unit_test::utils::find_last_of( filename.begin(), filename.end(),
path_sep.begin(), path_sep.end() );
if( it != filename.end() )
filename.trim_left( it + 1 );
return filename;
}
// ************************************************************************** //
// ************** junit_log_formatter ************** //
// ************************************************************************** //
void
junit_log_formatter::log_start( std::ostream& /*ostr*/, counter_t /*test_cases_amount*/)
{
map_tests.clear();
list_path_to_root.clear();
runner_log_entry.clear();
}
//____________________________________________________________________________//
class junit_result_helper : public test_tree_visitor {
private:
typedef junit_impl::junit_log_helper::assertion_entry assertion_entry;
typedef std::vector< assertion_entry >::const_iterator vect_assertion_entry_citerator;
typedef std::list<std::string>::const_iterator list_str_citerator;
public:
explicit junit_result_helper(
std::ostream& stream,
test_unit const& ts,
junit_log_formatter::map_trace_t const& mt,
junit_impl::junit_log_helper const& runner_log_,
bool display_build_info )
: m_stream(stream)
, m_ts( ts )
, m_map_test( mt )
, runner_log( runner_log_ )
, m_id( 0 )
, m_display_build_info(display_build_info)
{ }
void add_log_entry(assertion_entry const& log) const
{
std::string entry_type;
if( log.log_entry == assertion_entry::log_entry_failure ) {
entry_type = "failure";
}
else if( log.log_entry == assertion_entry::log_entry_error ) {
entry_type = "error";
}
else {
return;
}
m_stream
<< "<" << entry_type
<< " message" << utils::attr_value() << log.logentry_message
<< " type" << utils::attr_value() << log.logentry_type
<< ">";
if(!log.output.empty()) {
m_stream << utils::cdata() << "\n" + log.output;
}
m_stream << "</" << entry_type << ">";
}
struct conditional_cdata_helper {
std::ostream &ostr;
std::string const field;
bool empty;
conditional_cdata_helper(std::ostream &ostr_, std::string field_)
: ostr(ostr_)
, field(field_)
, empty(true)
{}
~conditional_cdata_helper() {
if(!empty) {
ostr << BOOST_TEST_L( "]]>" ) << "</" << field << '>' << std::endl;
}
}
void operator()(const std::string& s) {
bool current_empty = s.empty();
if(empty) {
if(!current_empty) {
empty = false;
ostr << '<' << field << '>' << BOOST_TEST_L( "<![CDATA[" );
}
}
if(!current_empty) {
ostr << s;
}
}
};
std::list<std::string> build_skipping_chain(test_unit const & tu) const
{
// we enter here because we know that the tu has been skipped.
// either junit has not seen this tu, or it is indicated as disabled
assert(m_map_test.count(tu.p_id) == 0 || results_collector.results( tu.p_id ).p_skipped);
std::list<std::string> out;
test_unit_id id(tu.p_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
test_unit const& tu_hierarchy = boost::unit_test::framework::get( id, TUT_ANY );
out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu_hierarchy.full_name()) + "'\n");
if(m_map_test.count(id) > 0)
{
// junit has seen the reason: this is enough for constructing the chain
break;
}
id = tu_hierarchy.p_parent_id;
}
junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
if( it_element_stack != m_map_test.end() )
{
out.push_back("- reason: '" + it_element_stack->second.skipping_reason + "'");
out.push_front("Test case disabled because of the following chain of decision:\n");
}
return out;
}
std::string get_class_name(test_unit const & tu_class) const {
std::string classname;
test_unit_id id(tu_class.p_parent_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID ) {
test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
classname = tu_name_normalize(tu.p_name) + "." + classname;
id = tu.p_parent_id;
}
// removes the trailing dot
if(!classname.empty() && *classname.rbegin() == '.') {
classname.erase(classname.size()-1);
}
return classname;
}
void write_testcase_header(test_unit const & tu,
test_results const *tr,
int nb_assertions) const
{
std::string name;
std::string classname;
if(tu.p_id == m_ts.p_id ) {
name = "boost_test";
}
else {
classname = get_class_name(tu);
name = tu_name_normalize(tu.p_name);
}
if( tu.p_type == TUT_SUITE ) {
if(tr->p_timed_out)
name += "-timed-execution";
else
name += "-setup-teardown";
}
m_stream << "<testcase assertions" << utils::attr_value() << nb_assertions;
if(!classname.empty())
m_stream << " classname" << utils::attr_value() << classname;
// test case name and time taken
m_stream
<< " name" << utils::attr_value() << name
<< " time" << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
<< ">" << std::endl;
}
void write_testcase_system_out(junit_impl::junit_log_helper const &detailed_log,
test_unit const * tu,
bool skipped) const
{
// system-out + all info/messages, the object skips the empty entries
conditional_cdata_helper system_out_helper(m_stream, "system-out");
// indicate why the test has been skipped first
if( skipped ) {
std::list<std::string> skipping_decision_chain = build_skipping_chain(*tu);
for(list_str_citerator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
it != ite;
++it)
{
system_out_helper(*it);
}
}
// stdout
for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
it != ite;
++it)
{
system_out_helper(*it);
}
// warning/info message last
for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
if(it->log_entry != assertion_entry::log_entry_info)
continue;
system_out_helper(it->output);
}
}
void write_testcase_system_err(junit_impl::junit_log_helper const &detailed_log,
test_unit const * tu,
test_results const *tr) const
{
// system-err output + test case informations
bool has_failed = (tr != 0) ? !tr->p_skipped && !tr->passed() : false;
if(!detailed_log.system_err.empty() || has_failed)
{
std::ostringstream o;
if(has_failed) {
o << "Failures detected in:" << std::endl;
}
else {
o << "ERROR STREAM:" << std::endl;
}
if(tu->p_type == TUT_SUITE) {
if( tu->p_id == m_ts.p_id ) {
o << " boost.test global setup/teardown" << std::endl;
} else {
o << "- test suite: " << tu_name_remove_newlines(tu->full_name()) << std::endl;
}
}
else {
o << "- test case: " << tu_name_remove_newlines(tu->full_name());
if(!tu->p_description.value.empty())
o << " '" << tu->p_description << "'";
o << std::endl
<< "- file: " << file_basename(tu->p_file_name) << std::endl
<< "- line: " << tu->p_line_num << std::endl
;
}
if(!detailed_log.system_err.empty())
o << std::endl << "STDERR BEGIN: ------------" << std::endl;
for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
it != ite;
++it)
{
o << *it;
}
if(!detailed_log.system_err.empty())
o << std::endl << "STDERR END ------------" << std::endl;
conditional_cdata_helper system_err_helper(m_stream, "system-err");
system_err_helper(o.str());
}
}
int get_nb_assertions(junit_impl::junit_log_helper const &detailed_log,
test_unit const & tu,
test_results const *tr) const {
int nb_assertions(-1);
if( tu.p_type == TUT_SUITE ) {
nb_assertions = 0;
for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
if(it->log_entry != assertion_entry::log_entry_info)
nb_assertions++;
}
}
else {
nb_assertions = static_cast<int>(tr->p_assertions_passed + tr->p_assertions_failed);
}
return nb_assertions;
}
void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
test_unit const & tu,
bool skipped,
test_results const *tr) const
{
int nb_assertions = get_nb_assertions(detailed_log, tu, tr);
if(!nb_assertions && tu.p_type == TUT_SUITE)
return;
write_testcase_header(tu, tr, nb_assertions);
if( skipped ) {
m_stream << "<skipped/>" << std::endl;
}
else {
for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
add_log_entry(*it);
}
}
write_testcase_system_out(detailed_log, &tu, skipped);
write_testcase_system_err(detailed_log, &tu, tr);
m_stream << "</testcase>" << std::endl;
}
void visit( test_case const& tc ) BOOST_OVERRIDE
{
test_results const& tr = results_collector.results( tc.p_id );
junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(tc.p_id);
if(it_find == m_map_test.end())
{
// test has been skipped and not seen by the logger
output_detailed_logs(junit_impl::junit_log_helper(), tc, true, &tr);
}
else {
output_detailed_logs(it_find->second, tc, tr.p_skipped, &tr);
}
}
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
test_results const& tr = results_collector.results( ts.p_id );
// unique test suite, without s, nesting not supported in CI
if( m_ts.p_id == ts.p_id ) {
m_stream << "<testsuite";
// think about: maybe we should add the number of fixtures of a test_suite as
// independent tests (field p_fixtures).
// same goes for the timed-execution: we can think of that as a separate test-unit
// in the suite.
// see https://llg.cubic.org/docs/junit/ and
// http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java?view=markup
m_stream
// << "disabled=\"" << tr.p_test_cases_skipped << "\" "
<< " tests" << utils::attr_value()
<< tr.p_test_cases_passed
+ tr.p_test_cases_failed
// + tr.p_test_cases_aborted // aborted is also failed, we avoid counting it twice
<< " skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " errors" << utils::attr_value() << tr.p_test_cases_aborted
<< " failures" << utils::attr_value()
<< tr.p_test_cases_failed
+ tr.p_test_suites_timed_out
+ tr.p_test_cases_timed_out
- tr.p_test_cases_aborted // failed is not aborted in the Junit sense
<< " id" << utils::attr_value() << m_id++
<< " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
<< " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
<< ">" << std::endl;
if(m_display_build_info)
{
m_stream << "<properties>" << std::endl;
m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << " />" << std::endl;
m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << " />" << std::endl;
m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << " />" << std::endl;
std::ostringstream o;
o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << " />" << std::endl;
m_stream << "</properties>" << std::endl;
}
}
if( !tr.p_skipped ) {
// if we land here, then this is a chance that we are logging the fixture setup/teardown of a test-suite.
// the setup/teardown logging of a test-case is part of the test case.
// we do not care about the test-suite that were skipped (really??)
junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(ts.p_id);
if(it_find != m_map_test.end()) {
output_detailed_logs(it_find->second, ts, false, &tr);
}
}
return true; // indicates that the children should also be parsed
}
void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
{
if( m_ts.p_id == ts.p_id ) {
write_testcase_system_out(runner_log, 0, false);
write_testcase_system_err(runner_log, 0, 0);
m_stream << "</testsuite>";
return;
}
}
private:
// Data members
std::ostream& m_stream;
test_unit const& m_ts;
junit_log_formatter::map_trace_t const& m_map_test;
junit_impl::junit_log_helper const& runner_log;
size_t m_id;
bool m_display_build_info;
};
void
junit_log_formatter::log_finish( std::ostream& ostr )
{
ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
// getting the root test suite
if(!map_tests.empty()) {
test_unit* root = &boost::unit_test::framework::get( map_tests.begin()->first, TUT_ANY );
// looking for the root of the SUBtree (we stay in the subtree)
while(root->p_parent_id != INV_TEST_UNIT_ID && map_tests.count(root->p_parent_id) > 0) {
root = &boost::unit_test::framework::get( root->p_parent_id, TUT_ANY );
}
junit_result_helper ch( ostr, *root, map_tests, this->runner_log_entry, m_display_build_info );
traverse_test_tree( root->p_id, ch, true ); // last is to ignore disabled suite special handling
}
else {
ostr << "<testsuites errors=\"1\">";
ostr << "<testsuite errors=\"1\" name=\"boost-test-framework\">";
ostr << "<testcase assertions=\"1\" name=\"test-setup\">";
ostr << "<system-out>Incorrect setup: no test case executed</system-out>";
ostr << "</testcase></testsuite></testsuites>";
}
return;
}
//____________________________________________________________________________//
void
junit_log_formatter::log_build_info( std::ostream& /*ostr*/, bool log_build_info )
{
m_display_build_info = log_build_info;
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_start( std::ostream& /*ostr*/, test_unit const& tu )
{
list_path_to_root.push_back( tu.p_id );
map_tests.insert(std::make_pair(tu.p_id, junit_impl::junit_log_helper())); // current_test_case_id not working here
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_finish( std::ostream& /*ostr*/, test_unit const& tu, unsigned long /*elapsed*/ )
{
// the time is already stored in the result_reporter
boost::ignore_unused( tu );
assert( tu.p_id == list_path_to_root.back() );
list_path_to_root.pop_back();
}
void
junit_log_formatter::test_unit_aborted( std::ostream& /*ostr*/, test_unit const& tu )
{
boost::ignore_unused( tu );
assert( tu.p_id == list_path_to_root.back() );
//list_path_to_root.pop_back();
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_timed_out( std::ostream& /*os*/, test_unit const& tu)
{
if(tu.p_type == TUT_SUITE)
{
// if we reach this call, it means that the test has already started and
// test_unit_start has already been called on the tu.
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
junit_impl::junit_log_helper::assertion_entry entry;
entry.logentry_message = "test-suite time out";
entry.logentry_type = "execution timeout";
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
entry.output = "the current suite exceeded the allocated execution time";
last_entry.assertion_entries.push_back(entry);
}
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_skipped( std::ostream& /*ostr*/, test_unit const& tu, const_string reason )
{
// if a test unit is skipped, then the start of this TU has not been called yet.
// we cannot use get_current_log_entry here, but the TU id should appear in the map.
// The "skip" boolean is given by the boost.test framework
junit_impl::junit_log_helper& v = map_tests[tu.p_id]; // not sure if we can use get_current_log_entry()
v.skipping_reason.assign(reason.begin(), reason.end());
}
//____________________________________________________________________________//
void
junit_log_formatter::log_exception_start( std::ostream& /*ostr*/, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
std::ostringstream o;
execution_exception::location const& loc = ex.where();
m_is_last_assertion_or_error = false;
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
junit_impl::junit_log_helper::assertion_entry entry;
entry.logentry_message = "unexpected exception";
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
switch(ex.code())
{
case execution_exception::cpp_exception_error:
entry.logentry_type = "uncaught exception";
break;
case execution_exception::timeout_error:
entry.logentry_type = "execution timeout";
break;
case execution_exception::user_error:
entry.logentry_type = "user, assert() or CRT error";
break;
case execution_exception::user_fatal_error:
// Looks like never used
entry.logentry_type = "user fatal error";
break;
case execution_exception::system_error:
entry.logentry_type = "system error";
break;
case execution_exception::system_fatal_error:
entry.logentry_type = "system fatal error";
break;
default:
entry.logentry_type = "no error"; // not sure how to handle this one
break;
}
o << "UNCAUGHT EXCEPTION:" << std::endl;
if( !loc.m_function.is_empty() )
o << "- function: \"" << loc.m_function << "\"" << std::endl;
o << "- file: " << file_basename(loc.m_file_name) << std::endl
<< "- line: " << loc.m_line_num << std::endl
<< std::endl;
o << "\nEXCEPTION STACK TRACE: --------------\n" << ex.what()
<< "\n-------------------------------------";
if( !checkpoint_data.m_file_name.is_empty() ) {
o << std::endl << std::endl
<< "Last checkpoint:" << std::endl
<< "- message: \"" << checkpoint_data.m_message << "\"" << std::endl
<< "- file: " << file_basename(checkpoint_data.m_file_name) << std::endl
<< "- line: " << checkpoint_data.m_line_num << std::endl
;
}
entry.output = o.str();
last_entry.assertion_entries.push_back(entry);
}
//____________________________________________________________________________//
void
junit_log_formatter::log_exception_finish( std::ostream& /*ostr*/ )
{
// sealing the last entry
assert(!get_current_log_entry().assertion_entries.back().sealed);
get_current_log_entry().assertion_entries.back().sealed = true;
}
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_start( std::ostream& /*ostr*/, log_entry_data const& entry_data, log_entry_types let )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
last_entry.skipping = false;
m_is_last_assertion_or_error = true;
switch(let)
{
case unit_test_log_formatter::BOOST_UTL_ET_INFO:
{
if(m_log_level_internal > log_successful_tests) {
last_entry.skipping = true;
break;
}
BOOST_FALLTHROUGH;
}
case unit_test_log_formatter::BOOST_UTL_ET_MESSAGE:
{
if(m_log_level_internal > log_messages) {
last_entry.skipping = true;
break;
}
BOOST_FALLTHROUGH;
}
case unit_test_log_formatter::BOOST_UTL_ET_WARNING:
{
if(m_log_level_internal > log_warnings) {
last_entry.skipping = true;
break;
}
std::ostringstream o;
junit_impl::junit_log_helper::assertion_entry entry;
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_info;
entry.logentry_message = "info";
entry.logentry_type = "message";
o << (let == unit_test_log_formatter::BOOST_UTL_ET_WARNING ?
"WARNING:" : (let == unit_test_log_formatter::BOOST_UTL_ET_MESSAGE ?
"MESSAGE:" : "INFO:"))
<< std::endl
<< "- file : " << file_basename(entry_data.m_file_name) << std::endl
<< "- line : " << entry_data.m_line_num << std::endl
<< "- message: "; // no CR
entry.output += o.str();
last_entry.assertion_entries.push_back(entry);
break;
}
default:
case unit_test_log_formatter::BOOST_UTL_ET_ERROR:
case unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR:
{
std::ostringstream o;
junit_impl::junit_log_helper::assertion_entry entry;
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_failure;
entry.logentry_message = "failure";
entry.logentry_type = (let == unit_test_log_formatter::BOOST_UTL_ET_ERROR ? "assertion error" : "fatal error");
o << "ASSERTION FAILURE:" << std::endl
<< "- file : " << file_basename(entry_data.m_file_name) << std::endl
<< "- line : " << entry_data.m_line_num << std::endl
<< "- message: " ; // no CR
entry.output += o.str();
last_entry.assertion_entries.push_back(entry);
break;
}
}
}
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_value( std::ostream& /*ostr*/, const_string value )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
return;
assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
if(!last_entry.assertion_entries.empty())
{
junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
log_entry.output += value;
}
else
{
// this may be a message coming from another observer
// the prefix is set in the log_entry_start
last_entry.system_out.push_back(std::string(value.begin(), value.end()));
}
}
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_finish( std::ostream& /*ostr*/ )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(!last_entry.skipping)
{
assert(last_entry.assertion_entries.empty() || !last_entry.assertion_entries.back().sealed);
if(!last_entry.assertion_entries.empty()) {
junit_impl::junit_log_helper::assertion_entry& log_entry = last_entry.assertion_entries.back();
log_entry.output += "\n\n"; // quote end, CR
log_entry.sealed = true;
}
else {
last_entry.system_out.push_back("\n\n"); // quote end, CR
}
}
last_entry.skipping = false;
}
//____________________________________________________________________________//
void
junit_log_formatter::entry_context_start( std::ostream& /*ostr*/, log_level )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
return;
std::vector< junit_impl::junit_log_helper::assertion_entry > &v_failure_or_error = last_entry.assertion_entries;
assert(!v_failure_or_error.back().sealed);
junit_impl::junit_log_helper::assertion_entry& last_log_entry = v_failure_or_error.back();
if(m_is_last_assertion_or_error)
{
last_log_entry.output += "\n- context:\n";
}
else
{
last_log_entry.output += "\n\nCONTEXT:\n";
}
}
//____________________________________________________________________________//
void
junit_log_formatter::entry_context_finish( std::ostream& /*ostr*/, log_level )
{
// no op, may be removed
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
return;
assert(!get_current_log_entry().assertion_entries.back().sealed);
}
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_context( std::ostream& /*ostr*/, log_level , const_string context_descr )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
return;
assert(!last_entry.assertion_entries.back().sealed);
junit_impl::junit_log_helper::assertion_entry& last_log_entry = get_current_log_entry().assertion_entries.back();
last_log_entry.output +=
(m_is_last_assertion_or_error ? " - '": "- '") + std::string(context_descr.begin(), context_descr.end()) + "'\n"; // quote end
}
//____________________________________________________________________________//
std::string
junit_log_formatter::get_default_stream_description() const {
std::string name = framework::master_test_suite().p_name.value;
static const std::string to_replace[] = { " ", "\"", "/", "\\", ":"};
static const std::string replacement[] = { "_", "_" , "_", "_" , "_"};
name = unit_test::utils::replace_all_occurrences_of(
name,
to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
std::ifstream check_init((name + ".xml").c_str());
if(!check_init)
return name + ".xml";
int index = 0;
for(; index < 100; index++) {
std::string candidate = name + "_" + utils::string_cast(index) + ".xml";
std::ifstream file(candidate.c_str());
if(!file)
return candidate;
}
return name + ".xml";
}
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_junit_log_formatter_IPP_020105GER

View File

@@ -0,0 +1,218 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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_parameters.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/setcolor.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 utils::custom_manip<struct quote_t> quote;
template<typename T>
inline std::ostream&
operator<<( utils::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 )
return;
if( total > 0 )
ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << name << ( v != 1 ? "s" : "" )
<< " out of " << total << ' ' << res << '\n';
else
ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << res << ' ' << name << ( v != 1 ? "s" : "" ) << '\n';
}
//____________________________________________________________________________//
} // local namespace
// ************************************************************************** //
// ************** plain_report_formatter ************** //
// ************************************************************************** //
void
plain_report_formatter::results_report_start( std::ostream& ostr )
{
m_indent = 0;
m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
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 = "has passed";
else if( tr.p_skipped )
descr = "was skipped";
else if( tr.p_timed_out )
descr = "has timed out";
else if( tr.p_aborted )
descr = "was aborted";
else
descr = "has failed";
ostr << std::setw( static_cast<int>(m_indent) ) << ""
<< "Test " << tu.p_type_name << ' ' << quote() << tu.full_name() << ' ' << descr;
if( tr.p_skipped ) {
ostr << "\n";
m_indent += 2;
return;
}
// aborted test case within failed ones, timed-out TC exclusive with failed/aborted
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_warned + tr.p_test_cases_failed + tr.p_test_cases_skipped + tr.p_test_cases_timed_out;
if( total_assertions > 0 || total_tc > 0 || tr.p_warnings_failed > 0)
ostr << " with:";
ostr << '\n';
m_indent += 2;
print_stat_value( ostr, tr.p_test_cases_passed , m_indent, total_tc , "test case", "passed" );
print_stat_value( ostr, tr.p_test_cases_warned , m_indent, total_tc , "test case", "passed with warnings" );
print_stat_value( ostr, tr.p_test_cases_failed , m_indent, total_tc , "test case", "failed" );
print_stat_value( ostr, tr.p_test_cases_timed_out, m_indent, total_tc , "test case", "timed-out" );
print_stat_value( ostr, tr.p_test_suites_timed_out, m_indent, tr.p_test_suites, "test suite", "timed-out" );
print_stat_value( ostr, tr.p_test_cases_skipped, m_indent, total_tc , "test case", "skipped" );
print_stat_value( ostr, tr.p_test_cases_aborted, m_indent, total_tc , "test case", "aborted" );
print_stat_value( ostr, tr.p_assertions_passed , m_indent, total_assertions, "assertion", "passed" );
print_stat_value( ostr, tr.p_assertions_failed , m_indent, total_assertions, "assertion", "failed" );
print_stat_value( ostr, tr.p_warnings_failed , m_indent, 0 , "warning" , "failed" );
print_stat_value( ostr, tr.p_expected_failures , m_indent, 0 , "failure" , "expected" );
ostr << '\n';
}
//____________________________________________________________________________//
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() ) {
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << "*** No errors detected\n";
return;
}
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, ostr, term_attr::BRIGHT, term_color::RED );
if( tr.p_skipped ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was skipped"
<< "; see standard output for details\n";
return;
}
if( tr.p_timed_out ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " has timed out"
<< "; see standard output for details\n";
return;
}
if( tr.p_aborted ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was aborted"
<< "; see standard output for details\n";
}
if( tr.p_assertions_failed == 0 ) {
if( !tr.p_aborted )
ostr << "*** Errors were detected in the test " << tu.p_type_name << ' ' << quote() << tu.full_name()
<< "; see standard output for details\n";
return;
}
counter_t num_failures = tr.p_assertions_failed;
ostr << "*** " << num_failures << " failure" << ( num_failures != 1 ? "s are" : " is" ) << " detected";
if( tr.p_expected_failures > 0 )
ostr << " (" << tr.p_expected_failures << " failure" << ( tr.p_expected_failures != 1 ? "s are" : " is" ) << " expected)";
ostr << " in the test " << tu.p_type_name << " " << quote() << tu.full_name() << "\n";
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,189 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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_parameters.hpp>
#include <boost/test/utils/setcolor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/test_case_counter.hpp>
#include <boost/test/tree/traverse.hpp>
// Boost
#include <boost/scoped_ptr.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** progress_monitor ************** //
// ************************************************************************** //
struct progress_display {
progress_display( counter_t expected_count, std::ostream& os )
: m_os(os)
, m_count( 0 )
, m_expected_count( expected_count )
, m_next_tic_count( 0 )
, m_tic( 0 )
{
m_os << "\n0% 10 20 30 40 50 60 70 80 90 100%"
<< "\n|----|----|----|----|----|----|----|----|----|----|"
<< std::endl;
if( !m_expected_count )
m_expected_count = 1; // prevent divide by zero
}
unsigned long operator+=( unsigned long increment )
{
if( (m_count += increment) < m_next_tic_count )
return m_count;
// use of floating point ensures that both large and small counts
// work correctly. static_cast<>() is also used several places
// to suppress spurious compiler warnings.
unsigned int tics_needed = static_cast<unsigned int>(
(static_cast<double>(m_count)/m_expected_count)*50.0 );
do {
m_os << '*' << std::flush;
} while( ++m_tic < tics_needed );
m_next_tic_count = static_cast<unsigned long>((m_tic/50.0) * m_expected_count);
if( m_count == m_expected_count ) {
if( m_tic < 51 )
m_os << '*';
m_os << std::endl;
}
return m_count;
}
unsigned long operator++() { return operator+=( 1 ); }
unsigned long count() const { return m_count; }
private:
BOOST_DELETED_FUNCTION(progress_display(progress_display const&))
BOOST_DELETED_FUNCTION(progress_display& operator=(progress_display const&))
std::ostream& m_os; // may not be present in all imps
unsigned long m_count;
unsigned long m_expected_count;
unsigned long m_next_tic_count;
unsigned int m_tic;
};
namespace {
struct progress_monitor_impl {
// Constructor
progress_monitor_impl()
: m_stream( &std::cout )
, m_color_output( false )
{
}
std::ostream* m_stream;
scoped_ptr<progress_display> m_progress_display;
bool m_color_output;
};
progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; return the_inst; }
#define PM_SCOPED_COLOR() \
BOOST_TEST_SCOPE_SETCOLOR( s_pm_impl().m_color_output, *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA )
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL(progress_monitor_t)
//____________________________________________________________________________//
void
progress_monitor_t::test_start( counter_t test_cases_amount, test_unit_id )
{
s_pm_impl().m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
PM_SCOPED_COLOR();
s_pm_impl().m_progress_display.reset( new progress_display( test_cases_amount, *s_pm_impl().m_stream ) );
}
//____________________________________________________________________________//
void
progress_monitor_t::test_aborted()
{
PM_SCOPED_COLOR();
(*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 )
{
PM_SCOPED_COLOR();
if( tu.p_type == TUT_CASE )
++(*s_pm_impl().m_progress_display);
}
//____________________________________________________________________________//
void
progress_monitor_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
PM_SCOPED_COLOR();
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;
}
//____________________________________________________________________________//
#undef PM_SCOPED_COLOR
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER

View File

@@ -0,0 +1,349 @@
// (C) Copyright Gennadiy Rozental 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
/// 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_log.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/test_case_counter.hpp>
#include <boost/test/tree/traverse.hpp>
// Boost
#include <boost/cstdlib.hpp>
// 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
{
// if it is skipped, it is not passed. However, if any children is not failed/aborted
// then their skipped status is not taken into account.
return !p_skipped &&
p_test_cases_failed == 0 &&
p_assertions_failed <= p_expected_failures &&
// p_test_cases_skipped == 0 &&
!p_timed_out &&
p_test_cases_timed_out == 0 &&
!aborted();
}
//____________________________________________________________________________//
bool
test_results::aborted() const
{
return p_aborted;
}
//____________________________________________________________________________//
bool
test_results::skipped() const
{
return p_skipped;
}
//____________________________________________________________________________//
int
test_results::result_code() const
{
return passed() ? exit_success
: ( (p_assertions_failed > p_expected_failures || p_skipped || p_timed_out || p_test_cases_timed_out )
? exit_test_failure
: exit_exception_failure );
}
//____________________________________________________________________________//
void
test_results::operator+=( test_results const& tr )
{
p_test_suites.value += tr.p_test_suites;
p_assertions_passed.value += tr.p_assertions_passed;
p_assertions_failed.value += tr.p_assertions_failed;
p_warnings_failed.value += tr.p_warnings_failed;
p_test_cases_passed.value += tr.p_test_cases_passed;
p_test_cases_warned.value += tr.p_test_cases_warned;
p_test_cases_failed.value += tr.p_test_cases_failed;
p_test_cases_skipped.value += tr.p_test_cases_skipped;
p_test_cases_aborted.value += tr.p_test_cases_aborted;
p_test_cases_timed_out.value += tr.p_test_cases_timed_out;
p_test_suites_timed_out.value += tr.p_test_suites_timed_out;
p_duration_microseconds.value += tr.p_duration_microseconds;
}
//____________________________________________________________________________//
void
test_results::clear()
{
p_test_suites.value = 0;
p_assertions_passed.value = 0;
p_assertions_failed.value = 0;
p_warnings_failed.value = 0;
p_expected_failures.value = 0;
p_test_cases_passed.value = 0;
p_test_cases_warned.value = 0;
p_test_cases_failed.value = 0;
p_test_cases_skipped.value = 0;
p_test_cases_aborted.value = 0;
p_test_cases_timed_out.value = 0;
p_test_suites_timed_out.value = 0;
p_duration_microseconds.value= 0;
p_aborted.value = false;
p_skipped.value = false;
p_timed_out.value = false;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** results_collector ************** //
// ************************************************************************** //
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; }
// deletes the entries of results_collector_impl
class clear_subtree_result : public test_tree_visitor {
public:
clear_subtree_result(results_collector_impl& store)
: m_store( store )
{}
private:
bool visit( test_unit const& tu) BOOST_OVERRIDE
{
typedef std::map<test_unit_id,test_results>::iterator iterator;
iterator found = m_store.m_results_store.find(tu.p_id);
if(found != m_store.m_results_store.end()) {
m_store.m_results_store.erase( found );
}
return true;
}
results_collector_impl& m_store;
};
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( results_collector_t )
//____________________________________________________________________________//
void
results_collector_t::test_start( counter_t, test_unit_id id )
{
// deletes the results under id only
clear_subtree_result tree_clear(s_rc_impl());
traverse_test_tree( id, tree_clear );
}
//____________________________________________________________________________//
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;
}
//____________________________________________________________________________//
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 ) BOOST_OVERRIDE
{
test_results const& tr = results_collector.results( tc.p_id );
m_tr += tr;
if( tr.passed() ) {
if( tr.p_warnings_failed )
m_tr.p_test_cases_warned.value++;
else
m_tr.p_test_cases_passed.value++;
}
else if( tr.p_timed_out ) {
m_tr.p_test_cases_timed_out.value++;
}
else if( tr.p_skipped || !tc.is_enabled() ) {
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 ) BOOST_OVERRIDE
{
if( m_ts.p_id == ts.p_id )
return true;
m_tr += results_collector.results( ts.p_id );
m_tr.p_test_suites.value++;
if( results_collector.results( ts.p_id ).p_timed_out )
m_tr.p_test_suites_timed_out.value++;
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 elapsed_in_microseconds )
{
test_results & tr = s_rc_impl().m_results_store[tu.p_id];
if( tu.p_type == TUT_SUITE ) {
results_collect_helper ch( tr, tu );
traverse_test_tree( tu, ch, true ); // true to ignore the status: we need to count the skipped/disabled tests
}
else {
bool num_failures_match = tr.p_aborted || tr.p_assertions_failed >= tr.p_expected_failures;
if( !num_failures_match )
BOOST_TEST_FRAMEWORK_MESSAGE( "Test case " << tu.full_name() << " has fewer failures than expected" );
bool check_any_assertions = tr.p_aborted || (tr.p_assertions_failed != 0) || (tr.p_assertions_passed != 0);
if( !check_any_assertions )
BOOST_TEST_FRAMEWORK_MESSAGE( "Test case " << tu.full_name() << " did not check any assertions" );
}
tr.p_duration_microseconds.value = elapsed_in_microseconds;
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.clear();
tr.p_skipped.value = true;
if( tu.p_type == TUT_SUITE ) {
test_case_counter tcc(true);
traverse_test_tree( tu, tcc, true ); // true because need to count the disabled tests/units
tr.p_test_cases_skipped.value = tcc.p_count;
}
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_timed_out(test_unit const& tu)
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.p_timed_out.value = true;
}
//____________________________________________________________________________//
void
results_collector_t::assertion_result( unit_test::assertion_result ar )
{
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
switch( ar ) {
case AR_PASSED: tr.p_assertions_passed.value++; break;
case AR_FAILED: tr.p_assertions_failed.value++; break;
case AR_TRIGGERED: tr.p_warnings_failed.value++; break;
}
if( tr.p_assertions_failed == 1 )
first_failed_assertion();
}
//____________________________________________________________________________//
void
results_collector_t::exception_caught( execution_exception const& ex)
{
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
tr.p_assertions_failed.value++;
if( ex.code() == execution_exception::timeout_error ) {
tr.p_timed_out.value = true;
}
}
//____________________________________________________________________________//
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

View File

@@ -0,0 +1,197 @@
// (C) Copyright Gennadiy Rozental 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$
//
// Description : result reporting facilities
// ***************************************************************************
#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/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/tree/visitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/traverse.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_stream( &std::cerr )
, m_stream_state_saver( new io_saver_type( std::cerr ) )
, m_report_level( CONFIRMATION_REPORT )
, m_formatter( new output::plain_report_formatter )
{}
// test tree visitor interface implementation
void visit( test_case const& tc ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_start( tc, *m_stream );
m_formatter->test_unit_report_finish( tc, *m_stream );
}
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_start( ts, *m_stream );
if( m_report_level == DETAILED_REPORT && !results_collector.results( ts.p_id ).p_skipped )
return true;
m_formatter->test_unit_report_finish( ts, *m_stream );
return false;
}
void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_finish( ts, *m_stream );
}
typedef scoped_ptr<io_saver_type> saver_ptr;
// Data members
std::ostream* m_stream;
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_stream = &ostr;
s_rr_impl().m_stream_state_saver.reset( new io_saver_type( ostr ) );
}
//____________________________________________________________________________//
std::ostream&
get_stream()
{
return *s_rr_impl().m_stream;
}
//____________________________________________________________________________//
void
set_format( output_format rf )
{
switch( rf ) {
default:
case OF_CLF:
set_format( new output::plain_report_formatter );
break;
case OF_XML:
set_format( new output::xml_report_formatter );
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_stream );
switch( l ) {
case CONFIRMATION_REPORT:
s_rr_impl().m_formatter->do_confirmation_report( framework::get<test_unit>( id ), *s_rr_impl().m_stream );
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_stream );
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

View File

@@ -0,0 +1,88 @@
// (c) Copyright Raffi Enficiaud 2017.
// 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
//! An observer for monitoring the success/failure of the other observers
// ***************************************************************************
#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
// Boost.Test
#include <boost/test/test_framework_init_observer.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
//____________________________________________________________________________//
// ************************************************************************** //
// ************** framework_init_observer_t ************** //
// ************************************************************************** //
void
framework_init_observer_t::clear()
{
m_has_failure = false;
}
//____________________________________________________________________________//
void
framework_init_observer_t::test_start( counter_t, test_unit_id )
{
clear();
}
//____________________________________________________________________________//
void
framework_init_observer_t::assertion_result( unit_test::assertion_result ar )
{
switch( ar ) {
case AR_FAILED: m_has_failure = true; break;
default:
break;
}
}
//____________________________________________________________________________//
void
framework_init_observer_t::exception_caught( execution_exception const& )
{
m_has_failure = true;
}
void
framework_init_observer_t::test_aborted()
{
m_has_failure = true;
}
//____________________________________________________________________________//
bool
framework_init_observer_t::has_failed() const
{
return m_has_failure;
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER

View File

@@ -0,0 +1,65 @@
// (C) Copyright Gennadiy Rozental 2001.
// (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
/// @brief 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

View File

@@ -0,0 +1,854 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/tools/context.hpp>
#include <boost/test/tools/output_test_stream.hpp>
#include <boost/test/tools/detail/fwd.hpp>
#include <boost/test/tools/detail/print_helper.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/execution_monitor.hpp> // execution_aborted
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/utils/algorithm.hpp>
// Boost
#include <boost/config.hpp>
// STL
#include <fstream>
#include <string>
#include <cstring>
#include <cctype>
#include <cwchar>
#include <stdexcept>
#include <vector>
#include <utility>
#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 unit_test {
// local static variable, needed here for visibility reasons
lazy_ostream lazy_ostream::inst = lazy_ostream();
}}
namespace boost {
namespace test_tools {
namespace tt_detail {
// ************************************************************************** //
// ************** print_log_value ************** //
// ************************************************************************** //
void
print_log_value<bool>::operator()( std::ostream& ostr, bool t )
{
ostr << std::boolalpha << t;
}
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<wchar_t>::operator()( std::ostream& ostr, wchar_t r )
{
std::mbstate_t state;
std::string mb(MB_CUR_MAX, '\0');
std::size_t ret = std::wcrtomb(&mb[0], r, &state);
if( ret > 0) {
ostr << mb;
}
else {
ostr << "(wchar_t unable to convert)";
}
}
//____________________________________________________________________________//
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 )
{
if(t) {
ostr << static_cast<const void*>(t);
}
else {
ostr << "null w-string";
}
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** TOOL BOX Implementation ************** //
// ************************************************************************** //
using ::boost::unit_test::lazy_ostream;
static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < " };
template<typename OutStream>
void
format_report( OutStream& os, assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
tool_level tl, check_type ct,
std::size_t num_args, va_list args,
char const* prefix, char const* suffix )
{
using namespace unit_test;
switch( ct ) {
case CHECK_PRED:
os << prefix << assertion_descr << suffix;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
case CHECK_BUILT_ASSERTION: {
os << prefix << assertion_descr << suffix;
if( tl != PASS ) {
const_string details_message = pr.message();
if( !details_message.is_empty() ) {
os << details_message;
}
}
break;
}
case CHECK_MSG:
if( tl == PASS )
os << prefix << "'" << assertion_descr << "'" << suffix;
else
os << assertion_descr;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
case CHECK_EQUAL:
case CHECK_NE:
case CHECK_LT:
case CHECK_LE:
case CHECK_GT:
case CHECK_GE: {
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* );
os << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
if( tl != PASS )
os << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
}
case CHECK_CLOSE:
case CHECK_CLOSE_FRACTION: {
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* );
os << "difference{" << pr.message()
<< "} between " << arg1_descr << "{" << *arg1_val
<< "} and " << arg2_descr << "{" << *arg2_val
<< ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
<< *toler_val;
if( ct == CHECK_CLOSE )
os << "%";
break;
}
case CHECK_SMALL: {
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* );
os << "absolute value of " << arg1_descr << "{" << *arg1_val << "}"
<< ( tl == PASS ? " doesn't exceed " : " exceeds " )
<< *toler_val;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
}
case CHECK_PRED_WITH_ARGS: {
std::vector< std::pair<char const*, lazy_ostream const*> > args_copy;
args_copy.reserve( num_args );
for( std::size_t i = 0; i < num_args; ++i ) {
char const* desc = va_arg( args, char const* );
lazy_ostream const* value = va_arg( args, lazy_ostream const* );
args_copy.push_back( std::make_pair( desc, value ) );
}
os << prefix << assertion_descr;
// print predicate call description
os << "( ";
for( std::size_t i = 0; i < num_args; ++i ) {
os << args_copy[i].first;
if( i != num_args-1 )
os << ", ";
}
os << " )" << suffix;
if( tl != PASS ) {
os << " for ( ";
for( std::size_t i = 0; i < num_args; ++i ) {
os << *args_copy[i].second;
if( i != num_args-1 )
os << ", ";
}
os << " )";
}
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
}
case CHECK_EQUAL_COLL: {
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* );
os << prefix << "{ " << left_begin_descr << ", " << left_end_descr << " } == { "
<< right_begin_descr << ", " << right_end_descr << " }"
<< suffix;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
}
case CHECK_BITWISE_EQUAL: {
char const* left_descr = va_arg( args, char const* );
char const* right_descr = va_arg( args, char const* );
os << prefix << left_descr << " =.= " << right_descr << suffix;
if( !pr.has_empty_message() )
os << ". " << pr.message();
break;
}
}
}
//____________________________________________________________________________//
bool
report_assertion( assertion_result const& ar,
lazy_ostream const& assertion_descr,
const_string file_name,
std::size_t line_num,
tool_level tl,
check_type ct,
std::size_t num_args, ... )
{
using namespace unit_test;
if( !framework::test_in_progress() ) {
// in case no test is in progress, we do not throw anything:
// raising an exception here may result in raising an exception in a destructor of a global fixture
// which will abort the process
// We flag this as aborted instead
//BOOST_TEST_I_ASSRT( framework::current_test_case_id() != INV_TEST_UNIT_ID,
// std::runtime_error( "Can't use testing tools outside of test case implementation." ) );
framework::test_aborted();
return false;
}
if( !!ar )
tl = PASS;
log_level ll;
char const* prefix;
char const* suffix;
switch( tl ) {
case PASS:
ll = log_successful_tests;
prefix = "check ";
suffix = " has passed";
break;
case WARN:
ll = log_warnings;
prefix = "condition ";
suffix = " is not satisfied";
break;
case CHECK:
ll = log_all_errors;
prefix = "check ";
suffix = " has failed";
break;
case REQUIRE:
ll = log_fatal_errors;
prefix = "critical check ";
suffix = " has failed";
break;
default:
return true;
}
unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
va_list args;
va_start( args, num_args );
format_report( unit_test_log, ar, assertion_descr, tl, ct, num_args, args, prefix, suffix );
va_end( args );
unit_test_log << unit_test::log::end();
switch( tl ) {
case PASS:
framework::assertion_result( AR_PASSED );
return true;
case WARN:
framework::assertion_result( AR_TRIGGERED );
return false;
case CHECK:
framework::assertion_result( AR_FAILED );
return false;
case REQUIRE:
framework::assertion_result( AR_FAILED );
framework::test_unit_aborted( framework::current_test_unit() );
BOOST_TEST_I_THROW( execution_aborted() );
// the previous line either throws or aborts and the return below is not reached
// return false;
BOOST_TEST_UNREACHABLE_RETURN(false);
}
return true;
}
//____________________________________________________________________________//
assertion_result
format_assertion_result( const_string expr_val, const_string details )
{
assertion_result res(false);
bool starts_new_line = first_char( expr_val ) == '\n';
if( !starts_new_line && !expr_val.is_empty() )
res.message().stream() << " [" << expr_val << "]";
if( !details.is_empty() ) {
if( first_char(details) != '[' )
res.message().stream() << ": ";
else
res.message().stream() << " ";
res.message().stream() << details;
}
if( starts_new_line )
res.message().stream() << "." << expr_val;
return res;
}
//____________________________________________________________________________//
BOOST_TEST_DECL std::string
prod_report_format( assertion_result const& ar, unit_test::lazy_ostream const& assertion_descr, check_type ct, std::size_t num_args, ... )
{
std::ostringstream msg_buff;
va_list args;
va_start( args, num_args );
format_report( msg_buff, ar, assertion_descr, CHECK, ct, num_args, args, "assertion ", " failed" );
va_end( args );
return msg_buff.str();
}
//____________________________________________________________________________//
assertion_result
equal_impl( char const* left, char const* right )
{
return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
}
//____________________________________________________________________________//
#if !defined( BOOST_NO_CWCHAR )
assertion_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;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** context_frame ************** //
// ************************************************************************** //
context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
: m_frame_id( unit_test::framework::add_context( context_descr, true ) )
{
}
//____________________________________________________________________________//
context_frame::~context_frame()
{
unit_test::framework::clear_context( m_frame_id );
}
//____________________________________________________________________________//
context_frame::operator bool()
{
return true;
}
//____________________________________________________________________________//
} // namespace tt_detail
// ************************************************************************** //
// ************** 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 = 0;
do {
m_pattern.get( res );
} while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
return res;
}
void check_and_fill( assertion_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 );
if( !m_pimpl->m_pattern.is_open() )
BOOST_TEST_FRAMEWORK_MESSAGE( "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;
}
//____________________________________________________________________________//
assertion_result
output_test_stream::is_empty( bool flush_stream )
{
sync();
assertion_result res( m_pimpl->m_synced_string.empty() );
m_pimpl->check_and_fill( res );
if( flush_stream )
flush();
return res;
}
//____________________________________________________________________________//
assertion_result
output_test_stream::check_length( std::size_t length_, bool flush_stream )
{
sync();
assertion_result res( m_pimpl->m_synced_string.length() == length_ );
m_pimpl->check_and_fill( res );
if( flush_stream )
flush();
return res;
}
//____________________________________________________________________________//
assertion_result
output_test_stream::is_equal( const_string arg, bool flush_stream )
{
sync();
assertion_result res( const_string( m_pimpl->m_synced_string ) == arg );
m_pimpl->check_and_fill( res );
if( flush_stream )
flush();
return res;
}
//____________________________________________________________________________//
std::string pretty_print_log(std::string str) {
static const std::string to_replace[] = { "\r", "\n" };
static const std::string replacement[] = { "\\r", "\\n" };
return unit_test::utils::replace_all_occurrences_of(
str,
to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
replacement, replacement + sizeof(replacement)/sizeof(replacement[0]));
}
assertion_result
output_test_stream::match_pattern( bool flush_stream )
{
const std::string::size_type n_chars_presuffix = 10;
sync();
assertion_result result( true );
const std::string stream_string_repr = get_stream_string_representation();
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 ) {
int offset = 0;
std::vector<char> last_elements;
for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
char c = m_pimpl->get_char();
if( last_elements.size() <= n_chars_presuffix ) {
last_elements.push_back( c );
}
else {
last_elements[ i % last_elements.size() ] = c;
}
bool is_same = !m_pimpl->m_pattern.fail() &&
!m_pimpl->m_pattern.eof() &&
(stream_string_repr[i+offset] == c);
if( !is_same ) {
result = false;
std::string::size_type prefix_size = (std::min)( i + offset, n_chars_presuffix );
std::string::size_type suffix_size = (std::min)( stream_string_repr.length() - i - offset,
n_chars_presuffix );
// try to log area around the mismatch
std::string substr = stream_string_repr.substr(0, i+offset);
std::size_t line = std::count(substr.begin(), substr.end(), '\n');
std::size_t column = i + offset - substr.rfind('\n');
result.message()
<< "Mismatch at position " << i
<< " (line " << line
<< ", column " << column
<< "): '" << pretty_print_log(std::string(1, stream_string_repr[i+offset])) << "' != '" << pretty_print_log(std::string(1, c)) << "' :\n";
// we already escape this substring because we need its actual size for the pretty print
// of the difference location.
std::string sub_str_prefix(pretty_print_log(stream_string_repr.substr( i + offset - prefix_size, prefix_size )));
// we need this substring as is because we compute the best matching substrings on it.
std::string sub_str_suffix(stream_string_repr.substr( i + offset, suffix_size));
result.message() << "... " << sub_str_prefix + pretty_print_log(sub_str_suffix) << " ..." << '\n';
result.message() << "... ";
for( std::size_t j = 0; j < last_elements.size() ; j++ )
result.message() << pretty_print_log(std::string(1, last_elements[(i + j + 1) % last_elements.size()]));
std::vector<char> last_elements_ordered;
last_elements_ordered.push_back(c);
for( std::string::size_type counter = 0; counter < suffix_size - 1 ; counter++ ) {
char c2 = m_pimpl->get_char();
if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
break;
result.message() << pretty_print_log(std::string(1, c2));
last_elements_ordered.push_back(c2);
}
// tries to find the best substring matching in the remainder of the
// two strings
std::size_t max_nb_char_in_common = 0;
std::size_t best_pattern_start_index = 0;
std::size_t best_stream_start_index = 0;
for( std::size_t pattern_start_index = best_pattern_start_index;
pattern_start_index < last_elements_ordered.size();
pattern_start_index++ ) {
for( std::size_t stream_start_index = best_stream_start_index;
stream_start_index < sub_str_suffix.size();
stream_start_index++ ) {
std::size_t max_size = (std::min)( last_elements_ordered.size() - pattern_start_index, sub_str_suffix.size() - stream_start_index );
if( max_nb_char_in_common > max_size )
break; // safely break to go to the outer loop
std::size_t nb_char_in_common = 0;
for( std::size_t k = 0; k < max_size; k++) {
if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
nb_char_in_common ++;
else
break; // we take fully matching substring only
}
if( nb_char_in_common > max_nb_char_in_common ) {
max_nb_char_in_common = nb_char_in_common;
best_pattern_start_index = pattern_start_index;
best_stream_start_index = stream_start_index;
}
}
}
// indicates with more precision the location of the mismatchs in "ascii arts" ...
result.message() << " ...\n... ";
for( std::string::size_type j = 0; j < sub_str_prefix.size(); j++) {
result.message() << ' ';
}
result.message() << '~'; // places the first tilde at the current char that mismatches
for( std::size_t k = 1; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) { // 1 is for the current char c
std::string s1(pretty_print_log(std::string(1, last_elements_ordered[(std::min)(k, best_pattern_start_index)])));
std::string s2(pretty_print_log(std::string(1, sub_str_suffix[(std::min)(k, best_stream_start_index)])));
for( int h = static_cast<int>((std::max)(s1.size(), s2.size())); h > 0; h--)
result.message() << "~";
}
if( m_pimpl->m_pattern.eof() ) {
result.message() << " (reference string shorter than current stream)";
}
result.message() << "\n";
// no need to continue if the EOF is reached
if( m_pimpl->m_pattern.eof() ) {
break;
}
// first char is a replicat of c, so we do not copy it.
for(std::string::size_type counter = 0; counter < last_elements_ordered.size() - 1 ; counter++)
last_elements[ (i + 1 + counter) % last_elements.size() ] = last_elements_ordered[counter + 1];
i += last_elements_ordered.size()-1;
offset += best_stream_start_index - best_pattern_start_index;
}
}
// not needed anymore
/*
if(offset > 0 && false) {
m_pimpl->m_pattern.ignore(
static_cast<std::streamsize>( offset ));
}
*/
}
else {
m_pimpl->m_pattern.write( stream_string_repr.c_str(),
static_cast<std::streamsize>( stream_string_repr.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::string
output_test_stream::get_stream_string_representation() const {
return m_pimpl->m_synced_string;
}
//____________________________________________________________________________//
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

View File

@@ -0,0 +1,584 @@
// (C) Copyright Gennadiy Rozental 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
/// Provides core implementation for Unit Test Framework.
/// Extensions can be provided in separate files
// ***************************************************************************
#ifndef BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER
// Boost.Test
#include <boost/detail/workaround.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/traverse.hpp>
#include <boost/test/tree/auto_registration.hpp>
#include <boost/test/tree/global_fixture.hpp>
#include <boost/test/utils/foreach.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/unit_test_parameters.hpp>
// STL
#include <algorithm>
#include <vector>
#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** test_unit ************** //
// ************************************************************************** //
test_unit::test_unit( const_string name, const_string file_name, std::size_t line_num, test_unit_type t )
: p_type( t )
, p_type_name( t == TUT_CASE ? "case" : "suite" )
, p_file_name( file_name )
, p_line_num( line_num )
, p_id( INV_TEST_UNIT_ID )
, p_parent_id( INV_TEST_UNIT_ID )
, p_name( std::string( name.begin(), name.size() ) )
, p_timeout( 0 )
, p_expected_failures( 0 )
, p_default_status( RS_INHERIT )
, p_run_status( RS_INVALID )
, p_sibling_rank(0)
{
}
//____________________________________________________________________________//
test_unit::test_unit( const_string module_name )
: p_type( TUT_SUITE )
, p_type_name( "module" )
, p_line_num( 0 )
, p_id( INV_TEST_UNIT_ID )
, p_parent_id( INV_TEST_UNIT_ID )
, p_name( std::string( module_name.begin(), module_name.size() ) )
, p_timeout( 0 )
, p_expected_failures( 0 )
, p_default_status( RS_INHERIT )
, p_run_status( RS_INVALID )
, p_sibling_rank(0)
{
}
//____________________________________________________________________________//
test_unit::~test_unit()
{
framework::deregister_test_unit( this );
}
//____________________________________________________________________________//
void
test_unit::depends_on( test_unit* tu )
{
BOOST_TEST_SETUP_ASSERT( p_id != framework::master_test_suite().p_id,
"Can't add dependency to the master test suite" );
p_dependencies.value.push_back( tu->p_id );
}
//____________________________________________________________________________//
void
test_unit::add_precondition( precondition_t const& pc )
{
p_preconditions.value.push_back( pc );
}
//____________________________________________________________________________//
test_tools::assertion_result
test_unit::check_preconditions() const
{
BOOST_TEST_FOREACH( test_unit_id, dep_id, p_dependencies.get() ) {
test_unit const& dep = framework::get( dep_id, TUT_ANY );
if( !dep.is_enabled() ) {
test_tools::assertion_result res(false);
res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" is disabled";
return res;
}
test_results const& test_rslt = unit_test::results_collector.results( dep_id );
if( !test_rslt.passed() ) {
test_tools::assertion_result res(false);
res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
return res;
}
if( test_rslt.p_test_cases_skipped > 0 ) {
test_tools::assertion_result res(false);
res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has skipped test cases";
return res;
}
}
BOOST_TEST_FOREACH( precondition_t, precondition, p_preconditions.get() ) {
test_tools::assertion_result res = precondition( p_id );
if( !res ) {
test_tools::assertion_result res_out(false);
res_out.message() << "precondition failed";
if( !res.has_empty_message() )
res_out.message() << ": " << res.message();
return res_out;
}
}
return true;
}
//____________________________________________________________________________//
void
test_unit::increase_exp_fail( counter_t num )
{
p_expected_failures.value += num;
if( p_parent_id != INV_TEST_UNIT_ID )
framework::get<test_suite>( p_parent_id ).increase_exp_fail( num );
}
//____________________________________________________________________________//
std::string
test_unit::full_name() const
{
if( p_parent_id == INV_TEST_UNIT_ID || p_parent_id == framework::master_test_suite().p_id )
return p_name;
std::string res = framework::get<test_suite>( p_parent_id ).full_name();
res.append("/");
res.append( p_name );
return res;
}
//____________________________________________________________________________//
void
test_unit::add_label( const_string l )
{
p_labels.value.push_back( std::string() + l );
}
//____________________________________________________________________________//
bool
test_unit::has_label( const_string l ) const
{
return std::find( p_labels->begin(), p_labels->end(), l ) != p_labels->end();
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** test_case ************** //
// ************************************************************************** //
test_case::test_case( const_string name, boost::function<void ()> const& test_func )
: test_unit( name, "", 0, static_cast<test_unit_type>(type) )
, p_test_func( test_func )
{
framework::register_test_unit( this );
}
//____________________________________________________________________________//
test_case::test_case( const_string name, const_string file_name, std::size_t line_num, boost::function<void ()> const& test_func )
: test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
, p_test_func( test_func )
{
framework::register_test_unit( this );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** test_suite ************** //
// ************************************************************************** //
//____________________________________________________________________________//
test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
: test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
{
framework::register_test_unit( this );
}
//____________________________________________________________________________//
test_suite::test_suite( const_string module_name )
: test_unit( module_name )
{
framework::register_test_unit( this );
}
//____________________________________________________________________________//
void
test_suite::add( test_unit* tu, counter_t expected_failures, unsigned timeout )
{
tu->p_timeout.value = timeout;
m_children.push_back( tu->p_id );
tu->p_parent_id.value = p_id;
if( tu->p_expected_failures != 0 )
increase_exp_fail( tu->p_expected_failures );
if( expected_failures )
tu->increase_exp_fail( expected_failures );
}
//____________________________________________________________________________//
void
test_suite::add( test_unit_generator const& gen, unsigned timeout )
{
test_unit* tu;
while((tu = gen.next()) != 0)
add( tu, 0, timeout );
}
//____________________________________________________________________________//
void
test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
{
test_unit* tu;
while((tu = gen.next()) != 0) {
decorators.store_in( *tu );
add( tu, 0 );
}
decorators.reset();
}
//____________________________________________________________________________//
void
test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
{
std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
m_generators.push_back(tmp_p);
decorators.reset();
}
//____________________________________________________________________________//
void
test_suite::generate( )
{
typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
it < ite;
++it)
{
test_unit* tu;
while((tu = it->first->next()) != 0) {
tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
//it->second.store_in( *tu );
add( tu, 0 );
}
}
m_generators.clear();
#if 0
test_unit* tu;
while((tu = gen.next()) != 0) {
decorators.store_in( *tu );
add( tu, 0 );
}
#endif
}
//____________________________________________________________________________//
void
test_suite::check_for_duplicate_test_cases() {
// check for clashing names #12597
std::set<std::string> names;
for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
it < ite;
++it) {
std::string name = framework::get(*it, TUT_ANY).p_name;
std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
BOOST_TEST_SETUP_ASSERT(ret.second,
"test unit with name '"
+ name
+ std::string("' registered multiple times in the test suite '")
+ this->p_name.value
+ "'");
}
return;
}
//____________________________________________________________________________//
void
test_suite::remove( test_unit_id id )
{
test_unit_id_list::iterator it = std::find( m_children.begin(), m_children.end(), id );
if( it != m_children.end() )
m_children.erase( it );
}
//____________________________________________________________________________//
test_unit_id
test_suite::get( const_string tu_name ) const
{
BOOST_TEST_FOREACH( test_unit_id, id, m_children ) {
if( tu_name == framework::get( id, ut_detail::test_id_2_unit_type( id ) ).p_name.get() )
return id;
}
return INV_TEST_UNIT_ID;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** master_test_suite ************** //
// ************************************************************************** //
master_test_suite_t::master_test_suite_t()
: test_suite( "Master Test Suite" )
, argc( 0 )
, argv( 0 )
{
p_default_status.value = RS_ENABLED;
}
// ************************************************************************** //
// ************** traverse_test_tree ************** //
// ************************************************************************** //
void
traverse_test_tree( test_case const& tc, test_tree_visitor& V, bool ignore_status )
{
if( tc.is_enabled() || ignore_status )
V.visit( tc );
}
//____________________________________________________________________________//
void
traverse_test_tree( test_suite const& suite, test_tree_visitor& V, bool ignore_status )
{
// skip disabled test suite unless we asked to ignore this condition
if( !ignore_status && !suite.is_enabled() )
return;
// Invoke test_suite_start callback
if( !V.test_suite_start( suite ) )
return;
// Recurse into children
std::size_t total_children = suite.m_children.size();
for( std::size_t i=0; i < total_children; ) {
// this statement can remove the test unit from this list
traverse_test_tree( suite.m_children[i], V, ignore_status );
if( total_children > suite.m_children.size() )
total_children = suite.m_children.size();
else
++i;
}
// Invoke test_suite_finish callback
V.test_suite_finish( suite );
}
//____________________________________________________________________________//
void
traverse_test_tree( test_unit_id id, test_tree_visitor& V, bool ignore_status )
{
if( ut_detail::test_id_2_unit_type( id ) == TUT_CASE )
traverse_test_tree( framework::get<test_case>( id ), V, ignore_status );
else
traverse_test_tree( framework::get<test_suite>( id ), V, ignore_status );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** object generators ************** //
// ************************************************************************** //
namespace ut_detail {
std::string
normalize_test_case_name( const_string name )
{
std::string norm_name( name.begin(), name.size() );
if( name[0] == '&' )
norm_name = norm_name.substr( 1 );
// trim spaces
std::size_t first_not_space = norm_name.find_first_not_of(' ');
if( first_not_space ) {
norm_name.erase(0, first_not_space);
}
std::size_t last_not_space = norm_name.find_last_not_of(' ');
if( last_not_space !=std::string::npos ) {
norm_name.erase(last_not_space + 1);
}
// sanitize all chars that might be used in runtime filters
static const char to_replace[] = { ':', '*', '@', '+', '!', '/', ',' };
for(std::size_t index = 0;
index < sizeof(to_replace)/sizeof(to_replace[0]);
index++) {
std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
}
return norm_name;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** auto_test_unit_registrar ************** //
// ************************************************************************** //
auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
{
framework::current_auto_test_suite().add( tc, exp_fail );
decorators.store_in( *tc );
decorators.reset();
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector_t& decorators )
{
test_unit_id id = framework::current_auto_test_suite().get( ts_name );
test_suite* ts;
if( id != INV_TEST_UNIT_ID ) {
ts = &framework::get<test_suite>( id );
BOOST_ASSERT( ts->p_parent_id == framework::current_auto_test_suite().p_id );
}
else {
ts = new test_suite( ts_name, ts_file, ts_line );
framework::current_auto_test_suite().add( ts );
}
decorators.store_in( *ts );
decorators.reset();
framework::current_auto_test_suite( ts );
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector_t& decorators )
{
framework::current_auto_test_suite().add( tc_gen, decorators );
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector_t& decorators )
{
framework::current_auto_test_suite().add( tc_gen, decorators );
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( int )
{
framework::current_auto_test_suite( 0, false );
}
//____________________________________________________________________________//
} // namespace ut_detail
// ************************************************************************** //
// ************** global_fixture ************** //
// ************************************************************************** //
global_fixture::global_fixture(): registered(false)
{
framework::register_global_fixture( *this );
registered = true;
}
void global_fixture::unregister_from_framework() {
// not accessing the framework singleton after deregistering -> release
// of the observer from the framework
if(registered) {
framework::deregister_global_fixture( *this );
}
registered = false;
}
global_fixture::~global_fixture()
{
this->unregister_from_framework();
}
// ************************************************************************** //
// ************** global_configuration ************** //
// ************************************************************************** //
global_configuration::global_configuration(): registered(false)
{
framework::register_observer( *this );
registered = true;
}
void global_configuration::unregister_from_framework()
{
// not accessing the framework singleton after deregistering -> release
// of the observer from the framework
if(registered) {
framework::deregister_observer( *this );
}
registered = false;
}
global_configuration::~global_configuration()
{
this->unregister_from_framework();
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_SUITE_IPP_012205GER

View File

@@ -0,0 +1,787 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/execution_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
#include <boost/test/utils/foreach.hpp>
#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/output/xml_log_formatter.hpp>
#include <boost/test/output/junit_log_formatter.hpp>
// Boost
#include <boost/shared_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 {
// log data
struct unit_test_log_data_helper_impl {
typedef boost::shared_ptr<unit_test_log_formatter> formatter_ptr;
typedef boost::shared_ptr<io_saver_type> saver_ptr;
bool m_enabled;
output_format m_format;
std::ostream* m_stream;
saver_ptr m_stream_state_saver;
formatter_ptr m_log_formatter;
bool m_entry_in_progress;
unit_test_log_data_helper_impl(unit_test_log_formatter* p_log_formatter, output_format format, bool enabled = false)
: m_enabled( enabled )
, m_format( format )
, m_stream( &std::cout )
, m_stream_state_saver( new io_saver_type( std::cout ) )
, m_log_formatter()
, m_entry_in_progress( false )
{
m_log_formatter.reset(p_log_formatter);
m_log_formatter->set_log_level(log_all_errors);
}
// helper functions
std::ostream& stream()
{
return *m_stream;
}
log_level get_log_level() const
{
return m_log_formatter->get_log_level();
}
};
struct unit_test_log_impl {
// Constructor
unit_test_log_impl()
{
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::compiler_log_formatter, OF_CLF, true) ); // only this one is active by default,
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::xml_log_formatter, OF_XML, false) );
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::junit_log_formatter, OF_JUNIT, false) );
}
typedef std::vector<unit_test_log_data_helper_impl> v_formatter_data_t;
v_formatter_data_t m_log_formatter_data;
typedef std::vector<unit_test_log_data_helper_impl*> vp_formatter_data_t;
vp_formatter_data_t m_active_log_formatter_data;
// entry data
log_entry_data m_entry_data;
bool has_entry_in_progress() const {
for( vp_formatter_data_t::const_iterator it(m_active_log_formatter_data.begin()), ite(m_active_log_formatter_data.end());
it < ite;
++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.m_entry_in_progress )
return true;
}
return false;
}
// check point data
log_checkpoint_data m_checkpoint_data;
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; }
//____________________________________________________________________________//
void
log_entry_context( log_level l, unit_test_log_data_helper_impl& current_logger_data)
{
framework::context_generator const& context = framework::get_context();
if( context.is_empty() )
return;
const_string frame;
current_logger_data.m_log_formatter->entry_context_start( current_logger_data.stream(), l );
while( !(frame=context.next()).is_empty() )
{
current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame );
}
current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l );
}
//____________________________________________________________________________//
void
clear_entry_context()
{
framework::clear_context();
}
// convenience
typedef unit_test_log_impl::vp_formatter_data_t vp_logger_t;
typedef unit_test_log_impl::v_formatter_data_t v_logger_t;
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( unit_test_log_t )
void
unit_test_log_t::configure( )
{
// configure is not test_start:
// test_start pushes the necessary log information when the test module is starting, and implies configure.
// configure: should be called each time the set of loggers, stream or configuration is changed.
s_log_impl().m_active_log_formatter_data.clear();
for( unit_test_log_impl::v_formatter_data_t::iterator it(s_log_impl().m_log_formatter_data.begin()),
ite(s_log_impl().m_log_formatter_data.end());
it < ite;
++it)
{
if( !it->m_enabled || it->get_log_level() == log_nothing )
continue;
s_log_impl().m_active_log_formatter_data.push_back(&*it);
it->m_entry_in_progress = false;
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_start( counter_t test_cases_amount, test_unit_id )
{
configure();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.m_log_formatter->log_start( current_logger_data.stream(), test_cases_amount );
current_logger_data.m_log_formatter->log_build_info(
current_logger_data.stream(),
runtime_config::get<bool>( runtime_config::btrt_build_info ));
//current_logger_data.stream().flush();
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_finish()
{
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.m_log_formatter->log_finish( current_logger_data.stream() );
current_logger_data.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().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_start( current_logger_data.stream(), tu );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
{
s_log_impl().m_checkpoint_data.clear();
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_finish( current_logger_data.stream(), tu, elapsed );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_unit_skipped( test_unit const& tu, const_string reason )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_skipped( current_logger_data.stream(), tu, reason );
}
}
void
unit_test_log_t::test_unit_aborted( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_aborted(current_logger_data.stream(), tu );
}
}
void
unit_test_log_t::test_unit_timed_out( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_timed_out(current_logger_data.stream(), tu );
}
}
//____________________________________________________________________________//
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( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( l >= current_logger_data.get_log_level() ) {
current_logger_data.m_log_formatter->log_exception_start( current_logger_data.stream(), s_log_impl().m_checkpoint_data, ex );
log_entry_context( l, current_logger_data );
current_logger_data.m_log_formatter->log_exception_finish( current_logger_data.stream() );
}
}
clear_entry_context();
}
//____________________________________________________________________________//
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().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.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().has_entry_in_progress() ) {
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
log_level l = s_log_impl().m_entry_data.m_level;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.m_entry_in_progress ) {
if( l >= current_logger_data.get_log_level() ) {
log_entry_context( l, current_logger_data );
}
current_logger_data.m_log_formatter->log_entry_finish( current_logger_data.stream() );
}
current_logger_data.m_entry_in_progress = false;
}
}
clear_entry_context();
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
log_entry_start(unit_test_log_data_helper_impl &current_logger_data)
{
if( current_logger_data.m_entry_in_progress )
return true;
switch( s_log_impl().m_entry_data.m_level ) {
case log_successful_tests:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_INFO );
break;
case log_messages:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_MESSAGE );
break;
case log_warnings:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.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:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_ERROR );
break;
case log_fatal_errors:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.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;
}
current_logger_data.m_entry_in_progress = true;
return true;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( const_string value )
{
if(value.empty()) {
return *this;
}
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() )
if( log_entry_start(current_logger_data) ) {
current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
}
}
return *this;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( lazy_ostream const& value )
{
if(value.empty()) {
return *this;
}
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() ) {
if( log_entry_start(current_logger_data) ) {
current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
}
}
}
return *this;
}
//____________________________________________________________________________//
void
unit_test_log_t::set_stream( std::ostream& str )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
current_logger_data.m_stream = &str;
current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::set_stream( output_format log_format, std::ostream& str )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
current_logger_data.m_stream = &str;
current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) );
break;
}
}
}
std::ostream*
unit_test_log_t::get_stream( output_format log_format ) const
{
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
return current_logger_data.m_stream;
}
}
return 0;
}
//____________________________________________________________________________//
log_level
unit_test_log_t::set_threshold_level( log_level lev )
{
if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level )
return invalid_log_level;
log_level ret = log_nothing;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
ret = (std::min)(ret, current_logger_data.m_log_formatter->get_log_level());
current_logger_data.m_log_formatter->set_log_level( lev );
}
return ret;
}
//____________________________________________________________________________//
log_level
unit_test_log_t::set_threshold_level( output_format log_format, log_level lev )
{
if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level )
return invalid_log_level;
log_level ret = log_nothing;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
ret = current_logger_data.m_log_formatter->get_log_level();
current_logger_data.m_log_formatter->set_log_level( lev );
break;
}
}
return ret;
}
//____________________________________________________________________________//
void
unit_test_log_t::set_format( output_format log_format )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
current_logger_data.m_enabled = current_logger_data.m_format == log_format;
}
}
//____________________________________________________________________________//
void
unit_test_log_t::add_format( output_format log_format )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
current_logger_data.m_enabled = true;
break;
}
}
}
//____________________________________________________________________________//
unit_test_log_formatter*
unit_test_log_t::get_formatter( output_format log_format ) {
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
return current_logger_data.m_log_formatter.get();
}
}
return 0;
}
void
unit_test_log_t::add_formatter( unit_test_log_formatter* the_formatter )
{
// remove only user defined logger
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
if( it->m_format == OF_CUSTOM_LOGGER) {
s_log_impl().m_log_formatter_data.erase(it);
break;
}
}
if( the_formatter ) {
s_log_impl().m_active_log_formatter_data.clear(); // otherwise dandling references
vloggers.push_back( unit_test_log_data_helper_impl(the_formatter, OF_CUSTOM_LOGGER, true) );
}
}
void
unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter )
{
if( s_log_impl().has_entry_in_progress() )
return;
// remove only user defined logger
log_level current_level = invalid_log_level;
std::ostream *current_stream = 0;
output_format previous_format = OF_INVALID;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
if( it->m_enabled ) {
if( current_level == invalid_log_level || it->m_format < previous_format || it->m_format == OF_CUSTOM_LOGGER) {
current_level = it->get_log_level();
current_stream = &(it->stream());
previous_format = it->m_format;
}
}
}
if( the_formatter ) {
add_formatter(the_formatter);
set_format(OF_CUSTOM_LOGGER);
set_threshold_level(OF_CUSTOM_LOGGER, current_level);
set_stream(OF_CUSTOM_LOGGER, *current_stream);
}
configure();
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** 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() );
}
void
unit_test_log_formatter::set_log_level(log_level new_log_level)
{
m_log_level = new_log_level;
}
log_level
unit_test_log_formatter::get_log_level() const
{
return m_log_level;
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER

View File

@@ -0,0 +1,315 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/results_reporter.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/traverse.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/foreach.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
// Boost
#include <boost/core/ignore_unused.hpp>
#include <boost/cstdlib.hpp>
// STL
#include <cstdio>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace ut_detail {
// ************************************************************************** //
// ************** hrf_content_reporter ************** //
// ************************************************************************** //
struct hrf_content_reporter : test_tree_visitor {
explicit hrf_content_reporter( std::ostream& os ) : m_os( os ), m_indent( -4 ) {} // skip master test suite
private:
void report_test_unit( test_unit const& tu )
{
m_os << std::setw( m_indent ) << "" << tu.p_name;
m_os << (tu.p_default_status == test_unit::RS_ENABLED ? "*" : " ");
//m_os << '[' << tu.p_sibling_rank << ']';
if( !tu.p_description->empty() )
m_os << ": " << tu.p_description;
m_os << "\n";
}
void visit( test_case const& tc ) BOOST_OVERRIDE { report_test_unit( tc ); }
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
if( m_indent >= 0 )
report_test_unit( ts );
m_indent += 4;
return true;
}
void test_suite_finish( test_suite const& ) BOOST_OVERRIDE
{
m_indent -= 4;
}
// Data members
std::ostream& m_os;
int m_indent;
};
// ************************************************************************** //
// ************** dot_content_reporter ************** //
// ************************************************************************** //
struct dot_content_reporter : test_tree_visitor {
explicit dot_content_reporter( std::ostream& os ) : m_os( os ) {}
private:
void report_test_unit( test_unit const& tu )
{
bool master_ts = tu.p_parent_id == INV_TEST_UNIT_ID;
m_os << "tu" << tu.p_id;
m_os << (master_ts ? "[shape=ellipse,peripheries=2" : "[shape=Mrecord" );
m_os << ",fontname=Helvetica";
m_os << (tu.p_default_status == test_unit::RS_ENABLED ? ",color=green" : ",color=yellow");
if( master_ts )
m_os << ",label=\"" << tu.p_name << "\"];\n";
else {
m_os << ",label=\"" << tu.p_name << "|" << tu.p_file_name << "(" << tu.p_line_num << ")";
if( tu.p_timeout > 0 )
m_os << "|timeout=" << tu.p_timeout;
if( tu.p_expected_failures != 0 )
m_os << "|expected failures=" << tu.p_expected_failures;
if( !tu.p_labels->empty() ) {
m_os << "|labels:";
BOOST_TEST_FOREACH( std::string const&, l, tu.p_labels.get() )
m_os << " @" << l;
}
m_os << "\"];\n";
}
if( !master_ts )
m_os << "tu" << tu.p_parent_id << " -> " << "tu" << tu.p_id << ";\n";
BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
test_unit const& dep = framework::get( dep_id, TUT_ANY );
m_os << "tu" << tu.p_id << " -> " << "tu" << dep.p_id << "[color=red,style=dotted,constraint=false];\n";
}
}
void visit( test_case const& tc ) BOOST_OVERRIDE
{
report_test_unit( tc );
}
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
if( ts.p_parent_id == INV_TEST_UNIT_ID )
m_os << "digraph G {rankdir=LR;\n";
report_test_unit( ts );
m_os << "{\n";
return true;
}
void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
{
m_os << "}\n";
if( ts.p_parent_id == INV_TEST_UNIT_ID )
m_os << "}\n";
}
std::ostream& m_os;
};
// ************************************************************************** //
// ************** labels_collector ************** //
// ************************************************************************** //
struct labels_collector : test_tree_visitor {
std::set<std::string> const& labels() const { return m_labels; }
private:
bool visit( test_unit const& tu ) BOOST_OVERRIDE
{
m_labels.insert( tu.p_labels->begin(), tu.p_labels->end() );
return true;
}
// Data members
std::set<std::string> m_labels;
};
struct framework_shutdown_helper {
~framework_shutdown_helper() {
try {
framework::shutdown();
}
catch(...) {
std::cerr << "Boost.Test shutdown exception caught" << std::endl;
}
}
};
} // namespace ut_detail
// ************************************************************************** //
// ************** unit_test_main ************** //
// ************************************************************************** //
int BOOST_TEST_DECL
unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
{
int result_code = 0;
ut_detail::framework_shutdown_helper shutdown_helper;
boost::ignore_unused(shutdown_helper);
BOOST_TEST_I_TRY {
framework::init( init_func, argc, argv );
if( runtime_config::get<bool>( runtime_config::btrt_wait_for_debugger ) ) {
results_reporter::get_stream() << "Press any key to continue..." << std::endl;
// getchar is defined as a macro in uClibc. Use parenthesis to fix
// gcc bug 58952 for gcc <= 4.8.2.
(std::getchar)();
results_reporter::get_stream() << "Continuing..." << std::endl;
}
framework::finalize_setup_phase();
output_format list_cont = runtime_config::get<output_format>( runtime_config::btrt_list_content );
if( list_cont != unit_test::OF_INVALID ) {
if( list_cont == unit_test::OF_DOT ) {
ut_detail::dot_content_reporter reporter( results_reporter::get_stream() );
traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
}
else {
ut_detail::hrf_content_reporter reporter( results_reporter::get_stream() );
traverse_test_tree( framework::master_test_suite().p_id, reporter, true );
}
return boost::exit_success;
}
if( runtime_config::get<bool>( runtime_config::btrt_list_labels ) ) {
ut_detail::labels_collector collector;
traverse_test_tree( framework::master_test_suite().p_id, collector, true );
results_reporter::get_stream() << "Available labels:\n ";
std::copy( collector.labels().begin(), collector.labels().end(),
std::ostream_iterator<std::string>( results_reporter::get_stream(), "\n " ) );
results_reporter::get_stream() << "\n";
return boost::exit_success;
}
framework::run();
result_code = !runtime_config::get<bool>( runtime_config::btrt_result_code )
? boost::exit_success
: results_collector.results( framework::master_test_suite().p_id ).result_code();
}
BOOST_TEST_I_CATCH( framework::nothing_to_test, ex ) {
result_code = ex.m_result_code;
}
BOOST_TEST_I_CATCH( framework::internal_error, ex ) {
results_reporter::get_stream() << "Boost.Test framework internal error: " << ex.what() << std::endl;
result_code = boost::exit_exception_failure;
}
BOOST_TEST_I_CATCH( framework::setup_error, ex ) {
results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
result_code = boost::exit_exception_failure;
}
BOOST_TEST_I_CATCH( std::logic_error, ex ) {
results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
result_code = boost::exit_exception_failure;
}
BOOST_TEST_I_CATCHALL() {
results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
result_code = boost::exit_exception_failure;
}
return result_code;
}
} // 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

View File

@@ -0,0 +1,78 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(unit_test_monitor_t)
// ************************************************************************** //
// ************** unit_test_monitor ************** //
// ************************************************************************** //
unit_test_monitor_t::error_level
unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned long int timeout_microseconds )
{
BOOST_TEST_I_TRY {
p_catch_system_errors.value = runtime_config::get<bool>( runtime_config::btrt_catch_sys_errors );
p_timeout.value = timeout_microseconds;
p_auto_start_dbg.value = runtime_config::get<bool>( runtime_config::btrt_auto_start_dbg );
p_use_alt_stack.value = runtime_config::get<bool>( runtime_config::btrt_use_alt_stack );
p_detect_fp_exceptions.value = runtime_config::get<bool>( runtime_config::btrt_detect_fp_except );
vexecute( func );
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
framework::test_unit_aborted( framework::current_test_unit() );
// 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

View File

@@ -0,0 +1,771 @@
// (C) Copyright Gennadiy Rozental 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$
//
// 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/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/iterator/token_iterator.hpp>
#include <boost/test/debug.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/detail/log_level.hpp>
#include <boost/test/detail/throw_exception.hpp>
// Boost.Runtime.Param
#include <boost/test/utils/runtime/parameter.hpp>
#include <boost/test/utils/runtime/argument.hpp>
#include <boost/test/utils/runtime/finalize.hpp>
#include <boost/test/utils/runtime/cla/parser.hpp>
#include <boost/test/utils/runtime/env/fetch.hpp>
// Boost
#include <boost/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/test/detail/enable_warnings.hpp>
#include <boost/cstdlib.hpp>
// STL
#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 {
namespace rt = boost::runtime;
// ************************************************************************** //
// ************** runtime_config ************** //
// ************************************************************************** //
namespace runtime_config {
// UTF parameters
std::string btrt_auto_start_dbg = "auto_start_dbg";
std::string btrt_break_exec_path = "break_exec_path";
std::string btrt_build_info = "build_info";
std::string btrt_catch_sys_errors = "catch_system_errors";
std::string btrt_color_output = "color_output";
std::string btrt_detect_fp_except = "detect_fp_exceptions";
std::string btrt_detect_mem_leaks = "detect_memory_leaks";
std::string btrt_list_content = "list_content";
std::string btrt_list_labels = "list_labels";
std::string btrt_log_format = "log_format";
std::string btrt_log_level = "log_level";
std::string btrt_log_sink = "log_sink";
std::string btrt_combined_logger = "logger";
std::string btrt_output_format = "output_format";
std::string btrt_random_seed = "random";
std::string btrt_report_format = "report_format";
std::string btrt_report_level = "report_level";
std::string btrt_report_mem_leaks = "report_memory_leaks_to";
std::string btrt_report_sink = "report_sink";
std::string btrt_result_code = "result_code";
std::string btrt_run_filters = "run_test";
std::string btrt_save_test_pattern = "save_pattern";
std::string btrt_show_progress = "show_progress";
std::string btrt_use_alt_stack = "use_alt_stack";
std::string btrt_wait_for_debugger = "wait_for_debugger";
std::string btrt_help = "help";
std::string btrt_usage = "usage";
std::string btrt_version = "version";
//____________________________________________________________________________//
namespace {
void
register_parameters( rt::parameters_store& store )
{
rt::option auto_start_dbg( btrt_auto_start_dbg, (
rt::description = "Automatically attaches debugger in case of system level failure (signal).",
rt::env_var = "BOOST_TEST_AUTO_START_DBG",
rt::help = "Specifies whether Boost.Test should attempt "
"to attach a debugger when fatal system error occurs. At the moment this feature "
"is only available on a few selected platforms: Win32 and *nix. There is a "
"default debugger configured for these platforms. You can manually configure "
"different debugger. For more details on how to configure the debugger see the "
"Boost.Test debug API, specifically the function boost::debug::set_debugger."
));
auto_start_dbg.add_cla_id( "--", btrt_auto_start_dbg, "=" );
auto_start_dbg.add_cla_id( "-", "d", " " );
store.add( auto_start_dbg );
///////////////////////////////////////////////
rt::parameter<std::string> break_exec_path( btrt_break_exec_path, (
rt::description = "For the exception safety testing allows to break at specific execution path.",
rt::env_var = "BOOST_TEST_BREAK_EXEC_PATH"
#ifndef BOOST_NO_CXX11_LAMBDAS
,
rt::callback = [](rt::cstring) {
BOOST_TEST_SETUP_ASSERT( false, "parameter break_exec_path is disabled in this release" );
}
#endif
));
break_exec_path.add_cla_id( "--", btrt_break_exec_path, "=" );
store.add( break_exec_path );
///////////////////////////////////////////////
rt::option build_info( btrt_build_info, (
rt::description = "Displays library build information.",
rt::env_var = "BOOST_TEST_BUILD_INFO",
rt::help = "Displays library build information, including: platform, "
"compiler, STL version and Boost version."
));
build_info.add_cla_id( "--", btrt_build_info, "=" );
build_info.add_cla_id( "-", "i", " " );
store.add( build_info );
///////////////////////////////////////////////
rt::option catch_sys_errors( btrt_catch_sys_errors, (
rt::description = "Allows to switch between catching and ignoring system errors (signals).",
rt::env_var = "BOOST_TEST_CATCH_SYSTEM_ERRORS",
rt::default_value =
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
false,
#else
true,
#endif
rt::help = "If option " + btrt_catch_sys_errors + " has value 'no' the frameworks does not attempt to catch "
"asynchronous system failure events (signals on *NIX platforms or structured exceptions on Windows). "
" Default value is "
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
"no."
#else
"true."
#endif
));
catch_sys_errors.add_cla_id( "--", btrt_catch_sys_errors, "=", true );
catch_sys_errors.add_cla_id( "-", "s", " " );
store.add( catch_sys_errors );
///////////////////////////////////////////////
rt::option color_output( btrt_color_output, (
rt::description = "Enables color output of the framework log and report messages.",
rt::env_var = "BOOST_TEST_COLOR_OUTPUT",
rt::default_value = true,
rt::help = "Produces color output for logs, reports and help. "
"Defaults to true. "
));
color_output.add_cla_id( "--", btrt_color_output, "=", true );
color_output.add_cla_id( "-", "x", " " );
store.add( color_output );
///////////////////////////////////////////////
rt::option detect_fp_except( btrt_detect_fp_except, (
rt::description = "Enables/disables floating point exceptions traps.",
rt::env_var = "BOOST_TEST_DETECT_FP_EXCEPTIONS",
rt::help = "Enables/disables hardware traps for the floating "
"point exceptions (if supported on your platfrom)."
));
detect_fp_except.add_cla_id( "--", btrt_detect_fp_except, "=", true );
store.add( detect_fp_except );
///////////////////////////////////////////////
rt::parameter<unsigned long> detect_mem_leaks( btrt_detect_mem_leaks, (
rt::description = "Turns on/off memory leaks detection (optionally breaking on specified alloc order number).",
rt::env_var = "BOOST_TEST_DETECT_MEMORY_LEAK",
rt::default_value = 1L,
rt::optional_value = 1L,
rt::value_hint = "<alloc order number>",
rt::help = "Enables/disables memory leaks detection. "
"This parameter has optional long integer value. The default value is 1, which "
"enables the memory leak detection. The value 0 disables memory leak detection. "
"Any value N greater than 1 is treated as leak allocation number and tells the "
"framework to setup runtime breakpoint at Nth heap allocation. If value is "
"omitted the default value is assumed."
));
detect_mem_leaks.add_cla_id( "--", btrt_detect_mem_leaks, "=" );
store.add( detect_mem_leaks );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::output_format> list_content( btrt_list_content, (
rt::description = "Lists the content of test tree - names of all test suites and test cases.",
rt::env_var = "BOOST_TEST_LIST_CONTENT",
rt::default_value = OF_INVALID,
rt::optional_value = OF_CLF,
rt::enum_values<unit_test::output_format>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "HRF", OF_CLF },
{ "DOT", OF_DOT }
},
#else
rt::enum_values_list<unit_test::output_format>()
( "HRF", OF_CLF )
( "DOT", OF_DOT )
,
#endif
rt::help = "Lists the test suites and cases "
"of the test module instead of executing the test cases. The format of the "
"desired output can be passed to the command. Currently the "
"framework supports two formats: human readable format (HRF) and dot graph "
"format (DOT). If value is omitted HRF value is assumed."
));
list_content.add_cla_id( "--", btrt_list_content, "=" );
store.add( list_content );
///////////////////////////////////////////////
rt::option list_labels( btrt_list_labels, (
rt::description = "Lists all available labels.",
rt::env_var = "BOOST_TEST_LIST_LABELS",
rt::help = "Option " + btrt_list_labels + " instructs the framework to list all the the labels "
"defined in the test module instead of executing the test cases."
));
list_labels.add_cla_id( "--", btrt_list_labels, "=" );
store.add( list_labels );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::output_format> log_format( btrt_log_format, (
rt::description = "Specifies log format.",
rt::env_var = "BOOST_TEST_LOG_FORMAT",
rt::default_value = OF_CLF,
rt::enum_values<unit_test::output_format>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "HRF", OF_CLF },
{ "CLF", OF_CLF },
{ "XML", OF_XML },
{ "JUNIT", OF_JUNIT },
},
#else
rt::enum_values_list<unit_test::output_format>()
( "HRF", OF_CLF )
( "CLF", OF_CLF )
( "XML", OF_XML )
( "JUNIT", OF_JUNIT )
,
#endif
rt::help = "Set the frameowrk's log format to one "
"of the formats supplied by the framework. The only acceptable values for this "
"parameter are the names of the output formats supplied by the framework. By "
"default the framework uses human readable format (HRF) for testing log. This "
"format is similar to compiler error format. Alternatively you can specify XML "
"or JUNIT as log format, which are easier to process by testing automation tools."
));
log_format.add_cla_id( "--", btrt_log_format, "=" );
log_format.add_cla_id( "-", "f", " " );
store.add( log_format );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::log_level> log_level( btrt_log_level, (
rt::description = "Specifies the logging level of the test execution.",
rt::env_var = "BOOST_TEST_LOG_LEVEL",
rt::default_value = log_all_errors,
rt::enum_values<unit_test::log_level>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "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 }
},
#else
rt::enum_values_list<unit_test::log_level>()
( "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 )
,
#endif
rt::help = "Set the framework's log level. "
"The log level defines the verbosity of the testing logs produced by a test "
"module. The verbosity ranges from a complete log, when all assertions "
"(both successful and failing) are reported, all notifications about "
"test units start and finish are included, to an empty log when nothing "
"is reported to a testing log stream."
));
log_level.add_cla_id( "--", btrt_log_level, "=" );
log_level.add_cla_id( "-", "l", " " );
store.add( log_level );
///////////////////////////////////////////////
rt::parameter<std::string> log_sink( btrt_log_sink, (
rt::description = "Specifies log sink: stdout (default), stderr or file name.",
rt::env_var = "BOOST_TEST_LOG_SINK",
rt::value_hint = "<stderr|stdout|file name>",
rt::help = "Sets the log sink - the location "
"where Boost.Test writes the logs of the test execution. It allows to easily redirect the "
"test logs to file or standard streams. By default testing log is "
"directed to standard output."
));
log_sink.add_cla_id( "--", btrt_log_sink, "=" );
log_sink.add_cla_id( "-", "k", " " );
store.add( log_sink );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::output_format> output_format( btrt_output_format, (
rt::description = "Specifies output format (both log and report).",
rt::env_var = "BOOST_TEST_OUTPUT_FORMAT",
rt::enum_values<unit_test::output_format>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "HRF", OF_CLF },
{ "CLF", OF_CLF },
{ "XML", OF_XML }
},
#else
rt::enum_values_list<unit_test::output_format>()
( "HRF", OF_CLF )
( "CLF", OF_CLF )
( "XML", OF_XML )
,
#endif
rt::help = "Combines an effect of " + btrt_report_format +
" and " + btrt_log_format + " parameters. If this parameter is specified, "
"it overrides the value of other two parameters. This parameter does not "
"have a default value. The only acceptable values are string names of "
"output formats: HRF - human readable format and XML - XML formats for "
"automation tools processing."
));
output_format.add_cla_id( "--", btrt_output_format, "=" );
output_format.add_cla_id( "-", "o", " " );
store.add( output_format );
/////////////////////////////////////////////// combined logger option
rt::parameter<std::string,rt::REPEATABLE_PARAM> combined_logger( btrt_combined_logger, (
rt::description = "Specifies log level and sink for one or several log format",
rt::env_var = "BOOST_TEST_LOGGER",
rt::value_hint = "log_format,log_level,log_sink[:log_format,log_level,log_sink]",
rt::help = "Specify one or more logging definition, which include the logger type, level and sink. "
"The log format, level and sink follow the same format as for the argument '--" + btrt_log_format +
"', '--" + btrt_log_level + "' and '--" + btrt_log_sink + "' respetively. "
"This command can take several logging definition separated by a ':', or be repeated "
"on the command line."
));
combined_logger.add_cla_id( "--", btrt_combined_logger, "=" );
store.add( combined_logger );
///////////////////////////////////////////////
rt::parameter<unsigned> random_seed( btrt_random_seed, (
rt::description = "Allows to switch between sequential and random order of test units execution."
" Optionally allows to specify concrete seed for random number generator.",
rt::env_var = "BOOST_TEST_RANDOM",
rt::default_value = 0U,
rt::optional_value = 1U,
rt::value_hint = "<seed>",
rt::help = "Instructs the framework to execute the "
"test cases in random order. This parameter accepts an optional unsigned "
"integer argument. If parameter is specified without the argument value testing "
"order is randomized based on current time. Alternatively you can specify "
"any positive value greater than 1 and it will be used as random seed for "
"the run. "
"By default, the test cases are executed in an "
"order defined by their declaration and the optional dependencies among the test units."
));
random_seed.add_cla_id( "--", btrt_random_seed, "=" );
store.add( random_seed );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::output_format> report_format( btrt_report_format, (
rt::description = "Specifies the test report format.",
rt::env_var = "BOOST_TEST_REPORT_FORMAT",
rt::default_value = OF_CLF,
rt::enum_values<unit_test::output_format>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "HRF", OF_CLF },
{ "CLF", OF_CLF },
{ "XML", OF_XML }
},
#else
rt::enum_values_list<unit_test::output_format>()
( "HRF", OF_CLF )
( "CLF", OF_CLF )
( "XML", OF_XML )
,
#endif
rt::help = "Set the framework's report format "
"to one of the formats supplied by the framework. The only acceptable values "
"for this parameter are the names of the output formats. By default the framework "
"uses human readable format (HRF) for results reporting. Alternatively you can "
"specify XML as report format. This format is easier to process by testing "
"automation tools."
));
report_format.add_cla_id( "--", btrt_report_format, "=" );
report_format.add_cla_id( "-", "m", " " );
store.add( report_format );
///////////////////////////////////////////////
rt::enum_parameter<unit_test::report_level> report_level( btrt_report_level, (
rt::description = "Specifies test report level.",
rt::env_var = "BOOST_TEST_REPORT_LEVEL",
rt::default_value = CONFIRMATION_REPORT,
rt::enum_values<unit_test::report_level>::value =
#if defined(BOOST_TEST_CLA_NEW_API)
{
{ "confirm", CONFIRMATION_REPORT },
{ "short", SHORT_REPORT },
{ "detailed", DETAILED_REPORT },
{ "no", NO_REPORT }
},
#else
rt::enum_values_list<unit_test::report_level>()
( "confirm", CONFIRMATION_REPORT )
( "short", SHORT_REPORT )
( "detailed", DETAILED_REPORT )
( "no", NO_REPORT )
,
#endif
rt::help = "Set the verbosity level of the "
"result report generated by the testing framework. Use value 'no' to "
"disable the results report completely."
));
report_level.add_cla_id( "--", btrt_report_level, "=" );
report_level.add_cla_id( "-", "r", " " );
store.add( report_level );
///////////////////////////////////////////////
rt::parameter<std::string> report_mem_leaks( btrt_report_mem_leaks, (
rt::description = "File where to report memory leaks to.",
rt::env_var = "BOOST_TEST_REPORT_MEMORY_LEAKS_TO",
rt::default_value = std::string(),
rt::value_hint = "<file name>",
rt::help = "Parameter " + btrt_report_mem_leaks + " allows to specify a file where to report "
"memory leaks to. The parameter does not have default value. If it is not specified, "
"memory leaks (if any) are reported to the standard error stream."
));
report_mem_leaks.add_cla_id( "--", btrt_report_mem_leaks, "=" );
store.add( report_mem_leaks );
///////////////////////////////////////////////
rt::parameter<std::string> report_sink( btrt_report_sink, (
rt::description = "Specifies report sink: stderr(default), stdout or file name.",
rt::env_var = "BOOST_TEST_REPORT_SINK",
rt::value_hint = "<stderr|stdout|file name>",
rt::help = "Sets the result report sink - "
"the location where the framework writes the result report to. "
"The sink may be a a file or a standard "
"stream. The default is 'stderr': the "
"standard error stream."
));
report_sink.add_cla_id( "--", btrt_report_sink, "=" );
report_sink.add_cla_id( "-", "e", " " );
store.add( report_sink );
///////////////////////////////////////////////
rt::option result_code( btrt_result_code, (
rt::description = "Disables test modules's result code generation.",
rt::env_var = "BOOST_TEST_RESULT_CODE",
rt::default_value = true,
rt::help = "The 'no' argument value for the parameter " + btrt_result_code + " instructs the "
"framework to always return zero result code. This can be used for test programs "
"executed within IDE. By default this parameter has value 'yes'."
));
result_code.add_cla_id( "--", btrt_result_code, "=", true );
result_code.add_cla_id( "-", "c", " " );
store.add( result_code );
///////////////////////////////////////////////
rt::parameter<std::string,rt::REPEATABLE_PARAM> tests_to_run( btrt_run_filters, (
rt::description = "Filters which tests to execute.",
rt::env_var = "BOOST_TEST_RUN_FILTERS",
rt::value_hint = "<test unit filter>",
rt::help = "Filters which test units to execute. "
"The framework supports both 'selection filters', which allow to select "
"which test units to enable from the set of available test units, and 'disabler "
"filters', which allow to disable some test units. Boost.test also supports "
"enabling/disabling test units at compile time. These settings identify the default "
"set of test units to run. Parameter " + btrt_run_filters + " is used to change this default. "
"This parameter is repeatable, so you can specify more than one filter if necessary."
));
tests_to_run.add_cla_id( "--", btrt_run_filters, "=" );
tests_to_run.add_cla_id( "-", "t", " " );
store.add( tests_to_run );
///////////////////////////////////////////////
rt::option save_test_pattern( btrt_save_test_pattern, (
rt::description = "Allows to switch between saving or matching test pattern file.",
rt::env_var = "BOOST_TEST_SAVE_PATTERN",
rt::help = "Parameter " + btrt_save_test_pattern + " facilitates switching mode of operation for "
"testing output streams.\n\nThis parameter serves no particular purpose within the "
"framework itself. It can be used by test modules relying on output_test_stream to "
"implement testing logic. Default mode is 'match' (false)."
));
save_test_pattern.add_cla_id( "--", btrt_save_test_pattern, "=" );
store.add( save_test_pattern );
///////////////////////////////////////////////
rt::option show_progress( btrt_show_progress, (
rt::description = "Turns on progress display.",
rt::env_var = "BOOST_TEST_SHOW_PROGRESS",
rt::help = "Instructs the framework to display the progress of the tests. "
"This feature is turned off by default."
));
show_progress.add_cla_id( "--", btrt_show_progress, "=" );
show_progress.add_cla_id( "-", "p", " " );
store.add( show_progress );
///////////////////////////////////////////////
rt::option use_alt_stack( btrt_use_alt_stack, (
rt::description = "Turns on/off usage of an alternative stack for signal handling.",
rt::env_var = "BOOST_TEST_USE_ALT_STACK",
rt::default_value = true,
rt::help = "Instructs the framework to use an alternative "
"stack for operating system's signals handling (on platforms where this is supported). "
"The feature is enabled by default, but can be disabled using this command line switch."
));
use_alt_stack.add_cla_id( "--", btrt_use_alt_stack, "=", true );
store.add( use_alt_stack );
///////////////////////////////////////////////
rt::option wait_for_debugger( btrt_wait_for_debugger, (
rt::description = "Forces test module to wait for button to be pressed before starting test run.",
rt::env_var = "BOOST_TEST_WAIT_FOR_DEBUGGER",
rt::help = "Instructs the framework to pause before starting "
"test units execution, so that you can attach a debugger to the test module process. "
"This feature is turned off by default."
));
wait_for_debugger.add_cla_id( "--", btrt_wait_for_debugger, "=" );
wait_for_debugger.add_cla_id( "-", "w", " " );
store.add( wait_for_debugger );
///////////////////////////////////////////////
rt::parameter<std::string> help( btrt_help, (
rt::description = "Help for framework parameters.",
rt::optional_value = std::string(),
rt::value_hint = "<parameter name>",
rt::help = "Displays help on the framework's parameters. "
"The parameter accepts an optional argument value. If present, an argument value is "
"interpreted as a parameter name (name guessing works as well, so for example "
"'--help=rand' displays help on the parameter 'random'). If the parameter name is unknown "
"or ambiguous error is reported. If argument value is absent, a summary of all "
"framework's parameter is displayed."
));
help.add_cla_id( "--", btrt_help, "=" );
store.add( help );
///////////////////////////////////////////////
rt::option usage( btrt_usage, (
rt::description = "Short message explaining usage of Boost.Test parameters."
));
usage.add_cla_id( "-", "?", " " );
store.add( usage );
///////////////////////////////////////////////
rt::option version( btrt_version, (
rt::description = "Prints Boost.Test version and exits."
));
version.add_cla_id( "--", btrt_version, " " );
store.add( version );
}
static rt::arguments_store s_arguments_store;
static rt::parameters_store s_parameters_store;
//____________________________________________________________________________//
} // local namespace
void
init( int& argc, char** argv )
{
shared_ptr<rt::cla::parser> parser;
BOOST_TEST_I_TRY {
// Initialize parameters list
if( s_parameters_store.is_empty() )
register_parameters( s_parameters_store );
// Clear up arguments store just in case (of multiple init invocations)
s_arguments_store.clear();
// Parse CLA they take precedence over environment
parser.reset( new rt::cla::parser( s_parameters_store, (rt::end_of_params = "--", rt::negation_prefix = "no_") ) );
argc = parser->parse( argc, argv, s_arguments_store );
// Try to fetch missing arguments from environment
rt::env::fetch_absent( s_parameters_store, s_arguments_store );
// Set arguments to default values if defined and perform all the validations
rt::finalize_arguments( s_parameters_store, s_arguments_store );
// check if colorized output is enabled
bool use_color = true;
if( s_arguments_store.has(btrt_color_output ) ) {
use_color = runtime_config::get<bool>(runtime_config::btrt_color_output);
}
// Report help if requested
if( runtime_config::get<bool>( btrt_version ) ) {
parser->version( std::cerr );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
else if( runtime_config::get<bool>( btrt_usage ) ) {
parser->usage( std::cerr, runtime::cstring(), use_color );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
else if( s_arguments_store.has( btrt_help ) ) {
parser->help(std::cerr,
s_parameters_store,
runtime_config::get<std::string>( btrt_help ),
use_color );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
// A bit of business logic: output_format takes precedence over log/report formats
if( s_arguments_store.has( btrt_output_format ) ) {
unit_test::output_format of = s_arguments_store.get<unit_test::output_format>( btrt_output_format );
s_arguments_store.set( btrt_report_format, of );
s_arguments_store.set( btrt_log_format, of );
}
}
BOOST_TEST_I_CATCH( rt::init_error, ex ) {
BOOST_TEST_SETUP_ASSERT( false, ex.msg );
}
BOOST_TEST_I_CATCH( rt::ambiguous_param, ex ) {
std::cerr << ex.msg << "\n Did you mean one of these?\n";
BOOST_TEST_FOREACH( rt::cstring, name, ex.m_amb_candidates )
std::cerr << " " << name << "\n";
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_exception_failure ) );
}
BOOST_TEST_I_CATCH( rt::unrecognized_param, ex ) {
std::cerr << ex.msg << "\n";
if( !ex.m_typo_candidates.empty() ) {
std::cerr << " Did you mean one of these?\n";
BOOST_TEST_FOREACH( rt::cstring, name, ex.m_typo_candidates )
std::cerr << " " << name << "\n";
}
else if( parser ) {
std::cerr << "\n";
parser->usage( std::cerr );
}
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_exception_failure ) );
}
BOOST_TEST_I_CATCH( rt::input_error, ex ) {
std::cerr << ex.msg << "\n\n";
if( parser )
parser->usage( std::cerr, ex.param_name );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_exception_failure ) );
}
}
//____________________________________________________________________________//
rt::arguments_store const&
argument_store()
{
return s_arguments_store;
}
//____________________________________________________________________________//
bool
save_pattern()
{
return runtime_config::get<bool>( btrt_save_test_pattern );
}
//____________________________________________________________________________//
} // namespace runtime_config
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_PARAMETERS_IPP_012205GER

View File

@@ -0,0 +1,225 @@
// (C) Copyright Gennadiy Rozental 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$
//
// Description : implements OF_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/execution_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/xml_printer.hpp>
// Boost
#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, bool log_build_info )
{
if( log_build_info ) {
ostr << "<BuildInfo"
<< " platform" << utils::attr_value() << BOOST_PLATFORM
<< " compiler" << utils::attr_value() << BOOST_COMPILER
<< " stl" << utils::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" << utils::attr_value() << tu.p_name.get();
if( !tu.p_file_name.empty() )
ostr << BOOST_TEST_L( " file" ) << utils::attr_value() << tu.p_file_name
<< BOOST_TEST_L( " line" ) << utils::attr_value() << tu.p_line_num;
ostr << ">";
}
//____________________________________________________________________________//
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, const_string reason )
{
ostr << "<" << tu_type_name( tu )
<< " name" << utils::attr_value() << tu.p_name.get()
<< " skipped" << utils::attr_value() << "yes"
<< " reason" << utils::attr_value() << reason
<< "/>";
}
//____________________________________________________________________________//
void
xml_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
ostr << "<Exception file" << utils::attr_value() << loc.m_file_name
<< " line" << utils::attr_value() << loc.m_line_num;
if( !loc.m_function.is_empty() )
ostr << " function" << utils::attr_value() << loc.m_function;
ostr << ">" << utils::cdata() << ex.what();
if( !checkpoint_data.m_file_name.is_empty() ) {
ostr << "<LastCheckpoint file" << utils::attr_value() << checkpoint_data.m_file_name
<< " line" << utils::attr_value() << checkpoint_data.m_line_num
<< ">"
<< utils::cdata() << checkpoint_data.m_message
<< "</LastCheckpoint>";
}
}
//____________________________________________________________________________//
void
xml_log_formatter::log_exception_finish( std::ostream& ostr )
{
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" ) << utils::attr_value() << entry_data.m_file_name
<< BOOST_TEST_L( " line" ) << utils::attr_value() << entry_data.m_line_num
<< BOOST_TEST_L( "><![CDATA[" );
m_value_closed = false;
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
{
utils::print_escaped_cdata( ostr, value );
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_finish( std::ostream& ostr )
{
if( !m_value_closed ) {
ostr << BOOST_TEST_L( "]]>" );
m_value_closed = true;
}
ostr << BOOST_TEST_L( "</" ) << m_curr_tag << BOOST_TEST_L( ">" );
m_curr_tag.clear();
}
//____________________________________________________________________________//
void
xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
{
if( !m_value_closed ) {
ostr << BOOST_TEST_L( "]]>" );
m_value_closed = true;
}
ostr << BOOST_TEST_L( "<Context>" );
}
//____________________________________________________________________________//
void
xml_log_formatter::entry_context_finish( std::ostream& ostr, log_level )
{
ostr << BOOST_TEST_L( "</Context>" );
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_context( std::ostream& ostr, log_level, const_string context_descr )
{
ostr << BOOST_TEST_L( "<Frame>" ) << utils::cdata() << context_descr << BOOST_TEST_L( "</Frame>" );
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,117 @@
// (C) Copyright Gennadiy Rozental 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$
//
// Description : OF_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/output/xml_report_formatter.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/xml_printer.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#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_timed_out )
descr = "timed-out";
else if( tr.p_aborted )
descr = "aborted";
else
descr = "failed";
ostr << '<' << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" )
<< " name" << utils::attr_value() << tu.p_name.get()
<< " result" << utils::attr_value() << descr
<< " assertions_passed" << utils::attr_value() << tr.p_assertions_passed
<< " assertions_failed" << utils::attr_value() << tr.p_assertions_failed
<< " warnings_failed" << utils::attr_value() << tr.p_warnings_failed
<< " expected_failures" << utils::attr_value() << tr.p_expected_failures
;
if( tu.p_type == TUT_SUITE ) {
ostr << " test_cases_passed" << utils::attr_value() << tr.p_test_cases_passed
<< " test_cases_passed_with_warnings" << utils::attr_value() << tr.p_test_cases_warned
<< " test_cases_failed" << utils::attr_value() << tr.p_test_cases_failed
<< " test_cases_skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " test_cases_aborted" << utils::attr_value() << tr.p_test_cases_aborted
<< " test_cases_timed_out" << utils::attr_value() << tr.p_test_cases_timed_out
<< " test_suites_timed_out"<< utils::attr_value() << tr.p_test_suites_timed_out
;
}
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