2
0
mirror of https://github.com/boostorg/test.git synced 2026-02-12 12:32:09 +00:00

Removing broken Singleton pattern

The singleton is not robust to initialization in several translation units between
shared library with hidden visibility. Removing

Fixing tests accordingly.
This commit is contained in:
Raffi Enficiaud
2018-09-23 23:44:47 +02:00
parent 4df5b095ea
commit f08bd860b2
21 changed files with 114 additions and 70 deletions

View File

@@ -147,12 +147,12 @@ public:
: m_dataset( ds )
, m_generated( false )
, m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
, m_tc_file( tc_file )
, m_tc_file( tc_file )
, m_tc_line( tc_line )
, m_tc_index( 0 )
{}
#endif
public:
virtual test_unit* next() const
{
@@ -273,7 +273,7 @@ BOOST_AUTO_TU_REGISTRAR( BOOST_PP_CAT(test_name, case) )( \
BOOST_STRINGIZE( test_name ), \
__FILE__, __LINE__, \
boost::unit_test::data::ds_detail::seed{} ->* dataset ), \
boost::unit_test::decorator::collector::instance() ); \
boost::unit_test::decorator::collector_t::instance() ); \
\
BOOST_AUTO_TEST_SUITE_END() \
\

View File

@@ -35,11 +35,15 @@ namespace unit_test {
namespace decorator {
// ************************************************************************** //
// ************** decorator::collector ************** //
// ************** decorator::collector_t ************** //
// ************************************************************************** //
collector&
collector::operator*( base const& d )
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(collector_t)
collector_t&
collector_t::operator*( base const& d )
{
m_tu_decorators.push_back( d.clone() );
@@ -49,7 +53,7 @@ collector::operator*( base const& d )
//____________________________________________________________________________//
void
collector::store_in( test_unit& tu )
collector_t::store_in( test_unit& tu )
{
tu.p_decorators.value.insert( tu.p_decorators.value.end(), m_tu_decorators.begin(), m_tu_decorators.end() );
}
@@ -57,7 +61,7 @@ collector::store_in( test_unit& tu )
//____________________________________________________________________________//
void
collector::reset()
collector_t::reset()
{
m_tu_decorators.clear();
}
@@ -65,7 +69,7 @@ collector::reset()
//____________________________________________________________________________//
std::vector<base_ptr>
collector::get_lazy_decorators() const
collector_t::get_lazy_decorators() const
{
return m_tu_decorators;
}
@@ -76,10 +80,10 @@ collector::get_lazy_decorators() const
// ************** decorator::base ************** //
// ************************************************************************** //
collector&
collector_t&
base::operator*() const
{
return collector::instance() * *this;
return collector_t::instance() * *this;
}
// ************************************************************************** //

View File

@@ -52,7 +52,7 @@ struct progress_display {
<< "\n|----|----|----|----|----|----|----|----|----|----|"
<< std::endl;
if( !m_expected_count )
if( !m_expected_count )
m_expected_count = 1; // prevent divide by zero
}
@@ -63,7 +63,7 @@ struct progress_display {
// use of floating point ensures that both large and small counts
// work correctly. static_cast<>() is also used several places
// to suppress spurious compiler warnings.
// to suppress spurious compiler warnings.
unsigned int tics_needed = static_cast<unsigned int>(
(static_cast<double>(m_count)/m_expected_count)*50.0 );
@@ -121,6 +121,10 @@ progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; retu
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL(progress_monitor_t)
//____________________________________________________________________________//
void
progress_monitor_t::test_start( counter_t test_cases_amount )
{

View File

@@ -139,6 +139,10 @@ results_collector_impl& s_rc_impl() { static results_collector_impl the_inst; re
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( results_collector_t )
//____________________________________________________________________________//
void
results_collector_t::test_start( counter_t )
{

View File

@@ -45,6 +45,14 @@ test_init_observer_check& s_tioc_impl() { static test_init_observer_check the_in
} // local namespace
//____________________________________________________________________________//
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(framework_init_observer_t)
//____________________________________________________________________________//
void
framework_init_observer_t::clear()
{

View File

@@ -274,7 +274,7 @@ test_suite::add( test_unit_generator const& gen, unsigned timeout )
//____________________________________________________________________________//
void
test_suite::add( test_unit_generator const& gen, decorator::collector& decorators )
test_suite::add( test_unit_generator const& gen, decorator::collector_t& decorators )
{
test_unit* tu;
while((tu = gen.next()) != 0) {
@@ -285,7 +285,7 @@ test_suite::add( test_unit_generator const& gen, decorator::collector& decorator
}
void
test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector& decorators )
test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
{
std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
m_generators.push_back(tmp_p);
@@ -453,7 +453,7 @@ normalize_test_case_name( const_string name )
// ************** auto_test_unit_registrar ************** //
// ************************************************************************** //
auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector& decorators, counter_t exp_fail )
auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail )
{
framework::current_auto_test_suite().add( tc, exp_fail );
@@ -463,7 +463,7 @@ auto_test_unit_registrar::auto_test_unit_registrar( test_case* tc, decorator::co
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector& decorators )
auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector_t& decorators )
{
test_unit_id id = framework::current_auto_test_suite().get( ts_name );
@@ -486,14 +486,14 @@ auto_test_unit_registrar::auto_test_unit_registrar( const_string ts_name, const_
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector& decorators )
auto_test_unit_registrar::auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector_t& decorators )
{
framework::current_auto_test_suite().add( tc_gen, decorators );
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector& decorators )
auto_test_unit_registrar::auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector_t& decorators )
{
framework::current_auto_test_suite().add( tc_gen, decorators );
}

View File

@@ -159,6 +159,10 @@ unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return th
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( unit_test_log_t )
//____________________________________________________________________________//
void
unit_test_log_t::test_start( counter_t test_cases_amount )
{

View File

@@ -29,6 +29,9 @@
namespace boost {
namespace unit_test {
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(unit_test_monitor_t)
// ************************************************************************** //
// ************** unit_test_monitor ************** //
// ************************************************************************** //

View File

@@ -31,7 +31,7 @@ namespace unit_test {
// ************************************************************************** //
/// This class implements test observer interface and updates test progress as test units finish or get aborted
class BOOST_TEST_DECL progress_monitor_t : public test_observer, public singleton<progress_monitor_t> {
class BOOST_TEST_DECL progress_monitor_t : public test_observer {
public:
/// @name Test observer interface
/// @{
@@ -49,7 +49,7 @@ public:
void set_stream( std::ostream& );
/// @}
private:
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( progress_monitor_t )
}; // progress_monitor_t

View File

@@ -84,7 +84,7 @@ public:
/// For test suites, this indicates if the test suite itself has been marked as
/// skipped, and not if the test suite contains any skipped test.
bool skipped() const;
/// Returns true if the test unit was aborted (hard failure)
bool aborted() const;
@@ -115,7 +115,7 @@ public:
/// of the test tree.
///
/// @see boost::unit_test::test_observer
class BOOST_TEST_DECL results_collector_t : public test_observer, public singleton<results_collector_t> {
class BOOST_TEST_DECL results_collector_t : public test_observer {
public:
virtual void test_start( counter_t );
@@ -135,7 +135,7 @@ public:
/// @param[in] tu_id id of a test unit
test_results const& results( test_unit_id tu_id ) const;
private:
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( results_collector_t )
};

View File

@@ -33,7 +33,7 @@ namespace unit_test {
/// This class collects the state of the init/termination of the unit test framework.
///
/// @see boost::unit_test::test_observer
class BOOST_TEST_DECL framework_init_observer_t : public test_observer, public singleton<framework_init_observer_t> {
class BOOST_TEST_DECL framework_init_observer_t : public test_observer {
public:
virtual void test_start( counter_t );
@@ -49,7 +49,7 @@ public:
/// Indicates if a failure has been recorded so far
bool has_failed( ) const;
private:
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( framework_init_observer_t )
};

View File

@@ -37,10 +37,10 @@ namespace ut_detail {
struct BOOST_TEST_DECL auto_test_unit_registrar {
// Constructors
auto_test_unit_registrar( test_case* tc, decorator::collector& decorators, counter_t exp_fail = 0 );
explicit auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector& decorators );
explicit auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector& decorators );
explicit auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector& decorators );
auto_test_unit_registrar( test_case* tc, decorator::collector_t& decorators, counter_t exp_fail = 0 );
explicit auto_test_unit_registrar( const_string ts_name, const_string ts_file, std::size_t ts_line, decorator::collector_t& decorators );
explicit auto_test_unit_registrar( test_unit_generator const& tc_gen, decorator::collector_t& decorators );
explicit auto_test_unit_registrar( boost::shared_ptr<test_unit_generator> tc_gen, decorator::collector_t& decorators );
explicit auto_test_unit_registrar( int );
};

View File

@@ -22,9 +22,8 @@
#include <boost/test/tree/fixture.hpp>
#include <boost/test/tools/assertion_result.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
// Boost
#include <boost/shared_ptr.hpp>
@@ -46,37 +45,40 @@ class test_unit;
namespace decorator {
// ************************************************************************** //
// ************** decorator::collector ************** //
// ************** decorator::collector_t ************** //
// ************************************************************************** //
class base;
typedef boost::shared_ptr<base> base_ptr;
class BOOST_TEST_DECL collector : public singleton<collector> {
class BOOST_TEST_DECL collector_t {
public:
collector& operator*( base const& d );
collector_t& operator*( base const& d );
void store_in( test_unit& tu );
void reset();
std::vector<base_ptr> get_lazy_decorators() const;
private:
BOOST_TEST_SINGLETON_CONS( collector )
// singleton pattern
BOOST_TEST_SINGLETON_CONS( collector_t )
private:
// Data members
std::vector<base_ptr> m_tu_decorators;
};
// ************************************************************************** //
// ************** decorator::base ************** //
// ************** decorator::base ************** //
// ************************************************************************** //
class BOOST_TEST_DECL base {
public:
// composition interface
collector& operator*() const;
collector_t& operator*() const;
// application interface
virtual void apply( test_unit& tu ) = 0;

View File

@@ -176,10 +176,10 @@ public:
void add( test_unit_generator const& gen, unsigned timeout = 0 );
/// @overload
void add( test_unit_generator const& gen, decorator::collector& decorators );
void add( test_unit_generator const& gen, decorator::collector_t& decorators );
/// @overload
void add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector& decorators );
void add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators );
//! Removes a test from the test suite.
void remove( test_unit_id id );

View File

@@ -109,7 +109,7 @@ private:
/// @see
/// - boost::unit_test::test_observer
/// - boost::unit_test::unit_test_log_formatter
class BOOST_TEST_DECL unit_test_log_t : public test_observer, public singleton<unit_test_log_t> {
class BOOST_TEST_DECL unit_test_log_t : public test_observer {
public:
// test_observer interface implementation
virtual void test_start( counter_t test_cases_amount );
@@ -221,6 +221,7 @@ private:
void log_entry_context( log_level l );
void clear_entry_context();
// Singleton
BOOST_TEST_SINGLETON_CONS( unit_test_log_t )
}; // unit_test_log_t

View File

@@ -30,7 +30,7 @@ namespace unit_test {
// ************** unit_test_monitor ************** //
// ************************************************************************** //
class BOOST_TEST_DECL unit_test_monitor_t : public singleton<unit_test_monitor_t>, public execution_monitor {
class BOOST_TEST_DECL unit_test_monitor_t :public execution_monitor {
public:
enum error_level {
test_ok = 0,
@@ -48,7 +48,7 @@ public:
// monitor method
error_level execute_and_translate( boost::function<void ()> const& func, unsigned timeout = 0 );
private:
// singleton pattern
BOOST_TEST_SINGLETON_CONS( unit_test_monitor_t )
};

View File

@@ -65,7 +65,7 @@ BOOST_AUTO_TU_REGISTRAR( suite_name )( \
#define BOOST_AUTO_TEST_SUITE_NO_DECOR( suite_name ) \
BOOST_AUTO_TEST_SUITE_WITH_DECOR( \
suite_name, \
boost::unit_test::decorator::collector::instance() ) \
boost::unit_test::decorator::collector_t::instance() ) \
/**/
#if BOOST_PP_VARIADICS
@@ -169,7 +169,7 @@ void test_name::test_method() \
#define BOOST_FIXTURE_TEST_CASE_NO_DECOR( test_name, F ) \
BOOST_FIXTURE_TEST_CASE_WITH_DECOR( test_name, F, \
boost::unit_test::decorator::collector::instance() ) \
boost::unit_test::decorator::collector_t::instance() ) \
/**/
#if BOOST_PP_VARIADICS
@@ -248,7 +248,7 @@ BOOST_AUTO_TU_REGISTRAR( test_name )( \
boost::unit_test::ut_detail::template_test_case_gen< \
BOOST_AUTO_TC_INVOKER( test_name ),TL >( \
BOOST_STRINGIZE( test_name ), __FILE__, __LINE__ ), \
boost::unit_test::decorator::collector::instance() ); \
boost::unit_test::decorator::collector_t::instance() ); \
\
template<typename type_name> \
void test_name<type_name>::test_method() \
@@ -321,7 +321,7 @@ static boost::unit_test::ut_detail::global_fixture_impl<F> BOOST_JOIN( gf_, F )
// ************************************************************************** //
#define BOOST_TEST_DECORATOR( D ) \
static boost::unit_test::decorator::collector const& \
static boost::unit_test::decorator::collector_t const& \
BOOST_TEST_APPEND_UNIQUE_ID(decorator_collector) = D; \
/**/
@@ -345,7 +345,7 @@ typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;
// ************************************************************************** //
// Facility for having a unique name based on __LINE__ and __COUNTER__ (later if available)
#if defined(__COUNTER__)
#if defined(__COUNTER__)
#define BOOST_TEST_INTERNAL_HAS_COUNTER
#endif

View File

@@ -37,7 +37,7 @@ namespace runtime {
// ************** runtime::param_error ************** //
// ************************************************************************** //
class param_error : public std::exception {
class BOOST_SYMBOL_VISIBLE param_error : public std::exception {
public:
~param_error() BOOST_NOEXCEPT_OR_NOTHROW {}
@@ -55,7 +55,7 @@ protected:
//____________________________________________________________________________//
class init_error : public param_error {
class BOOST_SYMBOL_VISIBLE init_error : public param_error {
protected:
explicit init_error( cstring param_name ) : param_error( param_name ) {}
~init_error() BOOST_NOEXCEPT_OR_NOTHROW {}
@@ -70,7 +70,7 @@ protected:
//____________________________________________________________________________//
template<typename Derived, typename Base>
class specific_param_error : public Base {
class BOOST_SYMBOL_VISIBLE specific_param_error : public Base {
protected:
explicit specific_param_error( cstring param_name ) : Base( param_name ) {}
~specific_param_error() BOOST_NOEXCEPT_OR_NOTHROW {}
@@ -155,7 +155,7 @@ SPECIFIC_EX_TYPE( missing_req_arg, input_error );
#undef SPECIFIC_EX_TYPE
class ambiguous_param : public specific_param_error<ambiguous_param, input_error> {
class BOOST_SYMBOL_VISIBLE ambiguous_param : public specific_param_error<ambiguous_param, input_error> {
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
explicit ambiguous_param( std::vector<cstring>&& amb_candidates )

View File

@@ -32,7 +32,7 @@ namespace unit_test {
// ************************************************************************** //
template<typename Derived>
class singleton {
class BOOST_TEST_DECL singleton {
public:
static Derived& instance() { static Derived the_inst; return the_inst; }
@@ -46,11 +46,25 @@ protected:
//____________________________________________________________________________//
#define BOOST_TEST_SINGLETON_CONS( type ) \
#define BOOST_TEST_SINGLETON_CONS_OLD( type ) \
friend class boost::unit_test::singleton<type>; \
type() {} \
/**/
#define BOOST_TEST_SINGLETON_CONS( type ) \
public: \
static type& instance(); \
private: \
BOOST_DELETED_FUNCTION(type(type const&)) \
BOOST_DELETED_FUNCTION(type& operator=(type const&)) \
BOOST_DEFAULTED_FUNCTION(type(), {}) \
BOOST_DEFAULTED_FUNCTION(~type(), {}) \
#define BOOST_TEST_SINGLETON_CONS_IMPL( type ) \
type& type::instance() { \
static type the_inst; return the_inst; \
} \
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
#define BOOST_TEST_SINGLETON_INST( inst ) \