From 847212ae0cc1aee7b1c26ea1b6bf4eef4910ce8b Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Thu, 22 Jun 2017 09:20:58 +0200 Subject: [PATCH 1/8] Improving global initialization and fixtures - new macros: BOOST_TEST_GLOBAL_FIXTURE: for global "real" fixtures BOOST_TEST_GLOBAL_CONFIGURATION: for global configuration of observers. - deprecating BOOST_GLOBAL_FIXTURE. BOOST_GLOBAL_FIXTURE and BOOST_TEST_GLOBAL_CONFIGURATION are currently fully equivalent, the former being confusing in term of scope/role is deprecated - SFINAE detection for a setup/teardown function within the fixture class - Attaching global fixture to the main or master test unit being executed, exactly as other fixtures. Global fixtures via BOOST_TEST_GLOBAL_FIXTURE registers themselves in a particular field of the framework and are attached each time the framework executes the tests, such that we can run the framework on another test root and still benefit from the global fixtures. The global fixtures are appended to already existing fixtures (in case the master test suite is not the root of the current execution tree). - Checking that the framework setup is not failing for running the test - RAII class for restoring the global fixtures - Tests on the setup/teardown detection - Tests on global fixtures and baseline - Fixing several logging issues Some additional refactoring - renaming m_curr_test_case to m_curr_test_unit - function for providing the current test unit (and not only the current test case) - for output_stream comparison: stops properly if the reference stream is shorter than the current one, initialises the read char correctly to 0 and prints a proper ~ at the mismatch location --- build/CMakeLists.txt | 1 + build/Jamfile.v2 | 2 + include/boost/test/detail/fwd_decl.hpp | 1 + include/boost/test/detail/global_typedef.hpp | 15 + include/boost/test/execution_monitor.hpp | 1 + include/boost/test/framework.hpp | 31 +- .../test/impl/compiler_log_formatter.ipp | 2 +- include/boost/test/impl/execution_monitor.ipp | 6 + include/boost/test/impl/framework.ipp | 184 +- include/boost/test/impl/results_collector.ipp | 6 + .../impl/test_framework_init_observer.ipp | 109 + include/boost/test/impl/test_tools.ipp | 43 +- include/boost/test/impl/test_tree.ipp | 19 + include/boost/test/impl/unit_test_log.ipp | 2 + include/boost/test/impl/unit_test_monitor.ipp | 2 +- .../boost/test/included/test_exec_monitor.hpp | 1 + include/boost/test/included/unit_test.hpp | 3 +- include/boost/test/progress_monitor.hpp | 2 +- include/boost/test/results_collector.hpp | 5 +- .../test/test_framework_init_observer.hpp | 63 + include/boost/test/tree/fixture.hpp | 65 +- include/boost/test/tree/global_fixture.hpp | 70 +- include/boost/test/tree/observer.hpp | 6 +- include/boost/test/unit_test_log.hpp | 2 +- include/boost/test/unit_test_suite.hpp | 16 + src/test_framework_init_observer.cpp | 15 + test/Jamfile.v2 | 2 + .../global-fixtures-test.pattern | 5831 +++++++++++++++++ test/framework-ts/log-formatter-test.cpp | 6 +- .../test-macro-global-fixture.cpp | 417 ++ .../test-fixture-detect-setup-teardown.cpp | 72 + 31 files changed, 6937 insertions(+), 63 deletions(-) create mode 100644 include/boost/test/impl/test_framework_init_observer.ipp create mode 100644 include/boost/test/test_framework_init_observer.hpp create mode 100644 src/test_framework_init_observer.cpp create mode 100644 test/baseline-outputs/global-fixtures-test.pattern create mode 100644 test/framework-ts/test-macro-global-fixture.cpp create mode 100644 test/writing-test-ts/test-fixture-detect-setup-teardown.cpp diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 458d904f..ad2ebd02 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -90,6 +90,7 @@ set(BOOST_UTF_SRC ${BOOST_TEST_ROOT_DIR}/src/progress_monitor.cpp ${BOOST_TEST_ROOT_DIR}/src/results_collector.cpp ${BOOST_TEST_ROOT_DIR}/src/results_reporter.cpp + ${BOOST_TEST_ROOT_DIR}/src/test_framework_init_observer.cpp ${BOOST_TEST_ROOT_DIR}/src/test_tools.cpp ${BOOST_TEST_ROOT_DIR}/src/test_tree.cpp ${BOOST_TEST_ROOT_DIR}/src/unit_test_log.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 529e0711..0665f3fd 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -47,6 +47,7 @@ TEST_EXEC_MON_SOURCES = progress_monitor results_collector results_reporter + test_framework_init_observer test_main test_tools test_tree @@ -69,6 +70,7 @@ UTF_SOURCES = progress_monitor results_collector results_reporter + test_framework_init_observer test_tools test_tree unit_test_log diff --git a/include/boost/test/detail/fwd_decl.hpp b/include/boost/test/detail/fwd_decl.hpp index 944d5226..d5c97fb7 100644 --- a/include/boost/test/detail/fwd_decl.hpp +++ b/include/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/include/boost/test/detail/global_typedef.hpp b/include/boost/test/detail/global_typedef.hpp index b9cfeb52..aeede00e 100644 --- a/include/boost/test/detail/global_typedef.hpp +++ b/include/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/include/boost/test/execution_monitor.hpp b/include/boost/test/execution_monitor.hpp index adfb0336..ed06ef25 100644 --- a/include/boost/test/execution_monitor.hpp +++ b/include/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/include/boost/test/framework.hpp b/include/boost/test/framework.hpp index f94bcf12..099c0296 100644 --- a/include/boost/test/framework.hpp +++ b/include/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/include/boost/test/impl/compiler_log_formatter.ipp b/include/boost/test/impl/compiler_log_formatter.ipp index a4e045ca..4887ff58 100644 --- a/include/boost/test/impl/compiler_log_formatter.ipp +++ b/include/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 diff --git a/include/boost/test/impl/execution_monitor.ipp b/include/boost/test/impl/execution_monitor.ipp index 0c5690ca..94b6f9fb 100644 --- a/include/boost/test/impl/execution_monitor.ipp +++ b/include/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/include/boost/test/impl/framework.ipp b/include/boost/test/impl/framework.ipp index 53738c24..ca35ce1c 100644 --- a/include/boost/test/impl/framework.ipp +++ b/include/boost/test/impl/framework.ipp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -71,6 +72,7 @@ namespace std { using ::time; using ::srand; } namespace boost { namespace unit_test { namespace framework { + namespace impl { // ************************************************************************** // @@ -457,6 +459,27 @@ void random_shuffle( RandomIt first, RandomIt last, RandomFunc &r ) #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 // ************************************************************************** // @@ -468,7 +491,7 @@ unsigned const TIMEOUT_EXCEEDED = static_cast( -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 ) @@ -625,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) @@ -664,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 @@ -736,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 ); @@ -746,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 } } @@ -755,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 ) ) @@ -813,7 +841,7 @@ public: master_test_suite_t* m_master_test_suite; std::vector 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; @@ -825,6 +853,8 @@ public: context_data m_context; int m_context_idx; + std::set m_global_fixtures; + boost::execution_monitor m_aux_em; std::map m_log_sinks; @@ -1069,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( runtime_config::btrt_show_progress ) ) { progress_monitor.set_stream( std::cout ); // defaults to stdout @@ -1261,6 +1292,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 ************** // // ************************************************************************** // @@ -1389,7 +1444,14 @@ current_auto_test_suite( test_suite* ts, bool push_or_pop ) test_case const& current_test_case() { - return get( impl::s_frk_state().m_curr_test_case ); + return get( 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]; } //____________________________________________________________________________// @@ -1397,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; } //____________________________________________________________________________// @@ -1422,6 +1484,17 @@ get( test_unit_id id, test_unit_type t ) // ************** framework::run ************** // // ************************************************************************** // +template +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 ) { @@ -1440,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( runtime_config::btrt_random_seed ); - switch( seed ) { - case 0: - break; - case 1: - seed = static_cast( 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 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 > 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( runtime_config::btrt_random_seed ); + switch( seed ) { + case 0: + break; + case 1: + seed = static_cast( 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 ); } //____________________________________________________________________________// @@ -1522,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/include/boost/test/impl/results_collector.ipp b/include/boost/test/impl/results_collector.ipp index daee8bc3..fd74bdb6 100644 --- a/include/boost/test/impl/results_collector.ipp +++ b/include/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/include/boost/test/impl/test_framework_init_observer.ipp b/include/boost/test/impl/test_framework_init_observer.ipp new file mode 100644 index 00000000..89f854aa --- /dev/null +++ b/include/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 +#include +#include + +//____________________________________________________________________________// + +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 + +#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER diff --git a/include/boost/test/impl/test_tools.ipp b/include/boost/test/impl/test_tools.ipp index 853b3913..37ebc20b 100644 --- a/include/boost/test/impl/test_tools.ipp +++ b/include/boost/test/impl/test_tools.ipp @@ -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 last_elements; for ( std::string::size_type i = 0; static_cast(i + offset) < static_cast(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/include/boost/test/impl/test_tree.ipp b/include/boost/test/impl/test_tree.ipp index 08bdad33..81995bb2 100644 --- a/include/boost/test/impl/test_tree.ipp +++ b/include/boost/test/impl/test_tree.ipp @@ -447,10 +447,29 @@ 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/include/boost/test/impl/unit_test_log.ipp b/include/boost/test/impl/unit_test_log.ipp index c52260b9..717e166b 100644 --- a/include/boost/test/impl/unit_test_log.ipp +++ b/include/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( 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; } } diff --git a/include/boost/test/impl/unit_test_monitor.ipp b/include/boost/test/impl/unit_test_monitor.ipp index fdd36f7c..cfb41a23 100644 --- a/include/boost/test/impl/unit_test_monitor.ipp +++ b/include/boost/test/impl/unit_test_monitor.ipp @@ -47,7 +47,7 @@ unit_test_monitor_t::execute_and_translate( boost::function 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/include/boost/test/included/test_exec_monitor.hpp b/include/boost/test/included/test_exec_monitor.hpp index 34b6ef44..e75b4698 100644 --- a/include/boost/test/included/test_exec_monitor.hpp +++ b/include/boost/test/included/test_exec_monitor.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/test/included/unit_test.hpp b/include/boost/test/included/unit_test.hpp index 993d75e4..90882eb1 100644 --- a/include/boost/test/included/unit_test.hpp +++ b/include/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 #include #include +#include #include #include #include @@ -31,7 +33,6 @@ #include #include #include -#include #include #include diff --git a/include/boost/test/progress_monitor.hpp b/include/boost/test/progress_monitor.hpp index e480ac66..2f661f58 100644 --- a/include/boost/test/progress_monitor.hpp +++ b/include/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/include/boost/test/results_collector.hpp b/include/boost/test/results_collector.hpp index 7d2c2bee..3acd7b87 100644 --- a/include/boost/test/results_collector.hpp +++ b/include/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/include/boost/test/test_framework_init_observer.hpp b/include/boost/test/test_framework_init_observer.hpp new file mode 100644 index 00000000..cdf5ef5e --- /dev/null +++ b/include/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 + +#include +#include + +#include + +#include + +//____________________________________________________________________________// + +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 { +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 + +#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER diff --git a/include/boost/test/tree/fixture.hpp b/include/boost/test/tree/fixture.hpp index 7bca5a8d..1cdceb75 100644 --- a/include/boost/test/tree/fixture.hpp +++ b/include/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 @@ -45,6 +42,56 @@ public: typedef shared_ptr test_unit_fixture_ptr; +// ************************************************************************** // +// ************** fixture helper functions ************** // +// ************************************************************************** // + + +namespace fixture_details { + + template + struct has_setup { + template struct detect {}; + template static char Test(detect*); + template static int Test(...); + static const bool value = sizeof(Test(0)) == sizeof(char); + }; + + template + struct has_teardown { + template struct detect {}; + template static char Test(detect*); + template static int Test(...); + static const bool value = sizeof(Test(0)) == sizeof(char); + }; + + template + struct call_setup { template void operator()(U& u) { } }; + + template <> + struct call_setup { template void operator()(U& u) { u.setup(); } }; + + template + struct call_teardown { template void operator()(U& u) { } }; + + template <> + struct call_teardown { template void operator()(U& u) { u.teardown(); } }; + + //! Calls the fixture "setup" if detected by the compiler, otherwise does nothing. + template + void setup_conditional(U& u) { + return call_setup::value>()(u); + } + + //! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing. + template + void teardown_conditional(U& u) { + return call_teardown::value>()(u); + } + +} + + // ************************************************************************** // // ************** class_based_fixture ************** // // ************************************************************************** // @@ -57,8 +104,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 ) ); fixture_details::setup_conditional(*m_inst); } + virtual void teardown() { fixture_details::teardown_conditional(*m_inst); m_inst.reset(); } // Data members scoped_ptr m_inst; @@ -75,8 +122,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 ); fixture_details::setup_conditional(*m_inst); } + virtual void teardown() { fixture_details::teardown_conditional(*m_inst); m_inst.reset(); } // Data members scoped_ptr m_inst; diff --git a/include/boost/test/tree/global_fixture.hpp b/include/boost/test/tree/global_fixture.hpp index 21145959..38ab146f 100644 --- a/include/boost/test/tree/global_fixture.hpp +++ b/include/boost/test/tree/global_fixture.hpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -26,14 +27,37 @@ 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 -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 +struct global_fixture_impl : public global_fixture { + // Constructor + global_fixture_impl() : m_fixture( 0 ) { + } + + // test fixture interface + virtual void setup() { + m_fixture = new F; + fixture_details::setup_conditional(*m_fixture); + } + + // test fixture interface + virtual void teardown() { + if(m_fixture) { + fixture_details::teardown_conditional(*m_fixture); + } + delete m_fixture; + m_fixture = 0; + } private: // Data members diff --git a/include/boost/test/tree/observer.hpp b/include/boost/test/tree/observer.hpp index 4db930fb..bd6fc9bf 100644 --- a/include/boost/test/tree/observer.hpp +++ b/include/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/include/boost/test/unit_test_log.hpp b/include/boost/test/unit_test_log.hpp index ba998b0c..4e6a97b3 100644 --- a/include/boost/test/unit_test_log.hpp +++ b/include/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/include/boost/test/unit_test_suite.hpp b/include/boost/test/unit_test_suite.hpp index b434fa9f..1247b681 100644 --- a/include/boost/test/unit_test_suite.hpp +++ b/include/boost/test/unit_test_suite.hpp @@ -290,6 +290,22 @@ void BOOST_JOIN( name, _impl )( boost::type* ) \ // ************************************************************************** // #define BOOST_GLOBAL_FIXTURE( F ) \ +static boost::unit_test::ut_detail::global_configuration_impl BOOST_JOIN( gf_, F ) \ +/**/ + +// ************************************************************************** // +// ************** BOOST_TEST_GLOBAL_CONFIGURATION ************** // +// ************************************************************************** // + +#define BOOST_TEST_GLOBAL_CONFIGURATION( F ) \ +static boost::unit_test::ut_detail::global_configuration_impl BOOST_JOIN( gf_, F ) \ +/**/ + +// ************************************************************************** // +// ************** BOOST_TEST_GLOBAL_FIXTURE ************** // +// ************************************************************************** // + +#define BOOST_TEST_GLOBAL_FIXTURE( F ) \ static boost::unit_test::ut_detail::global_fixture_impl BOOST_JOIN( gf_, F ) \ /**/ diff --git a/src/test_framework_init_observer.cpp b/src/test_framework_init_observer.cpp new file mode 100644 index 00000000..140329dd --- /dev/null +++ b/src/test_framework_init_observer.cpp @@ -0,0 +1,15 @@ +// (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 +//! Forwarding source +// ************************************************************************** + +#define BOOST_TEST_SOURCE +#include + +// EOF diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0401902b..1828dd2e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -136,6 +136,7 @@ test-suite "framework-ts" [ boost.test-self-test run : framework-ts : log-formatter-test : : baseline-outputs/log-formatter-test.pattern ] [ boost.test-self-test run : framework-ts : run-by-name-or-label-test ] [ boost.test-self-test run : framework-ts : version-uses-module-name : included ] + [ boost.test-self-test run : framework-ts : test-macro-global-fixture ] ; #_________________________________________________________________________________________________# @@ -156,6 +157,7 @@ test-suite "writing-test-ts" [ boost.test-self-test run : writing-test-ts : test-dataset-over-tuples : : : : : : $(requirements_datasets) ] [ boost.test-self-test run : writing-test-ts : nullptr-support-test : : : : : : [ requires cxx11_nullptr ] ] [ boost.test-self-test run : writing-test-ts : user-defined-types-logging-customization-points ] + [ boost.test-self-test run : writing-test-ts : test-fixture-detect-setup-teardown ] ; #_________________________________________________________________________________________________# diff --git a/test/baseline-outputs/global-fixtures-test.pattern b/test/baseline-outputs/global-fixtures-test.pattern new file mode 100644 index 00000000..bce003f9 --- /dev/null +++ b/test/baseline-outputs/global-fixtures-test.pattern @@ -0,0 +1,5831 @@ +*********************** +*********************** GlobalFixtureWithCtor<&good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithCtor<&almost_good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy": condition 2>3 is not satisfied [2 <= 3] +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors": condition 2>3 is not satisfied [2 <= 3] +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithCtor<&bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy": non sense +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy no errors": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy no errors": non sense +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithCtor: dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + + + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithCtor<&very_bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy no errors": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithCtor<&very_bad_exception> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithCtor: ctor +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy no errors": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithSetup<&good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithSetup<&almost_good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy": condition 2>3 is not satisfied [2 <= 3] +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors": condition 2>3 is not satisfied [2 <= 3] +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithSetup<&bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy": non sense +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy no errors": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy no errors": non sense +GlobalFixtureWithSetup::setup-calling function done +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + + + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithSetup<&very_bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy": very_bad_foo is fatal +Failure occurred in a following context: + some context +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy no errors": very_bad_foo is fatal +Failure occurred in a following context: + some context +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithSetup<&very_bad_exception> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithSetup ctor +GlobalFixtureWithSetup::setup-calling function +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy no errors": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +GlobalFixtureWithSetup dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithTeardown<&good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithTeardown::teardown-calling function +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithTeardown::teardown-calling function +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithTeardown<&almost_good_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy": condition 2>3 is not satisfied [2 <= 3] +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ3 is not satisfied [2 <= 3]]]> +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors": condition 2>3 is not satisfied [2 <= 3] +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ3 is not satisfied [2 <= 3]]]> +* 3-format ******************************************************************* + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + +*********************** +*********************** GlobalFixtureWithTeardown<&bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy": non sense +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy no errors": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy no errors": non sense +GlobalFixtureWithTeardown::teardown-calling function done +GlobalFixtureWithTeardown dtor +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + + + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithTeardown<&very_bad_foo> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy no errors": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + + + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + + + + +*********************** +*********************** GlobalFixtureWithTeardown<&very_bad_exception> +*********************** +* 1-format ******************************************************************* +Running 5 test cases... +xxx/test-macro-global-fixture.cpp:282: Entering test suite "Fake Test Suite Hierarchy" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:283: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:283: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:284: Entering test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:173: fatal error: in "Fake Test Suite Hierarchy/very_bad_foo": very_bad_foo is fatal +Failure occurred in a following context: + some context +xxx/test-macro-global-fixture.cpp:284: Leaving test case "very_bad_foo" +xxx/test-macro-global-fixture.cpp:285: Entering test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy/very_bad_exception": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy/very_bad_exception": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:285: Leaving test case "very_bad_exception" +xxx/test-macro-global-fixture.cpp:276: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:277: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:277: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:276: Leaving test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:279: Entering test suite "1 bad test case inside" +xxx/test-macro-global-fixture.cpp:280: Entering test case "bad_foo" +xxx/test-macro-global-fixture.cpp:152: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": +this is a message +xxx/test-macro-global-fixture.cpp:155: info: check true has passed +xxx/test-macro-global-fixture.cpp:159: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +xxx/test-macro-global-fixture.cpp:161: error: in "Fake Test Suite Hierarchy/1 bad test case inside/bad_foo": non sense +xxx/test-macro-global-fixture.cpp:280: Leaving test case "bad_foo" +xxx/test-macro-global-fixture.cpp:279: Leaving test suite "1 bad test case inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:282: Leaving test suite "Fake Test Suite Hierarchy" + +* 2-format ******************************************************************* +ZZZZZZZZZZZZZZZ +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + + + + + +* 3-format ******************************************************************* + + + + + + + + + + + + + + + + + + + + +* 1-format ******************************************************************* +Running 2 test cases... +xxx/test-macro-global-fixture.cpp:294: Entering test suite "Fake Test Suite Hierarchy no errors" +GlobalFixtureWithTeardown ctor +xxx/test-macro-global-fixture.cpp:296: Entering test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:148: warning: in "Fake Test Suite Hierarchy no errors/almost_good_foo": condition 2>3 is not satisfied [2 <= 3] +Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:296: Leaving test case "almost_good_foo" +xxx/test-macro-global-fixture.cpp:291: Entering test suite "1 test cases inside" +xxx/test-macro-global-fixture.cpp:292: Entering test case "good_foo" +Test case Fake Test Suite Hierarchy no errors/1 test cases inside/good_foo did not check any assertions +xxx/test-macro-global-fixture.cpp:292: Leaving test case "good_foo" +xxx/test-macro-global-fixture.cpp:291: Leaving test suite "1 test cases inside" +GlobalFixtureWithTeardown::teardown-calling function +xxx/test-macro-global-fixture.cpp:182: error: in "Fake Test Suite Hierarchy no errors": with some message +Failure occurred in a following context: + Context value=something + Context value2=something different +unknown location:0: fatal error: in "Fake Test Suite Hierarchy no errors": unknown type +xxx/test-macro-global-fixture.cpp:182: last checkpoint +Failure occurred in a following context: + exception context should be shown +xxx/test-macro-global-fixture.cpp:294: Leaving test suite "Fake Test Suite Hierarchy no errors" + +* 2-format ******************************************************************* +3 is not satisfied [2 <= 3]]]>ZZZZZZ +* 3-format ******************************************************************* + + + + + + + +3 is not satisfied [2 <= 3] + +MESSAGE: +- file : boost.test framework +- line : 212 +- message: Test case Fake Test Suite Hierarchy no errors/almost_good_foo did not check any assertions + +]]> + + + + + +* 3-format ******************************************************************* + + + + + + + + + + diff --git a/test/framework-ts/log-formatter-test.cpp b/test/framework-ts/log-formatter-test.cpp index abfb87fc..e72ad12e 100644 --- a/test/framework-ts/log-formatter-test.cpp +++ b/test/framework-ts/log-formatter-test.cpp @@ -11,7 +11,7 @@ // Boost.Test #define BOOST_TEST_MAIN -#include +#include #include #include #include @@ -113,7 +113,7 @@ void check( output_test_stream& output, test_suite* ts ) check( output, OF_CLF, ts->p_id ); check( output, OF_XML, ts->p_id ); check( output, OF_JUNIT, ts->p_id, log_successful_tests ); - check( output, OF_JUNIT, ts->p_id, log_cpp_exception_errors ); // should branch to the log log_all_errors + check( output, OF_JUNIT, ts->p_id, log_cpp_exception_errors ); // should branch to the log log_all_errors } //____________________________________________________________________________// @@ -186,7 +186,7 @@ public: "condition 2>3 is not satisfied\n", "condition 2>3 is not satisfied]", }; - + static const std::string to_replace[] = {"time=\"0.1234\"", get_basename() + ":*:" , "unknown location:*:", diff --git a/test/framework-ts/test-macro-global-fixture.cpp b/test/framework-ts/test-macro-global-fixture.cpp new file mode 100644 index 00000000..96dffe6c --- /dev/null +++ b/test/framework-ts/test-macro-global-fixture.cpp @@ -0,0 +1,417 @@ +// (C) Copyright Raffi Enficiaud 2016. +// 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. + +// checks issue https://svn.boost.org/trac/boost/ticket/5563 + +#define BOOST_TEST_MODULE test_macro_in_global_fixture +#include +#include +#include +#include +#include +#include +#include +#include +typedef boost::onullstream onullstream_type; +#include + +// BOOST +#include + +// STL +#include +#include + +using boost::test_tools::output_test_stream; +using namespace boost::unit_test; +namespace utf = boost::unit_test; + + +template < void (*function_to_call)() > +struct GlobalFixtureWithCtor { + GlobalFixtureWithCtor() { + BOOST_TEST_MESSAGE("GlobalFixtureWithCtor: ctor"); + (*function_to_call)(); + // having a message is ok + // although it should break existing logger consistency + } + ~GlobalFixtureWithCtor() { + BOOST_TEST_MESSAGE("GlobalFixtureWithCtor: dtor"); + } +}; + +template < void (*function_to_call)() > +struct GlobalFixtureWithSetup { + GlobalFixtureWithSetup() { + BOOST_TEST_MESSAGE("GlobalFixtureWithSetup ctor"); + } + virtual ~GlobalFixtureWithSetup() { + BOOST_TEST_MESSAGE("GlobalFixtureWithSetup dtor"); + } + + virtual void setup() { + BOOST_TEST_MESSAGE("GlobalFixtureWithSetup::setup-calling function"); + (*function_to_call)(); + BOOST_TEST_MESSAGE("GlobalFixtureWithSetup::setup-calling function done"); + } +}; + +template < void (*function_to_call)() > +struct GlobalFixtureWithTeardown { + GlobalFixtureWithTeardown() { + BOOST_TEST_MESSAGE("GlobalFixtureWithTeardown ctor"); + } + virtual ~GlobalFixtureWithTeardown() { + BOOST_TEST_MESSAGE("GlobalFixtureWithTeardown dtor"); + } + + virtual void teardown() { + BOOST_TEST_MESSAGE("GlobalFixtureWithTeardown::teardown-calling function"); + (*function_to_call)(); + BOOST_TEST_MESSAGE("GlobalFixtureWithTeardown::teardown-calling function done"); + } +}; + +template +void check_global_fixture( + output_test_stream& output, + output_format log_format, + test_unit_id id, + bool bt_module_failed = false, + bool has_setup_error = false, + log_level ll = log_successful_tests ) +{ + boost::unit_test::unit_test_log.set_format(log_format); + boost::unit_test::unit_test_log.set_stream(output); + boost::unit_test::unit_test_log.set_threshold_level(ll); + + // output before fixture registration + output << "* " << log_format << "-format *******************************************************************"; + output << std::endl; + + // register this as a global fixture + boost::unit_test::ut_detail::global_fixture_impl fixture_stack_element; + framework::finalize_setup_phase( id ); + + bool setup_error_caught = false; + try { + framework::run( id, false ); // do not continue the test tree to have the test_log_start/end + } + catch (framework::setup_error&) { + BOOST_TEST_MESSAGE("Framework setup_error caught"); + setup_error_caught = true; + } + + output << std::endl; + + // we do not want the result of the comparison go to the "output" stream + boost::unit_test::unit_test_log.set_format(OF_CLF); + boost::unit_test::unit_test_log.set_stream(std::cout); + + BOOST_TEST( setup_error_caught == has_setup_error ); + BOOST_TEST( bt_module_failed == (( results_collector.results( id ).result_code() != 0 ) || setup_error_caught )); + BOOST_TEST( output.match_pattern(true) ); // flushes the stream at the end of the comparison. +} + +template +void check_global_fixture( + output_test_stream& output, + test_suite* ts, + bool bt_module_failed = false, + bool has_setup_error = false) +{ + ts->p_default_status.value = test_unit::RS_ENABLED; + + check_global_fixture( output, OF_CLF, ts->p_id, bt_module_failed, has_setup_error ); + check_global_fixture( output, OF_XML, ts->p_id, bt_module_failed, has_setup_error ); + check_global_fixture( output, OF_JUNIT, ts->p_id, bt_module_failed, has_setup_error, log_successful_tests ); + check_global_fixture( output, OF_JUNIT, ts->p_id, bt_module_failed, has_setup_error, log_cpp_exception_errors ); // should branch to the log log_all_errors +} + +struct guard { + ~guard() + { + boost::unit_test::unit_test_log.set_format( runtime_config::get( runtime_config::btrt_log_format ) ); + boost::unit_test::unit_test_log.set_stream( std::cout ); + } +}; + +// this one should generate a message as it does not execute any assertion +void good_foo() {} + +void almost_good_foo() +{ + BOOST_TEST_WARN( 2>3 ); +} + +void bad_foo() { + BOOST_ERROR( "" ); + + BOOST_TEST_MESSAGE("this is a message"); + BOOST_CHECK(true); + + BOOST_TEST_INFO("Context value=something"); + BOOST_TEST_INFO("Context value2=something different"); + BOOST_ERROR( "with some message" ); + + BOOST_CHECK_MESSAGE( 1 == 2.3, "non sense" ); +} + +struct log_guard { + ~log_guard() + { + unit_test_log.set_stream( std::cout ); + } +}; + +void very_bad_foo() { + BOOST_TEST_CONTEXT("some context") { + BOOST_FAIL( "very_bad_foo is fatal" ); + } +} + +struct local_exception {}; + +void very_bad_exception() { + BOOST_TEST_INFO("Context value=something"); + BOOST_TEST_INFO("Context value2=something different"); + BOOST_ERROR( "with some message" ); + + BOOST_TEST_INFO("exception context should be shown"); + throw local_exception(); +} + +// to factorize out with the logger test +class output_test_stream_for_loggers : public output_test_stream { + +public: + explicit output_test_stream_for_loggers( + boost::unit_test::const_string pattern_file_name = boost::unit_test::const_string(), + bool match_or_save = true, + bool text_or_binary = true ) + : output_test_stream(pattern_file_name, match_or_save, text_or_binary) + {} + + static std::string normalize_path(const std::string &str) { + const std::string to_look_for[] = {"\\"}; + const std::string to_replace[] = {"/"}; + return utils::replace_all_occurrences_of( + str, + to_look_for, to_look_for + sizeof(to_look_for)/sizeof(to_look_for[0]), + to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]) + ); + } + + static std::string get_basename() { + static std::string basename; + + if(basename.empty()) { + basename = normalize_path(__FILE__); + std::string::size_type basename_pos = basename.rfind('/'); + if(basename_pos != std::string::npos) { + basename = basename.substr(basename_pos+1); + } + } + return basename; + } + + virtual std::string get_stream_string_representation() const { + std::string current_string = output_test_stream::get_stream_string_representation(); + + std::string pathname_fixes; + { + static const std::string to_look_for[] = {normalize_path(__FILE__)}; + static const std::string to_replace[] = {"xxx/" + get_basename() }; + pathname_fixes = utils::replace_all_occurrences_of( + current_string, + to_look_for, to_look_for + sizeof(to_look_for)/sizeof(to_look_for[0]), + to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]) + ); + } + + std::string other_vars_fixes; + { + static const std::string to_look_for[] = {"time=\"*\"", + get_basename() + "(*):", + "unknown location(*):", + "; testing time: *us\n", // removing this is far more easier than adding a testing time + "; testing time: *ms\n", + "*", + "condition 2>3 is not satisfied\n", + "condition 2>3 is not satisfied]", + }; + + static const std::string to_replace[] = {"time=\"0.1234\"", + get_basename() + ":*:" , + "unknown location:*:", + "\n", + "\n", + "ZZZ", + "condition 2>3 is not satisfied [2 <= 3]\n", + "condition 2>3 is not satisfied [2 <= 3]]", + }; + + other_vars_fixes = utils::replace_all_occurrences_with_wildcards( + pathname_fixes, + to_look_for, to_look_for + sizeof(to_look_for)/sizeof(to_look_for[0]), + to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]) + ); + } + + return other_vars_fixes; + } + +}; + + +BOOST_AUTO_TEST_CASE( some_test ) +{ + guard G; + ut_detail::ignore_unused_variable_warning( G ); + + test_suite* ts_1 = BOOST_TEST_SUITE( "1 test cases inside" ); + ts_1->add( BOOST_TEST_CASE( good_foo ) ); + + test_suite* ts_1b = BOOST_TEST_SUITE( "1 bad test case inside" ); + ts_1b->add( BOOST_TEST_CASE( bad_foo ), 1 ); + + test_suite* ts_main = BOOST_TEST_SUITE( "Fake Test Suite Hierarchy" ); + ts_main->add( BOOST_TEST_CASE( bad_foo ) ); + ts_main->add( BOOST_TEST_CASE( very_bad_foo ) ); + ts_main->add( BOOST_TEST_CASE( very_bad_exception ) ); + ts_main->add( ts_1 ); + ts_main->add( ts_1b ); + + // we need another tree + test_suite* ts2_0 = BOOST_TEST_SUITE( "0 test cases inside" ); + test_suite* ts2_1 = BOOST_TEST_SUITE( "1 test cases inside" ); + ts2_1->add( BOOST_TEST_CASE( good_foo ) ); + + test_suite* ts_main_no_error = BOOST_TEST_SUITE( "Fake Test Suite Hierarchy no errors" ); + ts_main_no_error->add( ts2_0 ); + ts_main_no_error->add( BOOST_TEST_CASE( almost_good_foo ) ); + ts_main_no_error->add( ts2_1 ); + +#define PATTERN_FILE_NAME "global-fixtures-test.pattern" + + std::string pattern_file_name( + framework::master_test_suite().argc == 1 + ? (runtime_config::save_pattern() ? PATTERN_FILE_NAME : "./baseline-outputs/" PATTERN_FILE_NAME ) + : framework::master_test_suite().argv[1] ); + + + output_test_stream_for_loggers test_output( pattern_file_name, !runtime_config::save_pattern() ); + + // legacy API, we test that we catch exceptions in the ctor, and tests + // in the suite are running or not depending on that + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithCtor<&good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithCtor<&good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithCtor<&good_foo> >( test_output, ts_main_no_error, false); + + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithCtor<&almost_good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithCtor<&almost_good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithCtor<&almost_good_foo> >( test_output, ts_main_no_error, false ); + + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithCtor<&bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithCtor<&bad_foo> >( test_output, ts_main, true ); // should fail the module + check_global_fixture< GlobalFixtureWithCtor<&bad_foo> >( test_output, ts_main_no_error, true ); + + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithCtor<&very_bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithCtor<&very_bad_foo> >( test_output, ts_main, true ); // should fail the module + check_global_fixture< GlobalFixtureWithCtor<&very_bad_foo> >( test_output, ts_main_no_error, true ); + + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithCtor<&very_bad_exception>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithCtor<&very_bad_exception> >( test_output, ts_main, true ); // should fail the module + check_global_fixture< GlobalFixtureWithCtor<&very_bad_exception> >( test_output, ts_main_no_error, true ); + + // here we test only for the setup function, tests should not be + // executed when setup fails, setup should be allowed to fail + + // setup does not fail + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithSetup<&good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithSetup<&good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithSetup<&good_foo> >( test_output, ts_main_no_error, false ); + + // setup does not fail, with messages + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithSetup<&almost_good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithSetup<&almost_good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithSetup<&almost_good_foo> >( test_output, ts_main_no_error, false ); + + // setup fails + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithSetup<&bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithSetup<&bad_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithSetup<&bad_foo> >( test_output, ts_main_no_error, true ); + + // setup fails badly + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithSetup<&very_bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithSetup<&very_bad_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithSetup<&very_bad_foo> >( test_output, ts_main_no_error, true ); + + // setup fails with exception + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithSetup<&very_bad_exception>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithSetup<&very_bad_exception> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithSetup<&very_bad_exception> >( test_output, ts_main_no_error, true ); + + // here we test only for the teardown function, tests should not be + // executed when setup fails, setup should be allowed to fail + + // teardown does not fail + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithTeardown<&good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithTeardown<&good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithTeardown<&good_foo> >( test_output, ts_main_no_error, false ); + + // teardown does not fail, with messages + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithTeardown<&almost_good_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithTeardown<&almost_good_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithTeardown<&almost_good_foo> >( test_output, ts_main_no_error, false ); + + // teardown fails + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithTeardown<&bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithTeardown<&bad_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithTeardown<&bad_foo> >( test_output, ts_main_no_error, true ); + + // teardown fails badly + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithTeardown<&very_bad_foo>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithTeardown<&very_bad_foo> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithTeardown<&very_bad_foo> >( test_output, ts_main_no_error, true ); + + // teardown fails with exception + test_output << "***********************" << std::endl; + test_output << "*********************** GlobalFixtureWithTeardown<&very_bad_exception>" << std::endl; + test_output << "***********************" << std::endl; + check_global_fixture< GlobalFixtureWithTeardown<&very_bad_exception> >( test_output, ts_main, true ); + check_global_fixture< GlobalFixtureWithTeardown<&very_bad_exception> >( test_output, ts_main_no_error, true ); + +} diff --git a/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp b/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp new file mode 100644 index 00000000..f7778dd5 --- /dev/null +++ b/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp @@ -0,0 +1,72 @@ +// (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. + +// checks issue https://svn.boost.org/trac/boost/ticket/5563 + +// we need the included version to be able to access the current framework state +// through boost::unit_test::framework::impl::s_frk_state() + +#define BOOST_TEST_MODULE test_fixture_detect_setup_teardown +#include +#include +#include +#include +#include +#include + +using namespace boost::unit_test; + +class fixture_without { +public: + fixture_without() {} + ~fixture_without() {} +}; + +class fixture_with { +public: + fixture_with() {} + void setup() {} + void teardown() {} + ~fixture_with() {} +}; + +class fixture_with_child : public fixture_with { +public: + fixture_with_child() {} + ~fixture_with_child() {} +}; + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect ) +{ + BOOST_CHECK(!fixture_details::has_setup::value); + BOOST_CHECK(!fixture_details::has_setup::value); + + fixture_without obj; + fixture_details::setup_conditional(obj); + fixture_details::teardown_conditional(obj); +} + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both ) +{ + BOOST_CHECK(fixture_details::has_setup::value); + BOOST_CHECK(fixture_details::has_setup::value); + + fixture_with obj; + fixture_details::setup_conditional(obj); + fixture_details::teardown_conditional(obj); +} + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both_from_child ) +{ + // cannot detect this with the C++03 approach + BOOST_CHECK(!fixture_details::has_setup::value); + BOOST_CHECK(!fixture_details::has_setup::value); + + fixture_with_child obj; + fixture_details::setup_conditional(obj); + fixture_details::teardown_conditional(obj); +} From 1ba4e0a9b8b556f22b04ba0235ef32a20827b509 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Tue, 20 Jun 2017 02:19:51 +0200 Subject: [PATCH 2/8] Fixture setup/teardown detection for C++11 capable compilers --- include/boost/test/tree/fixture.hpp | 68 +++++++++++++------ include/boost/test/tree/global_fixture.hpp | 4 +- test/Jamfile.v2 | 1 + ...st-fixture-detect-setup-teardown-cpp11.cpp | 68 +++++++++++++++++++ .../test-fixture-detect-setup-teardown.cpp | 36 +++++----- 5 files changed, 137 insertions(+), 40 deletions(-) create mode 100644 test/writing-test-ts/test-fixture-detect-setup-teardown-cpp11.cpp diff --git a/include/boost/test/tree/fixture.hpp b/include/boost/test/tree/fixture.hpp index 1cdceb75..f1206782 100644 --- a/include/boost/test/tree/fixture.hpp +++ b/include/boost/test/tree/fixture.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -46,25 +47,53 @@ typedef shared_ptr test_unit_fixture_ptr; // ************** fixture helper functions ************** // // ************************************************************************** // +namespace impl_fixture { -namespace fixture_details { +#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + + template struct fixture_detect {}; template struct has_setup { - template struct detect {}; - template static char Test(detect*); + private: + template static char Test(fixture_detect*); template static int Test(...); + public: static const bool value = sizeof(Test(0)) == sizeof(char); }; template struct has_teardown { - template struct detect {}; - template static char Test(detect*); + private: + template static char Test(fixture_detect*); template static int Test(...); + public: static const bool value = sizeof(Test(0)) == sizeof(char); }; +#else + + template struct fixture_detect { typedef char type; }; + template + struct has_setup { + private: + template static auto Test(U*) -> typename fixture_detect().setup())>::type; + template static int Test(...); + public: + static const bool value = sizeof(Test(0)) == sizeof(char); + }; + + template + struct has_teardown { + private: + template static auto Test(U*) -> typename fixture_detect().teardown())>::type; + template static int Test(...); + public: + static const bool value = sizeof(Test(0)) == sizeof(char); + }; + +#endif + template struct call_setup { template void operator()(U& u) { } }; @@ -76,19 +105,18 @@ namespace fixture_details { template <> struct call_teardown { template void operator()(U& u) { u.teardown(); } }; +} - //! Calls the fixture "setup" if detected by the compiler, otherwise does nothing. - template - void setup_conditional(U& u) { - return call_setup::value>()(u); - } - - //! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing. - template - void teardown_conditional(U& u) { - return call_teardown::value>()(u); - } +//! Calls the fixture "setup" if detected by the compiler, otherwise does nothing. +template +void setup_conditional(U& u) { + return impl_fixture::call_setup::value>()(u); +} +//! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing. +template +void teardown_conditional(U& u) { + return impl_fixture::call_teardown::value>()(u); } @@ -104,8 +132,8 @@ public: private: // Fixture interface - virtual void setup() { m_inst.reset( new F( m_arg ) ); fixture_details::setup_conditional(*m_inst); } - virtual void teardown() { fixture_details::teardown_conditional(*m_inst); 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 m_inst; @@ -122,8 +150,8 @@ public: private: // Fixture interface - virtual void setup() { m_inst.reset( new F ); fixture_details::setup_conditional(*m_inst); } - virtual void teardown() { fixture_details::teardown_conditional(*m_inst); 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 m_inst; diff --git a/include/boost/test/tree/global_fixture.hpp b/include/boost/test/tree/global_fixture.hpp index 38ab146f..7c96d34e 100644 --- a/include/boost/test/tree/global_fixture.hpp +++ b/include/boost/test/tree/global_fixture.hpp @@ -96,13 +96,13 @@ struct global_fixture_impl : public global_fixture { // test fixture interface virtual void setup() { m_fixture = new F; - fixture_details::setup_conditional(*m_fixture); + setup_conditional(*m_fixture); } // test fixture interface virtual void teardown() { if(m_fixture) { - fixture_details::teardown_conditional(*m_fixture); + teardown_conditional(*m_fixture); } delete m_fixture; m_fixture = 0; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1828dd2e..a1aba4aa 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -158,6 +158,7 @@ test-suite "writing-test-ts" [ boost.test-self-test run : writing-test-ts : nullptr-support-test : : : : : : [ requires cxx11_nullptr ] ] [ boost.test-self-test run : writing-test-ts : user-defined-types-logging-customization-points ] [ boost.test-self-test run : writing-test-ts : test-fixture-detect-setup-teardown ] + [ boost.test-self-test run : writing-test-ts : test-fixture-detect-setup-teardown-cpp11 : : : : : : [ requires cxx11_decltype cxx11_trailing_result_types ] ] ; #_________________________________________________________________________________________________# diff --git a/test/writing-test-ts/test-fixture-detect-setup-teardown-cpp11.cpp b/test/writing-test-ts/test-fixture-detect-setup-teardown-cpp11.cpp new file mode 100644 index 00000000..9c5f7b52 --- /dev/null +++ b/test/writing-test-ts/test-fixture-detect-setup-teardown-cpp11.cpp @@ -0,0 +1,68 @@ +// (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. + +// checks issue https://svn.boost.org/trac/boost/ticket/5563 in particular +// the ability of the framework to detect new fixture signatures. + +#define BOOST_TEST_MODULE test_fixture_detect_setup_teardown_cpp11 +#include +#include +#include +#include + +using namespace boost::unit_test; + +class fixture_without { +public: + fixture_without() {} + ~fixture_without() {} +}; + +class fixture_with { +public: + fixture_with() {} + void setup() {} + void teardown() {} + ~fixture_with() {} +}; + +class fixture_with_child : public fixture_with { +public: + fixture_with_child() {} + ~fixture_with_child() {} +}; + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect ) +{ + BOOST_CHECK(!impl_fixture::has_setup::value); + BOOST_CHECK(!impl_fixture::has_setup::value); + + fixture_without obj; + setup_conditional(obj); + teardown_conditional(obj); +} + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both ) +{ + BOOST_CHECK(impl_fixture::has_setup::value); + BOOST_CHECK(impl_fixture::has_setup::value); + + fixture_with obj; + setup_conditional(obj); + teardown_conditional(obj); +} + +BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both_from_child ) +{ + // should detect this with the C++11/declspec approach + BOOST_CHECK(impl_fixture::has_setup::value); + BOOST_CHECK(impl_fixture::has_setup::value); + + fixture_with_child obj; + setup_conditional(obj); + teardown_conditional(obj); +} diff --git a/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp b/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp index f7778dd5..d475cb27 100644 --- a/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp +++ b/test/writing-test-ts/test-fixture-detect-setup-teardown.cpp @@ -5,18 +5,14 @@ // See http://www.boost.org/libs/test for the library home page. -// checks issue https://svn.boost.org/trac/boost/ticket/5563 - -// we need the included version to be able to access the current framework state -// through boost::unit_test::framework::impl::s_frk_state() +// checks issue https://svn.boost.org/trac/boost/ticket/5563 in particular +// the ability of the framework to detect new fixture signatures. #define BOOST_TEST_MODULE test_fixture_detect_setup_teardown #include #include -#include #include #include -#include using namespace boost::unit_test; @@ -42,31 +38,35 @@ public: BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect ) { - BOOST_CHECK(!fixture_details::has_setup::value); - BOOST_CHECK(!fixture_details::has_setup::value); + BOOST_CHECK(!impl_fixture::has_setup::value); + BOOST_CHECK(!impl_fixture::has_setup::value); fixture_without obj; - fixture_details::setup_conditional(obj); - fixture_details::teardown_conditional(obj); + setup_conditional(obj); + teardown_conditional(obj); } BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both ) { - BOOST_CHECK(fixture_details::has_setup::value); - BOOST_CHECK(fixture_details::has_setup::value); + BOOST_CHECK(impl_fixture::has_setup::value); + BOOST_CHECK(impl_fixture::has_setup::value); fixture_with obj; - fixture_details::setup_conditional(obj); - fixture_details::teardown_conditional(obj); + setup_conditional(obj); + teardown_conditional(obj); } +#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + BOOST_AUTO_TEST_CASE( fixture_setup_teardown_detect_both_from_child ) { // cannot detect this with the C++03 approach - BOOST_CHECK(!fixture_details::has_setup::value); - BOOST_CHECK(!fixture_details::has_setup::value); + BOOST_CHECK(!impl_fixture::has_setup::value); + BOOST_CHECK(!impl_fixture::has_setup::value); fixture_with_child obj; - fixture_details::setup_conditional(obj); - fixture_details::teardown_conditional(obj); + setup_conditional(obj); + teardown_conditional(obj); } + +#endif From 8710eb8277b5dea585551b0012b5f9bddc535e01 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Tue, 20 Jun 2017 02:34:29 +0200 Subject: [PATCH 3/8] Fixture setup/teardown now applied to BOOST_FIXTURE_TEST_CASE familly of macros --- include/boost/test/unit_test_suite.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/test/unit_test_suite.hpp b/include/boost/test/unit_test_suite.hpp index 1247b681..49f6926a 100644 --- a/include/boost/test/unit_test_suite.hpp +++ b/include/boost/test/unit_test_suite.hpp @@ -144,10 +144,11 @@ struct test_name : public F { void test_method(); }; \ static void BOOST_AUTO_TC_INVOKER( test_name )() \ { \ BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry."); \ - test_name t; \ + test_name 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); \ } \ \ struct BOOST_AUTO_TC_UNIQUE_ID( test_name ) {}; \ @@ -230,10 +231,11 @@ struct BOOST_AUTO_TC_INVOKER( test_name ) { \ static void run( boost::type* = 0 ) \ { \ BOOST_TEST_CHECKPOINT('"' << #test_name <<"\" fixture entry."); \ - test_name t; \ + test_name 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); \ } \ }; \ \ From 5757d9cd164eade4dd9d202d155ce0b0205b11e0 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Thu, 22 Jun 2017 09:03:24 +0200 Subject: [PATCH 4/8] Fixing logging issues for JUnit with global fixtures - considering skipped tests: a skipped test is not considered as an error, especially when there was no logged information - removing CR/LF from TU names - updating the JUnit output - additional refactoring of junit --- .../boost/test/impl/junit_log_formatter.ipp | 238 +++++++++++------- .../log-formatter-test.pattern | 46 +--- 2 files changed, 162 insertions(+), 122 deletions(-) diff --git a/include/boost/test/impl/junit_log_formatter.ipp b/include/boost/test/impl/junit_log_formatter.ipp index dd528bc9..2dd17309 100644 --- a/include/boost/test/impl/junit_log_formatter.ipp +++ b/include/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( "\\/" ); @@ -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::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,18 +179,18 @@ public: } }; - std::list build_skipping_chain(test_case const & tc) const + std::list 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 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"); + out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu.full_name()) + "'\n"); if(m_map_test.count(id) > 0) { // junit has seen the reason: this is enough for constructing the chain @@ -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 << "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 << "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 skipping_decision_chain = build_skipping_chain(*tc); - for(std::list::const_iterator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end()); + std::list 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::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 << "'"; + 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(tc->p_file_name) << std::endl - << "- line: " << tc->p_line_num << std::endl - ; + 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::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 << "" << 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 << "" << 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 << "" << std::endl; + // unique test suite, without s, nesting not supported in CI + if( m_ts.p_id == ts.p_id ) { + m_stream << "" << std::endl; - m_stream << "" << std::endl; - std::ostringstream o; - o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; - m_stream << "" << std::endl; + if(m_display_build_info) + { + m_stream << "" << std::endl; + m_stream << "" << 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 ) + if( m_ts.p_id == ts.p_id ) { + write_testcase_system_out(runner_log, 0, false); + write_testcase_system_err(runner_log, 0, 0); + + m_stream << ""; return; - - write_testcase_system_out(runner_log, 0, false, 0); - write_testcase_system_err(runner_log, 0, 0); - - m_stream << ""; + } } private: diff --git a/test/baseline-outputs/log-formatter-test.pattern b/test/baseline-outputs/log-formatter-test.pattern index ff4b977c..5f5b2302 100644 --- a/test/baseline-outputs/log-formatter-test.pattern +++ b/test/baseline-outputs/log-formatter-test.pattern @@ -7,14 +7,14 @@ xxx/log-formatter-test.cpp:210: Leaving test case "good_foo" xxx/log-formatter-test.cpp:209: Leaving test suite "1 test cases inside" * 2-format ******************************************************************* -ZZZ +ZZZ * 3-format ******************************************************************* @@ -82,7 +82,6 @@ INFO: ]]> @@ -116,7 +115,6 @@ ASSERTION FAILURE: ]]> @@ -132,7 +130,7 @@ xxx/log-formatter-test.cpp:216: Leaving test case "almost_good_foo" xxx/log-formatter-test.cpp:215: Leaving test suite "1 almost good test case inside" * 2-format ******************************************************************* -3 is not satisfied [2 <= 3]]]>ZZZ +3 is not satisfied [2 <= 3]]]>ZZZ * 3-format ******************************************************************* @@ -144,7 +142,7 @@ xxx/log-formatter-test.cpp:215: Leaving test suite "1 almost good test case insi MESSAGE: - file : boost.test framework -- line : 206 +- line : 212 - message: Test case 1 almost good test case inside/almost_good_foo did not check any assertions ]]> @@ -175,14 +173,14 @@ xxx/log-formatter-test.cpp:220: Leaving test case "bad_foo" xxx/log-formatter-test.cpp:218: Leaving test suite "2 test cases inside" * 2-format ******************************************************************* -ZZZZZZ +ZZZZZZ * 3-format ******************************************************************* @@ -223,7 +221,6 @@ INFO: ]]> @@ -259,7 +256,6 @@ ASSERTION FAILURE: ]]> @@ -327,7 +323,6 @@ INFO: ]]> @@ -344,7 +339,6 @@ ASSERTION FAILURE: ]]> @@ -384,7 +378,6 @@ ASSERTION FAILURE: ]]> @@ -401,7 +394,6 @@ ASSERTION FAILURE: ]]> @@ -494,7 +486,6 @@ INFO: ]]> @@ -511,7 +502,6 @@ ASSERTION FAILURE: ]]> @@ -547,7 +537,6 @@ CONTEXT: - 'exception context should be shown' ]]> @@ -588,7 +577,6 @@ INFO: ]]> @@ -622,7 +610,6 @@ ASSERTION FAILURE: ]]> @@ -639,7 +626,6 @@ ASSERTION FAILURE: ]]> @@ -675,7 +661,6 @@ CONTEXT: - 'exception context should be shown' ]]> @@ -705,7 +690,6 @@ ASSERTION FAILURE: ]]> @@ -785,14 +769,14 @@ xxx/log-formatter-test.cpp:222: Test suite "Fake Test Suite Hierarchy/3 test cas xxx/log-formatter-test.cpp:236: Leaving test suite "Fake Test Suite Hierarchy" * 2-format ******************************************************************* -ZZZZZZZZZZZZZZZZZZZZZZZZ +ZZZZZZZZZZZZZZZZZZZZZZZZ * 3-format ******************************************************************* @@ -833,7 +817,6 @@ INFO: ]]> @@ -841,7 +824,7 @@ INFO: @@ -882,7 +865,6 @@ INFO: ]]> @@ -944,7 +926,6 @@ INFO: ]]> @@ -961,7 +942,6 @@ ASSERTION FAILURE: ]]> @@ -997,7 +977,6 @@ CONTEXT: - 'exception context should be shown' ]]> @@ -1038,7 +1017,6 @@ INFO: ]]> @@ -1074,7 +1052,6 @@ ASSERTION FAILURE: ]]> @@ -1106,7 +1083,6 @@ ASSERTION FAILURE: ]]> @@ -1157,7 +1133,6 @@ ASSERTION FAILURE: ]]> @@ -1174,7 +1149,6 @@ ASSERTION FAILURE: ]]> @@ -1210,7 +1184,6 @@ CONTEXT: - 'exception context should be shown' ]]> @@ -1240,7 +1213,6 @@ ASSERTION FAILURE: ]]> From e1b211f2544328ae015237c706e3f1c2bbd05ef0 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Thu, 22 Jun 2017 09:22:02 +0200 Subject: [PATCH 5/8] Documentation update for the new macros - BOOST_TEST_GLOBAL_FIXTURE explained - BOOST_TEST_GLOBAL_INITIALIZATION explained - changed the examples, deprecating BOOST_GLOBAL_FIXTURE - in the logger part, introduced the fact that BOOST_TEST_GLOBAL_INITIALIZATION should be used and no assertion is supported in this case --- doc/adv_scenarios/link_reference.qbk | 24 +++- doc/examples/example20.run.cpp | 2 +- doc/examples/example50.output | 4 +- doc/examples/example50.run-fail.cpp | 20 +-- doc/examples/example52.output | 4 +- doc/examples/example52.run-fail.cpp | 8 +- doc/examples/fixture_04.output | 13 ++ doc/examples/fixture_04.run-fail.cpp | 44 ++++++ doc/test.qbk | 4 +- doc/test_organization/fixtures.qbk | 143 ++++++++++++-------- doc/test_organization/test_suites.qbk | 32 ++--- doc/test_organization/testorg_reference.qbk | 37 +++-- doc/test_organization/testorg_summary.qbk | 2 +- doc/test_output/logger_api.qbk | 9 +- example/unit_test_example_09_1.cpp | 10 +- example/unit_test_example_09_2.cpp | 10 +- include/boost/test/unit_test_suite.hpp | 11 +- 17 files changed, 252 insertions(+), 125 deletions(-) create mode 100644 doc/examples/fixture_04.output create mode 100644 doc/examples/fixture_04.run-fail.cpp diff --git a/doc/adv_scenarios/link_reference.qbk b/doc/adv_scenarios/link_reference.qbk index 47c9c29f..94885fff 100644 --- a/doc/adv_scenarios/link_reference.qbk +++ b/doc/adv_scenarios/link_reference.qbk @@ -8,6 +8,7 @@ [section:link_references Build scenarios and behaviors] +[/-----------------------------------------------------------------] [section:link_boost_test_main_macro `BOOST_TEST_MAIN`] When defined, this macro creates a stub for the test module initialization (the main entry part). This @@ -25,6 +26,7 @@ macro also expands properly into a `main` function in case the shared library va [endsect] +[/-----------------------------------------------------------------] [section:link_boost_test_module_macro `BOOST_TEST_MODULE`] Serves the same purpose as the macro __BOOST_TEST_MAIN__ but, in addition, defines the name of the master test suite. @@ -39,21 +41,24 @@ An example may be found [link ref_BOOST_TEST_MODULE here]. [endsect] - +[/-----------------------------------------------------------------] [section:link_boost_test_alternative_init_macro `BOOST_TEST_ALTERNATIVE_INIT_API`] [endsect] +[/-----------------------------------------------------------------] [section:link_boost_test_no_lib `BOOST_TEST_NO_LIB`] Define this flag to prevent auto-linking. [note The same flag is used for the __UTF__ and the __PEM__ components.] [endsect] +[/-----------------------------------------------------------------] [section:link_boost_test_dyn_link `BOOST_TEST_DYN_LINK`] Define this flag to link against the __UTF__ shared library. [note The same flag is used for the __UTF__ and the __PEM__ components.] [endsect] +[/-----------------------------------------------------------------] [section:link_boost_test_no_main `BOOST_TEST_NO_MAIN`] Prevents the auto generation of the test module initialization functions. This macro is particularly relevant for manually registered tests in conjunction with dynamic variant of the __UTF__. When defined, a `main` function @@ -84,6 +89,23 @@ int main(int argc, char* argv[]) `` [endsect] +[/-----------------------------------------------------------------] +[section:link_boost_test_global_configuration `BOOST_TEST_GLOBAL_CONFIGURATION`] +Declares a class that will be constructed during the initialization of the test framework, and destructed afterwards. +The framework will not call any other member function than the constructor and destructor. +In particular the constructor and destructor will be called prior and after to the [link boost_test.tests_organization.fixtures.global global fixtures] +setup and teardown. + +This facility is provided to perform additional configuration, in particular programmatic configuration +of the loggers and reporters. See [link boost_test.test_output.logging_api this section] for more details. + +[warning No logging or any other call to the framework assertion is allowed in the constructor and destructor, as its purpose is + to set-up the loggers/reporters, and the assertions are calling the logging/reporting facility. + Any such assertion during the execution of the will result in the abortion of the test module .] + +[endsect] + +[/-----------------------------------------------------------------] [section:config_disable_alt_stack `BOOST_TEST_DISABLE_ALT_STACK`] Disables the support of the alternative stack. diff --git a/doc/examples/example20.run.cpp b/doc/examples/example20.run.cpp index 0ef81670..be9b1fdf 100644 --- a/doc/examples/example20.run.cpp +++ b/doc/examples/example20.run.cpp @@ -19,7 +19,7 @@ struct MyConfig { //____________________________________________________________________________// -BOOST_GLOBAL_FIXTURE( MyConfig ); +BOOST_TEST_GLOBAL_FIXTURE( MyConfig ); BOOST_AUTO_TEST_CASE( test_case ) { diff --git a/doc/examples/example50.output b/doc/examples/example50.output index 51aa1985..91275646 100644 --- a/doc/examples/example50.output +++ b/doc/examples/example50.output @@ -4,5 +4,5 @@ *** 1 failures is detected in test suite "example" > cat example.log Running 1 test case... -test.cpp(20): error in "test_case": check false failed -//] \ No newline at end of file +test.cpp(26): error in "test_case": check false failed +//] diff --git a/doc/examples/example50.run-fail.cpp b/doc/examples/example50.run-fail.cpp index 4831621b..f1382e99 100644 --- a/doc/examples/example50.run-fail.cpp +++ b/doc/examples/example50.run-fail.cpp @@ -10,25 +10,19 @@ #include #include -struct MyConfig -{ - MyConfig() : test_log( "example.log" ) - { - boost::unit_test::unit_test_log.set_stream( test_log ); +struct MyConfig { + MyConfig() : test_log( "example.log" ) { + boost::unit_test::unit_test_log.set_stream( test_log ); } - ~MyConfig() - { - boost::unit_test::unit_test_log.set_stream( std::cout ); + ~MyConfig() { + boost::unit_test::unit_test_log.set_stream( std::cout ); } - std::ofstream test_log; }; -BOOST_GLOBAL_FIXTURE( MyConfig ); +BOOST_TEST_GLOBAL_CONFIGURATION( MyConfig ); -BOOST_AUTO_TEST_CASE( test_case ) -{ +BOOST_AUTO_TEST_CASE( test_case ) { BOOST_TEST( false ); } - //] diff --git a/doc/examples/example52.output b/doc/examples/example52.output index 409f16aa..b8ed1210 100644 --- a/doc/examples/example52.output +++ b/doc/examples/example52.output @@ -1,4 +1,4 @@ //[example_output > example --report_level=no -check false failed -//] \ No newline at end of file +check false failed +//] diff --git a/doc/examples/example52.run-fail.cpp b/doc/examples/example52.run-fail.cpp index eb282384..9700327d 100644 --- a/doc/examples/example52.run-fail.cpp +++ b/doc/examples/example52.run-fail.cpp @@ -11,17 +11,15 @@ using namespace boost::unit_test; struct MyConfig { - MyConfig() - { + MyConfig() { unit_test_log.set_format( OF_XML ); } ~MyConfig() {} }; -BOOST_GLOBAL_FIXTURE( MyConfig ); +BOOST_TEST_GLOBAL_CONFIGURATION( MyConfig ); -BOOST_AUTO_TEST_CASE( test_case0 ) -{ +BOOST_AUTO_TEST_CASE( test_case0 ) { BOOST_TEST( false ); } //] diff --git a/doc/examples/fixture_04.output b/doc/examples/fixture_04.output new file mode 100644 index 00000000..9f332273 --- /dev/null +++ b/doc/examples/fixture_04.output @@ -0,0 +1,13 @@ +//[example_output +> fixture_04 --log_level=message +Running 2 test cases... +ctor fixture i=0 +setup fixture i=0 +running test_case1 +running test_case2 +./fixture_04.run-fail.cpp:42: error: in "test_case2": check MyGlobalFixture::i == 3 has failed [1 != 3] +teardown fixture i=1 +dtor fixture i=3 + +*** 1 failure is detected in the test module "fixture_04" +//] diff --git a/doc/examples/fixture_04.run-fail.cpp b/doc/examples/fixture_04.run-fail.cpp new file mode 100644 index 00000000..c41d3f48 --- /dev/null +++ b/doc/examples/fixture_04.run-fail.cpp @@ -0,0 +1,44 @@ +// (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. + +//[example_code +#define BOOST_TEST_MODULE fixture_04 +#include + +struct MyGlobalFixture { + MyGlobalFixture() { + BOOST_TEST_MESSAGE( "ctor fixture i=" << i ); + } + void setup() { + BOOST_TEST_MESSAGE( "setup fixture i=" << i ); + i++; + } + void teardown() { + BOOST_TEST_MESSAGE( "teardown fixture i=" << i ); + i += 2; + } + ~MyGlobalFixture() { + BOOST_TEST_MESSAGE( "dtor fixture i=" << i ); + } + static int i; +}; +int MyGlobalFixture::i = 0; + +BOOST_TEST_GLOBAL_FIXTURE( MyGlobalFixture ); + +BOOST_AUTO_TEST_CASE(test_case1) +{ + BOOST_TEST_MESSAGE("running test_case1"); + BOOST_TEST(MyGlobalFixture::i == 1); +} + +BOOST_AUTO_TEST_CASE(test_case2) +{ + BOOST_TEST_MESSAGE("running test_case2"); + BOOST_TEST(MyGlobalFixture::i == 3); +} +//] diff --git a/doc/test.qbk b/doc/test.qbk index 54083abe..6b998f48 100644 --- a/doc/test.qbk +++ b/doc/test.qbk @@ -45,6 +45,7 @@ [def __BOOST_TEST_NO_LIB__ [link boost_test.utf_reference.link_references.link_boost_test_no_lib `BOOST_TEST_NO_LIB`]] [def __BOOST_TEST_NO_MAIN__ [link boost_test.utf_reference.link_references.link_boost_test_no_main `BOOST_TEST_NO_MAIN`]] [def __BOOST_TEST_MODULE__ [link boost_test.utf_reference.link_references.link_boost_test_module_macro `BOOST_TEST_MODULE`]] +[def __BOOST_TEST_GLOBAL_CONFIGURATION__ [link boost_test.utf_reference.link_references.link_boost_test_global_configuration `BOOST_TEST_GLOBAL_CONFIGURATION`]] [def __BOOST_TEST_CHECKPOINT__ [link boost_test.utf_reference.testout_reference.test_output_macro_checkpoint `BOOST_TEST_CHECKPOINT`]] [def __BOOST_TEST_PASSPOINT__ [link boost_test.utf_reference.testout_reference.test_output_macro_passpoint `BOOST_TEST_PASSPOINT`]] @@ -116,7 +117,8 @@ [/ fixtures] [def __BOOST_FIXTURE_TEST_CASE__ [link boost_test.utf_reference.test_org_reference.test_org_boost_test_case_fixture `BOOST_FIXTURE_TEST_CASE`]] [def __BOOST_FIXTURE_TEST_SUITE__ [link boost_test.utf_reference.test_org_reference.test_org_boost_test_suite_fixture `BOOST_FIXTURE_TEST_SUITE`]] -[def __BOOST_GLOBAL_FIXTURE__ [link boost_test.utf_reference.test_org_reference.test_org_boost_global_fixture `BOOST_GLOBAL_FIXTURE`]] +[def __BOOST_GLOBAL_FIXTURE__ [link boost_test.utf_reference.test_org_reference.test_org_boost_global_fixture `BOOST_GLOBAL_FIXTURE`]] +[def __BOOST_TEST_GLOBAL_FIXTURE__ [link boost_test.utf_reference.test_org_reference.test_org_boost_test_global_fixture `BOOST_TEST_GLOBAL_FIXTURE`]] [/ log] [def __BOOST_TEST_LOG_LEVEL__ [link boost_test.utf_reference.rt_param_reference.log_level `BOOST_TEST_LOG_LEVEL`]] [/ this is an environment variable] diff --git a/doc/test_organization/fixtures.qbk b/doc/test_organization/fixtures.qbk index 53b87c77..274227e7 100644 --- a/doc/test_organization/fixtures.qbk +++ b/doc/test_organization/fixtures.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2003 Boost.Test contributors + / Copyright (c) 2003 Boost.Test contributors / / 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) @@ -8,7 +8,7 @@ [section:fixtures Fixtures] In general terms a test fixture or test context is the collection of one or more of the following items, required to perform the test: - + * preconditions * particular states of tested units * necessary cleanup procedures @@ -22,19 +22,19 @@ has become even more popular. Single XP adopted test modules may contain hundred many requiring very similar test setup/cleanup. This is the problem that the test fixture is designed to solve. In practice a test fixture usually is a combination of `setup` and `teardown` functions, associated with test case. -The former serves the purposes of test setup. The later is dedicated to the cleanup tasks. Ideally we'd like for a -test module author to be able to define variables used in fixtures on the stack and, at the same time, to refer to +The former serves the purposes of test setup. The later is dedicated to the cleanup tasks. Ideally we'd like for a +test module author to be able to define variables used in fixtures on the stack and, at the same time, to refer to them directly in a test case. - + It's important to understand that C++ provides a way to implement a straightforward test fixture solution -that almost satisfies our requirements without any extra support from the test framework. Here is how simple test +that almost satisfies our requirements without any extra support from the test framework. Here is how simple test module with such a fixture may look like: `` struct MyFixture { MyFixture() { i = new int; *i = 0 } ~MyFixture() { delete i; } - + int* i; }; @@ -51,7 +51,6 @@ __BOOST_AUTO_TEST_CASE__( test_case2 ) } `` - This is a generic solution that can be used to implement any kind of shared setup or cleanup procedure. Still there are several more or less minor practical issues with this pure C++ based fixtures solution: @@ -60,18 +59,18 @@ there are several more or less minor practical issues with this pure C++ based f * There is no place to execute a ['global] fixture, which performs ['global] setup/cleanup procedures before and after testing. -The __UTF__ lets you define a fixture according to [link boost_test.tests_organization.fixtures.models several generic interfaces], +The __UTF__ lets you define a fixture according to [link boost_test.tests_organization.fixtures.models several generic interfaces], and thus helps you with following tasks: -* define shared setup/teardown procedures for a single or group of test cases -* define setup/teardown procedures which are performed once per test suite -* define global setup/teardown procedures which are performed once per test module +* define shared setup/teardown procedures for a single or group of test cases +* define setup/teardown procedures which are performed once per test suite +* define [link boost_test.tests_organization.fixtures.global global setup/teardown] procedures which are performed once per test module [/ ###################################################################################### ] [section:models Fixture models] Several fixture interfaces are supported by the __UTF__. The choice of the interface depends -mainly on the usage of the fixture. +mainly on the usage of the fixture. [h3 Fixture class model] The __UTF__ defines the generic fixture class model as follows: @@ -84,33 +83,57 @@ struct { `` In other words a fixture is expected to be implemented as a class where the class constructor serves as a `setup` -method and class destructor serves as `teardown` method. The __UTF__ opted to avoid explicit names in fixture -interface for `setup` and `teardown` methods, since it is considered most natural in C++ for tasks similar to RAII and -coincides with the pure C++ solution discussed above. +method and class destructor serves as `teardown` method. + +The class model above has some limitations though: + +* it is not possible to have exceptions in the teardown function, especially any test assertions that aborts the + current test case is not possible (as those use exceptions) +* it is sometimes more natural to use the constructor/destructor to perform the necessary resource allocation/release + of the fixture, and that will be consumed in the test cases, and check for the proper state of the fixture in separate functions. + Those checks are the pre-conditions for the test case to run, and the post-conditions that should be met after the test case + has been running. + +This is why the __UTF__ also supports (Boost 1.65 on) optional `setup` and/or `teardown` functions as follow: + +`` +struct { + (); // ctor + ~(); // dtor + void setup(); // setup, optional + void teardown(); // teardown, optional +}; +`` + +[note As mentioned, the declaration/implementation of the `setup` and `teardown` are optional: + the __UTF__ will check the existence of those and will call them adequately. However in C++98, + it is not possible to detect those declaration in case those are inherited (it works fine for + compiler supporting `auto` and `decltype`). +] This model is expected from fixtures used with __BOOST_FIXTURE_TEST_CASE__ and __BOOST_FIXTURE_TEST_SUITE__. -[caution The above interface prevents you from reporting errors in the `teardown` procedure using an exception. It does make - sense though: if somehow more than one fixture is assigned to a test unit (e.g. using __decorator_fixture__ decorator), - you want all `teardown` procedures to run, even if some may experience problems. -] - [h3 Flexible models] -In addition to __BOOST_FIXTURE_TEST_CASE__ and __BOOST_FIXTURE_TEST_SUITE__ the __UTF__ allows to associate fixture with -test unit using the decorator __decorator_fixture__. This decorator supports additional models for declaring +In addition to __BOOST_FIXTURE_TEST_CASE__ and __BOOST_FIXTURE_TEST_SUITE__ the __UTF__ allows to associate fixture with +test unit using the decorator __decorator_fixture__. This decorator supports additional models for declaring the `setup` and `teardown`: * a fixture defined according to the fixture class model above -* a fixture defined according to the extended fixture class model, which allows for the fixture constructor to +* a fixture defined according to the extended fixture class model, which allows for the fixture constructor to takes one argument. For example: struct Fx { std::string s; - Fx(std::string s = "") : s(s) - { BOOST_TEST_MESSAGE("set up " << s); } - ~Fx() { BOOST_TEST_MESSAGE("tear down " << s); } + Fx(std::string s_ = "") : s(s_) + { BOOST_TEST_MESSAGE("ctor " << s); } + void setup() + { BOOST_TEST_MESSAGE("optional setup " << s); } + void setup() + { BOOST_TEST_MESSAGE("optional teardown " << s); } + ~Fx() + { BOOST_TEST_MESSAGE("dtor " << s); } }; * a fixture defined as a pair of free functions for the `setup` and `teardown` (latter optional) @@ -127,7 +150,7 @@ For complete example of test module which uses these models please check decorat [/ ###################################################################################### ] [section:case Test case fixture] A /test case fixture/ is a fixture consumed by a test case: the fixture `setup` is called before the test case executes, -and the fixture `teardown` is called after the test case finished its execution, independently from its execution state. +and the fixture `teardown` is called after the test case finished its execution, independently from its execution state. The __UTF__ provides several ways of defining fixtures for test-cases, each of which having their properties: @@ -140,30 +163,30 @@ The __UTF__ provides several ways of defining fixtures for test-cases, each of w The following two methods are available for declaring a fixture attached to one particular test case: * the use of the macro __BOOST_FIXTURE_TEST_CASE__ in place of __BOOST_AUTO_TEST_CASE__, which let access to the members of the fixture -* the use of the decorator __decorator_fixture__, which does not let access to the members but enables - the definition of several fixtures for one test case. +* the use of the decorator __decorator_fixture__, which does not let access to the members but enables + the definition of several fixtures for one test case. [/ ------------------------------------------------------------------------ ] [#test_case_fixture_macro][h4 Fixture with `BOOST_FIXTURE_TEST_CASE`] -`BOOST_FIXTURE_TEST_CASE` serves as a test case declaration with a fixture, and is meant be used in place of +`BOOST_FIXTURE_TEST_CASE` serves as a test case declaration with a fixture, and is meant be used in place of the test case declaration with __BOOST_AUTO_TEST_CASE__: `` BOOST_FIXTURE_TEST_CASE(test_case_name, fixture_name); `` -The only difference from the macro __BOOST_AUTO_TEST_CASE__ is the presence of an extra argument `fixture_name`. +The only difference from the macro __BOOST_AUTO_TEST_CASE__ is the presence of an extra argument `fixture_name`. The public and protected members of the fixture are directly accessible from the test case body. Only -one fixture can be attached to a test-case [footnote it is still possible to define a class inheriting from several +one fixture can be attached to a test-case [footnote it is still possible to define a class inheriting from several fixtures, that will act as a proxy fixture.]. [note You can't access private members of fixture, but then why would you make anything private?] [bt_example example18..Per test case fixture..run-fail] -In this example only `test_case1` and `test_case2` have fixture `F` assigned. -You still need to refer to the fixture name in every test case. [link test_case_fixture_subtree This] section +In this example only `test_case1` and `test_case2` have fixture `F` assigned. +You still need to refer to the fixture name in every test case. [link test_case_fixture_subtree This] section explains how a same fixture can be declared for a subtree under a test suite. [/ ------------------------------------------------------------------------ ] @@ -173,7 +196,7 @@ By using the decorator __decorator_fixture__, it is possible to: * attach several fixtures to a unique test case * use a flexible fixture interface (see [link boost_test.tests_organization.fixtures.models here]) -[note Using the decorator approach, it is not possible to access the members of the fixture (in case the fixture is implemented +[note Using the decorator approach, it is not possible to access the members of the fixture (in case the fixture is implemented as a class)] @@ -196,7 +219,7 @@ of the fixture, but also do not need to refer to the fixture name in test case d the same fixture automatically. [tip If necessary you can reset the fixture for a particular test case using the macro - __BOOST_FIXTURE_TEST_CASE__. Similarly you can reset the fixture for a particular sub + __BOOST_FIXTURE_TEST_CASE__. Similarly you can reset the fixture for a particular sub test suite using __BOOST_FIXTURE_TEST_SUITE__. ] @@ -207,19 +230,18 @@ the same fixture automatically. [bt_example fixture_02..Test suite level fixture..run] -[caution The fixture constructor and destructor is called for each test cases (the state of the +[caution The fixture constructor/setup and teardown/destructor is called for each test cases (the state of the fixture is not shared among the test cases).] - - [endsect] [/ per test case] [/ ###################################################################################### ] [section:per_test_suite_fixture Test suite entry/exit fixture] -It is possible to define a test suite entry/exit fixture, so that the `setup` function is called only once upon entering -the test suite, prior to running any of its test cases; and similarly the `teardown` function is also called only once -upon the test suite exit, after all the enclosed test cases have been run. This is facilitated by the +It is possible to define a test suite entry/exit fixture, so that the `setup` function is called only once upon entering +the test suite, prior to running any of its test cases. +Similarly the `teardown` function is also called only once +upon the test suite exit, after all the enclosed test cases have been run. This is facilitated by the /decorator/ __decorator_fixture__. [bt_example fixture_03..Test suite entry/exit fixture..run] @@ -233,38 +255,43 @@ In case of this fixture type, however, it is not possible to access any members [/ ###################################################################################### ] [section:global Global fixture] -Any global initialization that needs to be performed every time testing begins or a global cleanup that is to be -performed once testing is finished is called a global fixture. The __UTF__ global fixture design is based on the +Any global initialization that needs to be performed before any test begins, or a cleanup that is to be +performed after all tests are finished is called a /global fixture/. A global fixture is equivalent to a +[link boost_test.tests_organization.fixtures.per_test_suite_fixture test-suite +entry/exit] fixture (executed once), where in this case the test-suite is the +[link boost_test.tests_organization.test_suite.master_test_suite master test suite]. + +The __UTF__ global fixture design is based on the [link boost_test.tests_organization.fixtures.models generic test class fixture model]. The global fixture design allows any number of global fixtures to be defined in any test file that constitutes a test module. -Though some initialization can be implemented in the test module initialization function, there are several +Though some initialization can be implemented in the test module initialization function, there are several reasons to prefer the global fixture approach: -* There is no place for cleanup/`teardown` operations in the initialization function. -* Unlike the initialization function, the global fixture `setup` method invocation is guarded by the execution - monitor. That means that all uncaught errors that occur during initialization are properly reported. +* There is no place for `cleanup`/`teardown` operations in the initialization function. +* Unlike the initialization function, the global fixture construction, `setup` and `teardown` methods invocation are guarded by the + execution monitor. That means that all uncaught errors that occur during initialization are properly reported. * Any number of different global fixtures can be defined, which allows you to split initialization code by category. * The fixture allows you to place matching `setup`/`teardown` code in close vicinity in your test module code. -* If the whole test tree is constructed automatically the initialization function is empty and auto-generated by - the __UTF__. To introduce the initialization function can be more work than the use of a global fixture facility, +* If the whole test tree is constructed automatically, the initialization function is empty and auto-generated by + the __UTF__. Introducing the initialization function can be more work than using the global fixture facility, while global fixture is more to the point. * Since all fixtures follow the same generic model you can easily switch from local per test case fixtures to the global one. -* If you are using the interactive test runner (non-supplied yet) global test fixtures are applied to every run, - while an initialization function is executed only once during a test module startup (just make sure that - it's what you really want). -To define a global test module fixture you need to implement a class that matched generic fixture model and -passed it as an argument to the macro __BOOST_GLOBAL_FIXTURE__. +To define a global test module fixture you need: + +# to implement a class that matches the + [link boost_test.tests_organization.fixtures.models fixture model] +# and to pass the class as an argument to the macro __BOOST_TEST_GLOBAL_FIXTURE__. `` - BOOST_GLOBAL_FIXTURE(fixture_name); + BOOST_TEST_GLOBAL_FIXTURE( fixture_name ); `` The statement, that performs global fixture definition, has to reside at a test file scope. -[bt_example example20..Global fixture..run] +[bt_example fixture_04..Global fixture..run-fail] [endsect] [/section Global fixtures] diff --git a/doc/test_organization/test_suites.qbk b/doc/test_organization/test_suites.qbk index ef89fa8e..a44b0d51 100644 --- a/doc/test_organization/test_suites.qbk +++ b/doc/test_organization/test_suites.qbk @@ -1,13 +1,13 @@ [/ - / Copyright (c) 2003 Boost.Test contributors + / Copyright (c) 2003 Boost.Test contributors / / 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) /] [section:test_suite Test suite] -If you consider test cases as leaves on the test tree, the test suite can be considered as branch and the master -test suite as a root. Unlike real trees though, our tree in many cases consists only of leaves attached +If you consider test cases as leaves on the test tree, the test suite can be considered as branch and the /master +test suite/ as the /root/. Unlike real trees though, our tree in many cases consists only of leaves attached directly to the root. This is common for all test cases to reside directly in the master test suite. If you do want to construct a hierarchical test suite structure the __UTF__ provides both manual and automated test suite creation and registration facilities: @@ -15,20 +15,20 @@ test suite creation and registration facilities: # Test suite with automated registration # Manually registered test suite -In addition the __UTF__ presents a notion of the -[link boost_test.tests_organization.test_suite.master_test_suite Master Test Suite]. -The most important reason to learn about this component is that it provides an ability to access +In addition the __UTF__ presents a notion of the +[link boost_test.tests_organization.test_suite.master_test_suite Master Test Suite]. +The most important reason to learn about this component is that it provides an ability to access command line arguments supplied to a test module. [#ref_BOOST_AUTO_TEST_SUITE][h3 Automated registration] The solution the __UTF__ presents for automated test suite creation and registration is designed to facilitate -multiple points of definition, arbitrary test suites depth and smooth integration with automated test case creation -and registration. This facility should significantly simplify a test tree construction process in comparison with +multiple points of definition, arbitrary test suites depth and smooth integration with automated test case creation +and registration. This facility should significantly simplify a test tree construction process in comparison with manual explicit registration case. The implementation is based on the order of file scope variables definitions within a single compilation unit. -The semantic of this facility is very similar to the namespace feature of C++, including support for test suite +The semantic of this facility is very similar to the namespace feature of C++, including support for test suite extension. To start test suite use the macro __BOOST_AUTO_TEST_SUITE__. To end test suite use the macro __BOOST_AUTO_TEST_SUITE_END__. The same test suite can be restarted multiple times inside the same test file or in a different test files. In a result all test units will be part of the same test suite in a constructed test tree. @@ -57,9 +57,9 @@ you can see from the output both `test_case1` and `test_case2` reside in the sam [bt_example example53..Test suite extension using automated registration facility..run-fail] [h3 Test suites with manual registration] -To create a test suite manually you need to +To create a test suite manually you need to -# create an instance of [classref boost::unit_test::test_suite] class, +# create an instance of [classref boost::unit_test::test_suite] class, # register it in test tree, and # populate it with test cases (or lower level test suites). @@ -87,10 +87,10 @@ default no errors are expected. The third optional parameter - `timeout` - defines the timeout value for the test unit. As of now the __UTF__ isn't able to set a timeout for the test suite execution, so this parameter makes sense only for test case registration. By default no timeout is set. See the method -[memberref boost::execution_monitor::execute] for more details about the timeout value. [warning is the reference +[memberref boost::execution_monitor::execute] for more details about the timeout value. [warning is the reference good? It looks to me that [memberref boost::unit_test::test_suite::add] is better] -To register group of test units in one function call, the [classref boost::unit_test::test_suite `test_suite`] class provides another +To register group of test units in one function call, the [classref boost::unit_test::test_suite `test_suite`] class provides another [memberref boost::unit_test::test_suite::add `add`] interface covered in the advanced section of this documentation. @@ -123,8 +123,8 @@ The example below creates a test tree, which can be represented by the following [section:master_test_suite Master Test Suite] -As defined in introduction section the master test suite is a root node of a test tree. Each test module built -with the __UTF__ always has the master test suite defined. The __UTF__ maintain the master test suite instance +As defined in introduction section the master test suite is the *root* node of the test tree. Each test module built +with the __UTF__ always has the (unique) master test suite defined. The __UTF__ maintain the master test suite instance internally. All other test units are registered as direct or indirect children of the master test suite. `` @@ -192,7 +192,7 @@ macro value becomes the name of the master test suite. The name may include spac [bt_example example15..Naming master test suite explicitly in the test module initialization function..run] -Without the __BOOST_TEST_MAIN__ and the __BOOST_TEST_MODULE__ flags defined, the test module initialization +Without the __BOOST_TEST_MAIN__ and the __BOOST_TEST_MODULE__ flags defined, the test module initialization function has to be manually implemented. The master test suite name can be reset at any point within this function. [endsect] [/ command line interface] diff --git a/doc/test_organization/testorg_reference.qbk b/doc/test_organization/testorg_reference.qbk index d2a8b4dd..df841b7b 100644 --- a/doc/test_organization/testorg_reference.qbk +++ b/doc/test_organization/testorg_reference.qbk @@ -166,13 +166,20 @@ See [link boost_test.tests_organization.fixtures.case here] for more details. [/-----------------------------------------------------------------] [section:test_org_boost_global_fixture `BOOST_GLOBAL_FIXTURE`] -Declares and registers a global fixture. The global fixture is called before any of the test case in the test tree is executed. +This macro is deprecated in favor of __BOOST_TEST_GLOBAL_FIXTURE__ and __BOOST_TEST_GLOBAL_CONFIGURATION__. +[endsect] [/section:test_org_boost_test_case_fixture] + +[/-----------------------------------------------------------------] +[section:test_org_boost_test_global_fixture `BOOST_TEST_GLOBAL_FIXTURE`] +Declares and registers a global fixture. The global fixture acts exactly as a suite fixture attached to the +[link boost_test.tests_organization.test_suite.master_test_suite master test suite], +and is called before any of the test case in the test tree is executed. + The class implementing the fixture should have the appropriate [link boost_test.tests_organization.fixtures.models interface]. As any fixture, it is possible to have test assertions in the global fixture. See [link boost_test.tests_organization.fixtures.global here] for more details. -[endsect] [/section:test_org_boost_test_case_fixture] - +[endsect] [/section:test_org_boost_test_global_fixture] @@ -257,12 +264,24 @@ template Decorator `fixture` specifies a pair of functions (like `set_up` and `tear_down`) to be called before and after the corresponding test unit. At the suite level the `set_up` function is called once -- before the suite execution starts -and `tear_down` function is called once -- after the suite execution ends. It comes in three forms. First expects two -functions for set-up and tear-down (the second one can be skipped). The second expects a `DefaultConstructible` class. -Its default constructor will be used as set-up function and its destructor as a tear-down function. Third requires a -class with one-argument public constructor. Argument `arg` is forwarded to the constructor and this is the set-up -function, its destructor is the tear-down function. There is no way to get access to the members of these fixtures from -within the test case or test suite. +-- and `tear_down` function is called once -- after the suite execution ends. It comes in three forms. + +First expects two +functions for set-up and tear-down (the second one can be skipped). + +The second expects a `DefaultConstructible` class. +Its default constructor will be used as set-up function and its destructor as a tear-down function. + +The third form requires a +class with one-argument public constructor. Argument `arg` is forwarded to the constructor. + +For the second and third form, the framework detects if there is a `setup` and/or `teardown` function implemented in the class, +with the same declaration as described in the [link boost_test.tests_organization.fixtures.models fixture model]. +If those member function are declared, they will be called right after construction and just +before destruction respectively. + +[note There is no way to get access to the members of these fixtures from +within the test case or test suite.] [bt_example decorator_12..decorator fixture..run] diff --git a/doc/test_organization/testorg_summary.qbk b/doc/test_organization/testorg_summary.qbk index ae7935b5..c6b3e878 100644 --- a/doc/test_organization/testorg_summary.qbk +++ b/doc/test_organization/testorg_summary.qbk @@ -88,7 +88,7 @@ [Declares a fixture for a test suite (the setup/teardown is called for each test of the test suite)] ] [ - [__BOOST_GLOBAL_FIXTURE__] + [__BOOST_TEST_GLOBAL_FIXTURE__] [Declares a fixture globally to the test module] ] diff --git a/doc/test_output/logger_api.qbk b/doc/test_output/logger_api.qbk index 3b615ecf..4aef20d5 100644 --- a/doc/test_output/logger_api.qbk +++ b/doc/test_output/logger_api.qbk @@ -9,10 +9,15 @@ While many test log configuration tasks can be performed at runtime using predefined framework parameters, the __UTF__ provides a compile time interface as well. The interface gives you full power over what, where and how to -log. The interface is provided by singleton class [classref boost::unit_test::unit_test_log_t] and is +log. The interface of the logger is provided by singleton class [classref boost::unit_test::unit_test_log_t] and is accessible through local file scope reference to single instance of this class -``boost::unit_test::unit_test_log`` +`` +boost::unit_test::unit_test_log +`` + +In order to install customization of the logger, the __UTF__ provides the __BOOST_TEST_GLOBAL_CONFIGURATION__ facility +that acts in a similar fashion to a global fixture. [/ ------------------------------------------------------------------------------------------------ ] diff --git a/example/unit_test_example_09_1.cpp b/example/unit_test_example_09_1.cpp index 84b112e2..62357703 100644 --- a/example/unit_test_example_09_1.cpp +++ b/example/unit_test_example_09_1.cpp @@ -1,6 +1,6 @@ // (C) Copyright Gennadiy Rozental 2005-2014. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -14,13 +14,13 @@ //____________________________________________________________________________// -struct MyConfig { - MyConfig() { std::cout << "global setup part1\n"; } - ~MyConfig() { std::cout << "global teardown part1\n"; } +struct MyConfig { + MyConfig() { std::cout << "global setup part1\n"; } + ~MyConfig() { std::cout << "global teardown part1\n"; } }; // structure MyConfig is used as a global fixture - it's invoked pre and post any testing is performed -BOOST_GLOBAL_FIXTURE( MyConfig ); +BOOST_TEST_GLOBAL_FIXTURE( MyConfig ); //____________________________________________________________________________// diff --git a/example/unit_test_example_09_2.cpp b/example/unit_test_example_09_2.cpp index 89124de8..3a22a5e9 100644 --- a/example/unit_test_example_09_2.cpp +++ b/example/unit_test_example_09_2.cpp @@ -1,6 +1,6 @@ // (C) Copyright Gennadiy Rozental 2005-2014. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. @@ -14,13 +14,13 @@ //____________________________________________________________________________// -struct MyConfig2 { - MyConfig2() { std::cout << "global setup part2\n"; } - ~MyConfig2() { std::cout << "global teardown part2\n"; } +struct MyConfig2 { + MyConfig2() { std::cout << "global setup part2\n"; } + ~MyConfig2() { std::cout << "global teardown part2\n"; } }; // structure MyConfig2 is used as a global fixture. You could have any number of global fxtures -BOOST_GLOBAL_FIXTURE( MyConfig2 ); +BOOST_TEST_GLOBAL_FIXTURE( MyConfig2 ); //____________________________________________________________________________// diff --git a/include/boost/test/unit_test_suite.hpp b/include/boost/test/unit_test_suite.hpp index 49f6926a..13ff804b 100644 --- a/include/boost/test/unit_test_suite.hpp +++ b/include/boost/test/unit_test_suite.hpp @@ -143,12 +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."); \ - test_name t; boost::unit_test::setup_conditional(t); \ - BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \ + BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor"); \ + test_name t; \ + 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 ) {}; \ From 5e9d1e04f683e580a80eee3317f5d5aa5c414182 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Fri, 23 Jun 2017 15:00:09 +0200 Subject: [PATCH 6/8] Change logs --- doc/closing_chapters/change_log.qbk | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/closing_chapters/change_log.qbk b/doc/closing_chapters/change_log.qbk index 6d28cd62..f569f6bc 100644 --- a/doc/closing_chapters/change_log.qbk +++ b/doc/closing_chapters/change_log.qbk @@ -9,11 +9,22 @@ [h4 Boost.Test v3.6 / boost 1.65] +[h5 Breaking changes] +* __BOOST_GLOBAL_FIXTURE__ is flagged as deprecated and will be removed in a later version +* Using test assertions and macros is not allowed when used inside __BOOST_GLOBAL_FIXTURE__. Please use __BOOST_TEST_GLOBAL_FIXTURE__ + instead (see below). + [h5 New features] * VS2017 / C++17 compatibility (thanks to Daniela Engert) +* Deprecating __BOOST_GLOBAL_FIXTURE__ in favor of __BOOST_TEST_GLOBAL_FIXTURE__ and __BOOST_TEST_GLOBAL_CONFIGURATION__. This + helps separating the logic of the fixtures associated to the master test suite, from the one used for setting up the logging + and reporting facility, and results in a general cleaner design. [h5 Bugfixes and feature requests] # [pull_request 106] replace deprecated binders and adapters, and `random_shuffle` by more modern equivalents +# [ticket 5282] Test fixtures do not support virtual inheritance +# [ticket 5563] using a test macro in a global fixture crashes Boost.Test +# [ticket 11962] `BOOST_TEST_MESSAGE` in fixture constructor - invalid XML [h4 Boost.Test v3.5 / boost 1.64] @@ -24,10 +35,10 @@ [link boost_test.test_output.log_formats.test_log_output log-level] set between `success` and `non-fatal error`, and defaults to `general information`. * [link boost_test.test_output.log_formats.log_junit_format JUnit output format] is now more - performant in case a lot of checks are done in a test module. + performant in case a lot of checks are done in a test module. [h5 Bugfixes and feature requests] -# [pull_request 107] `BOOST_NO_EXCEPTIONS` typo making `throw_exception` unusable under some circumstances +# [pull_request 107] `BOOST_NO_EXCEPTIONS` typo making `throw_exception` unusable under some circumstances # [pull_request 108] Change capital variable names to lowercase # [ticket 11756] boost.Test: non standards compliant use of `FE_*` macros (unable to compile boost test library on FPU-less arches) (reopened) # [ticket 12540] Provide customisation point for printing types in tests From 91253a1ab1a291e76fe930468e832479b771e060 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Sat, 24 Jun 2017 21:53:14 +0200 Subject: [PATCH 7/8] Warnings --- include/boost/test/tree/fixture.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/test/tree/fixture.hpp b/include/boost/test/tree/fixture.hpp index f1206782..8e07b2aa 100644 --- a/include/boost/test/tree/fixture.hpp +++ b/include/boost/test/tree/fixture.hpp @@ -95,13 +95,13 @@ namespace impl_fixture { #endif template - struct call_setup { template void operator()(U& u) { } }; + struct call_setup { template void operator()(U& ) { } }; template <> struct call_setup { template void operator()(U& u) { u.setup(); } }; template - struct call_teardown { template void operator()(U& u) { } }; + struct call_teardown { template void operator()(U& ) { } }; template <> struct call_teardown { template void operator()(U& u) { u.teardown(); } }; From 680f24e95334a7f55f8909c789f49cbcacadd4a4 Mon Sep 17 00:00:00 2001 From: Raffi Enficiaud Date: Sun, 25 Jun 2017 11:53:37 +0200 Subject: [PATCH 8/8] Passing the pattern file as argument --- test/Jamfile.v2 | 2 +- test/framework-ts/test-macro-global-fixture.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index a1aba4aa..02a31cef 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -136,7 +136,7 @@ test-suite "framework-ts" [ boost.test-self-test run : framework-ts : log-formatter-test : : baseline-outputs/log-formatter-test.pattern ] [ boost.test-self-test run : framework-ts : run-by-name-or-label-test ] [ boost.test-self-test run : framework-ts : version-uses-module-name : included ] - [ boost.test-self-test run : framework-ts : test-macro-global-fixture ] + [ boost.test-self-test run : framework-ts : test-macro-global-fixture : : baseline-outputs/global-fixtures-test.pattern ] ; #_________________________________________________________________________________________________# diff --git a/test/framework-ts/test-macro-global-fixture.cpp b/test/framework-ts/test-macro-global-fixture.cpp index 96dffe6c..732b7026 100644 --- a/test/framework-ts/test-macro-global-fixture.cpp +++ b/test/framework-ts/test-macro-global-fixture.cpp @@ -244,7 +244,7 @@ public: "condition 2>3 is not satisfied\n", "condition 2>3 is not satisfied]", }; - + static const std::string to_replace[] = {"time=\"0.1234\"", get_basename() + ":*:" , "unknown location:*:",