summaryrefslogtreecommitdiff
path: root/boost/test
diff options
context:
space:
mode:
Diffstat (limited to 'boost/test')
-rw-r--r--boost/test/data/monomorphic/collection.hpp2
-rw-r--r--boost/test/data/monomorphic/fwd.hpp4
-rw-r--r--boost/test/data/monomorphic/generate.hpp2
-rw-r--r--boost/test/data/monomorphic/grid.hpp2
-rw-r--r--boost/test/data/monomorphic/singleton.hpp2
-rw-r--r--boost/test/data/test_case.hpp1
-rw-r--r--boost/test/detail/fwd_decl.hpp1
-rw-r--r--boost/test/detail/global_typedef.hpp15
-rw-r--r--boost/test/execution_monitor.hpp1
-rw-r--r--boost/test/framework.hpp31
-rw-r--r--boost/test/impl/compiler_log_formatter.ipp16
-rw-r--r--boost/test/impl/execution_monitor.ipp6
-rw-r--r--boost/test/impl/framework.ipp210
-rw-r--r--boost/test/impl/junit_log_formatter.ipp274
-rw-r--r--boost/test/impl/results_collector.ipp6
-rw-r--r--boost/test/impl/test_framework_init_observer.ipp109
-rw-r--r--boost/test/impl/test_tools.ipp45
-rw-r--r--boost/test/impl/test_tree.ipp19
-rw-r--r--boost/test/impl/unit_test_log.ipp6
-rw-r--r--boost/test/impl/unit_test_monitor.ipp2
-rw-r--r--boost/test/impl/xml_log_formatter.ipp4
-rw-r--r--boost/test/included/test_exec_monitor.hpp1
-rw-r--r--boost/test/included/unit_test.hpp3
-rw-r--r--boost/test/output/compiler_log_formatter.hpp4
-rw-r--r--boost/test/output/junit_log_formatter.hpp4
-rw-r--r--boost/test/output/xml_log_formatter.hpp4
-rw-r--r--boost/test/progress_monitor.hpp2
-rw-r--r--boost/test/results_collector.hpp5
-rw-r--r--boost/test/test_framework_init_observer.hpp63
-rw-r--r--boost/test/tools/collection_comparison_op.hpp100
-rw-r--r--boost/test/tools/cstring_comparison_op.hpp11
-rw-r--r--boost/test/tools/fpc_op.hpp118
-rw-r--r--boost/test/tree/fixture.hpp93
-rw-r--r--boost/test/tree/global_fixture.hpp70
-rw-r--r--boost/test/tree/observer.hpp6
-rw-r--r--boost/test/unit_test_log.hpp2
-rw-r--r--boost/test/unit_test_log_formatter.hpp12
-rw-r--r--boost/test/unit_test_suite.hpp29
-rw-r--r--boost/test/utils/algorithm.hpp18
-rw-r--r--boost/test/utils/basic_cstring/basic_cstring.hpp13
-rw-r--r--boost/test/utils/basic_cstring/compare.hpp6
-rw-r--r--boost/test/utils/is_cstring.hpp41
-rw-r--r--boost/test/utils/is_forward_iterable.hpp88
43 files changed, 1127 insertions, 324 deletions
diff --git a/boost/test/data/monomorphic/collection.hpp b/boost/test/data/monomorphic/collection.hpp
index 49e81458bf..71a4863f41 100644
--- a/boost/test/data/monomorphic/collection.hpp
+++ b/boost/test/data/monomorphic/collection.hpp
@@ -75,7 +75,7 @@ struct is_dataset<collection<C>> : mpl::true_ {};
//! @overload boost::unit_test::data::make()
template<typename C>
-inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
+inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c )
{
return monomorphic::collection<C>( std::forward<C>(c) );
diff --git a/boost/test/data/monomorphic/fwd.hpp b/boost/test/data/monomorphic/fwd.hpp
index cf6d3b0000..dcd1b84165 100644
--- a/boost/test/data/monomorphic/fwd.hpp
+++ b/boost/test/data/monomorphic/fwd.hpp
@@ -119,7 +119,7 @@ make(DataSet&& ds)
//! @overload boost::unit_test::data::make()
template<typename T>
-inline typename std::enable_if<!is_forward_iterable<T>::value &&
+inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!is_array<typename remove_reference<T>::type>::value,
monomorphic::singleton<T>>::type
@@ -129,7 +129,7 @@ make( T&& v );
//! @overload boost::unit_test::data::make()
template<typename C>
-inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
+inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c );
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/generate.hpp b/boost/test/data/monomorphic/generate.hpp
index af3b5c0bb9..614ef3aad5 100644
--- a/boost/test/data/monomorphic/generate.hpp
+++ b/boost/test/data/monomorphic/generate.hpp
@@ -16,6 +16,8 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
+#include <boost/core/ref.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/grid.hpp b/boost/test/data/monomorphic/grid.hpp
index 3e1b36abad..2cf66189a0 100644
--- a/boost/test/data/monomorphic/grid.hpp
+++ b/boost/test/data/monomorphic/grid.hpp
@@ -22,6 +22,8 @@
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/data/monomorphic/sample_merge.hpp>
+#include <boost/mpl/identity.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
diff --git a/boost/test/data/monomorphic/singleton.hpp b/boost/test/data/monomorphic/singleton.hpp
index 586487a6d7..b0abd0eabb 100644
--- a/boost/test/data/monomorphic/singleton.hpp
+++ b/boost/test/data/monomorphic/singleton.hpp
@@ -81,7 +81,7 @@ struct is_dataset<singleton<T>> : mpl::true_ {};
/// @overload boost::unit_test::data::make()
template<typename T>
-inline typename std::enable_if<!is_forward_iterable<T>::value &&
+inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!boost::is_array<typename boost::remove_reference<T>::type>::value,
monomorphic::singleton<T>
diff --git a/boost/test/data/test_case.hpp b/boost/test/data/test_case.hpp
index dd9de141c4..2275f90fff 100644
--- a/boost/test/data/test_case.hpp
+++ b/boost/test/data/test_case.hpp
@@ -16,6 +16,7 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/dataset.hpp>
#include <boost/test/data/for_each_sample.hpp>
+#include <boost/test/tree/test_unit.hpp>
// Boost
#include <boost/preprocessor/repetition/enum_params.hpp>
diff --git a/boost/test/detail/fwd_decl.hpp b/boost/test/detail/fwd_decl.hpp
index 944d52267d..d5c97fb706 100644
--- a/boost/test/detail/fwd_decl.hpp
+++ b/boost/test/detail/fwd_decl.hpp
@@ -26,6 +26,7 @@ class master_test_suite_t;
class test_tree_visitor;
class test_observer;
+class test_unit_fixture;
// singletons
class unit_test_monitor_t;
diff --git a/boost/test/detail/global_typedef.hpp b/boost/test/detail/global_typedef.hpp
index b9cfeb5206..aeede00e9c 100644
--- a/boost/test/detail/global_typedef.hpp
+++ b/boost/test/detail/global_typedef.hpp
@@ -71,6 +71,21 @@ test_id_2_unit_type( test_unit_id id )
return (id & 0xFFFF0000) != 0 ? TUT_CASE : TUT_SUITE;
}
+//! Helper class for restoring the current test unit ID in a RAII manner
+struct test_unit_id_restore {
+ test_unit_id_restore(test_unit_id& to_restore_, test_unit_id new_value)
+ : to_restore(to_restore_)
+ , bkup(to_restore_) {
+ to_restore = new_value;
+ }
+ ~test_unit_id_restore() {
+ to_restore = bkup;
+ }
+private:
+ test_unit_id& to_restore;
+ test_unit_id bkup;
+};
+
//____________________________________________________________________________//
} // namespace ut_detail
diff --git a/boost/test/execution_monitor.hpp b/boost/test/execution_monitor.hpp
index adfb0336ca..ed06ef254e 100644
--- a/boost/test/execution_monitor.hpp
+++ b/boost/test/execution_monitor.hpp
@@ -270,6 +270,7 @@ public:
/// Simple model for the location of failure in a source code
struct BOOST_TEST_DECL location {
explicit location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );
+ explicit location( const_string file_name, size_t line_num = 0, char const* func = 0 );
const_string m_file_name; ///< File name
size_t m_line_num; ///< Line number
diff --git a/boost/test/framework.hpp b/boost/test/framework.hpp
index f94bcf125d..099c02969b 100644
--- a/boost/test/framework.hpp
+++ b/boost/test/framework.hpp
@@ -74,7 +74,7 @@ BOOST_TEST_DECL bool test_in_progress();
/// This function shuts down the framework and clears up its mono-state.
///
/// It needs to be at the very end of test module execution
-BOOST_TEST_DECL void shutdown();
+BOOST_TEST_DECL void shutdown();
/// @}
/// @name Test unit registration
@@ -132,12 +132,28 @@ BOOST_TEST_DECL void clear();
/// @param[in] to test observer object to add
BOOST_TEST_DECL void register_observer( test_observer& to );
-/// Excldes the observer object form the framework's list of test observers
+/// Excludes the observer object form the framework's list of test observers
/// @param[in] to test observer object to exclude
BOOST_TEST_DECL void deregister_observer( test_observer& to );
/// @}
+/// @name Global fixtures registration
+/// @{
+
+/// Adds a new global fixture to be setup before any other tests starts and tore down after
+/// any other tests finished.
+/// Test unit fixture lifetime should exceed the testing execution timeframe
+/// @param[in] tuf fixture to add
+BOOST_TEST_DECL void register_global_fixture( test_unit_fixture& tuf );
+
+/// Removes a test global fixture from the framework
+///
+/// Test unit fixture lifetime should exceed the testing execution timeframe
+/// @param[in] tuf fixture to remove
+BOOST_TEST_DECL void deregister_global_fixture( test_unit_fixture& tuf );
+/// @}
+
/// @name Assertion/uncaught exception context support
/// @{
/// Context accessor
@@ -178,6 +194,15 @@ BOOST_TEST_DECL context_generator get_context();
/// @returns a reference the master test suite instance
BOOST_TEST_DECL master_test_suite_t& master_test_suite();
+/// This function provides an access to the test unit currently being executed.
+
+/// The difference with current_test_case is about the time between a test-suite
+/// is being set up or torn down (fixtures) and when the test-cases of that suite start.
+
+/// This function is only valid during test execution phase.
+/// @see current_test_case_id, current_test_case
+BOOST_TEST_DECL test_unit const& current_test_unit();
+
/// This function provides an access to the test case currently being executed.
/// This function is only valid during test execution phase.
@@ -231,6 +256,8 @@ BOOST_TEST_DECL void assertion_result( unit_test::assertion_resul
BOOST_TEST_DECL void exception_caught( execution_exception const& );
/// Reports aborted test unit to all test observers
BOOST_TEST_DECL void test_unit_aborted( test_unit const& );
+/// Reports aborted test module to all test observers
+BOOST_TEST_DECL void test_aborted( );
/// @}
namespace impl {
diff --git a/boost/test/impl/compiler_log_formatter.ipp b/boost/test/impl/compiler_log_formatter.ipp
index a4e045cae0..0e83448b14 100644
--- a/boost/test/impl/compiler_log_formatter.ipp
+++ b/boost/test/impl/compiler_log_formatter.ipp
@@ -52,7 +52,7 @@ namespace {
std::string
test_phase_identifier()
{
- return framework::test_in_progress() ? framework::current_test_case().full_name() : std::string( "Test setup" );
+ return framework::test_in_progress() ? framework::current_test_unit().full_name() : std::string( "Test setup" );
}
} // local namespace
@@ -260,21 +260,29 @@ compiler_log_formatter::print_prefix( std::ostream& output, const_string file_na
void
compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
{
- output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
+ 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 )
+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, const_string context_descr )
+compiler_log_formatter::log_entry_context( std::ostream& output, log_level l, const_string context_descr )
{
output << "\n " << context_descr;
}
diff --git a/boost/test/impl/execution_monitor.ipp b/boost/test/impl/execution_monitor.ipp
index 0c5690ca89..94b6f9fbe7 100644
--- a/boost/test/impl/execution_monitor.ipp
+++ b/boost/test/impl/execution_monitor.ipp
@@ -1342,6 +1342,12 @@ execution_exception::location::location( char const* file_name, size_t line_num,
, m_function( func )
{}
+execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
+: m_file_name( file_name )
+, m_line_num( line_num )
+, m_function( func )
+{}
+
//____________________________________________________________________________//
// ************************************************************************** //
diff --git a/boost/test/impl/framework.ipp b/boost/test/impl/framework.ipp
index a35e8a54ac..ca35ce1c2a 100644
--- a/boost/test/impl/framework.ipp
+++ b/boost/test/impl/framework.ipp
@@ -27,6 +27,7 @@
#include <boost/test/results_collector.hpp>
#include <boost/test/progress_monitor.hpp>
#include <boost/test/results_reporter.hpp>
+#include <boost/test/test_framework_init_observer.hpp>
#include <boost/test/tree/observer.hpp>
#include <boost/test/tree/test_unit.hpp>
@@ -56,6 +57,9 @@
#include <cstdlib>
#include <ctime>
#include <numeric>
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+#include <iterator>
+#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::time; using ::srand; }
@@ -68,6 +72,7 @@ namespace std { using ::time; using ::srand; }
namespace boost {
namespace unit_test {
namespace framework {
+
namespace impl {
// ************************************************************************** //
@@ -435,6 +440,46 @@ parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_
//____________________________________________________________________________//
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+
+// a poor man's implementation of random_shuffle
+template< class RandomIt, class RandomFunc >
+void random_shuffle( RandomIt first, RandomIt last, RandomFunc &r )
+{
+ typedef typename std::iterator_traits<RandomIt>::difference_type difference_type;
+ difference_type n = last - first;
+ for (difference_type i = n-1; i > 0; --i) {
+ difference_type j = r(i+1);
+ if (j != i) {
+ using std::swap;
+ swap(first[i], first[j]);
+ }
+ }
+}
+
+#endif
+
+
+// A simple handle for registering the global fixtures to the master test suite
+// without deleting an existing static object (the global fixture itself) when the program
+// terminates (shared_ptr).
+class global_fixture_handle : public test_unit_fixture {
+public:
+ global_fixture_handle(test_unit_fixture* fixture) : m_global_fixture(fixture) {}
+ ~global_fixture_handle() {}
+
+ virtual void setup() {
+ m_global_fixture->setup();
+ }
+ virtual void teardown() {
+ m_global_fixture->teardown();
+ }
+
+private:
+ test_unit_fixture* m_global_fixture;
+};
+
+
} // namespace impl
// ************************************************************************** //
@@ -446,7 +491,7 @@ unsigned const TIMEOUT_EXCEEDED = static_cast<unsigned>( -1 );
class state {
public:
state()
- : m_curr_test_case( INV_TEST_UNIT_ID )
+ : m_curr_test_unit( INV_TEST_UNIT_ID )
, m_next_test_case_id( MIN_TEST_CASE_ID )
, m_next_test_suite_id( MIN_TEST_SUITE_ID )
, m_test_in_progress( false )
@@ -603,7 +648,7 @@ public:
}
};
- // Executed the test tree with the root at specified test unit
+ // Executes the test tree with the root at specified test unit
execution_result execute_test_tree( test_unit_id tu_id,
unsigned timeout = 0,
random_generator_helper const * const p_random_generator = 0)
@@ -642,9 +687,15 @@ public:
// 30. Execute setup fixtures if any; any failure here leads to test unit abortion
BOOST_TEST_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
result = unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::setup, F ) );
if( result != unit_test_monitor_t::test_ok )
break;
+ test_results const& test_rslt = unit_test::results_collector.results( m_curr_test_unit );
+ if( test_rslt.aborted() ) {
+ result = unit_test_monitor_t::precondition_failure;
+ break;
+ }
}
// This is the time we are going to spend executing the test unit
@@ -688,7 +739,11 @@ public:
const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
+#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
+ impl::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
+#else
std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
+#endif
BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
@@ -710,8 +765,7 @@ public:
m_context_idx = 0;
// setup current test case
- test_unit_id bkup = m_curr_test_case;
- m_curr_test_case = tc.p_id;
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tc.p_id);
// execute the test case body
result = unit_test_monitor.execute_and_translate( tc.p_test_func, timeout );
@@ -720,8 +774,7 @@ public:
// cleanup leftover context
m_context.clear();
- // restore state and abort if necessary
- m_curr_test_case = bkup;
+ // restore state (scope exit) and abort if necessary
}
}
@@ -729,6 +782,7 @@ public:
if( !unit_test_monitor.is_critical_error( result ) ) {
// execute teardown fixtures if any in reverse order
BOOST_TEST_REVERSE_FOREACH( test_unit_fixture_ptr, F, tu.p_fixtures.get() ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(m_curr_test_unit, tu.p_id);
result = (std::min)( result, unit_test_monitor.execute_and_translate( boost::bind( &test_unit_fixture::teardown, F ), 0 ) );
if( unit_test_monitor.is_critical_error( result ) )
@@ -787,7 +841,7 @@ public:
master_test_suite_t* m_master_test_suite;
std::vector<test_suite*> m_auto_test_suites;
- test_unit_id m_curr_test_case;
+ test_unit_id m_curr_test_unit;
test_unit_store m_test_units;
test_unit_id m_next_test_case_id;
@@ -799,6 +853,8 @@ public:
context_data m_context;
int m_context_idx;
+ std::set<test_unit_fixture*> m_global_fixtures;
+
boost::execution_monitor m_aux_em;
std::map<output_format, runtime_config::stream_holder> m_log_sinks;
@@ -1043,6 +1099,7 @@ init( init_unit_test_func init_func, int argc, char* argv[] )
// 40. Register default test observers
register_observer( results_collector );
register_observer( unit_test_log );
+ register_observer( framework_init_observer );
if( runtime_config::get<bool>( runtime_config::btrt_show_progress ) ) {
progress_monitor.set_stream( std::cout ); // defaults to stdout
@@ -1236,6 +1293,30 @@ deregister_observer( test_observer& to )
//____________________________________________________________________________//
// ************************************************************************** //
+// ************** register_global_fixture ************** //
+// ************************************************************************** //
+
+void
+register_global_fixture( test_unit_fixture& tuf )
+{
+ impl::s_frk_state().m_global_fixtures.insert( &tuf );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** deregister_global_fixture ************** //
+// ************************************************************************** //
+
+void
+deregister_global_fixture( test_unit_fixture &tuf )
+{
+ impl::s_frk_state().m_global_fixtures.erase( &tuf );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
// ************** add_context ************** //
// ************************************************************************** //
@@ -1363,7 +1444,14 @@ current_auto_test_suite( test_suite* ts, bool push_or_pop )
test_case const&
current_test_case()
{
- return get<test_case>( impl::s_frk_state().m_curr_test_case );
+ return get<test_case>( impl::s_frk_state().m_curr_test_unit );
+}
+
+
+test_unit const&
+current_test_unit()
+{
+ return *impl::s_frk_state().m_test_units[impl::s_frk_state().m_curr_test_unit];
}
//____________________________________________________________________________//
@@ -1371,7 +1459,7 @@ current_test_case()
test_unit_id
current_test_case_id()
{
- return impl::s_frk_state().m_curr_test_case;
+ return impl::s_frk_state().m_curr_test_unit;
}
//____________________________________________________________________________//
@@ -1396,6 +1484,17 @@ get( test_unit_id id, test_unit_type t )
// ************** framework::run ************** //
// ************************************************************************** //
+template <class Cont>
+struct swap_on_delete {
+ swap_on_delete(Cont& c1, Cont& c2) : m_c1(c1), m_c2(c2){}
+ ~swap_on_delete() {
+ m_c1.swap(m_c2);
+ }
+
+ Cont& m_c1;
+ Cont& m_c2;
+};
+
void
run( test_unit_id id, bool continue_test )
{
@@ -1414,39 +1513,90 @@ run( test_unit_id id, bool continue_test )
bool was_in_progress = framework::test_in_progress();
bool call_start_finish = !continue_test || !was_in_progress;
-
- impl::s_frk_state().m_test_in_progress = true;
+ bool init_ok = true;
+ const_string setup_error;
if( call_start_finish ) {
+ // indicates the framework that no test is in progress now if observers need to be notified
+ impl::s_frk_state().m_test_in_progress = false;
+ // unit_test::framework_init_observer will get cleared first
BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
BOOST_TEST_I_TRY {
- impl::s_frk_state().m_aux_em.vexecute( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
+ ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
+ unit_test_monitor_t::error_level result = unit_test_monitor.execute_and_translate( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
+ if( init_ok ) {
+ if( result != unit_test_monitor_t::test_ok ) {
+ init_ok = false;
+ }
+ else {
+ if( unit_test::framework_init_observer.has_failed() ) {
+ init_ok = false;
+ }
+ }
+ }
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
- BOOST_TEST_SETUP_ASSERT( false, ex.what() );
+ if( init_ok ) {
+ // log only the first error
+ init_ok = false;
+ setup_error = ex.what();
+ }
+ // break; // we should continue otherwise loggers may have improper structure (XML start missing for instance)
}
}
}
- unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
- switch( seed ) {
- case 0:
- break;
- case 1:
- seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
- default:
- BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
- std::srand( seed );
+ if( init_ok ) {
+
+ // attaching the global fixtures to the main entry point
+ test_unit& entry_test_unit = framework::get( id, TUT_ANY );
+ std::vector<test_unit_fixture_ptr> v_saved_fixture(entry_test_unit.p_fixtures.value.begin(),
+ entry_test_unit.p_fixtures.value.end());
+
+ BOOST_TEST_FOREACH( test_unit_fixture*, tuf, impl::s_frk_state().m_global_fixtures ) {
+ entry_test_unit.p_fixtures.value.insert( entry_test_unit.p_fixtures.value.begin(),
+ test_unit_fixture_ptr(new impl::global_fixture_handle(tuf)) );
+ }
+
+ swap_on_delete< std::vector<test_unit_fixture_ptr> > raii_fixture(v_saved_fixture, entry_test_unit.p_fixtures.value);
+
+ // now work in progress
+ impl::s_frk_state().m_test_in_progress = true;
+ unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
+ switch( seed ) {
+ case 0:
+ break;
+ case 1:
+ seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
+ default:
+ BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
+ std::srand( seed );
+ }
+
+ // executing the test tree
+ impl::s_frk_state().execute_test_tree( id );
+
+ // removing previously added global fixtures: dtor raii_fixture
}
- impl::s_frk_state().execute_test_tree( id );
+ impl::s_frk_state().m_test_in_progress = false;
+ unit_test::framework_init_observer.clear();
if( call_start_finish ) {
- BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
+ // indicates the framework that no test is in progress anymore if observers need to be notified
+ // and this is a teardown, so assertions should not raise any exception otherwise an exception
+ // might be raised in a dtor of a global fixture
+ impl::s_frk_state().m_test_in_progress = false;
+ BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
+ ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
to->test_finish();
+ }
}
impl::s_frk_state().m_test_in_progress = was_in_progress;
+
+ // propagates the init/teardown error if any
+ BOOST_TEST_SETUP_ASSERT( init_ok && !unit_test::framework_init_observer.has_failed(), setup_error );
}
//____________________________________________________________________________//
@@ -1496,6 +1646,18 @@ test_unit_aborted( test_unit const& tu )
to->test_unit_aborted( tu );
}
+// ************************************************************************** //
+// ************** test_aborted ************** //
+// ************************************************************************** //
+
+void
+test_aborted( )
+{
+ BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
+ to->test_aborted( );
+}
+
+
//____________________________________________________________________________//
} // namespace framework
diff --git a/boost/test/impl/junit_log_formatter.ipp b/boost/test/impl/junit_log_formatter.ipp
index dd528bc903..0ec8d43832 100644
--- a/boost/test/impl/junit_log_formatter.ipp
+++ b/boost/test/impl/junit_log_formatter.ipp
@@ -69,6 +69,12 @@ inline std::string tu_name_normalize(std::string full_name)
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( "\\/" );
@@ -86,7 +92,7 @@ const_string file_basename(const_string filename) {
// ************************************************************************** //
void
-junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
+junit_log_formatter::log_start( std::ostream& /*ostr*/, counter_t /*test_cases_amount*/)
{
map_tests.clear();
list_path_to_root.clear();
@@ -96,6 +102,11 @@ junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
//____________________________________________________________________________//
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,
@@ -111,10 +122,19 @@ public:
, m_display_build_info(display_build_info)
{ }
- void add_log_entry(std::string const& entry_type,
- test_case const& tc,
- junit_impl::junit_log_helper::assertion_entry const& log) const
+ 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
@@ -159,24 +179,24 @@ public:
}
};
- std::list<std::string> build_skipping_chain(test_case const & tc) const
+ std::list<std::string> build_skipping_chain(test_unit const & tu) const
{
- // we enter here because we know that the tc has been skipped.
- // either junit has not seen this tc, or it is indicated as disabled
- assert(m_map_test.count(tc.p_id) == 0 || results_collector.results( tc.p_id ).p_skipped);
+ // 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(tc.p_id);
+ test_unit_id id(tu.p_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
- test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
- out.push_back("- disabled test unit: '" + tu.full_name() + "'\n");
+ 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.p_parent_id;
+ 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() )
@@ -188,9 +208,9 @@ public:
return out;
}
- std::string get_class_name(test_case const & tc) const {
+ std::string get_class_name(test_unit const & tu_class) const {
std::string classname;
- test_unit_id id(tc.p_parent_id);
+ 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;
@@ -205,39 +225,47 @@ public:
return classname;
}
- void write_testcase_header(test_case const & tc,
- test_results const *tr = 0) const
+ void write_testcase_header(test_unit const & tu,
+ test_results const *tr,
+ int nb_assertions) const
{
- //
- // test case header
+ std::string name;
+ std::string classname;
- // total number of assertions
- m_stream << "<testcase assertions" << utils::attr_value() << tr->p_assertions_passed + tr->p_assertions_failed;
+ if(tu.p_id == m_ts.p_id ) {
+ name = "boost_test";
+ }
+ else {
+ classname = get_class_name(tu);
+ name = tu_name_normalize(tu.p_name);
+ }
- // class name
- const std::string classname = get_class_name(tc);
+ if( tu.p_type == TUT_SUITE ) {
+ 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() << tu_name_normalize(tc.p_name)
+ << " 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_case const * tc,
- bool skipped,
- test_results const *tr = 0) const
+ 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(*tc);
- for(std::list<std::string>::const_iterator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
+ 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)
{
@@ -246,7 +274,7 @@ public:
}
// stdout
- for(std::list<std::string>::const_iterator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
+ for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
it != ite;
++it)
{
@@ -254,25 +282,24 @@ public:
}
// warning/info message last
- for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator it(detailed_log.assertion_entries.begin());
+ for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
- if(it->log_entry != junit_impl::junit_log_helper::assertion_entry::log_entry_info)
+ 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_case const * tc,
- test_results const *tr = 0) const
+ test_unit const * tu,
+ test_results const *tr) const
{
// system-err output + test case informations
- bool has_failed = (tr != 0) ? !tr->passed() : false;
+ bool has_failed = (tr != 0) ? !tr->p_skipped && !tr->passed() : false;
if(!detailed_log.system_err.empty() || has_failed)
{
- conditional_cdata_helper system_err_helper(m_stream, "system-err");
std::ostringstream o;
if(has_failed) {
o << "Failures detected in:" << std::endl;
@@ -281,58 +308,89 @@ public:
o << "ERROR STREAM:" << std::endl;
}
- o << "- test case: " << tc->full_name() << std::endl;
- if(!tc->p_description.value.empty())
- o << " '" << tc->p_description << "'";
-
- o << std::endl
- << "- file: " << file_basename(tc->p_file_name) << std::endl
- << "- line: " << tc->p_line_num << 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;
- system_err_helper(o.str());
- for(std::list<std::string>::const_iterator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
+ for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
it != ite;
++it)
{
- system_err_helper(*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 = tr->p_assertions_passed + tr->p_assertions_failed;
}
+
+ return nb_assertions;
}
void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
- test_case const & tc,
+ test_unit const & tu,
bool skipped,
- test_results const *tr = 0) const
+ test_results const *tr) const
{
- write_testcase_header(tc, tr);
+ 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(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator it(detailed_log.assertion_entries.begin());
+ for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
- if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_failure) {
- add_log_entry("failure", tc, *it);
- }
- else if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_error) {
- add_log_entry("error", tc, *it);
- }
+ add_log_entry(*it);
}
}
- write_testcase_system_out(detailed_log, &tc, skipped, tr);
- write_testcase_system_err(detailed_log, &tc, tr);
+ write_testcase_system_out(detailed_log, &tu, skipped);
+ write_testcase_system_err(detailed_log, &tu, tr);
m_stream << "</testcase>" << std::endl;
}
@@ -353,35 +411,45 @@ public:
bool test_suite_start( test_suite const& ts )
{
- // unique test suite, without s, nesting not supported in CI
- if( m_ts.p_id != ts.p_id )
- return true;
-
test_results const& tr = results_collector.results( ts.p_id );
- m_stream << "<testsuite";
- m_stream
- // << "disabled=\"" << tr.p_test_cases_skipped << "\" "
- << " tests" << utils::attr_value() << tr.p_test_cases_passed
- << " 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
- << " 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;
+ // unique test suite, without s, nesting not supported in CI
+ if( m_ts.p_id == ts.p_id ) {
+ m_stream << "<testsuite";
+
+ m_stream
+ // << "disabled=\"" << tr.p_test_cases_skipped << "\" "
+ << " tests" << utils::attr_value() << tr.p_test_cases_passed
+ << " 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
+ << " 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;
+ }
+ }
- 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
@@ -389,13 +457,13 @@ public:
virtual void test_suite_finish( test_suite const& ts )
{
- if( m_ts.p_id != ts.p_id )
- return;
+ if( m_ts.p_id == ts.p_id ) {
+ write_testcase_system_out(runner_log, 0, false);
+ write_testcase_system_err(runner_log, 0, 0);
- write_testcase_system_out(runner_log, 0, false, 0);
- write_testcase_system_err(runner_log, 0, 0);
-
- m_stream << "</testsuite>";
+ m_stream << "</testsuite>";
+ return;
+ }
}
private:
@@ -439,7 +507,7 @@ junit_log_formatter::log_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_build_info( std::ostream& ostr )
+junit_log_formatter::log_build_info( std::ostream& /*ostr*/ )
{
m_display_build_info = true;
}
@@ -447,7 +515,7 @@ junit_log_formatter::log_build_info( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
+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
@@ -458,7 +526,7 @@ junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
+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
assert( tu.p_id == list_path_to_root.back() );
@@ -466,7 +534,7 @@ junit_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu,
}
void
-junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
+junit_log_formatter::test_unit_aborted( std::ostream& /*ostr*/, test_unit const& tu )
{
assert( tu.p_id == list_path_to_root.back() );
//list_path_to_root.pop_back();
@@ -475,7 +543,7 @@ junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
//____________________________________________________________________________//
void
-junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu, const_string reason )
+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.
@@ -487,7 +555,7 @@ junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu,
//____________________________________________________________________________//
void
-junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+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();
@@ -555,7 +623,7 @@ junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_dat
//____________________________________________________________________________//
void
-junit_log_formatter::log_exception_finish( std::ostream& ostr )
+junit_log_formatter::log_exception_finish( std::ostream& /*ostr*/ )
{
// sealing the last entry
assert(!get_current_log_entry().assertion_entries.back().sealed);
@@ -565,7 +633,7 @@ junit_log_formatter::log_exception_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& entry_data, log_entry_types let )
+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;
@@ -638,7 +706,7 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
+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)
@@ -662,7 +730,7 @@ junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_finish( std::ostream& ostr )
+junit_log_formatter::log_entry_finish( std::ostream& /*ostr*/ )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(!last_entry.skipping)
@@ -685,7 +753,7 @@ junit_log_formatter::log_entry_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
+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)
@@ -708,7 +776,7 @@ junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
-junit_log_formatter::entry_context_finish( std::ostream& ostr )
+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();
@@ -720,7 +788,7 @@ junit_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-junit_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+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)
diff --git a/boost/test/impl/results_collector.ipp b/boost/test/impl/results_collector.ipp
index daee8bc3bf..fd74bdb65c 100644
--- a/boost/test/impl/results_collector.ipp
+++ b/boost/test/impl/results_collector.ipp
@@ -59,6 +59,12 @@ test_results::passed() const
!p_aborted;
}
+bool
+test_results::aborted() const
+{
+ return p_aborted;
+}
+
//____________________________________________________________________________//
int
diff --git a/boost/test/impl/test_framework_init_observer.ipp b/boost/test/impl/test_framework_init_observer.ipp
new file mode 100644
index 0000000000..89f854aaed
--- /dev/null
+++ b/boost/test/impl/test_framework_init_observer.ipp
@@ -0,0 +1,109 @@
+// (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 ************** //
+// ************************************************************************** //
+
+namespace {
+
+struct test_init_observer_check {
+ bool has_failure;
+
+ void clear()
+ {
+ has_failure = false;
+ }
+};
+
+
+test_init_observer_check& s_tioc_impl() { static test_init_observer_check the_inst; return the_inst; }
+
+} // local namespace
+
+void
+framework_init_observer_t::clear()
+{
+ if(!framework::test_in_progress())
+ s_tioc_impl().clear();
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::test_start( counter_t )
+{
+ clear();
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::assertion_result( unit_test::assertion_result ar )
+{
+ test_init_observer_check& tr = s_tioc_impl();
+ switch( ar ) {
+ case AR_TRIGGERED: break;
+ case AR_PASSED: break;
+ case AR_FAILED: tr.has_failure = true; break;
+ default:
+ break;
+ }
+}
+
+//____________________________________________________________________________//
+
+void
+framework_init_observer_t::exception_caught( execution_exception const& )
+{
+ test_init_observer_check& tr = s_tioc_impl();
+ tr.has_failure = true;
+}
+
+void
+framework_init_observer_t::test_aborted()
+{
+ s_tioc_impl().has_failure = true;
+}
+
+
+//____________________________________________________________________________//
+
+bool
+framework_init_observer_t::has_failed() const
+{
+ return s_tioc_impl().has_failure;
+}
+
+//____________________________________________________________________________//
+
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
diff --git a/boost/test/impl/test_tools.ipp b/boost/test/impl/test_tools.ipp
index 853b3913ee..7e01453313 100644
--- a/boost/test/impl/test_tools.ipp
+++ b/boost/test/impl/test_tools.ipp
@@ -121,7 +121,7 @@ print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const*
#if !defined(BOOST_NO_CXX11_NULLPTR)
void
-print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t p )
+print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t )
{
ostr << "nullptr";
}
@@ -310,8 +310,19 @@ report_assertion( assertion_result const& ar,
{
using namespace unit_test;
- 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." ) );
+ 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;
@@ -369,10 +380,9 @@ report_assertion( assertion_result const& ar,
case REQUIRE:
framework::assertion_result( AR_FAILED );
-
- framework::test_unit_aborted( framework::current_test_case() );
-
+ framework::test_unit_aborted( framework::current_test_unit() );
BOOST_TEST_I_THROW( execution_aborted() );
+ return false;
}
return true;
@@ -493,7 +503,7 @@ struct output_test_stream::Impl
char get_char()
{
- char res;
+ char res = 0;
do {
m_pattern.get( res );
} while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
@@ -619,6 +629,7 @@ output_test_stream::match_pattern( bool flush_stream )
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 ) {
@@ -698,7 +709,7 @@ output_test_stream::match_pattern( bool flush_stream )
if( last_elements_ordered[pattern_start_index + k] == sub_str_suffix[stream_start_index + k] )
nb_char_in_common ++;
else
- break; // we take fully macthing substring only
+ break; // we take fully matching substring only
}
if( nb_char_in_common > max_nb_char_in_common ) {
@@ -709,20 +720,32 @@ output_test_stream::match_pattern( bool flush_stream )
}
}
- // indicates with more precision the location of the mismatchs in ascii arts ...
+ // 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() << ' ';
}
- for( std::size_t k = 0; k < (std::max)(best_pattern_start_index, best_stream_start_index); k++ ) { // 1 is for the current char c
+ 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 = (std::max)(s1.size(), s2.size()); h > 0; h--)
- result.message() << "~";
+ 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];
diff --git a/boost/test/impl/test_tree.ipp b/boost/test/impl/test_tree.ipp
index 08bdad3360..81995bb29f 100644
--- a/boost/test/impl/test_tree.ipp
+++ b/boost/test/impl/test_tree.ipp
@@ -448,9 +448,28 @@ auto_test_unit_registrar::auto_test_unit_registrar( int )
global_fixture::global_fixture()
{
+ framework::register_global_fixture( *this );
+}
+
+global_fixture::~global_fixture()
+{
+ framework::deregister_global_fixture( *this );
+}
+
+// ************************************************************************** //
+// ************** global_configuration ************** //
+// ************************************************************************** //
+
+global_configuration::global_configuration()
+{
framework::register_observer( *this );
}
+global_configuration::~global_configuration()
+{
+ framework::deregister_observer( *this );
+}
+
//____________________________________________________________________________//
} // namespace unit_test
diff --git a/boost/test/impl/unit_test_log.ipp b/boost/test/impl/unit_test_log.ipp
index c52260b94b..6ef7d930a2 100644
--- a/boost/test/impl/unit_test_log.ipp
+++ b/boost/test/impl/unit_test_log.ipp
@@ -171,6 +171,8 @@ unit_test_log_t::test_start( counter_t test_cases_amount )
if( runtime_config::get<bool>( runtime_config::btrt_build_info ) )
current_logger_data.m_log_formatter->log_build_info( current_logger_data.stream() );
+ //current_logger_data.stream().flush();
+
current_logger_data.m_entry_in_progress = false;
}
}
@@ -472,14 +474,14 @@ unit_test_log_t::log_entry_context( log_level l )
{
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
- current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), frame );
+ current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame );
}
}
}
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
- current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream() );
+ current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l );
}
}
}
diff --git a/boost/test/impl/unit_test_monitor.ipp b/boost/test/impl/unit_test_monitor.ipp
index fdd36f7c3a..cfb41a239c 100644
--- a/boost/test/impl/unit_test_monitor.ipp
+++ b/boost/test/impl/unit_test_monitor.ipp
@@ -47,7 +47,7 @@ unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
- framework::test_unit_aborted( framework::current_test_case() );
+ framework::test_unit_aborted( framework::current_test_unit() );
// translate execution_exception::error_code to error_level
switch( ex.code() ) {
diff --git a/boost/test/impl/xml_log_formatter.ipp b/boost/test/impl/xml_log_formatter.ipp
index 81284020dd..ef44f1eade 100644
--- a/boost/test/impl/xml_log_formatter.ipp
+++ b/boost/test/impl/xml_log_formatter.ipp
@@ -199,7 +199,7 @@ xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
-xml_log_formatter::entry_context_finish( std::ostream& ostr )
+xml_log_formatter::entry_context_finish( std::ostream& ostr, log_level )
{
ostr << BOOST_TEST_L( "</Context>" );
}
@@ -207,7 +207,7 @@ xml_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
-xml_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+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>" );
}
diff --git a/boost/test/included/test_exec_monitor.hpp b/boost/test/included/test_exec_monitor.hpp
index 34b6ef44dd..e75b4698f2 100644
--- a/boost/test/included/test_exec_monitor.hpp
+++ b/boost/test/included/test_exec_monitor.hpp
@@ -23,6 +23,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
+#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_main.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>
diff --git a/boost/test/included/unit_test.hpp b/boost/test/included/unit_test.hpp
index 993d75e4c0..90882eb178 100644
--- a/boost/test/included/unit_test.hpp
+++ b/boost/test/included/unit_test.hpp
@@ -5,6 +5,7 @@
// See http://www.boost.org/libs/test for the library home page.
//
+//
//!@file
//!@brief Included (vs. linked) version of Unit Test Framework
// ***************************************************************************
@@ -24,6 +25,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
+#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>
#include <boost/test/impl/unit_test_log.ipp>
@@ -31,7 +33,6 @@
#include <boost/test/impl/unit_test_monitor.ipp>
#include <boost/test/impl/unit_test_parameters.ipp>
#include <boost/test/impl/xml_log_formatter.ipp>
-#include <boost/test/impl/junit_log_formatter.ipp>
#include <boost/test/impl/xml_report_formatter.ipp>
#include <boost/test/unit_test.hpp>
diff --git a/boost/test/output/compiler_log_formatter.hpp b/boost/test/output/compiler_log_formatter.hpp
index cb6172aab6..50359334b1 100644
--- a/boost/test/output/compiler_log_formatter.hpp
+++ b/boost/test/output/compiler_log_formatter.hpp
@@ -51,8 +51,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level l, const_string );
+ void entry_context_finish( std::ostream&, log_level l );
protected:
virtual void print_prefix( std::ostream&, const_string file, std::size_t line );
diff --git a/boost/test/output/junit_log_formatter.hpp b/boost/test/output/junit_log_formatter.hpp
index 325a1d8a17..713d3b016c 100644
--- a/boost/test/output/junit_log_formatter.hpp
+++ b/boost/test/output/junit_log_formatter.hpp
@@ -118,8 +118,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level, const_string );
+ void entry_context_finish( std::ostream&, log_level );
//! Discards changes in the log level
virtual void set_log_level(log_level ll)
diff --git a/boost/test/output/xml_log_formatter.hpp b/boost/test/output/xml_log_formatter.hpp
index 4d848a0425..1d8dec0f95 100644
--- a/boost/test/output/xml_log_formatter.hpp
+++ b/boost/test/output/xml_log_formatter.hpp
@@ -54,8 +54,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
- void log_entry_context( std::ostream&, const_string );
- void entry_context_finish( std::ostream& );
+ void log_entry_context( std::ostream&, log_level, const_string );
+ void entry_context_finish( std::ostream&, log_level );
private:
// Data members
diff --git a/boost/test/progress_monitor.hpp b/boost/test/progress_monitor.hpp
index e480ac669d..2f661f5825 100644
--- a/boost/test/progress_monitor.hpp
+++ b/boost/test/progress_monitor.hpp
@@ -41,7 +41,7 @@ public:
virtual void test_unit_finish( test_unit const&, unsigned long );
virtual void test_unit_skipped( test_unit const&, const_string );
- virtual int priority() { return 3; }
+ virtual int priority() { return 4; }
/// @}
/// @name Configuration
diff --git a/boost/test/results_collector.hpp b/boost/test/results_collector.hpp
index 7d2c2bee58..3acd7b87bc 100644
--- a/boost/test/results_collector.hpp
+++ b/boost/test/results_collector.hpp
@@ -79,6 +79,9 @@ public:
/// Returns true if test unit passed
bool passed() const;
+ /// Returns true if the test unit was aborted (hard failure)
+ bool aborted() const;
+
/// Produces result code for the test unit execution
///
/// This methhod return one of the result codes defined in @c boost/cstdlib.hpp
@@ -119,7 +122,7 @@ public:
virtual void assertion_result( unit_test::assertion_result );
virtual void exception_caught( execution_exception const& );
- virtual int priority() { return 2; }
+ virtual int priority() { return 3; }
/// Results access per test unit
///
diff --git a/boost/test/test_framework_init_observer.hpp b/boost/test/test_framework_init_observer.hpp
new file mode 100644
index 0000000000..cdf5ef5edd
--- /dev/null
+++ b/boost/test/test_framework_init_observer.hpp
@@ -0,0 +1,63 @@
+// (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
+/// @brief Defines an observer that monitors the init of the unit test framework
+// ***************************************************************************
+
+#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
+#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
+
+// Boost.Test
+#include <boost/test/tree/observer.hpp>
+
+#include <boost/test/detail/global_typedef.hpp>
+#include <boost/test/detail/fwd_decl.hpp>
+
+#include <boost/test/utils/trivial_singleton.hpp>
+
+#include <boost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace boost {
+namespace unit_test {
+
+// ************************************************************************** //
+/// @brief Monitors the init of the framework
+///
+/// This class collects the state of the init/termination of the unit test framework.
+///
+/// @see boost::unit_test::test_observer
+class BOOST_TEST_DECL framework_init_observer_t : public test_observer, public singleton<framework_init_observer_t> {
+public:
+
+ virtual void test_start( counter_t );
+
+ virtual void assertion_result( unit_test::assertion_result );
+ virtual void exception_caught( execution_exception const& );
+ virtual void test_aborted();
+
+ virtual int priority() { return 0; }
+
+ void clear();
+
+ /// Indicates if a failure has been recorded so far
+ bool has_failed( ) const;
+
+private:
+ BOOST_TEST_SINGLETON_CONS( framework_init_observer_t )
+};
+
+BOOST_TEST_SINGLETON_INST( framework_init_observer )
+
+} // namespace unit_test
+} // namespace boost
+
+#include <boost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
diff --git a/boost/test/tools/collection_comparison_op.hpp b/boost/test/tools/collection_comparison_op.hpp
index 396de502f8..864103fb4a 100644
--- a/boost/test/tools/collection_comparison_op.hpp
+++ b/boost/test/tools/collection_comparison_op.hpp
@@ -38,6 +38,15 @@ namespace assertion {
template<typename T>
struct specialized_compare : public mpl::false_ {};
+template <typename T>
+struct is_c_array : public mpl::false_ {};
+
+template<typename T, std::size_t N>
+struct is_c_array<T [N]> : public mpl::true_ {};
+
+template<typename T, std::size_t N>
+struct is_c_array<T (&)[N]> : public mpl::true_ {};
+
#define BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE(Col) \
namespace boost { namespace test_tools { namespace assertion { \
template<> \
@@ -55,17 +64,21 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
+ unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
+ && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
assertion_result ar( true );
- typename Lhs::const_iterator first1 = lhs.begin();
- typename Rhs::const_iterator first2 = rhs.begin();
- typename Lhs::const_iterator last1 = lhs.end();
- typename Rhs::const_iterator last2 = rhs.end();
- std::size_t pos = 0;
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
+ typename t_Lhs_iterator::const_iterator first1 = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator first2 = t_Rhs_iterator::begin(rhs);
+ typename t_Lhs_iterator::const_iterator last1 = t_Lhs_iterator::end(lhs);
+ typename t_Rhs_iterator::const_iterator last2 = t_Rhs_iterator::end(rhs);
+ std::size_t pos = 0;
for( ; (first1 != last1) && (first2 != last2); ++first1, ++first2, ++pos ) {
assertion_result const& element_ar = OP::eval(*first1, *first2);
@@ -113,8 +126,7 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- (!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
- (!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
+ (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
@@ -122,8 +134,8 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
return lexicographic_compare<OP, can_be_equal, prefer_shorter>(
- boost::unit_test::basic_cstring<lhs_char_type>(lhs),
- boost::unit_test::basic_cstring<rhs_char_type>(rhs));
+ lhs_char_type(lhs),
+ rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -135,23 +147,27 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
+ unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
+ && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
assertion_result ar( true );
- if( lhs.size() != rhs.size() ) {
+ if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) ) {
ar = false;
- ar.message() << "\nCollections size mismatch: " << lhs.size() << " != " << rhs.size();
+ ar.message() << "\nCollections size mismatch: " << t_Lhs_iterator::size(lhs) << " != " << t_Rhs_iterator::size(rhs);
return ar;
}
- typename Lhs::const_iterator left = lhs.begin();
- typename Rhs::const_iterator right = rhs.begin();
- std::size_t pos = 0;
+ typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
+ std::size_t pos = 0;
- for( ; pos < lhs.size(); ++left, ++right, ++pos ) {
+ for( ; pos < t_Lhs_iterator::size(lhs); ++left, ++right, ++pos ) {
assertion_result const element_ar = OP::eval( *left, *right );
if( element_ar )
continue;
@@ -171,16 +187,15 @@ element_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
- (!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
- (!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
+ (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type;
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
- return element_compare<OP>(boost::unit_test::basic_cstring<lhs_char_type>(lhs),
- boost::unit_test::basic_cstring<rhs_char_type>(rhs));
+ return element_compare<OP>(lhs_char_type(lhs),
+ rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -193,14 +208,17 @@ template <typename OP, typename Lhs, typename Rhs>
inline assertion_result
non_equality_compare( Lhs const& lhs, Rhs const& rhs )
{
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
+
assertion_result ar( true );
- if( lhs.size() != rhs.size() )
+ if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) )
return ar;
- typename Lhs::const_iterator left = lhs.begin();
- typename Rhs::const_iterator right = rhs.begin();
- typename Lhs::const_iterator end = lhs.end();
+ typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
+ typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
+ typename t_Lhs_iterator::const_iterator end = t_Lhs_iterator::end(lhs);
for( ; left != end; ++left, ++right ) {
if( OP::eval( *left, *right ) )
@@ -367,22 +385,34 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*
#define DEFINE_COLLECTION_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
- unit_test::is_forward_iterable<Lhs>::value \
- && !unit_test::is_cstring<Lhs>::value \
- && unit_test::is_forward_iterable<Rhs>::value \
- && !unit_test::is_cstring<Rhs>::value>::type> { \
+ unit_test::is_forward_iterable<Lhs>::value \
+ && !unit_test::is_cstring_comparable<Lhs>::value \
+ && unit_test::is_forward_iterable<Rhs>::value \
+ && !unit_test::is_cstring_comparable<Rhs>::value>::type> { \
public: \
typedef assertion_result result_type; \
+ typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator_helper; \
+ typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator_helper; \
\
typedef name<Lhs, Rhs> OP; \
+ \
typedef typename \
- mpl::if_c<is_same<typename decay<Lhs>::type, \
- typename decay<Rhs>::type>::value, \
- typename cctraits<OP>::is_specialized, \
- mpl::false_>::type is_specialized; \
+ mpl::if_c< \
+ mpl::or_< \
+ typename is_c_array<Lhs>::type, \
+ typename is_c_array<Rhs>::type \
+ >::value, \
+ mpl::true_, \
+ typename \
+ mpl::if_c<is_same<typename decay<Lhs>::type, \
+ typename decay<Rhs>::type>::value, \
+ typename cctraits<OP>::is_specialized, \
+ mpl::false_>::type \
+ >::type is_specialized; \
\
- typedef name<typename Lhs::value_type, \
- typename Rhs::value_type> elem_op; \
+ typedef name<typename t_Lhs_iterator_helper::value_type, \
+ typename t_Rhs_iterator_helper::value_type \
+ > elem_op; \
\
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs) \
diff --git a/boost/test/tools/cstring_comparison_op.hpp b/boost/test/tools/cstring_comparison_op.hpp
index 09cbf267e2..50f181d858 100644
--- a/boost/test/tools/cstring_comparison_op.hpp
+++ b/boost/test/tools/cstring_comparison_op.hpp
@@ -37,8 +37,8 @@ namespace op {
#define DEFINE_CSTRING_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
- ( unit_test::is_cstring<Lhs>::value \
- && unit_test::is_cstring<Rhs>::value) \
+ ( unit_test::is_cstring_comparable<Lhs>::value \
+ && unit_test::is_cstring_comparable<Rhs>::value) \
>::type > \
{ \
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type; \
@@ -46,13 +46,14 @@ struct name<Lhs,Rhs,typename boost::enable_if_c< \
public: \
typedef assertion_result result_type; \
\
- typedef name<lhs_char_type, rhs_char_type> elem_op; \
+ typedef name< \
+ typename lhs_char_type::value_type, \
+ typename rhs_char_type::value_type> elem_op; \
\
static bool \
eval( Lhs const& lhs, Rhs const& rhs) \
{ \
- return unit_test::basic_cstring<lhs_char_type>(lhs) oper \
- unit_test::basic_cstring<rhs_char_type>(rhs); \
+ return lhs_char_type(lhs) oper rhs_char_type(rhs); \
} \
\
template<typename PrevExprType> \
diff --git a/boost/test/tools/fpc_op.hpp b/boost/test/tools/fpc_op.hpp
index 18364a27b9..b879d218f2 100644
--- a/boost/test/tools/fpc_op.hpp
+++ b/boost/test/tools/fpc_op.hpp
@@ -38,22 +38,19 @@ namespace op {
template<typename OP>
struct fpctraits {
- static const bool cmp_direct = true;
-};
-
-template <typename Lhs, typename Rhs>
-struct fpctraits<op::NE<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ // indicate if we should perform the operation with a "logical OR"
+ // with the "equality under tolerance".
+ static const bool equality_logical_disjunction = true;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::LT<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ static const bool equality_logical_disjunction = false;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::GT<Lhs,Rhs> > {
- static const bool cmp_direct = false;
+ static const bool equality_logical_disjunction = false;
};
//____________________________________________________________________________//
@@ -62,26 +59,24 @@ struct fpctraits<op::GT<Lhs,Rhs> > {
// ************** set of overloads to select correct fpc algo ************** //
// ************************************************************************** //
// we really only care about EQ vs NE. All other comparisons use direct first
-// and then need EQ. For example a < b (tolerance t) IFF a < b OR a == b (tolerance t)
+// and then need EQ. For example a <= b (tolerance t) IFF a <= b OR a == b (tolerance t)
template <typename FPT, typename Lhs, typename Rhs, typename OP>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* cmp_operator)
{
- fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
-
- assertion_result ar( P( lhs, rhs ) );
- if( !ar )
- ar.message() << "Relative difference exceeds tolerance ["
- << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
- return ar;
+ bool result = cmp_operator->eval_direct(lhs, rhs);
+ if(fpctraits<OP>::equality_logical_disjunction) {
+ return result || compare_fpv<FPT>(lhs, rhs, (op::EQ<Lhs, Rhs>*)0);
+ }
+ return result && compare_fpv<FPT>(lhs, rhs, (op::NE<Lhs, Rhs>*)0);
}
//____________________________________________________________________________//
-template <typename FPT, typename OP>
+template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, OP* )
+compare_fpv_near_zero( FPT const& fpv, op::EQ<Lhs,Rhs>* )
{
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
@@ -96,22 +91,6 @@ compare_fpv_near_zero( FPT const& fpv, OP* )
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
-{
- fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
-
- assertion_result ar( !P( lhs, rhs ) );
- if( !ar )
- ar.message() << "Relative difference is within tolerance ["
- << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
-
- return ar;
-}
-
-//____________________________________________________________________________//
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
{
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
@@ -126,35 +105,49 @@ compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::LT<Lhs,Rhs>* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, op::EQ<Lhs,Rhs>* )
{
- return lhs >= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
-}
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, op::LT<Lhs,Rhs>* )
-{
- return fpv >= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
+ if( lhs == 0 ) {
+ return compare_fpv_near_zero( rhs, (op::EQ<Lhs,Rhs>*)0 );
+ }
+ else if( rhs == 0) {
+ return compare_fpv_near_zero( lhs, (op::EQ<Lhs,Rhs>*)0 );
+ }
+ else {
+ fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
+
+ assertion_result ar( P( lhs, rhs ) );
+ if( !ar )
+ ar.message() << "Relative difference exceeds tolerance ["
+ << P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
+ return ar;
+ }
}
//____________________________________________________________________________//
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
-compare_fpv( Lhs const& lhs, Rhs const& rhs, op::GT<Lhs,Rhs>* )
-{
- return lhs <= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
-}
-
-template <typename FPT, typename Lhs, typename Rhs>
-inline assertion_result
-compare_fpv_near_zero( FPT const& fpv, op::GT<Lhs,Rhs>* )
+compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
{
- return fpv <= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
+ if( lhs == 0 ) {
+ return compare_fpv_near_zero( rhs, (op::NE<Lhs,Rhs>*)0 );
+ }
+ else if( rhs == 0 ) {
+ return compare_fpv_near_zero( lhs, (op::NE<Lhs,Rhs>*)0 );
+ }
+ else {
+ fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
+
+ assertion_result ar( !P( lhs, rhs ) );
+ if( !ar )
+ ar.message() << "Relative difference is within tolerance ["
+ << P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
+
+ return ar;
+ }
}
-
//____________________________________________________________________________//
#define DEFINE_FPV_COMPARISON( oper, name, rev ) \
@@ -177,22 +170,9 @@ public: \
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs ) \
{ \
- if( lhs == 0 ) \
- { \
- return compare_fpv_near_zero( rhs, (OP*)0 ); \
- } \
- \
- if( rhs == 0 ) \
- { \
- return compare_fpv_near_zero( lhs, (OP*)0 ); \
- } \
- \
- bool direct_res = eval_direct( lhs, rhs ); \
- \
- if( (direct_res && fpctraits<OP>::cmp_direct) || \
- fpc_tolerance<FPT>() == FPT(0) ) \
+ if( fpc_tolerance<FPT>() == FPT(0) ) \
{ \
- return direct_res; \
+ return eval_direct( lhs, rhs ); \
} \
\
return compare_fpv<FPT>( lhs, rhs, (OP*)0 ); \
diff --git a/boost/test/tree/fixture.hpp b/boost/test/tree/fixture.hpp
index 7bca5a8de3..8e07b2aa1d 100644
--- a/boost/test/tree/fixture.hpp
+++ b/boost/test/tree/fixture.hpp
@@ -5,11 +5,8 @@
// See http://www.boost.org/libs/test for the library home page.
//
-// File : $RCSfile$
-//
-// Version : $Revision: 74640 $
-//
-// Description : defines fixture interface and object makers
+/// @file
+/// Defines fixture interface and object makers
// ***************************************************************************
#ifndef BOOST_TEST_TREE_FIXTURE_HPP_100311GER
@@ -22,6 +19,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/function/function0.hpp>
+#include <boost/utility/declval.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -46,6 +44,83 @@ public:
typedef shared_ptr<test_unit_fixture> test_unit_fixture_ptr;
// ************************************************************************** //
+// ************** fixture helper functions ************** //
+// ************************************************************************** //
+
+namespace impl_fixture {
+
+#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
+
+ template<typename U, void (U::*)()> struct fixture_detect {};
+
+ template<typename T>
+ struct has_setup {
+ private:
+ template<typename U> static char Test(fixture_detect<U, &U::setup>*);
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+ template<typename T>
+ struct has_teardown {
+ private:
+ template<typename U> static char Test(fixture_detect<U, &U::teardown>*);
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+#else
+
+ template<typename U> struct fixture_detect { typedef char type; };
+ template<typename T>
+ struct has_setup {
+ private:
+ template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().setup())>::type;
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+ template<typename T>
+ struct has_teardown {
+ private:
+ template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().teardown())>::type;
+ template<typename U> static int Test(...);
+ public:
+ static const bool value = sizeof(Test<T>(0)) == sizeof(char);
+ };
+
+#endif
+
+ template <bool has_setup = false>
+ struct call_setup { template <class U> void operator()(U& ) { } };
+
+ template <>
+ struct call_setup<true> { template <class U> void operator()(U& u) { u.setup(); } };
+
+ template <bool has_teardown = false>
+ struct call_teardown { template <class U> void operator()(U& ) { } };
+
+ template <>
+ struct call_teardown<true> { template <class U> void operator()(U& u) { u.teardown(); } };
+}
+
+//! Calls the fixture "setup" if detected by the compiler, otherwise does nothing.
+template <class U>
+void setup_conditional(U& u) {
+ return impl_fixture::call_setup<impl_fixture::has_setup<U>::value>()(u);
+}
+
+//! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing.
+template <class U>
+void teardown_conditional(U& u) {
+ return impl_fixture::call_teardown<impl_fixture::has_teardown<U>::value>()(u);
+}
+
+
+// ************************************************************************** //
// ************** class_based_fixture ************** //
// ************************************************************************** //
@@ -57,8 +132,8 @@ public:
private:
// Fixture interface
- virtual void setup() { m_inst.reset( new F( m_arg ) ); }
- virtual void teardown() { m_inst.reset(); }
+ virtual void setup() { m_inst.reset( new F( m_arg ) ); setup_conditional(*m_inst); }
+ virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;
@@ -75,8 +150,8 @@ public:
private:
// Fixture interface
- virtual void setup() { m_inst.reset( new F ); }
- virtual void teardown() { m_inst.reset(); }
+ virtual void setup() { m_inst.reset( new F ); setup_conditional(*m_inst); }
+ virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;
diff --git a/boost/test/tree/global_fixture.hpp b/boost/test/tree/global_fixture.hpp
index 2114595929..7c96d34e89 100644
--- a/boost/test/tree/global_fixture.hpp
+++ b/boost/test/tree/global_fixture.hpp
@@ -17,6 +17,7 @@
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/tree/observer.hpp>
+#include <boost/test/tree/fixture.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -27,13 +28,36 @@ namespace boost {
namespace unit_test {
// ************************************************************************** //
+// ************** global_configuration ************** //
+// ************************************************************************** //
+
+class BOOST_TEST_DECL global_configuration : public test_observer {
+
+public:
+ // Constructor
+ global_configuration();
+
+ // Dtor
+ virtual ~global_configuration();
+
+ // Happens after the framework global observer init has been done
+ virtual int priority() { return 1; }
+};
+
+
+
+// ************************************************************************** //
// ************** global_fixture ************** //
// ************************************************************************** //
-class BOOST_TEST_DECL global_fixture : public test_observer {
+class BOOST_TEST_DECL global_fixture : public test_unit_fixture {
+
public:
// Constructor
global_fixture();
+
+ // Dtor
+ virtual ~global_fixture();
};
//____________________________________________________________________________//
@@ -41,14 +65,48 @@ public:
namespace ut_detail {
template<typename F>
-struct global_fixture_impl : public global_fixture {
+struct global_configuration_impl : public global_configuration {
// Constructor
- global_fixture_impl() : m_fixture( 0 ) {}
+ global_configuration_impl() : m_configuration_observer( 0 ) {
+ }
// test observer interface
- virtual void test_start( counter_t ) { m_fixture = new F; }
- virtual void test_finish() { delete m_fixture; m_fixture = 0; }
- virtual void test_aborted() { delete m_fixture; m_fixture = 0; }
+ virtual void test_start( counter_t ) {
+ m_configuration_observer = new F;
+ }
+
+ // test observer interface
+ virtual void test_finish() {
+ if(m_configuration_observer) {
+ delete m_configuration_observer;
+ m_configuration_observer = 0;
+ }
+ }
+private:
+ // Data members
+ F* m_configuration_observer;
+};
+
+template<typename F>
+struct global_fixture_impl : public global_fixture {
+ // Constructor
+ global_fixture_impl() : m_fixture( 0 ) {
+ }
+
+ // test fixture interface
+ virtual void setup() {
+ m_fixture = new F;
+ setup_conditional(*m_fixture);
+ }
+
+ // test fixture interface
+ virtual void teardown() {
+ if(m_fixture) {
+ teardown_conditional(*m_fixture);
+ }
+ delete m_fixture;
+ m_fixture = 0;
+ }
private:
// Data members
diff --git a/boost/test/tree/observer.hpp b/boost/test/tree/observer.hpp
index 4db930fb07..bd6fc9bff5 100644
--- a/boost/test/tree/observer.hpp
+++ b/boost/test/tree/observer.hpp
@@ -34,7 +34,7 @@ namespace unit_test {
/// Boost.Test framework on the current execution state.
///
/// Several observers can be running at the same time, and it is not unusual to
-/// have interactions among them. The test_observer#priority member function allows the specification
+/// have interactions among them. The @ref test_observer::priority member function allows the specification
/// of a particular order among them (lowest priority executed first, except specified otherwise).
///
class BOOST_TEST_DECL test_observer {
@@ -44,10 +44,8 @@ public:
//!
//! @param[in] number_of_test_cases indicates the number of test cases. Only active
//! test cases are taken into account.
- //!
virtual void test_start( counter_t /* number_of_test_cases */ ) {}
-
//! Called after the framework ends executing the test cases
//!
//! @note The call is made with a reversed priority order.
@@ -98,6 +96,8 @@ public:
//! additional data about the exception.
virtual void exception_caught( execution_exception const& ) {}
+ //! The priority indicates the order at which this observer is initialized
+ //! and tore down in the UTF framework. The order is lowest to highest priority.
virtual int priority() { return 0; }
protected:
diff --git a/boost/test/unit_test_log.hpp b/boost/test/unit_test_log.hpp
index ba998b0ca4..4e6a97b3c2 100644
--- a/boost/test/unit_test_log.hpp
+++ b/boost/test/unit_test_log.hpp
@@ -123,7 +123,7 @@ public:
virtual void exception_caught( execution_exception const& ex );
- virtual int priority() { return 1; }
+ virtual int priority() { return 2; }
// log configuration methods
//! Sets the stream for all loggers
diff --git a/boost/test/unit_test_log_formatter.hpp b/boost/test/unit_test_log_formatter.hpp
index 77fec40aed..79b74e0849 100644
--- a/boost/test/unit_test_log_formatter.hpp
+++ b/boost/test/unit_test_log_formatter.hpp
@@ -248,7 +248,7 @@ public:
// @name Log entry context report
/// Invoked by Unit Test Framework to start log entry context report
-
+ //
/// Unit Test Framework logs for failed assertions and uncaught exceptions context if one was defined by a test module.
/// Context consists of multiple "scopes" identified by description messages assigned by the test module using
/// BOOST_TEST_INFO/BOOST_TEST_CONTEXT statements.
@@ -258,18 +258,20 @@ public:
virtual void entry_context_start( std::ostream& os, log_level l ) = 0;
/// Invoked by Unit Test Framework to report log entry context "scope" description
-
+ //
/// Each "scope" description is reported by separate call to log_entry_context.
/// @param[in] os output stream to write a messages into
+ /// @param[in] l entry log_level, to be used to fine tune the message
/// @param[in] value context "scope" description
/// @see log_entry_start, entry_context_finish
- virtual void log_entry_context( std::ostream& os, const_string value ) = 0;
+ virtual void log_entry_context( std::ostream& os, log_level l, const_string value ) = 0;
/// Invoked by Unit Test Framework to finish log entry context report
-
+ ///
/// @param[in] os output stream to write a messages into
+ /// @param[in] l entry log_level, to be used to fine tune the message
/// @see log_entry_start, entry_context_context
- virtual void entry_context_finish( std::ostream& os ) = 0;
+ virtual void entry_context_finish( std::ostream& os, log_level l ) = 0;
// @}
// @name Log level management
diff --git a/boost/test/unit_test_suite.hpp b/boost/test/unit_test_suite.hpp
index b434fa9f97..13ff804b44 100644
--- a/boost/test/unit_test_suite.hpp
+++ b/boost/test/unit_test_suite.hpp
@@ -143,11 +143,15 @@ struct test_name : public F { void test_method(); }; \
\
static void BOOST_AUTO_TC_INVOKER( test_name )() \
{ \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor"); \
test_name t; \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture setup"); \
+ boost::unit_test::setup_conditional(t); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
t.test_method(); \
- BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture teardown"); \
+ boost::unit_test::teardown_conditional(t); \
+ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor"); \
} \
\
struct BOOST_AUTO_TC_UNIQUE_ID( test_name ) {}; \
@@ -230,10 +234,11 @@ struct BOOST_AUTO_TC_INVOKER( test_name ) { \
static void run( boost::type<TestType>* = 0 ) \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name <<"\" fixture entry."); \
- test_name<TestType> t; \
+ test_name<TestType> t; boost::unit_test::setup_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
t.test_method(); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
+ boost::unit_test::teardown_conditional(t); \
} \
}; \
\
@@ -290,6 +295,22 @@ void BOOST_JOIN( name, _impl )( boost::type<type_name>* ) \
// ************************************************************************** //
#define BOOST_GLOBAL_FIXTURE( F ) \
+static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
+/**/
+
+// ************************************************************************** //
+// ************** BOOST_TEST_GLOBAL_CONFIGURATION ************** //
+// ************************************************************************** //
+
+#define BOOST_TEST_GLOBAL_CONFIGURATION( F ) \
+static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
+/**/
+
+// ************************************************************************** //
+// ************** BOOST_TEST_GLOBAL_FIXTURE ************** //
+// ************************************************************************** //
+
+#define BOOST_TEST_GLOBAL_FIXTURE( F ) \
static boost::unit_test::ut_detail::global_fixture_impl<F> BOOST_JOIN( gf_, F ) \
/**/
diff --git a/boost/test/utils/algorithm.hpp b/boost/test/utils/algorithm.hpp
index a5491816eb..7f16816c3a 100644
--- a/boost/test/utils/algorithm.hpp
+++ b/boost/test/utils/algorithm.hpp
@@ -15,10 +15,16 @@
// STL
#include <utility>
#include <algorithm> // std::find
-#include <functional> // std::bind1st
+#include <functional> // std::bind1st or std::bind
#include <boost/test/detail/suppress_warnings.hpp>
+#ifdef BOOST_NO_CXX98_BINDERS
+#define BOOST_TEST_BIND1ST(F,A) std::bind( (F), (A), std::placeholders::_1 )
+#else
+#define BOOST_TEST_BIND1ST(F,A) std::bind1st( (F), (A) )
+#endif
+
//____________________________________________________________________________//
namespace boost {
@@ -109,7 +115,7 @@ find_first_not_of( ForwardIterator1 first1, ForwardIterator1 last1,
Predicate pred )
{
while( first1 != last1 ) {
- if( std::find_if( first2, last2, std::bind1st( pred, *first1 ) ) == last2 )
+ if( std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *first1 ) ) == last2 )
break;
++first1;
}
@@ -159,9 +165,9 @@ find_last_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
- while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ) {}
+ while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ) {}
- return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
+ return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//
@@ -206,9 +212,9 @@ find_last_not_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
- while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) != last2 ) {}
+ while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) != last2 ) {}
- return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
+ return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//
diff --git a/boost/test/utils/basic_cstring/basic_cstring.hpp b/boost/test/utils/basic_cstring/basic_cstring.hpp
index d6259990e0..fdd87d5211 100644
--- a/boost/test/utils/basic_cstring/basic_cstring.hpp
+++ b/boost/test/utils/basic_cstring/basic_cstring.hpp
@@ -44,7 +44,7 @@ class basic_cstring {
public:
// Subtypes
typedef ut_detail::bcs_char_traits<CharT> traits_type;
- typedef typename ut_detail::bcs_char_traits<CharT>::std_string std_string;
+ typedef typename traits_type::std_string std_string;
typedef CharT value_type;
typedef typename remove_cv<value_type>::type value_ret_type;
@@ -72,6 +72,7 @@ public:
// Constructors; default copy constructor is generated by compiler
basic_cstring();
+ basic_cstring( basic_cstring const & );
basic_cstring( std_string const& s );
basic_cstring( pointer s );
template<typename LenType>
@@ -188,6 +189,16 @@ basic_cstring<CharT>::basic_cstring()
template<typename CharT>
inline
+basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
+: m_begin( s.m_begin )
+, m_end( s.m_end )
+{
+}
+
+//____________________________________________________________________________//
+
+template<typename CharT>
+inline
basic_cstring<CharT>::basic_cstring( std_string const& s )
: m_begin( s.c_str() )
, m_end( m_begin + s.size() )
diff --git a/boost/test/utils/basic_cstring/compare.hpp b/boost/test/utils/basic_cstring/compare.hpp
index b416b1f2b9..2a256fc6be 100644
--- a/boost/test/utils/basic_cstring/compare.hpp
+++ b/boost/test/utils/basic_cstring/compare.hpp
@@ -76,9 +76,13 @@ case_ins_eq( basic_cstring<CharT> x, basic_cstring<CharT> y )
// ************************************************************************** //
template<class CharT>
-class case_ins_less : public std::binary_function<basic_cstring<CharT>,basic_cstring<CharT>,bool>
+class case_ins_less
{
public:
+ typedef bool result_type;
+ typedef basic_cstring<CharT> first_argument_type;
+ typedef basic_cstring<CharT> second_argument_type;
+
bool operator()( basic_cstring<CharT> x, basic_cstring<CharT> y ) const
{
return x.size() != y.size()
diff --git a/boost/test/utils/is_cstring.hpp b/boost/test/utils/is_cstring.hpp
index 914c7cf673..12326b0418 100644
--- a/boost/test/utils/is_cstring.hpp
+++ b/boost/test/utils/is_cstring.hpp
@@ -23,6 +23,7 @@
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/add_const.hpp>
+#include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
#include <string>
//____________________________________________________________________________//
@@ -51,19 +52,36 @@ struct is_cstring_impl<char*> : public mpl::true_ {};
template<>
struct is_cstring_impl<wchar_t*> : public mpl::true_ {};
+template <typename T, bool is_cstring = is_cstring_impl<typename boost::decay<T>::type>::value >
+struct deduce_cstring_impl;
+
+template <typename T, bool is_cstring >
+struct deduce_cstring_impl<T&, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
+
+template <typename T, bool is_cstring >
+struct deduce_cstring_impl<T const, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
+
template <typename T>
-struct deduce_cstring_impl {
+struct deduce_cstring_impl<T, true> {
typedef typename boost::add_const<
typename boost::remove_pointer<
typename boost::decay<T>::type
>::type
- >::type type;
+ >::type U;
+ typedef boost::unit_test::basic_cstring<U> type;
+};
+
+template <typename T>
+struct deduce_cstring_impl< T, false > {
+ typedef typename
+ boost::remove_const<
+ typename boost::remove_reference<T>::type
+ >::type type;
};
template <typename T>
-struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
- // const is required here
- typedef typename boost::add_const<T>::type type;
+struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> >, false > {
+ typedef boost::unit_test::basic_cstring<typename boost::add_const<T>::type> type;
};
} // namespace ut_detail
@@ -71,8 +89,17 @@ struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
template<typename T>
struct is_cstring : public ut_detail::is_cstring_impl<typename decay<T>::type> {};
+template<typename T, bool is_cstring = is_cstring<typename boost::decay<T>::type>::value >
+struct is_cstring_comparable: public mpl::false_ {};
+
+template<typename T>
+struct is_cstring_comparable< T, true > : public mpl::true_ {};
+
+template<typename T>
+struct is_cstring_comparable< std::basic_string<T, std::char_traits<T> >, false > : public mpl::true_ {};
+
template<typename T>
-struct is_cstring< std::basic_string<T, std::char_traits<T> > > : public mpl::true_ {};
+struct is_cstring_comparable< boost::unit_test::basic_cstring<T>, false > : public mpl::true_ {};
template <class T>
struct deduce_cstring {
@@ -80,7 +107,7 @@ struct deduce_cstring {
boost::remove_const<
typename boost::remove_reference<T>::type
>::type U;
- typedef typename ut_detail::deduce_cstring_impl<U>::type type;
+ typedef typename ut_detail::deduce_cstring_impl<typename boost::decay<U>::type>::type type;
};
} // namespace unit_test
diff --git a/boost/test/utils/is_forward_iterable.hpp b/boost/test/utils/is_forward_iterable.hpp
index b218e96cba..e8f5d39467 100644
--- a/boost/test/utils/is_forward_iterable.hpp
+++ b/boost/test/utils/is_forward_iterable.hpp
@@ -36,6 +36,7 @@
// Boost
#include <boost/utility/declval.hpp>
+#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp>
@@ -51,6 +52,9 @@
namespace boost {
namespace unit_test {
+template<typename T>
+struct is_forward_iterable;
+
// ************************************************************************** //
// ************** is_forward_iterable ************** //
// ************************************************************************** //
@@ -65,6 +69,9 @@ struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
template<typename T>
struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
+template<typename T, std::size_t N>
+struct is_forward_iterable< T [N] > : public mpl::true_ {};
+
template<typename T, typename A>
struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
@@ -86,6 +93,7 @@ struct is_forward_iterable< std::string > : public mpl::true_ {};
namespace ut_detail {
+// SFINAE helper
template<typename T>
struct is_present : public mpl::true_ {};
@@ -110,10 +118,12 @@ template <class T>
struct has_member_begin {
private:
struct nil_t {};
- template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin());
+ template<typename U> static auto test( U* ) -> decltype(std::begin(boost::declval<U&>())); // does not work with boost::begin
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
+
+
};
//____________________________________________________________________________//
@@ -122,7 +132,7 @@ template <class T>
struct has_member_end {
private:
struct nil_t {};
- template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end());
+ template<typename U> static auto test( U* ) -> decltype(std::end(boost::declval<U&>())); // does not work with boost::end
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
@@ -134,24 +144,36 @@ template <class T, class enabled = void>
struct is_forward_iterable_impl : std::false_type {
};
-//____________________________________________________________________________//
-
template <class T>
struct is_forward_iterable_impl<
T,
typename std::enable_if<
- is_present<typename T::const_iterator>::value &&
- is_present<typename T::value_type>::value &&
- has_member_size<T>::value &&
- has_member_begin<T>::value &&
- has_member_end<T>::value &&
- !is_cstring<T>::value
+ has_member_begin<T>::value &&
+ has_member_end<T>::value
>::type
> : std::true_type
{};
//____________________________________________________________________________//
+template <class T, class enabled = void>
+struct is_container_forward_iterable_impl : std::false_type {
+};
+
+template <class T>
+struct is_container_forward_iterable_impl<
+ T,
+ typename std::enable_if<
+ is_present<typename T::const_iterator>::value &&
+ is_present<typename T::value_type>::value &&
+ has_member_size<T>::value &&
+ is_forward_iterable_impl<T>::value
+ >::type
+> : is_forward_iterable_impl<T>
+{};
+
+//____________________________________________________________________________//
+
} // namespace ut_detail
/*! Indicates that a specific type implements the forward iterable concept. */
@@ -163,8 +185,54 @@ struct is_forward_iterable {
enum { value = is_fwd_it_t::value };
};
+/*! Indicates that a specific type implements the forward iterable concept. */
+template<typename T>
+struct is_container_forward_iterable {
+ typedef typename std::remove_reference<T>::type T_ref;
+ typedef ut_detail::is_container_forward_iterable_impl<T_ref> is_fwd_it_t;
+ typedef mpl::bool_<is_fwd_it_t::value> type;
+ enum { value = is_fwd_it_t::value };
+};
+
#endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */
+template <typename T, bool is_forward_iterable = is_forward_iterable<T>::value >
+struct bt_iterator_traits;
+
+template <typename T>
+struct bt_iterator_traits< T, true >{
+ BOOST_STATIC_ASSERT((is_forward_iterable<T>::value)); //, "only for forward iterable types");
+ typedef typename T::const_iterator const_iterator;
+ typedef typename T::value_type value_type;
+
+ static const_iterator begin(T const& container) {
+ return container.begin();
+ }
+ static const_iterator end(T const& container) {
+ return container.end();
+ }
+ static std::size_t size(T const& container) {
+ return container.size();
+ }
+};
+
+template <typename T, std::size_t N>
+struct bt_iterator_traits< T [N], true > {
+ typedef typename boost::add_const<T>::type T_const;
+ typedef typename boost::add_pointer<T_const>::type const_iterator;
+ typedef T value_type;
+
+ static const_iterator begin(T_const (&array)[N]) {
+ return &array[0];
+ }
+ static const_iterator end(T_const (&array)[N]) {
+ return &array[N];
+ }
+ static std::size_t size(T_const (&)[N]) {
+ return N;
+ }
+};
+
} // namespace unit_test
} // namespace boost