updated boost on windows

This commit is contained in:
Bassem Girgis
2019-08-13 21:48:48 -05:00
parent 7d77d485fd
commit b40a3bee82
5162 changed files with 473027 additions and 116452 deletions

View File

@@ -37,6 +37,11 @@
#endif
//! Defined when the initializer_list implementation is buggy, such as for VS2013
#if defined(_MSC_VER) && _MSC_VER < 1900
# define BOOST_TEST_ERRONEOUS_INIT_LIST
#endif
//____________________________________________________________________________//
#define BOOST_TEST_DS_ERROR( msg ) BOOST_TEST_I_THROW( std::logic_error( msg ) )

View File

@@ -77,7 +77,7 @@ invoke_action( Action const& action, T&& args, std::true_type /* is_tuple */ )
template<typename DataSet, typename Action>
inline typename std::enable_if<monomorphic::is_dataset<DataSet>::value,void>::type
for_each_sample( DataSet && samples,
for_each_sample( DataSet const & samples,
Action const& act,
data::size_t number_of_samples = BOOST_TEST_DS_INFINITE_SIZE )
{

View File

@@ -1,19 +0,0 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief specific generators
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_HPP_112011GER
// Boost.Test
#include <boost/test/data/monomorphic/generators/xrange.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_HPP_112011GER

View File

@@ -49,6 +49,11 @@ struct make_index_sequence<B,E,typename std::enable_if<E==B+1,void>::type> {
typedef index_sequence<B> type;
};
template <>
struct make_index_sequence<0, 0> {
typedef index_sequence<> type;
};
template <typename... T>
using index_sequence_for = typename make_index_sequence<0, sizeof...(T)>::type;

View File

@@ -22,6 +22,7 @@
#include <boost/test/data/monomorphic/join.hpp>
#include <boost/test/data/monomorphic/singleton.hpp>
#include <boost/test/data/monomorphic/zip.hpp>
#include <boost/test/data/monomorphic/delayed.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_HPP_102211GER

View File

@@ -75,7 +75,7 @@ struct is_dataset<collection<C>> : mpl::true_ {};
//! @overload boost::unit_test::data::make()
template<typename C>
inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c )
{
return monomorphic::collection<C>( std::forward<C>(c) );

View File

@@ -0,0 +1,124 @@
// (C) Copyright Raffi Enficiaud 2018.
// 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
/// Defines a lazy/delayed dataset store
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_DELAYED_HPP_062018GER
#define BOOST_TEST_DATA_MONOMORPHIC_DELAYED_HPP_062018GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/data/index_sequence.hpp>
#include <boost/core/ref.hpp>
#include <algorithm>
#include <memory>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_HDR_TUPLE)
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** delayed_dataset ************** //
// ************************************************************************** //
/// Delayed dataset
///
/// This dataset holds another dataset that is instanciated on demand. It is
/// constructed with the @c data::make_delayed<dataset_t>(arg1,....) instead of the
/// @c data::make.
template <class dataset_t, class ...Args>
class delayed_dataset
{
public:
enum { arity = dataset_t::arity };
using iterator = decltype(std::declval<dataset_t>().begin());
delayed_dataset(Args... args)
: m_args(std::make_tuple(std::forward<Args>(args)...))
{}
// Mostly for VS2013
delayed_dataset(delayed_dataset&& b)
: m_args(std::move(b.m_args))
, m_dataset(std::move(b.m_dataset))
{}
boost::unit_test::data::size_t size() const {
return this->get().size();
}
// iterator
iterator begin() const {
return this->get().begin();
}
private:
dataset_t& get() const {
if(!m_dataset) {
m_dataset = create(boost::unit_test::data::index_sequence_for<Args...>());
}
return *m_dataset;
}
template<std::size_t... I>
std::unique_ptr<dataset_t>
create(boost::unit_test::data::index_sequence<I...>) const
{
return std::unique_ptr<dataset_t>{new dataset_t(std::get<I>(m_args)...)};
}
std::tuple<typename std::decay<Args>::type...> m_args;
mutable std::unique_ptr<dataset_t> m_dataset;
};
//____________________________________________________________________________//
//! A lazy/delayed dataset is a dataset.
template <class dataset_t, class ...Args>
struct is_dataset< delayed_dataset<dataset_t, Args...> > : boost::mpl::true_ {};
//____________________________________________________________________________//
} // namespace monomorphic
//! Delayed dataset instanciation
template<class dataset_t, class ...Args>
inline typename std::enable_if<
monomorphic::is_dataset< dataset_t >::value,
monomorphic::delayed_dataset<dataset_t, Args...>
>::type
make_delayed(Args... args)
{
return monomorphic::delayed_dataset<dataset_t, Args...>( std::forward<Args>(args)... );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#endif
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_DELAYED_HPP_062018GER

View File

@@ -43,9 +43,6 @@ namespace monomorphic {
#if !defined(BOOST_TEST_DOXYGEN_DOC__)
template<typename T, typename Specific>
class dataset;
template<typename T>
class singleton;
@@ -58,6 +55,12 @@ class array;
template<typename T>
class init_list;
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_HDR_TUPLE)
template<class dataset_t, class ...Args>
class delayed_dataset;
#endif
#endif
// ************************************************************************** //
@@ -73,6 +76,8 @@ struct is_dataset : mpl::false_ {};
//! A reference to a dataset is a dataset
template<typename DataSet>
struct is_dataset<DataSet&> : is_dataset<DataSet> {};
template<typename DataSet>
struct is_dataset<DataSet&&> : is_dataset<DataSet> {};
//____________________________________________________________________________//
@@ -80,6 +85,18 @@ struct is_dataset<DataSet&> : is_dataset<DataSet> {};
template<typename DataSet>
struct is_dataset<DataSet const> : is_dataset<DataSet> {};
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//! Helper to check if a list of types contains a dataset
template<class DataSet, class...>
struct has_dataset : is_dataset<DataSet> {};
template<class DataSet0, class DataSet1, class... DataSetTT>
struct has_dataset<DataSet0, DataSet1, DataSetTT...>
: std::integral_constant<bool, is_dataset<DataSet0>::value || has_dataset<DataSet1, DataSetTT...>::value>
{};
#endif
} // namespace monomorphic
// ************************************************************************** //
@@ -119,7 +136,7 @@ make(DataSet&& ds)
//! @overload boost::unit_test::data::make()
template<typename T>
inline typename std::enable_if<!is_forward_iterable<T>::value &&
inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!is_array<typename remove_reference<T>::type>::value,
monomorphic::singleton<T>>::type
@@ -129,7 +146,7 @@ make( T&& v );
//! @overload boost::unit_test::data::make()
template<typename C>
inline typename std::enable_if<is_forward_iterable<C>::value,monomorphic::collection<C>>::type
inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c );
//____________________________________________________________________________//
@@ -160,6 +177,31 @@ make( std::initializer_list<T>&& );
//____________________________________________________________________________//
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_TEST_ERRONEOUS_INIT_LIST)
//! @overload boost::unit_test::data::make()
template<class T, class ...Args>
inline typename std::enable_if<
!monomorphic::has_dataset<T, Args...>::value,
monomorphic::init_list<T>
>::type
make( T&& arg0, Args&&... args );
#endif
//____________________________________________________________________________//
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_HDR_TUPLE)
template<class dataset_t, class ...Args>
inline typename std::enable_if<
monomorphic::is_dataset< dataset_t >::value,
monomorphic::delayed_dataset<dataset_t, Args...>
>::type
make_delayed(Args... args);
#endif
//____________________________________________________________________________//
namespace result_of {
//! Result of the make call.

View File

@@ -16,6 +16,8 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/core/ref.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//

View File

@@ -25,9 +25,9 @@ namespace unit_test {
namespace data {
namespace {
nfp::keyword<struct begin_t> begin;
nfp::keyword<struct end_t> end;
nfp::keyword<struct step_t> step;
nfp::keyword<struct begin_t> begin BOOST_ATTRIBUTE_UNUSED;
nfp::keyword<struct end_t> end BOOST_ATTRIBUTE_UNUSED;
nfp::keyword<struct step_t> step BOOST_ATTRIBUTE_UNUSED;
} // local namespace
} // namespace data

View File

@@ -22,6 +22,9 @@
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -102,7 +105,10 @@ public:
{}
// dataset interface
data::size_t size() const { return m_ds1.size() * m_ds2.size(); }
data::size_t size() const {
BOOST_TEST_DS_ASSERT( !m_ds1.size().is_inf() && !m_ds2.size().is_inf(), "Grid axes can't have infinite size" );
return m_ds1.size() * m_ds2.size();
}
iterator begin() const { return iterator( m_ds1.begin(), m_ds2 ); }
private:
@@ -138,8 +144,6 @@ inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_datase
>::type
operator*( DataSet1&& ds1, DataSet2&& ds2 )
{
BOOST_TEST_DS_ASSERT( !ds1.size().is_inf() && !ds2.size().is_inf(), "Grid axes can't have infinite size" );
return grid<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ), std::forward<DataSet2>( ds2 ) );
}

View File

@@ -16,6 +16,10 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/core/ignore_unused.hpp>
#include <vector>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -26,23 +30,35 @@ namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** array ************** //
// ************** initializer_list ************** //
// ************************************************************************** //
/// Dataset view of a C array
/// Dataset view from an initializer_list or variadic template arguments
///
/// The data should be stored in the dataset, and since the elements
/// are passed by an @c std::initializer_list , it implies a copy of
/// the elements.
template<typename T>
class init_list {
public:
typedef T sample;
enum { arity = 1 };
typedef T const* iterator;
typedef typename std::vector<T>::const_iterator iterator;
//! Constructor swallows initializer_list
init_list( std::initializer_list<T>&& il )
: m_data( std::forward<std::initializer_list<T>>( il ) )
//! Constructor copies content of initializer_list
init_list( std::initializer_list<T> il )
: m_data( il )
{}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_TEST_ERRONEOUS_INIT_LIST)
//! Variadic template initialization
template <class ...Args>
init_list( Args&& ... args ) {
int dummy[] = { 0, (m_data.emplace_back(std::forward<Args&&>(args)), 0)... };
boost::ignore_unused(dummy);
}
#endif
//! dataset interface
data::size_t size() const { return m_data.size(); }
@@ -50,7 +66,39 @@ public:
private:
// Data members
std::initializer_list<T> m_data;
std::vector<T> m_data;
};
//! Specialization of init_list for type bool
template <>
class init_list<bool> {
public:
typedef bool sample;
enum { arity = 1 };
typedef std::vector<bool>::const_iterator iterator;
//! Constructor copies content of initializer_list
init_list( std::initializer_list<bool>&& il )
: m_data( std::forward<std::initializer_list<bool>>( il ) )
{}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_TEST_ERRONEOUS_INIT_LIST)
//! Variadic template initialization
template <class ...Args>
init_list( Args&& ... args ) : m_data{ args... }
{ }
#endif
//! dataset interface
data::size_t size() const { return m_data.size(); }
iterator begin() const { return m_data.begin(); }
private:
// Data members
std::vector<bool> m_data;
};
//____________________________________________________________________________//
@@ -71,6 +119,20 @@ make( std::initializer_list<T>&& il )
return monomorphic::init_list<T>( std::forward<std::initializer_list<T>>( il ) );
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_TEST_ERRONEOUS_INIT_LIST)
template<class T, class ...Args>
inline typename std::enable_if<
!monomorphic::has_dataset<T, Args...>::value,
monomorphic::init_list<T>
>::type
make( T&& arg0, Args&&... args )
{
return monomorphic::init_list<T>( std::forward<T>(arg0), std::forward<Args>( args )... );
}
#endif
} // namespace data
} // namespace unit_test
} // namespace boost

View File

@@ -16,6 +16,9 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -40,22 +43,33 @@ class join {
typedef typename dataset1_decay::iterator dataset1_iter;
typedef typename dataset2_decay::iterator dataset2_iter;
using iter1_ret = decltype(*std::declval<DataSet1>().begin());
using iter2_ret = decltype(*std::declval<DataSet2>().begin());
public:
typedef typename dataset1_decay::sample sample;
enum { arity = dataset1_decay::arity };
using sample_t = typename std::conditional<
std::is_reference<iter1_ret>::value && std::is_reference<iter2_ret>::value && std::is_same<iter1_ret, iter2_ret>::value,
iter1_ret,
typename std::remove_reference<iter1_ret>::type
>::type
;
struct iterator {
// Constructor
explicit iterator( dataset1_iter it1, dataset2_iter it2, data::size_t first_size )
explicit iterator( dataset1_iter&& it1, dataset2_iter&& it2, data::size_t first_size )
: m_it1( std::move( it1 ) )
, m_it2( std::move( it2 ) )
, m_first_size( first_size )
{}
// forward iterator interface
sample const& operator*() const { return m_first_size > 0 ? *m_it1 : *m_it2; }
void operator++() { if( m_first_size > 0 ) { --m_first_size; ++m_it1; } else ++m_it2; }
// The returned sample should be by value, as the operator* may return a temporary object
sample_t operator*() const { return m_first_size > 0 ? *m_it1 : *m_it2; }
void operator++() { if( m_first_size > 0 ) { --m_first_size; ++m_it1; } else ++m_it2; }
private:
// Data members

View File

@@ -32,9 +32,11 @@ namespace monomorphic {
/// Models a single element data set
template<typename T>
class singleton {
public:
private:
typedef typename boost::decay<T>::type sample;
public:
enum { arity = 1 };
struct iterator {
@@ -81,7 +83,7 @@ struct is_dataset<singleton<T>> : mpl::true_ {};
/// @overload boost::unit_test::data::make()
template<typename T>
inline typename std::enable_if<!is_forward_iterable<T>::value &&
inline typename std::enable_if<!is_container_forward_iterable<T>::value &&
!monomorphic::is_dataset<T>::value &&
!boost::is_array<typename boost::remove_reference<T>::type>::value,
monomorphic::singleton<T>

View File

@@ -20,6 +20,9 @@
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -70,33 +73,50 @@ public:
dataset2_iter m_iter2;
};
typedef typename iterator::iterator_sample sample;
//! Constructor
//!
//! The datasets are moved and not copied.
zip( DataSet1&& ds1, DataSet2&& ds2, data::size_t size )
zip( DataSet1&& ds1, DataSet2&& ds2/*, data::size_t size*/ )
: m_ds1( std::forward<DataSet1>( ds1 ) )
, m_ds2( std::forward<DataSet2>( ds2 ) )
, m_size( size )
//, m_size( size )
{}
//! Move constructor
zip( zip&& j )
: m_ds1( std::forward<DataSet1>( j.m_ds1 ) )
, m_ds2( std::forward<DataSet2>( j.m_ds2 ) )
, m_size( j.m_size )
//, m_size( j.m_size )
{}
// dataset interface
data::size_t size() const { return m_size; }
data::size_t size() const { return zip_size(); }
iterator begin() const { return iterator( m_ds1.begin(), m_ds2.begin() ); }
private:
// Data members
DataSet1 m_ds1;
DataSet2 m_ds2;
data::size_t m_size;
//data::size_t m_size;
//! Handles the sise of the resulting zipped dataset.
data::size_t zip_size() const
{
data::size_t ds1_size = m_ds1.size();
data::size_t ds2_size = m_ds2.size();
if( ds1_size == ds2_size )
return ds1_size;
if( ds1_size == 1 || ds1_size.is_inf() )
return ds2_size;
if( ds2_size == 1 || ds2_size.is_inf() )
return ds1_size;
BOOST_TEST_DS_ERROR( "Can't zip datasets of different sizes" );
}
};
//____________________________________________________________________________//
@@ -107,32 +127,6 @@ struct is_dataset<zip<DataSet1,DataSet2>> : mpl::true_ {};
//____________________________________________________________________________//
namespace ds_detail {
//! Handles the sise of the resulting zipped dataset.
template<typename DataSet1, typename DataSet2>
inline data::size_t
zip_size( DataSet1&& ds1, DataSet2&& ds2 )
{
data::size_t ds1_size = ds1.size();
data::size_t ds2_size = ds2.size();
if( ds1_size == ds2_size )
return ds1_size;
if( ds1_size == 1 || ds1_size.is_inf() )
return ds2_size;
if( ds2_size == 1 || ds2_size.is_inf() )
return ds1_size;
BOOST_TEST_DS_ERROR( "Can't zip datasets of different sizes" );
}
} // namespace ds_detail
//____________________________________________________________________________//
namespace result_of {
//! Result type of the zip operator.
@@ -153,8 +147,8 @@ inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_datase
operator^( DataSet1&& ds1, DataSet2&& ds2 )
{
return zip<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ),
std::forward<DataSet2>( ds2 ),
ds_detail::zip_size( ds1, ds2 ) );
std::forward<DataSet2>( ds2 )/*,
ds_detail::zip_size( ds1, ds2 )*/ );
}
//____________________________________________________________________________//

View File

@@ -16,6 +16,7 @@
#include <boost/test/data/config.hpp>
#include <boost/test/data/dataset.hpp>
#include <boost/test/data/for_each_sample.hpp>
#include <boost/test/tree/test_unit.hpp>
// Boost
#include <boost/preprocessor/repetition/enum_params.hpp>
@@ -32,13 +33,16 @@
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/bind.hpp>
#include <boost/type_traits/is_copy_constructible.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/test/tools/detail/print_helper.hpp>
#include <boost/test/utils/string_cast.hpp>
#include <list>
#include <string>
#include <boost/test/detail/suppress_warnings.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
&& !defined(BOOST_TEST_DATASET_MAX_ARITY)
# define BOOST_TEST_DATASET_MAX_ARITY 10
@@ -122,15 +126,17 @@ public:
// Constructor
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
: m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
: m_dataset( std::forward<DataSet>( ds ) )
, m_generated( false )
, m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
, m_tc_file( tc_file )
, m_tc_line( tc_line )
, m_tc_index( 0 )
{
data::for_each_sample( std::forward<DataSet>( ds ), *this );
}
{}
test_case_gen( test_case_gen&& gen )
: m_tc_name( gen.m_tc_name )
: m_dataset( std::move( gen.m_dataset ) )
, m_generated( gen.m_generated )
, m_tc_name( gen.m_tc_name )
, m_tc_file( gen.m_tc_file )
, m_tc_line( gen.m_tc_line )
, m_tc_index( gen.m_tc_index )
@@ -138,17 +144,23 @@ public:
{}
#else
test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
: m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
, m_tc_file( tc_file )
: m_dataset( ds )
, m_generated( false )
, m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
, m_tc_file( tc_file )
, m_tc_line( tc_line )
, m_tc_index( 0 )
{
data::for_each_sample( ds, *this );
}
{}
#endif
public:
virtual test_unit* next() const
{
if(!m_generated) {
data::for_each_sample( m_dataset, *this );
m_generated = true;
}
if( m_test_cases.empty() )
return 0;
@@ -158,8 +170,10 @@ public:
return res;
}
#if !defined(BOOST_TEST_DATASET_VARIADIC)
// see BOOST_TEST_DATASET_MAX_ARITY to increase the default supported arity
// there is also a limit on boost::bind
#define TC_MAKE(z,arity,_) \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
void operator()( BOOST_PP_ENUM_BINARY_PARAMS(arity, Arg, const& arg) ) const \
@@ -178,8 +192,8 @@ public:
new test_case( genTestCaseName(),
m_tc_file,
m_tc_line,
boost::bind( &TestCase::template test_method<Arg...>,
boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
std::bind( &TestCase::template test_method<Arg...>,
boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
}
#endif
@@ -190,6 +204,8 @@ private:
}
// Data members
DataSet m_dataset;
mutable bool m_generated;
std::string m_tc_name;
const_string m_tc_file;
std::size_t m_tc_line;
@@ -201,10 +217,10 @@ private:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename TestCase,typename DataSet>
test_case_gen<TestCase,DataSet>
boost::shared_ptr<test_unit_generator> //test_case_gen<TestCase,DataSet>
make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
{
return test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, std::forward<DataSet>(ds) );
return boost::shared_ptr<test_unit_generator>(new test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, std::forward<DataSet>(ds) ));
}
#else
template<typename TestCase,typename DataSet>
@@ -236,20 +252,29 @@ struct BOOST_PP_CAT(test_name, case) : public F { \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
static void test_method( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry.");\
BOOST_PP_CAT(test_name, case) t; \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
BOOST_TEST_CONTEXT( "" \
BOOST_PP_SEQ_FOR_EACH(BOOST_DATA_TEST_CONTEXT, _, params)) \
t._impl(BOOST_PP_SEQ_ENUM(params)); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor");\
BOOST_PP_CAT(test_name, case) t; \
BOOST_TEST_CHECKPOINT('"' \
<< #test_name << "\" fixture setup"); \
boost::unit_test::setup_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
t._impl(BOOST_PP_SEQ_ENUM(params)); \
BOOST_TEST_CHECKPOINT('"' \
<< #test_name << "\" fixture teardown"); \
boost::unit_test::teardown_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor");\
} \
} \
private: \
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
void _impl(BOOST_DATA_TEST_CASE_PARAMS( params )); \
}; \
\
BOOST_AUTO_TEST_SUITE( test_name ) \
BOOST_AUTO_TEST_SUITE( test_name, \
*boost::unit_test::decorator::stack_decorator()) \
\
BOOST_AUTO_TU_REGISTRAR( BOOST_PP_CAT(test_name, case) )( \
boost::unit_test::data::ds_detail::make_test_case_gen< \
@@ -257,7 +282,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

@@ -78,10 +78,27 @@ class type_info;
//____________________________________________________________________________//
// Sun compiler does not support visibility on enums
#if defined(__SUNPRO_CC)
#define BOOST_TEST_ENUM_SYMBOL_VISIBLE
#else
#define BOOST_TEST_ENUM_SYMBOL_VISIBLE BOOST_SYMBOL_VISIBLE
#endif
//____________________________________________________________________________//
#if defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_TEST_DYN_LINK)
# define BOOST_TEST_DYN_LINK
#endif
// in case any of the define from cmake/b2 is set
#if !defined(BOOST_TEST_DYN_LINK) \
&& (defined(BOOST_UNIT_TEST_FRAMEWORK_DYN_LINK) \
|| defined(BOOST_TEST_EXEC_MONITOR_DYN_LINK) \
|| defined(BOOST_PRG_EXEC_MONITOR_DYN_LINK) )
# define BOOST_TEST_DYN_LINK
#endif
#if defined(BOOST_TEST_INCLUDED)
# undef BOOST_TEST_DYN_LINK
#endif
@@ -90,12 +107,12 @@ class type_info;
# define BOOST_TEST_ALTERNATIVE_INIT_API
# ifdef BOOST_TEST_SOURCE
# define BOOST_TEST_DECL BOOST_SYMBOL_EXPORT
# define BOOST_TEST_DECL BOOST_SYMBOL_EXPORT BOOST_SYMBOL_VISIBLE
# else
# define BOOST_TEST_DECL BOOST_SYMBOL_IMPORT
# define BOOST_TEST_DECL BOOST_SYMBOL_IMPORT BOOST_SYMBOL_VISIBLE
# endif // BOOST_TEST_SOURCE
#else
# define BOOST_TEST_DECL
# define BOOST_TEST_DECL BOOST_SYMBOL_VISIBLE
#endif
#if !defined(BOOST_TEST_MAIN) && defined(BOOST_AUTO_TEST_MAIN)

View File

@@ -26,7 +26,7 @@
# pragma warning(pop)
#endif
#if BOOST_CLANG
#if defined(BOOST_CLANG) && (BOOST_CLANG == 1)
#pragma clang diagnostic pop
#endif

View File

@@ -26,6 +26,8 @@ class master_test_suite_t;
class test_tree_visitor;
class test_observer;
class test_unit_fixture;
class global_fixture;
// singletons
class unit_test_monitor_t;

View File

@@ -13,7 +13,6 @@
#define BOOST_TEST_GLOBAL_TYPEDEF_HPP_021005GER
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/detail/workaround.hpp>
#define BOOST_TEST_L( s ) ::boost::unit_test::const_string( s, sizeof( s ) - 1 )
#define BOOST_TEST_STRINGIZE( s ) BOOST_TEST_L( BOOST_STRINGIZE( s ) )
@@ -71,6 +70,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
@@ -86,6 +100,45 @@ T static_constant<T>::value;
//____________________________________________________________________________//
// helper defines for singletons.
// BOOST_TEST_SINGLETON_CONS should appear in the class body,
// BOOST_TEST_SINGLETON_CONS_IMPL should be in only one translation unit. The
// global instance should be declared by BOOST_TEST_SINGLETON_INST.
#define BOOST_TEST_SINGLETON_CONS_NO_CTOR( type ) \
public: \
static type& instance(); \
private: \
BOOST_DELETED_FUNCTION(type(type const&)) \
BOOST_DELETED_FUNCTION(type& operator=(type const&)) \
BOOST_DEFAULTED_FUNCTION(~type(), {}) \
/**/
#define BOOST_TEST_SINGLETON_CONS( type ) \
BOOST_TEST_SINGLETON_CONS_NO_CTOR(type) \
private: \
BOOST_DEFAULTED_FUNCTION(type(), {}) \
/**/
#define BOOST_TEST_SINGLETON_CONS_IMPL( type ) \
type& type::instance() { \
static type the_inst; return the_inst; \
} \
/**/
//____________________________________________________________________________//
#if defined(__APPLE_CC__) && defined(__GNUC__) && __GNUC__ < 4
#define BOOST_TEST_SINGLETON_INST( inst ) \
static BOOST_JOIN( inst, _t)& inst BOOST_ATTRIBUTE_UNUSED = BOOST_JOIN (inst, _t)::instance();
#else
#define BOOST_TEST_SINGLETON_INST( inst ) \
namespace { BOOST_JOIN( inst, _t)& inst BOOST_ATTRIBUTE_UNUSED = BOOST_JOIN( inst, _t)::instance(); }
#endif
} // namespace unit_test
} // namespace boost

View File

@@ -12,6 +12,8 @@
#ifndef BOOST_TEST_LOG_LEVEL_HPP_011605GER
#define BOOST_TEST_LOG_LEVEL_HPP_011605GER
#include <boost/test/detail/config.hpp>
namespace boost {
namespace unit_test {
@@ -20,7 +22,7 @@ namespace unit_test {
// ************************************************************************** //
// each log level includes all subsequent higher loging levels
enum log_level {
enum BOOST_TEST_ENUM_SYMBOL_VISIBLE log_level {
invalid_log_level = -1,
log_successful_tests = 0,
log_test_units = 1,

View File

@@ -26,13 +26,15 @@
# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated
#endif
#if BOOST_CLANG
#if defined(BOOST_CLANG) && (BOOST_CLANG == 1)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wvariadic-macros"
# pragma clang diagnostic ignored "-Wmissing-declarations"
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 4 * 10000 + 6 * 100)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wvariadic-macros"
# pragma GCC diagnostic ignored "-Wmissing-declarations"
#endif

View File

@@ -33,7 +33,7 @@ namespace ut_detail {
template<typename E>
BOOST_NORETURN inline void
throw_exception(E const& e) { abort(); }
throw_exception(E const& /*e*/) { abort(); }
#define BOOST_TEST_I_TRY
#define BOOST_TEST_I_CATCH( T, var ) for(T const& var = *(T*)0; false;)

View File

@@ -1,56 +0,0 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
//!@file
//!@brief contains mics. workarounds
// ***************************************************************************
#ifndef BOOST_TEST_WORKAROUND_HPP_021005GER
#define BOOST_TEST_WORKAROUND_HPP_021005GER
// Boost
#include <boost/config.hpp> // compilers workarounds and std::ptrdiff_t
// STL
#include <iterator> // for std::distance
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace ut_detail {
#ifdef BOOST_NO_STD_DISTANCE
template <class T>
std::ptrdiff_t distance( T const& x_, T const& y_ )
{
std::ptrdiff_t res = 0;
std::distance( x_, y_, res );
return res;
}
//____________________________________________________________________________//
#else
using std::distance;
#endif
template <class T> inline void ignore_unused_variable_warning(const T&) {}
} // namespace ut_detail
} // namespace unit_test
} // namespace boost
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_WORKAROUND_HPP_021005GER

View File

@@ -111,7 +111,8 @@ namespace boost {
///
/// @section DesignRationale Design Rationale
///
/// The Execution Monitor design assumes that it can be used when no (or almost no) memory available. Also the Execution Monitor is intended to be portable to as many platforms as possible.
/// The Execution Monitor design assumes that it can be used when no (or almost no) memory available. Also the Execution Monitor
/// is intended to be portable to as many platforms as possible.
///
/// @section UserGuide User's guide
/// The Execution Monitor is designed to solve the problem of executing potentially dangerous function that may result in any number of error conditions,
@@ -237,7 +238,7 @@ protected:
/// this class never allocates any memory and assumes that strings it refers to are either some constants or live in a some kind of persistent (preallocated) memory.
// ************************************************************************** //
class BOOST_TEST_DECL execution_exception {
class BOOST_SYMBOL_VISIBLE execution_exception {
typedef boost::unit_test::const_string const_string;
public:
/// These values are sometimes used as program return codes.
@@ -270,6 +271,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
@@ -336,9 +338,9 @@ public:
/// Specifies the seconds that elapse before a timer_error occurs.
///
/// The @em p_timeout property is an integer timeout (in seconds) for monitored function execution. Use this parameter to monitor code with possible deadlocks
/// or indefinite loops. This feature is only available for some operating systems (not yet Microsoft Windows).
unit_test::readwrite_property<unsigned> p_timeout;
/// The @em p_timeout property is an integer timeout (in microseconds) for monitored function execution. Use this parameter to monitor code with possible deadlocks
/// or infinite loops. This feature is only available for some operating systems (not yet Microsoft Windows).
unit_test::readwrite_property<unsigned long int> p_timeout;
/// Should monitor use alternative stack for the signal catching.
///
@@ -514,8 +516,12 @@ enum masks {
BOOST_FPE_ALL = MCW_EM,
#elif !defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)/* *** */
BOOST_FPE_DIVBYZERO = BOOST_FPE_OFF,
BOOST_FPE_INEXACT = BOOST_FPE_OFF,
BOOST_FPE_INVALID = BOOST_FPE_OFF,
BOOST_FPE_OVERFLOW = BOOST_FPE_OFF,
BOOST_FPE_UNDERFLOW = BOOST_FPE_OFF,
BOOST_FPE_ALL = BOOST_FPE_OFF,
#else /* *** */
#if defined(FE_DIVBYZERO)

View File

@@ -18,8 +18,6 @@
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
// STL
@@ -74,7 +72,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 +130,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( global_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( global_fixture& tuf );
/// @}
/// @name Assertion/uncaught exception context support
/// @{
/// Context accessor
@@ -178,6 +192,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 +254,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 {

View File

@@ -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
@@ -80,14 +80,16 @@ compiler_log_formatter::log_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
compiler_log_formatter::log_build_info( std::ostream& output )
compiler_log_formatter::log_build_info( std::ostream& output, bool log_build_info )
{
output << "Platform: " << BOOST_PLATFORM << '\n'
<< "Compiler: " << BOOST_COMPILER << '\n'
<< "STL : " << BOOST_STDLIB << '\n'
<< "Boost : " << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << std::endl;
if(log_build_info) {
output << "Platform: " << BOOST_PLATFORM << '\n'
<< "Compiler: " << BOOST_COMPILER << '\n'
<< "STL : " << BOOST_STDLIB << '\n'
<< "Boost : " << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << std::endl;
}
}
//____________________________________________________________________________//
@@ -182,30 +184,25 @@ compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data co
switch( let ) {
case BOOST_UTL_ET_INFO:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
if( m_color_output )
output << setcolor( term_attr::BRIGHT, term_color::GREEN );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::GREEN );
output << "info: ";
break;
case BOOST_UTL_ET_MESSAGE:
if( m_color_output )
output << setcolor( term_attr::BRIGHT, term_color::CYAN );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::CYAN );
break;
case BOOST_UTL_ET_WARNING:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
if( m_color_output )
output << setcolor( term_attr::BRIGHT, term_color::YELLOW );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::YELLOW );
output << "warning: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
if( m_color_output )
output << setcolor( term_attr::BRIGHT, term_color::RED );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::RED );
output << "error: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_FATAL_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
if( m_color_output )
output << setcolor( term_attr::UNDERLINE, term_color::RED );
output << setcolor( m_color_output, term_attr::UNDERLINE, term_color::RED );
output << "fatal error: in \"" << test_phase_identifier() << "\": ";
break;
}
@@ -233,7 +230,7 @@ void
compiler_log_formatter::log_entry_finish( std::ostream& output )
{
if( m_color_output )
output << utils::setcolor();
output << utils::setcolor(m_color_output);
output << std::endl;
}
@@ -260,21 +257,29 @@ compiler_log_formatter::print_prefix( std::ostream& output, const_string file_na
void
compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
{
output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
if( l == log_messages ) {
output << "\n[context:";
}
else {
output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::entry_context_finish( std::ostream& output )
compiler_log_formatter::entry_context_finish( std::ostream& output, log_level l )
{
if( l == log_messages ) {
output << "]";
}
output.flush();
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_context( std::ostream& output, const_string context_descr )
compiler_log_formatter::log_entry_context( std::ostream& output, log_level /*l*/, const_string context_descr )
{
output << "\n " << context_descr;
}

View File

@@ -17,12 +17,13 @@
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/workaround.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/debug.hpp>
#include <boost/test/debug_config.hpp>
#include <boost/core/ignore_unused.hpp>
// Implementation on Windows
#if defined(_WIN32) && !defined(UNDER_CE) && !defined(BOOST_DISABLE_WIN32) // ******* WIN32
@@ -768,7 +769,7 @@ struct safe_handle_helper
}
}
~safe_handle_helper()
~safe_handle_helper()
{
close_handle();
}
@@ -804,7 +805,7 @@ attach_debugger( bool break_or_continue )
if( !dbg_init_done_ev )
return false;
safe_handle_helper safe_handle_obj( dbg_init_done_ev );
// *************************************************** //
@@ -822,7 +823,7 @@ attach_debugger( bool break_or_continue )
DWORD format_size = MAX_CMD_LINE;
DWORD type = REG_SZ;
bool b_read_key = s_info.m_reg_query_value &&
bool b_read_key = s_info.m_reg_query_value &&
((*s_info.m_reg_query_value)(
reg_key, // handle of open key
"Debugger", // name of subkey to query
@@ -833,7 +834,7 @@ attach_debugger( bool break_or_continue )
if( !s_info.m_reg_close_key || (*s_info.m_reg_close_key)( reg_key ) != ERROR_SUCCESS )
return false;
if( !b_read_key )
return false;
@@ -938,7 +939,7 @@ attach_debugger( bool break_or_continue )
return true;
#else // ****************************************************** default
(void) break_or_continue; // silence 'unused variable' warning
return false;
#endif
@@ -953,7 +954,7 @@ attach_debugger( bool break_or_continue )
void
detect_memory_leaks( bool on_off, unit_test::const_string report_file )
{
unit_test::ut_detail::ignore_unused_variable_warning( on_off );
boost::ignore_unused( on_off );
#ifdef BOOST_MS_CRT_BASED_DEBUG
int flags = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
@@ -975,7 +976,7 @@ detect_memory_leaks( bool on_off, unit_test::const_string report_file )
_CrtSetDbgFlag ( flags );
#else
unit_test::ut_detail::ignore_unused_variable_warning( report_file );
boost::ignore_unused( report_file );
#endif // BOOST_MS_CRT_BASED_DEBUG
}
@@ -989,7 +990,7 @@ detect_memory_leaks( bool on_off, unit_test::const_string report_file )
void
break_memory_alloc( long mem_alloc_order_num )
{
unit_test::ut_detail::ignore_unused_variable_warning( mem_alloc_order_num );
boost::ignore_unused( mem_alloc_order_num );
#ifdef BOOST_MS_CRT_BASED_DEBUG
// only set the value if one was supplied (do not use default used by UTF just as a indicator to enable leak detection)
@@ -1006,4 +1007,3 @@ break_memory_alloc( long mem_alloc_order_num )
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DEBUG_API_IPP_112006GER

View File

@@ -5,10 +5,6 @@
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : unit test decorators implementation
// ***************************************************************************
@@ -35,13 +31,17 @@ 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() );
m_tu_decorators_stack.begin()->push_back( d.clone() );
return *this;
}
@@ -49,17 +49,41 @@ 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() );
tu.p_decorators.value.insert(
tu.p_decorators.value.end(),
m_tu_decorators_stack.begin()->begin(),
m_tu_decorators_stack.begin()->end() );
}
//____________________________________________________________________________//
void
collector::reset()
collector_t::reset()
{
m_tu_decorators.clear();
if(m_tu_decorators_stack.size() > 1) {
m_tu_decorators_stack.erase(m_tu_decorators_stack.begin());
}
else {
assert(m_tu_decorators_stack.size() == 1);
m_tu_decorators_stack.begin()->clear();
}
}
void
collector_t::stack()
{
assert(m_tu_decorators_stack.size() >= 1);
m_tu_decorators_stack.insert(m_tu_decorators_stack.begin(), std::vector<base_ptr>());
}
//____________________________________________________________________________//
std::vector<base_ptr>
collector_t::get_lazy_decorators() const
{
return *m_tu_decorators_stack.begin();
}
//____________________________________________________________________________//
@@ -68,10 +92,28 @@ collector::reset()
// ************** decorator::base ************** //
// ************************************************************************** //
collector&
collector_t&
base::operator*() const
{
return collector::instance() * *this;
return collector_t::instance() * *this;
}
// ************************************************************************** //
// ************** decorator::stack_decorator ************** //
// ************************************************************************** //
collector_t&
stack_decorator::operator*() const
{
collector_t& instance = collector_t::instance();
instance.stack();
return instance * *this;
}
void
stack_decorator::apply( test_unit& tu )
{
// does nothing by definition
}
// ************************************************************************** //

View File

@@ -23,7 +23,6 @@
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/workaround.hpp>
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/debug.hpp>
@@ -35,6 +34,7 @@
#ifndef BOOST_NO_EXCEPTIONS
#include <boost/exception/get_error_info.hpp> // for get_error_info
#include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
#include <boost/exception/diagnostic_information.hpp>
#endif
// STL
@@ -47,28 +47,32 @@
#include <cassert> // for assert
#include <cstddef> // for NULL
#include <cstdio> // for vsnprintf
#include <stdio.h>
#include <cstdarg> // for varargs
#include <stdarg.h>
#include <cmath> // for ceil
#include <iostream> // for varargs
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strerror; using ::strlen; using ::strncat; }
namespace std { using ::strerror; using ::strlen; using ::strncat; using ::ceil; }
#endif
// to use vsnprintf
#if defined(__SUNPRO_CC) || defined(__SunOS)
# include <stdio.h>
# include <stdarg.h>
#if defined(__SUNPRO_CC) || defined(__SunOS) || defined(__QNXNTO__) || defined(__VXWORKS__)
using std::va_list;
#endif
// to use vsnprintf
#if defined(__QNXNTO__)
# include <stdio.h>
using std::va_list;
#if defined(__VXWORKS__)
# define BOOST_TEST_LIMITED_SIGNAL_DETAILS
#endif
#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
# if !defined(_WIN32_WINNT) // WinXP
# define _WIN32_WINNT 0x0501
# endif
# include <windows.h>
# if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
@@ -102,6 +106,10 @@ using std::va_list;
# define BOOST_TEST_CRT_SET_HOOK(H) (void*)(H)
# endif
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) /* WinXP */
# define BOOST_TEST_WIN32_WAITABLE_TIMERS
# endif
# if (!BOOST_WORKAROUND(_MSC_VER, >= 1400 ) && \
!defined(BOOST_COMO)) || defined(UNDER_CE)
@@ -210,7 +218,8 @@ namespace detail {
# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
#elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
defined(UNDER_CE)
defined(UNDER_CE) || \
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
#else
# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
@@ -363,11 +372,17 @@ system_signal_exception::report() const
return; // no error actually occur?
switch( m_sig_info->si_code ) {
#ifdef __VXWORKS__
// a bit of a hack to adapt code to small m_sig_info VxWorks uses
#define si_addr si_value.sival_int
#define si_band si_value.sival_int
#else
case SI_USER:
report_error( execution_exception::system_error,
"signal: generated by kill() (or family); uid=%d; pid=%d",
(int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
break;
#endif
case SI_QUEUE:
report_error( execution_exception::system_error,
"signal: sent by sigqueue()" );
@@ -686,7 +701,7 @@ signal_action::~signal_action()
class signal_handler {
public:
// Constructor
explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack );
explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout_microseconds, bool attach_dbg, char* alt_stack );
// Destructor
~signal_handler();
@@ -709,7 +724,7 @@ public:
private:
// Data members
signal_handler* m_prev_handler;
unsigned m_timeout;
unsigned m_timeout_microseconds;
// Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
signal_action m_ILL_action;
@@ -733,24 +748,24 @@ signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
//____________________________________________________________________________//
signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack )
signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout_microseconds, bool attach_dbg, char* alt_stack )
: m_prev_handler( s_active_handler )
, m_timeout( timeout )
, m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
, m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
, m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
, m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
, m_timeout_microseconds( timeout_microseconds )
, m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
, m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
, m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
, m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
#ifdef BOOST_TEST_CATCH_SIGPOLL
, m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
, m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
#endif
, m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
, m_ALRM_action( SIGALRM, timeout > 0 , attach_dbg, alt_stack )
, m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
, m_ALRM_action( SIGALRM, timeout_microseconds > 0, attach_dbg, alt_stack )
{
s_active_handler = this;
if( m_timeout > 0 ) {
if( m_timeout_microseconds > 0 ) {
::alarm( 0 );
::alarm( timeout );
::alarm( static_cast<unsigned int>(std::ceil(timeout_microseconds / 1E6) )); // alarm has a precision to the seconds
}
#ifdef BOOST_TEST_USE_ALT_STACK
@@ -776,7 +791,7 @@ signal_handler::~signal_handler()
{
assert( s_active_handler == this );
if( m_timeout > 0 )
if( m_timeout_microseconds > 0 )
::alarm( 0 );
#ifdef BOOST_TEST_USE_ALT_STACK
@@ -892,8 +907,10 @@ public:
, m_se_id( 0 )
, m_fault_address( 0 )
, m_dir( false )
, m_timeout( false )
{}
void set_timed_out();
void report() const;
int operator()( unsigned id, _EXCEPTION_POINTERS* exps );
@@ -904,6 +921,7 @@ private:
unsigned m_se_id;
void* m_fault_address;
bool m_dir;
bool m_timeout;
};
//____________________________________________________________________________//
@@ -918,6 +936,14 @@ seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
//____________________________________________________________________________//
void
system_signal_exception::set_timed_out()
{
m_timeout = true;
}
//____________________________________________________________________________//
int
system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
{
@@ -1069,7 +1095,12 @@ system_signal_exception::report() const
break;
default:
detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
if( m_timeout ) {
detail::report_error(execution_exception::timeout_error, "timeout while executing function");
}
else {
detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
}
break;
}
}
@@ -1128,6 +1159,31 @@ execution_monitor::catch_signals( boost::function<int ()> const& F )
#endif
}
#if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
HANDLE htimer = INVALID_HANDLE_VALUE;
BOOL bTimerSuccess = FALSE;
if( p_timeout ) {
htimer = ::CreateWaitableTimer(
NULL,
TRUE,
TEXT("Boost.Test timer"));
if( htimer != INVALID_HANDLE_VALUE ) {
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = - static_cast<signed long int>(p_timeout) * 10; // resolution of 100 ns
bTimerSuccess = ::SetWaitableTimer(
htimer,
&liDueTime,
0,
0,
0,
FALSE); // Do not restore a suspended system
}
}
#endif
detail::system_signal_exception SSE( this );
int ret_val = 0;
@@ -1141,8 +1197,26 @@ execution_monitor::catch_signals( boost::function<int ()> const& F )
__except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
throw SSE;
}
// we check for time outs: we do not have any signaling facility on Win32
// however, we signal a timeout as a hard error as for the other operating systems
// and throw the signal error handler
if( bTimerSuccess && htimer != INVALID_HANDLE_VALUE) {
if (::WaitForSingleObject(htimer, 0) == WAIT_OBJECT_0) {
SSE.set_timed_out();
throw SSE;
}
}
}
__finally {
#if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
if( htimer != INVALID_HANDLE_VALUE ) {
::CloseHandle(htimer);
}
#endif
if( l_catch_system_errors ) {
BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
@@ -1198,7 +1272,7 @@ execution_monitor::execute( boost::function<int ()> const& F )
BOOST_TEST_I_TRY {
detail::fpe_except_guard G( p_detect_fp_exceptions );
unit_test::ut_detail::ignore_unused_variable_warning( G );
boost::ignore_unused( G );
return catch_signals( F );
}
@@ -1217,6 +1291,16 @@ execution_monitor::execute( boost::function<int ()> const& F )
{ detail::report_error( execution_exception::cpp_exception_error,
"std::string: %s", ex.c_str() ); }
// boost::exception (before std::exception, with extended diagnostic)
catch( boost::exception const& ex )
{ detail::report_error( execution_exception::cpp_exception_error,
&ex,
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
"unknown boost::exception" ); }
#else
boost::diagnostic_information(ex).c_str() ); }
#endif
// std:: exceptions
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
@@ -1235,15 +1319,8 @@ execution_monitor::execute( boost::function<int ()> const& F )
#endif
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
#else
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
#endif
CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
@@ -1257,15 +1334,6 @@ execution_monitor::execute( boost::function<int ()> const& F )
CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
#undef CATCH_AND_REPORT_STD_EXCEPTION
catch( boost::exception const& ex )
{ detail::report_error( execution_exception::cpp_exception_error,
&ex,
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
"unknown boost::exception" ); }
#else
typeid(ex).name() ); }
#endif
// system errors
catch( system_error const& ex )
{ detail::report_error( execution_exception::cpp_exception_error,
@@ -1342,6 +1410,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 )
{}
//____________________________________________________________________________//
// ************************************************************************** //

View File

@@ -27,12 +27,14 @@
#include <boost/test/results_collector.hpp>
#include <boost/test/progress_monitor.hpp>
#include <boost/test/results_reporter.hpp>
#include <boost/test/test_framework_init_observer.hpp>
#include <boost/test/tree/observer.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/traverse.hpp>
#include <boost/test/tree/test_case_counter.hpp>
#include <boost/test/tree/global_fixture.hpp>
#if BOOST_TEST_SUPPORT_TOKEN_ITERATOR
#include <boost/test/utils/iterator/token_iterator.hpp>
@@ -46,7 +48,7 @@
#include <boost/test/detail/throw_exception.hpp>
// Boost
#include <boost/timer.hpp>
#include <boost/test/utils/timer.hpp>
#include <boost/bind.hpp>
// STL
@@ -56,6 +58,10 @@
#include <cstdlib>
#include <ctime>
#include <numeric>
#include <cmath>
#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
#include <iterator>
#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::time; using ::srand; }
@@ -68,6 +74,7 @@ namespace std { using ::time; using ::srand; }
namespace boost {
namespace unit_test {
namespace framework {
namespace impl {
// ************************************************************************** //
@@ -342,12 +349,10 @@ public:
, m_dep_collector( dep_collector )
{}
private:
// test_tree_visitor interface
virtual bool visit( test_unit const& tu )
{
const_cast<test_unit&>(tu).p_run_status.value = m_new_status == test_unit::RS_INVALID ? tu.p_default_status : m_new_status;
if( m_dep_collector ) {
BOOST_TEST_FOREACH( test_unit_id, dep_id, tu.p_dependencies.get() ) {
test_unit const& dep = framework::get( dep_id, TUT_ANY );
@@ -364,6 +369,7 @@ private:
return true;
}
private:
// Data members
test_unit::run_status m_new_status;
test_unit_id_list* m_dep_collector;
@@ -435,18 +441,59 @@ parse_filters( test_unit_id master_tu_id, test_unit_id_list& tu_to_enable, test_
//____________________________________________________________________________//
#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
// a poor man's implementation of random_shuffle
template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc &r )
{
typedef typename std::iterator_traits<RandomIt>::difference_type difference_type;
difference_type n = last - first;
for (difference_type i = n-1; i > 0; --i) {
difference_type j = r(i+1);
if (j != i) {
using std::swap;
swap(first[i], first[j]);
}
}
}
#endif
// A simple handle for registering the global fixtures to the master test suite
// without deleting an existing static object (the global fixture itself) when the program
// terminates (shared_ptr).
class global_fixture_handle : public test_unit_fixture {
public:
global_fixture_handle(test_unit_fixture* fixture) : m_global_fixture(fixture) {}
~global_fixture_handle() {}
virtual void setup() {
m_global_fixture->setup();
}
virtual void teardown() {
m_global_fixture->teardown();
}
private:
test_unit_fixture* m_global_fixture;
};
} // namespace impl
// ************************************************************************** //
// ************** framework::state ************** //
// ************************************************************************** //
unsigned const TIMEOUT_EXCEEDED = static_cast<unsigned>( -1 );
unsigned long int const TIMEOUT_EXCEEDED = static_cast<unsigned long int>( -1 );
class state {
public:
state()
: m_curr_test_case( INV_TEST_UNIT_ID )
: m_master_test_suite( 0 )
, 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 )
@@ -565,13 +612,27 @@ public:
tu_to_enable.pop_back();
// 35. Ignore test units which already enabled
// 35. Ignore test units which are already enabled
if( tu.is_enabled() )
continue;
// set new status and add all dependencies into tu_to_enable
set_run_status enabler( test_unit::RS_ENABLED, &tu_to_enable );
traverse_test_tree( tu.p_id, enabler, true );
// Add the dependencies of the parent suites, see trac #13149
test_unit_id parent_id = tu.p_parent_id;
while( parent_id != INV_TEST_UNIT_ID
&& parent_id != master_tu_id )
{
// we do not use the traverse_test_tree as otherwise it would enable the sibblings and subtree
// of the test case we want to enable (we need to enable the parent suites and their dependencies only)
// the parent_id needs to be enabled in order to be properly parsed by finalize_run_status, the visit
// does the job
test_unit& tu_parent = framework::get( parent_id, TUT_ANY );
enabler.visit( tu_parent );
parent_id = tu_parent.p_parent_id;
}
}
// 40. Apply all disablers
@@ -603,9 +664,9 @@ 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,
unsigned long int timeout_microseconds = 0,
random_generator_helper const * const p_random_generator = 0)
{
test_unit const& tu = framework::get( tu_id, TUT_ANY );
@@ -617,15 +678,16 @@ public:
// 10. Check preconditions, including zero time left for execution and
// successful execution of all dependencies
if( timeout == TIMEOUT_EXCEEDED ) {
if( timeout_microseconds == TIMEOUT_EXCEEDED ) {
// notify all observers about skipped test unit
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
to->test_unit_skipped( tu, "timeout for the test unit is exceeded" );
return unit_test_monitor_t::os_timeout;
}
else if( timeout == 0 || timeout > tu.p_timeout ) // deduce timeout for this test unit
timeout = tu.p_timeout;
else if( timeout_microseconds == 0 || (tu.p_timeout > 0 && timeout_microseconds > (tu.p_timeout * 1000000) ) ) // deduce timeout for this test unit
timeout_microseconds = tu.p_timeout * 1000000;
test_tools::assertion_result const precondition_res = tu.check_preconditions();
if( !precondition_res ) {
@@ -633,7 +695,10 @@ public:
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
to->test_unit_skipped( tu, precondition_res.message() );
return unit_test_monitor_t::precondition_failure;
// It is not an error to skip the test if any of the parent tests
// have failed. This one should be reported as skipped as if it was
// disabled
return unit_test_monitor_t::test_ok;
}
// 20. Notify all observers about the start of the test unit
@@ -642,17 +707,27 @@ 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::test_setup_failure;
break;
}
}
// This is the time we are going to spend executing the test unit
unsigned long elapsed = 0;
// This is the time we are going to spend executing the test unit (in microseconds
// as expected by test_observer::test_unit_finish)
unsigned long elapsed_microseconds = 0;
if( result == unit_test_monitor_t::test_ok ) {
// 40. We are going to time the execution
boost::timer tu_timer;
boost::unit_test::timer::timer tu_timer;
// we pass the random generator
const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
if( tu.p_type == TUT_SUITE ) {
test_suite const& ts = static_cast<test_suite const&>( tu );
@@ -661,16 +736,33 @@ public:
typedef std::pair<counter_t,test_unit_id> value_type;
BOOST_TEST_FOREACH( value_type, chld, ts.m_ranked_children ) {
unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
// tu_timer.elapsed() returns nanosec, timeout and child_timeout in microsec
unsigned long int chld_timeout = child_timeout(
timeout_microseconds,
static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) ));
result = (std::min)( result, execute_test_tree( chld.second, chld_timeout ) );
result = (std::min)( result, execute_test_tree( chld.second, chld_timeout, &rand_gen ) );
if( unit_test_monitor.is_critical_error( result ) )
break;
// we check for the time elapsed. If this is too high, we fail the current suite and return from here
elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
if( (timeout_microseconds > 0) && (elapsed_microseconds > timeout_microseconds) && (timeout_microseconds != TIMEOUT_EXCEEDED ) ) {
BOOST_TEST_FOREACH( test_observer*, to, m_observers ) {
to->test_unit_timed_out(tu);
}
result = (std::min)( result, unit_test_monitor_t::os_timeout );
timeout_microseconds = TIMEOUT_EXCEEDED;
//break;
// we continue to explore the children, such that we can at least update their
// status to skipped
}
}
}
else {
// Go through ranges of chldren with the same dependency rank and shuffle them
// Go through ranges of children with the same dependency rank and shuffle them
// independently. Execute each subtree in this order
test_unit_id_list children_with_the_same_rank;
@@ -686,22 +778,37 @@ public:
it++;
}
const random_generator_helper& rand_gen = p_random_generator ? *p_random_generator : random_generator_helper();
#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE
impl::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
#else
std::random_shuffle( children_with_the_same_rank.begin(), children_with_the_same_rank.end(), rand_gen );
#endif
BOOST_TEST_FOREACH( test_unit_id, chld, children_with_the_same_rank ) {
unsigned chld_timeout = child_timeout( timeout, tu_timer.elapsed() );
unsigned long int chld_timeout = child_timeout(
timeout_microseconds,
static_cast<unsigned long int>(microsecond_wall_time(tu_timer.elapsed())) );
result = (std::min)( result, execute_test_tree( chld, chld_timeout, &rand_gen ) );
if( unit_test_monitor.is_critical_error( result ) )
break;
// we check for the time elapsed. If this is too high, we fail the current suite and return from here
elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
if( (timeout_microseconds > 0) && (elapsed_microseconds > timeout_microseconds) && (timeout_microseconds != TIMEOUT_EXCEEDED ) ) {
BOOST_TEST_FOREACH( test_observer*, to, m_observers ) {
to->test_unit_timed_out(tu);
}
result = (std::min)( result, unit_test_monitor_t::os_timeout );
timeout_microseconds = TIMEOUT_EXCEEDED;
//break;
// we continue to explore the children, such that we can at least update their
// status to skipped
}
}
}
}
elapsed = static_cast<unsigned long>( tu_timer.elapsed() * 1e6 );
}
else { // TUT_CASE
test_case const& tc = static_cast<test_case const&>( tu );
@@ -710,18 +817,16 @@ 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 );
elapsed = static_cast<unsigned long>( tu_timer.elapsed() * 1e6 );
// execute the test case body, transforms the time out to seconds
result = unit_test_monitor.execute_and_translate( tc.p_test_func, timeout_microseconds );
elapsed_microseconds = static_cast<unsigned long int>( microsecond_wall_time(tu_timer.elapsed()) );
// cleanup leftover context
m_context.clear();
// restore state and abort if necessary
m_curr_test_case = bkup;
// restore state (scope exit) and abort if necessary
}
}
@@ -729,6 +834,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 ) )
@@ -744,21 +850,21 @@ public:
// notify all observers about completion
BOOST_TEST_REVERSE_FOREACH( test_observer*, to, m_observers )
to->test_unit_finish( tu, elapsed );
to->test_unit_finish( tu, elapsed_microseconds );
return result;
}
//////////////////////////////////////////////////////////////////
unsigned child_timeout( unsigned tu_timeout, double elapsed )
unsigned long int child_timeout( unsigned long tu_timeout_microseconds, unsigned long elpsed_microsec )
{
if( tu_timeout == 0U )
return 0U;
if( tu_timeout_microseconds == 0UL || tu_timeout_microseconds == TIMEOUT_EXCEEDED)
return tu_timeout_microseconds;
unsigned elpsed_sec = static_cast<unsigned>(elapsed); // rounding to number of whole seconds
return tu_timeout > elpsed_sec ? tu_timeout - elpsed_sec : TIMEOUT_EXCEEDED;
return tu_timeout_microseconds > elpsed_microsec ?
tu_timeout_microseconds - elpsed_microsec
: TIMEOUT_EXCEEDED;
}
struct priority_order {
@@ -787,7 +893,7 @@ public:
master_test_suite_t* m_master_test_suite;
std::vector<test_suite*> m_auto_test_suites;
test_unit_id m_curr_test_case;
test_unit_id m_curr_test_unit;
test_unit_store m_test_units;
test_unit_id m_next_test_case_id;
@@ -799,6 +905,8 @@ public:
context_data m_context;
int m_context_idx;
std::set<global_fixture*> m_global_fixtures;
boost::execution_monitor m_aux_em;
std::map<output_format, runtime_config::stream_holder> m_log_sinks;
@@ -838,6 +946,30 @@ struct sum_to_first_only {
bool is_first;
};
void
shutdown_loggers_and_reports()
{
s_frk_state().m_log_sinks.clear();
s_frk_state().m_report_sink.setup( "stderr" );
}
void
unregister_global_fixture_and_configuration()
{
// we make a copy as the set will change in the iteration
std::set<global_fixture*> gfixture_copy(s_frk_state().m_global_fixtures);
BOOST_TEST_FOREACH( global_fixture*, tuf, gfixture_copy ) {
tuf->unregister_from_framework();
}
s_frk_state().m_global_fixtures.clear();
state::observer_store gobserver_copy(s_frk_state().m_observers);
BOOST_TEST_FOREACH( test_observer*, to, gobserver_copy ) {
framework::deregister_observer( *to );
}
s_frk_state().m_observers.clear();
}
void
setup_loggers()
{
@@ -857,8 +989,15 @@ setup_loggers()
unit_test_log.set_format( format );
runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format];
if( runtime_config::has( runtime_config::btrt_log_sink ) )
stream_logger.setup( runtime_config::get<std::string>( runtime_config::btrt_log_sink ) );
if( runtime_config::has( runtime_config::btrt_log_sink ) ) {
// we remove all streams in this case, so we do not specify the format
boost::function< void () > log_cleaner = boost::bind( &unit_test_log_t::set_stream,
&unit_test_log,
boost::ref(std::cout)
);
stream_logger.setup( runtime_config::get<std::string>( runtime_config::btrt_log_sink ),
log_cleaner );
}
unit_test_log.set_stream( stream_logger.ref() );
}
else
@@ -970,7 +1109,6 @@ setup_loggers()
}
}
BOOST_TEST_I_ASSRT( formatter_log_level != invalid_log_level,
boost::runtime::access_to_missing_argument()
<< "Unable to determine the log level from '"
@@ -985,12 +1123,18 @@ setup_loggers()
unit_test_log.set_threshold_level( format, formatter_log_level );
runtime_config::stream_holder& stream_logger = s_frk_state().m_log_sinks[format];
boost::function< void () > log_cleaner = boost::bind( &unit_test_log_t::set_stream,
&unit_test_log,
format,
boost::ref(std::cout) );
if( ++current_format_specs != utils::string_token_iterator() &&
current_format_specs->size() ) {
stream_logger.setup( *current_format_specs );
stream_logger.setup( *current_format_specs,
log_cleaner );
}
else {
stream_logger.setup( formatter->get_default_stream_description() );
stream_logger.setup( formatter->get_default_stream_description(),
log_cleaner );
}
unit_test_log.set_stream( format, stream_logger.ref() );
}
@@ -1036,13 +1180,20 @@ init( init_unit_test_func init_func, int argc, char* argv[] )
results_reporter::set_level( runtime_config::get<report_level>( runtime_config::btrt_report_level ) );
results_reporter::set_format( runtime_config::get<output_format>( runtime_config::btrt_report_format ) );
if( runtime_config::has( runtime_config::btrt_report_sink ) )
s_frk_state().m_report_sink.setup( runtime_config::get<std::string>( runtime_config::btrt_report_sink ) );
if( runtime_config::has( runtime_config::btrt_report_sink ) ) {
boost::function< void () > report_cleaner = boost::bind( &results_reporter::set_stream,
boost::ref(std::cerr)
);
s_frk_state().m_report_sink.setup( runtime_config::get<std::string>( runtime_config::btrt_report_sink ),
report_cleaner );
}
results_reporter::set_stream( s_frk_state().m_report_sink.ref() );
// 40. Register default test observers
register_observer( results_collector );
register_observer( unit_test_log );
register_observer( framework_init_observer );
if( runtime_config::get<bool>( runtime_config::btrt_show_progress ) ) {
progress_monitor.set_stream( std::cout ); // defaults to stdout
@@ -1078,9 +1229,18 @@ finalize_setup_phase( test_unit_id master_tu_id )
master_tu_id = master_test_suite().p_id;
// 10. Apply all decorators to the auto test units
// 10. checks for consistency (duplicate names, etc)
class apply_decorators : public test_tree_visitor {
private:
// test_tree_visitor interface
virtual bool test_suite_start( test_suite const& ts)
{
const_cast<test_suite&>(ts).generate();
const_cast<test_suite&>(ts).check_for_duplicate_test_cases();
return test_tree_visitor::test_suite_start(ts);
}
virtual bool visit( test_unit const& tu )
{
BOOST_TEST_FOREACH( decorator::base_ptr, d, tu.p_decorators.get() )
@@ -1116,6 +1276,13 @@ test_in_progress()
void
shutdown()
{
// shuts down the loggers singleton to avoid any further reference to the
// framework during the destruction of those
impl::shutdown_loggers_and_reports();
// unregisters any global fixture and configuration object
impl::unregister_global_fixture_and_configuration();
// eliminating some fake memory leak reports. See for more details:
// http://connect.microsoft.com/VisualStudio/feedback/details/106937/memory-leaks-reported-by-debug-crt-inside-typeinfo-name
@@ -1235,6 +1402,30 @@ deregister_observer( test_observer& to )
//____________________________________________________________________________//
// ************************************************************************** //
// ************** register_global_fixture ************** //
// ************************************************************************** //
void
register_global_fixture( global_fixture& tuf )
{
impl::s_frk_state().m_global_fixtures.insert( &tuf );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** deregister_global_fixture ************** //
// ************************************************************************** //
void
deregister_global_fixture( global_fixture &tuf )
{
impl::s_frk_state().m_global_fixtures.erase( &tuf );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** add_context ************** //
// ************************************************************************** //
@@ -1363,7 +1554,14 @@ current_auto_test_suite( test_suite* ts, bool push_or_pop )
test_case const&
current_test_case()
{
return get<test_case>( impl::s_frk_state().m_curr_test_case );
return get<test_case>( impl::s_frk_state().m_curr_test_unit );
}
test_unit const&
current_test_unit()
{
return *impl::s_frk_state().m_test_units[impl::s_frk_state().m_curr_test_unit];
}
//____________________________________________________________________________//
@@ -1371,7 +1569,7 @@ current_test_case()
test_unit_id
current_test_case_id()
{
return impl::s_frk_state().m_curr_test_case;
return impl::s_frk_state().m_curr_test_unit;
}
//____________________________________________________________________________//
@@ -1396,6 +1594,17 @@ get( test_unit_id id, test_unit_type t )
// ************** framework::run ************** //
// ************************************************************************** //
template <class Cont>
struct swap_on_delete {
swap_on_delete(Cont& c1, Cont& c2) : m_c1(c1), m_c2(c2){}
~swap_on_delete() {
m_c1.swap(m_c2);
}
Cont& m_c1;
Cont& m_c2;
};
void
run( test_unit_id id, bool continue_test )
{
@@ -1414,39 +1623,93 @@ run( test_unit_id id, bool continue_test )
bool was_in_progress = framework::test_in_progress();
bool call_start_finish = !continue_test || !was_in_progress;
impl::s_frk_state().m_test_in_progress = true;
bool init_ok = true;
const_string setup_error;
if( call_start_finish ) {
// indicates the framework that no test is in progress now if observers need to be notified
impl::s_frk_state().m_test_in_progress = false;
// unit_test::framework_init_observer will get cleared first
BOOST_TEST_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
BOOST_TEST_I_TRY {
impl::s_frk_state().m_aux_em.vexecute( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
unit_test_monitor_t::error_level result = unit_test_monitor.execute_and_translate( boost::bind( &test_observer::test_start, to, tcc.p_count ) );
if( init_ok ) {
if( result != unit_test_monitor_t::test_ok ) {
init_ok = false;
}
else {
if( unit_test::framework_init_observer.has_failed() ) {
init_ok = false;
}
}
}
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
BOOST_TEST_SETUP_ASSERT( false, ex.what() );
if( init_ok ) {
// log only the first error
init_ok = false;
setup_error = ex.what();
}
// break; // we should continue otherwise loggers may have improper structure (XML start missing for instance)
}
}
}
unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
switch( seed ) {
case 0:
break;
case 1:
seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
default:
BOOST_TEST_FRAMEWORK_MESSAGE( "Test cases order is shuffled using seed: " << seed );
std::srand( seed );
if( init_ok ) {
// attaching the global fixtures to the main entry point
test_unit& entry_test_unit = framework::get( id, TUT_ANY );
std::vector<test_unit_fixture_ptr> v_saved_fixture(entry_test_unit.p_fixtures.value.begin(),
entry_test_unit.p_fixtures.value.end());
BOOST_TEST_FOREACH( test_unit_fixture*, tuf, impl::s_frk_state().m_global_fixtures ) {
entry_test_unit.p_fixtures.value.insert( entry_test_unit.p_fixtures.value.begin(),
test_unit_fixture_ptr(new impl::global_fixture_handle(tuf)) );
}
swap_on_delete< std::vector<test_unit_fixture_ptr> > raii_fixture(v_saved_fixture, entry_test_unit.p_fixtures.value);
// now work in progress
impl::s_frk_state().m_test_in_progress = true;
unsigned seed = runtime_config::get<unsigned>( runtime_config::btrt_random_seed );
switch( seed ) {
case 0:
break;
case 1:
seed = static_cast<unsigned>( std::rand() ^ std::time( 0 ) ); // better init using std::rand() ^ ...
BOOST_FALLTHROUGH;
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;
results_reporter::make_report( INV_REPORT_LEVEL, id );
unit_test::framework_init_observer.clear();
if( call_start_finish ) {
BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers )
// indicates the framework that no test is in progress anymore if observers need to be notified
// and this is a teardown, so assertions should not raise any exception otherwise an exception
// might be raised in a dtor of a global fixture
impl::s_frk_state().m_test_in_progress = false;
BOOST_TEST_REVERSE_FOREACH( test_observer*, to, impl::s_frk_state().m_observers ) {
ut_detail::test_unit_id_restore restore_current_test_unit(impl::s_frk_state().m_curr_test_unit, id);
to->test_finish();
}
}
impl::s_frk_state().m_test_in_progress = was_in_progress;
// propagates the init/teardown error if any
BOOST_TEST_SETUP_ASSERT( init_ok && !unit_test::framework_init_observer.has_failed(), setup_error );
}
//____________________________________________________________________________//
@@ -1496,6 +1759,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

View File

@@ -35,6 +35,7 @@
// Boost
#include <boost/version.hpp>
#include <boost/core/ignore_unused.hpp>
// STL
#include <iostream>
@@ -69,6 +70,12 @@ inline std::string tu_name_normalize(std::string full_name)
return full_name;
}
inline std::string tu_name_remove_newlines(std::string full_name)
{
full_name.erase(std::remove(full_name.begin(), full_name.end(), '\n'), full_name.end());
return full_name;
}
const_string file_basename(const_string filename) {
const_string path_sep( "\\/" );
@@ -86,7 +93,7 @@ const_string file_basename(const_string filename) {
// ************************************************************************** //
void
junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
junit_log_formatter::log_start( std::ostream& /*ostr*/, counter_t /*test_cases_amount*/)
{
map_tests.clear();
list_path_to_root.clear();
@@ -96,6 +103,11 @@ junit_log_formatter::log_start( std::ostream& ostr, counter_t test_cases_amount)
//____________________________________________________________________________//
class junit_result_helper : public test_tree_visitor {
private:
typedef junit_impl::junit_log_helper::assertion_entry assertion_entry;
typedef std::vector< assertion_entry >::const_iterator vect_assertion_entry_citerator;
typedef std::list<std::string>::const_iterator list_str_citerator;
public:
explicit junit_result_helper(
std::ostream& stream,
@@ -111,10 +123,19 @@ public:
, m_display_build_info(display_build_info)
{ }
void add_log_entry(std::string const& entry_type,
test_case const& tc,
junit_impl::junit_log_helper::assertion_entry const& log) const
void add_log_entry(assertion_entry const& log) const
{
std::string entry_type;
if( log.log_entry == assertion_entry::log_entry_failure ) {
entry_type = "failure";
}
else if( log.log_entry == assertion_entry::log_entry_error ) {
entry_type = "error";
}
else {
return;
}
m_stream
<< "<" << entry_type
<< " message" << utils::attr_value() << log.logentry_message
@@ -159,24 +180,24 @@ public:
}
};
std::list<std::string> build_skipping_chain(test_case const & tc) const
std::list<std::string> build_skipping_chain(test_unit const & tu) const
{
// we enter here because we know that the tc has been skipped.
// either junit has not seen this tc, or it is indicated as disabled
assert(m_map_test.count(tc.p_id) == 0 || results_collector.results( tc.p_id ).p_skipped);
// we enter here because we know that the tu has been skipped.
// either junit has not seen this tu, or it is indicated as disabled
assert(m_map_test.count(tu.p_id) == 0 || results_collector.results( tu.p_id ).p_skipped);
std::list<std::string> out;
test_unit_id id(tc.p_id);
test_unit_id id(tu.p_id);
while( id != m_ts.p_id && id != INV_TEST_UNIT_ID) {
test_unit const& tu = boost::unit_test::framework::get( id, TUT_ANY );
out.push_back("- disabled test unit: '" + tu.full_name() + "'\n");
test_unit const& tu_hierarchy = boost::unit_test::framework::get( id, TUT_ANY );
out.push_back("- disabled test unit: '" + tu_name_remove_newlines(tu_hierarchy.full_name()) + "'\n");
if(m_map_test.count(id) > 0)
{
// junit has seen the reason: this is enough for constructing the chain
break;
}
id = tu.p_parent_id;
id = tu_hierarchy.p_parent_id;
}
junit_log_formatter::map_trace_t::const_iterator it_element_stack(m_map_test.find(id));
if( it_element_stack != m_map_test.end() )
@@ -188,9 +209,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 +226,50 @@ public:
return classname;
}
void write_testcase_header(test_case const & tc,
test_results const *tr = 0) const
void write_testcase_header(test_unit const & tu,
test_results const *tr,
int nb_assertions) const
{
//
// test case header
std::string name;
std::string classname;
// total number of assertions
m_stream << "<testcase assertions" << utils::attr_value() << tr->p_assertions_passed + tr->p_assertions_failed;
if(tu.p_id == m_ts.p_id ) {
name = "boost_test";
}
else {
classname = get_class_name(tu);
name = tu_name_normalize(tu.p_name);
}
// class name
const std::string classname = get_class_name(tc);
if( tu.p_type == TUT_SUITE ) {
if(tr->p_timed_out)
name += "-timed-execution";
else
name += "-setup-teardown";
}
m_stream << "<testcase assertions" << utils::attr_value() << nb_assertions;
if(!classname.empty())
m_stream << " classname" << utils::attr_value() << classname;
// test case name and time taken
m_stream
<< " name" << utils::attr_value() << tu_name_normalize(tc.p_name)
<< " name" << utils::attr_value() << name
<< " time" << utils::attr_value() << double(tr->p_duration_microseconds) * 1E-6
<< ">" << std::endl;
}
void write_testcase_system_out(junit_impl::junit_log_helper const &detailed_log,
test_case const * tc,
bool skipped,
test_results const *tr = 0) const
test_unit const * tu,
bool skipped) const
{
// system-out + all info/messages, the object skips the empty entries
conditional_cdata_helper system_out_helper(m_stream, "system-out");
// indicate why the test has been skipped first
if( skipped ) {
std::list<std::string> skipping_decision_chain = build_skipping_chain(*tc);
for(std::list<std::string>::const_iterator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
std::list<std::string> skipping_decision_chain = build_skipping_chain(*tu);
for(list_str_citerator it(skipping_decision_chain.begin()), ite(skipping_decision_chain.end());
it != ite;
++it)
{
@@ -246,7 +278,7 @@ public:
}
// stdout
for(std::list<std::string>::const_iterator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
for(list_str_citerator it(detailed_log.system_out.begin()), ite(detailed_log.system_out.end());
it != ite;
++it)
{
@@ -254,25 +286,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 +312,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<std::string>::const_iterator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
for(list_str_citerator it(detailed_log.system_err.begin()), ite(detailed_log.system_err.end());
it != ite;
++it)
{
system_err_helper(*it);
o << *it;
}
if(!detailed_log.system_err.empty())
o << std::endl << "STDERR END ------------" << std::endl;
conditional_cdata_helper system_err_helper(m_stream, "system-err");
system_err_helper(o.str());
}
}
int get_nb_assertions(junit_impl::junit_log_helper const &detailed_log,
test_unit const & tu,
test_results const *tr) const {
int nb_assertions(-1);
if( tu.p_type == TUT_SUITE ) {
nb_assertions = 0;
for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
if(it->log_entry != assertion_entry::log_entry_info)
nb_assertions++;
}
}
else {
nb_assertions = static_cast<int>(tr->p_assertions_passed + tr->p_assertions_failed);
}
return nb_assertions;
}
void output_detailed_logs(junit_impl::junit_log_helper const &detailed_log,
test_case const & tc,
test_unit const & tu,
bool skipped,
test_results const *tr = 0) const
test_results const *tr) const
{
write_testcase_header(tc, tr);
int nb_assertions = get_nb_assertions(detailed_log, tu, tr);
if(!nb_assertions && tu.p_type == TUT_SUITE)
return;
write_testcase_header(tu, tr, nb_assertions);
if( skipped ) {
m_stream << "<skipped/>" << std::endl;
}
else {
for(std::vector< junit_impl::junit_log_helper::assertion_entry >::const_iterator it(detailed_log.assertion_entries.begin());
for(vect_assertion_entry_citerator it(detailed_log.assertion_entries.begin());
it != detailed_log.assertion_entries.end();
++it)
{
if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_failure) {
add_log_entry("failure", tc, *it);
}
else if(it->log_entry == junit_impl::junit_log_helper::assertion_entry::log_entry_error) {
add_log_entry("error", tc, *it);
}
add_log_entry(*it);
}
}
write_testcase_system_out(detailed_log, &tc, skipped, tr);
write_testcase_system_err(detailed_log, &tc, tr);
write_testcase_system_out(detailed_log, &tu, skipped);
write_testcase_system_err(detailed_log, &tu, tr);
m_stream << "</testcase>" << std::endl;
}
@@ -353,35 +415,58 @@ public:
bool test_suite_start( test_suite const& ts )
{
// unique test suite, without s, nesting not supported in CI
if( m_ts.p_id != ts.p_id )
return true;
test_results const& tr = results_collector.results( ts.p_id );
m_stream << "<testsuite";
m_stream
// << "disabled=\"" << tr.p_test_cases_skipped << "\" "
<< " tests" << utils::attr_value() << tr.p_test_cases_passed
<< " skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " errors" << utils::attr_value() << tr.p_test_cases_aborted
<< " failures" << utils::attr_value() << tr.p_test_cases_failed
<< " id" << utils::attr_value() << m_id++
<< " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
<< " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
<< ">" << std::endl;
// unique test suite, without s, nesting not supported in CI
if( m_ts.p_id == ts.p_id ) {
m_stream << "<testsuite";
if(m_display_build_info)
{
m_stream << "<properties>" << std::endl;
m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << std::endl;
m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << std::endl;
m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << std::endl;
// think about: maybe we should add the number of fixtures of a test_suite as
// independant tests (field p_fixtures).
// same goes for the timed-execution: we can think of that as a separate test-unit
// in the suite.
// see https://llg.cubic.org/docs/junit/ and
// http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java?view=markup
m_stream
// << "disabled=\"" << tr.p_test_cases_skipped << "\" "
<< " tests" << utils::attr_value()
<< tr.p_test_cases_passed
+ tr.p_test_cases_failed
// + tr.p_test_cases_aborted // aborted is also failed, we avoid counting it twice
<< " skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " errors" << utils::attr_value() << tr.p_test_cases_aborted
<< " failures" << utils::attr_value()
<< tr.p_test_cases_failed
+ tr.p_test_suites_timed_out
+ tr.p_test_cases_timed_out
- tr.p_test_cases_aborted // failed is not aborted in the Junit sense
<< " id" << utils::attr_value() << m_id++
<< " name" << utils::attr_value() << tu_name_normalize(ts.p_name)
<< " time" << utils::attr_value() << (tr.p_duration_microseconds * 1E-6)
<< ">" << std::endl;
std::ostringstream o;
o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << std::endl;
m_stream << "</properties>" << std::endl;
if(m_display_build_info)
{
m_stream << "<properties>" << std::endl;
m_stream << "<property name=\"platform\" value" << utils::attr_value() << BOOST_PLATFORM << " />" << std::endl;
m_stream << "<property name=\"compiler\" value" << utils::attr_value() << BOOST_COMPILER << " />" << std::endl;
m_stream << "<property name=\"stl\" value" << utils::attr_value() << BOOST_STDLIB << " />" << std::endl;
std::ostringstream o;
o << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100;
m_stream << "<property name=\"boost\" value" << utils::attr_value() << o.str() << " />" << std::endl;
m_stream << "</properties>" << std::endl;
}
}
if( !tr.p_skipped ) {
// if we land here, then this is a chance that we are logging the fixture setup/teardown of a test-suite.
// the setup/teardown logging of a test-case is part of the test case.
// we do not care about the test-suite that were skipped (really??)
junit_log_formatter::map_trace_t::const_iterator it_find = m_map_test.find(ts.p_id);
if(it_find != m_map_test.end()) {
output_detailed_logs(it_find->second, ts, false, &tr);
}
}
return true; // indicates that the children should also be parsed
@@ -389,13 +474,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 << "</testsuite>";
return;
write_testcase_system_out(runner_log, 0, false, 0);
write_testcase_system_err(runner_log, 0, 0);
m_stream << "</testsuite>";
}
}
private:
@@ -439,15 +524,15 @@ junit_log_formatter::log_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
junit_log_formatter::log_build_info( std::ostream& ostr )
junit_log_formatter::log_build_info( std::ostream& /*ostr*/, bool log_build_info )
{
m_display_build_info = true;
m_display_build_info = log_build_info;
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
junit_log_formatter::test_unit_start( std::ostream& /*ostr*/, test_unit const& tu )
{
list_path_to_root.push_back( tu.p_id );
map_tests.insert(std::make_pair(tu.p_id, junit_impl::junit_log_helper())); // current_test_case_id not working here
@@ -457,17 +542,20 @@ junit_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
junit_log_formatter::test_unit_finish( std::ostream& /*ostr*/, test_unit const& tu, unsigned long /*elapsed*/ )
{
// the time is already stored in the result_reporter
boost::ignore_unused( tu );
assert( tu.p_id == list_path_to_root.back() );
list_path_to_root.pop_back();
}
void
junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
junit_log_formatter::test_unit_aborted( std::ostream& /*ostr*/, test_unit const& tu )
{
boost::ignore_unused( tu );
assert( tu.p_id == list_path_to_root.back() );
//list_path_to_root.pop_back();
}
@@ -475,7 +563,26 @@ junit_log_formatter::test_unit_aborted( std::ostream& os, test_unit const& tu )
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu, const_string reason )
junit_log_formatter::test_unit_timed_out( std::ostream& /*os*/, test_unit const& tu)
{
if(tu.p_type == TUT_SUITE)
{
// if we reach this call, it means that the test has already started and
// test_unit_start has already been called on the tu.
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
junit_impl::junit_log_helper::assertion_entry entry;
entry.logentry_message = "test-suite time out";
entry.logentry_type = "execution timeout";
entry.log_entry = junit_impl::junit_log_helper::assertion_entry::log_entry_error;
entry.output = "the current suite exceeded the allocated execution time";
last_entry.assertion_entries.push_back(entry);
}
}
//____________________________________________________________________________//
void
junit_log_formatter::test_unit_skipped( std::ostream& /*ostr*/, test_unit const& tu, const_string reason )
{
// if a test unit is skipped, then the start of this TU has not been called yet.
// we cannot use get_current_log_entry here, but the TU id should appear in the map.
@@ -487,7 +594,7 @@ junit_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu,
//____________________________________________________________________________//
void
junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
junit_log_formatter::log_exception_start( std::ostream& /*ostr*/, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
std::ostringstream o;
execution_exception::location const& loc = ex.where();
@@ -555,7 +662,7 @@ junit_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_dat
//____________________________________________________________________________//
void
junit_log_formatter::log_exception_finish( std::ostream& ostr )
junit_log_formatter::log_exception_finish( std::ostream& /*ostr*/ )
{
// sealing the last entry
assert(!get_current_log_entry().assertion_entries.back().sealed);
@@ -565,7 +672,7 @@ junit_log_formatter::log_exception_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& entry_data, log_entry_types let )
junit_log_formatter::log_entry_start( std::ostream& /*ostr*/, log_entry_data const& entry_data, log_entry_types let )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
last_entry.skipping = false;
@@ -578,7 +685,7 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
last_entry.skipping = true;
break;
}
// no break on purpose
BOOST_FALLTHROUGH;
}
case unit_test_log_formatter::BOOST_UTL_ET_MESSAGE:
{
@@ -586,7 +693,7 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
last_entry.skipping = true;
break;
}
// no break on purpose
BOOST_FALLTHROUGH;
}
case unit_test_log_formatter::BOOST_UTL_ET_WARNING:
{
@@ -638,7 +745,7 @@ junit_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const&
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
junit_log_formatter::log_entry_value( std::ostream& /*ostr*/, const_string value )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
@@ -662,7 +769,7 @@ junit_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_finish( std::ostream& ostr )
junit_log_formatter::log_entry_finish( std::ostream& /*ostr*/ )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(!last_entry.skipping)
@@ -685,7 +792,7 @@ junit_log_formatter::log_entry_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
junit_log_formatter::entry_context_start( std::ostream& /*ostr*/, log_level )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)
@@ -708,7 +815,7 @@ junit_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
junit_log_formatter::entry_context_finish( std::ostream& ostr )
junit_log_formatter::entry_context_finish( std::ostream& /*ostr*/, log_level )
{
// no op, may be removed
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
@@ -720,7 +827,7 @@ junit_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
junit_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
junit_log_formatter::log_entry_context( std::ostream& /*ostr*/, log_level , const_string context_descr )
{
junit_impl::junit_log_helper& last_entry = get_current_log_entry();
if(last_entry.skipping)

View File

@@ -108,6 +108,8 @@ plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostrea
descr = "has passed";
else if( tr.p_skipped )
descr = "was skipped";
else if( tr.p_timed_out )
descr = "has timed out";
else if( tr.p_aborted )
descr = "was aborted";
else
@@ -122,8 +124,9 @@ plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostrea
return;
}
// aborted test case within failed ones, timed-out TC exclusive with failed/aborted
counter_t total_assertions = tr.p_assertions_passed + tr.p_assertions_failed;
counter_t total_tc = tr.p_test_cases_passed + tr.p_test_cases_warned + tr.p_test_cases_failed + tr.p_test_cases_skipped;
counter_t total_tc = tr.p_test_cases_passed + tr.p_test_cases_warned + tr.p_test_cases_failed + tr.p_test_cases_skipped + tr.p_test_cases_timed_out;
if( total_assertions > 0 || total_tc > 0 || tr.p_warnings_failed > 0)
ostr << " with:";
@@ -134,6 +137,8 @@ plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostrea
print_stat_value( ostr, tr.p_test_cases_passed , m_indent, total_tc , "test case", "passed" );
print_stat_value( ostr, tr.p_test_cases_warned , m_indent, total_tc , "test case", "passed with warnings" );
print_stat_value( ostr, tr.p_test_cases_failed , m_indent, total_tc , "test case", "failed" );
print_stat_value( ostr, tr.p_test_cases_timed_out, m_indent, total_tc , "test case", "timed-out" );
print_stat_value( ostr, tr.p_test_suites_timed_out, m_indent, tr.p_test_suites, "test suite", "timed-out" );
print_stat_value( ostr, tr.p_test_cases_skipped, m_indent, total_tc , "test case", "skipped" );
print_stat_value( ostr, tr.p_test_cases_aborted, m_indent, total_tc , "test case", "aborted" );
print_stat_value( ostr, tr.p_assertions_passed , m_indent, total_assertions, "assertion", "passed" );
@@ -174,6 +179,12 @@ plain_report_formatter::do_confirmation_report( test_unit const& tu, std::ostrea
return;
}
if( tr.p_timed_out ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " has timed out"
<< "; see standard output for details\n";
return;
}
if( tr.p_aborted ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was aborted"
<< "; see standard output for details\n";

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

@@ -5,11 +5,9 @@
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implements Unit Test results collecting facility.
/// @file
/// Test results collecting facility.
///
// ***************************************************************************
#ifndef BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
@@ -19,6 +17,7 @@
#include <boost/test/unit_test_log.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/visitor.hpp>
@@ -52,11 +51,31 @@ test_results::test_results()
bool
test_results::passed() const
{
// if it is skipped, it is not passed. However, if any children is not failed/aborted
// then their skipped status is not taken into account.
return !p_skipped &&
p_test_cases_failed == 0 &&
p_assertions_failed <= p_expected_failures &&
p_test_cases_skipped == 0 &&
!p_aborted;
// p_test_cases_skipped == 0 &&
!p_timed_out &&
p_test_cases_timed_out == 0 &&
!aborted();
}
//____________________________________________________________________________//
bool
test_results::aborted() const
{
return p_aborted;
}
//____________________________________________________________________________//
bool
test_results::skipped() const
{
return p_skipped;
}
//____________________________________________________________________________//
@@ -65,7 +84,7 @@ int
test_results::result_code() const
{
return passed() ? exit_success
: ( (p_assertions_failed > p_expected_failures || p_skipped )
: ( (p_assertions_failed > p_expected_failures || p_skipped || p_timed_out || p_test_cases_timed_out )
? exit_test_failure
: exit_exception_failure );
}
@@ -75,6 +94,7 @@ test_results::result_code() const
void
test_results::operator+=( test_results const& tr )
{
p_test_suites.value += tr.p_test_suites;
p_assertions_passed.value += tr.p_assertions_passed;
p_assertions_failed.value += tr.p_assertions_failed;
p_warnings_failed.value += tr.p_warnings_failed;
@@ -83,6 +103,8 @@ test_results::operator+=( test_results const& tr )
p_test_cases_failed.value += tr.p_test_cases_failed;
p_test_cases_skipped.value += tr.p_test_cases_skipped;
p_test_cases_aborted.value += tr.p_test_cases_aborted;
p_test_cases_timed_out.value += tr.p_test_cases_timed_out;
p_test_suites_timed_out.value += tr.p_test_suites_timed_out;
p_duration_microseconds.value += tr.p_duration_microseconds;
}
@@ -91,6 +113,7 @@ test_results::operator+=( test_results const& tr )
void
test_results::clear()
{
p_test_suites.value = 0;
p_assertions_passed.value = 0;
p_assertions_failed.value = 0;
p_warnings_failed.value = 0;
@@ -100,9 +123,12 @@ test_results::clear()
p_test_cases_failed.value = 0;
p_test_cases_skipped.value = 0;
p_test_cases_aborted.value = 0;
p_test_cases_timed_out.value = 0;
p_test_suites_timed_out.value = 0;
p_duration_microseconds.value= 0;
p_aborted.value = false;
p_skipped.value = false;
p_timed_out.value = false;
}
//____________________________________________________________________________//
@@ -123,6 +149,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 )
{
@@ -159,6 +189,8 @@ public:
else
m_tr.p_test_cases_passed.value++;
}
else if( tr.p_timed_out )
m_tr.p_test_cases_timed_out.value++;
else if( tr.p_skipped )
m_tr.p_test_cases_skipped.value++;
else {
@@ -174,6 +206,10 @@ public:
return true;
m_tr += results_collector.results( ts.p_id );
m_tr.p_test_suites.value++;
if( results_collector.results( ts.p_id ).p_timed_out )
m_tr.p_test_suites_timed_out.value++;
return false;
}
@@ -192,6 +228,8 @@ results_collector_t::test_unit_finish( test_unit const& tu, unsigned long elapse
results_collect_helper ch( s_rc_impl().m_results_store[tu.p_id], tu );
traverse_test_tree( tu, ch );
s_rc_impl().m_results_store[tu.p_id].p_duration_microseconds.value = elapsed_in_microseconds;
}
else {
test_results & tr = s_rc_impl().m_results_store[tu.p_id];
@@ -213,7 +251,6 @@ void
results_collector_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.clear();
tr.p_skipped.value = true;
@@ -228,6 +265,15 @@ results_collector_t::test_unit_skipped( test_unit const& tu, const_string /*reas
//____________________________________________________________________________//
void
results_collector_t::test_unit_timed_out(test_unit const& tu)
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.p_timed_out.value = true;
}
//____________________________________________________________________________//
void
results_collector_t::assertion_result( unit_test::assertion_result ar )
{
@@ -246,11 +292,14 @@ results_collector_t::assertion_result( unit_test::assertion_result ar )
//____________________________________________________________________________//
void
results_collector_t::exception_caught( execution_exception const& )
results_collector_t::exception_caught( execution_exception const& ex)
{
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
tr.p_assertions_failed.value++;
if( ex.code() == execution_exception::timeout_error ) {
tr.p_timed_out.value = true;
}
}
//____________________________________________________________________________//

View File

@@ -0,0 +1,117 @@
// (c) Copyright Raffi Enficiaud 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
//! @file
//! An observer for monitoring the success/failure of the other observers
// ***************************************************************************
#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER
// Boost.Test
#include <boost/test/test_framework_init_observer.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
//____________________________________________________________________________//
// ************************************************************************** //
// ************** framework_init_observer_t ************** //
// ************************************************************************** //
namespace {
struct test_init_observer_check {
bool has_failure;
void clear()
{
has_failure = false;
}
};
test_init_observer_check& s_tioc_impl() { static test_init_observer_check the_inst; return the_inst; }
} // local namespace
//____________________________________________________________________________//
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(framework_init_observer_t)
//____________________________________________________________________________//
void
framework_init_observer_t::clear()
{
if(!framework::test_in_progress())
s_tioc_impl().clear();
}
//____________________________________________________________________________//
void
framework_init_observer_t::test_start( counter_t )
{
clear();
}
//____________________________________________________________________________//
void
framework_init_observer_t::assertion_result( unit_test::assertion_result ar )
{
test_init_observer_check& tr = s_tioc_impl();
switch( ar ) {
case AR_TRIGGERED: break;
case AR_PASSED: break;
case AR_FAILED: tr.has_failure = true; break;
default:
break;
}
}
//____________________________________________________________________________//
void
framework_init_observer_t::exception_caught( execution_exception const& )
{
test_init_observer_check& tr = s_tioc_impl();
tr.has_failure = true;
}
void
framework_init_observer_t::test_aborted()
{
s_tioc_impl().has_failure = true;
}
//____________________________________________________________________________//
bool
framework_init_observer_t::has_failed() const
{
return s_tioc_impl().has_failure;
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_IPP_021105GER

View File

@@ -16,6 +16,7 @@
#define BOOST_TEST_TEST_TOOLS_IPP_012205GER
// Boost.Test
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_log.hpp>
#include <boost/test/tools/context.hpp>
#include <boost/test/tools/output_test_stream.hpp>
@@ -59,6 +60,13 @@ namespace std { using ::wcscmp; }
#endif
# endif
namespace boost {
namespace unit_test {
// local static variable, needed here for visibility reasons
lazy_ostream lazy_ostream::inst = lazy_ostream();
}}
namespace boost {
namespace test_tools {
namespace tt_detail {
@@ -119,14 +127,6 @@ print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const*
ostr << ( t ? t : L"null string" );
}
#if !defined(BOOST_NO_CXX11_NULLPTR)
void
print_log_value<std::nullptr_t>::operator()( std::ostream& ostr, std::nullptr_t p )
{
ostr << "nullptr";
}
#endif
//____________________________________________________________________________//
// ************************************************************************** //
@@ -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,11 @@ 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() );
// the previous line either throws or aborts and the return below is not reached
// return false;
BOOST_UNREACHABLE_RETURN(false);
}
return true;
@@ -493,7 +505,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 +631,7 @@ output_test_stream::match_pattern( bool flush_stream )
int offset = 0;
std::vector<char> last_elements;
for ( std::string::size_type i = 0; static_cast<int>(i + offset) < static_cast<int>(stream_string_repr.length()); ++i ) {
char c = m_pimpl->get_char();
if( last_elements.size() <= n_chars_presuffix ) {
@@ -698,7 +711,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 +722,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];

View File

@@ -30,12 +30,10 @@
#include <boost/test/unit_test_parameters.hpp>
// Boost
#include <boost/timer.hpp>
// STL
#include <algorithm>
#include <vector>
#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -124,7 +122,7 @@ test_unit::check_preconditions() const
test_results const& test_rslt = unit_test::results_collector.results( dep_id );
if( !test_rslt.passed() ) {
test_tools::assertion_result res(false);
res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << "\" has failed";
res.message() << "dependency test " << dep.p_type_name << " \"" << dep.full_name() << (test_rslt.skipped() ? "\" was skipped":"\" has failed");
return res;
}
@@ -223,7 +221,7 @@ test_case::test_case( const_string name, const_string file_name, std::size_t lin
//____________________________________________________________________________//
test_suite::test_suite( const_string name, const_string file_name, std::size_t line_num )
: test_unit( name, file_name, line_num, static_cast<test_unit_type>(type) )
: test_unit( ut_detail::normalize_test_case_name( name ), file_name, line_num, static_cast<test_unit_type>(type) )
{
framework::register_test_unit( this );
}
@@ -266,19 +264,80 @@ 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) {
decorators.store_in( *tu );
add( tu, 0 );
}
decorators.reset();
}
//____________________________________________________________________________//
void
test_suite::add( boost::shared_ptr<test_unit_generator> gen_ptr, decorator::collector_t& decorators )
{
std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > tmp_p(gen_ptr, decorators.get_lazy_decorators() );
m_generators.push_back(tmp_p);
decorators.reset();
}
//____________________________________________________________________________//
void
test_suite::generate( )
{
typedef std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > element_t;
for(std::vector<element_t>::iterator it(m_generators.begin()), ite(m_generators.end());
it < ite;
++it)
{
test_unit* tu;
while((tu = it->first->next()) != 0) {
tu->p_decorators.value.insert( tu->p_decorators.value.end(), it->second.begin(), it->second.end() );
//it->second.store_in( *tu );
add( tu, 0 );
}
}
m_generators.clear();
#if 0
test_unit* tu;
while((tu = gen.next()) != 0) {
decorators.store_in( *tu );
add( tu, 0 );
}
#endif
}
//____________________________________________________________________________//
void
test_suite::check_for_duplicate_test_cases() {
// check for clashing names #12597
std::set<std::string> names;
for( test_unit_id_list::const_iterator it(m_children.begin()), ite(m_children.end());
it < ite;
++it) {
std::string name = framework::get(*it, TUT_ANY).p_name;
std::pair<std::set<std::string>::iterator, bool> ret = names.insert(name);
BOOST_TEST_SETUP_ASSERT(ret.second,
"test unit with name '"
+ name
+ std::string("' registered multiple times in the test suite '")
+ this->p_name.value
+ "'");
}
return;
}
//____________________________________________________________________________//
void
test_suite::remove( test_unit_id id )
{
@@ -380,9 +439,25 @@ normalize_test_case_name( const_string name )
if( name[0] == '&' )
norm_name = norm_name.substr( 1 );
std::replace(norm_name.begin(), norm_name.end(), ' ', '_');
std::replace(norm_name.begin(), norm_name.end(), ':', '_');
// trim spaces
std::size_t first_not_space = norm_name.find_first_not_of(' ');
if( first_not_space ) {
norm_name.erase(0, first_not_space);
}
std::size_t last_not_space = norm_name.find_last_not_of(' ');
if( last_not_space !=std::string::npos ) {
norm_name.erase(last_not_space + 1);
}
// sanitize all chars that might be used in runtime filters
static const char to_replace[] = { ':', '*', '@', '+', '!', '/' };
for(std::size_t index = 0;
index < sizeof(to_replace)/sizeof(to_replace[0]);
index++) {
std::replace(norm_name.begin(), norm_name.end(), to_replace[index], '_');
}
return norm_name;
}
@@ -393,7 +468,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 );
@@ -403,7 +478,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 );
@@ -426,11 +501,19 @@ 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_t& decorators )
{
framework::current_auto_test_suite().add( tc_gen, decorators );
}
//____________________________________________________________________________//
auto_test_unit_registrar::auto_test_unit_registrar( int )
@@ -446,9 +529,49 @@ auto_test_unit_registrar::auto_test_unit_registrar( int )
// ************** global_fixture ************** //
// ************************************************************************** //
global_fixture::global_fixture()
global_fixture::global_fixture(): registered(false)
{
framework::register_global_fixture( *this );
registered = true;
}
void global_fixture::unregister_from_framework() {
// not accessing the framework singleton after deregistering -> release
// of the observer from the framework
if(registered) {
framework::deregister_global_fixture( *this );
}
registered = false;
}
global_fixture::~global_fixture()
{
this->unregister_from_framework();
}
// ************************************************************************** //
// ************** global_configuration ************** //
// ************************************************************************** //
global_configuration::global_configuration(): registered(false)
{
framework::register_observer( *this );
registered = true;
}
void global_configuration::unregister_from_framework()
{
// not accessing the framework singleton after deregistering -> release
// of the observer from the framework
if(registered) {
framework::deregister_observer( *this );
}
registered = false;
}
global_configuration::~global_configuration()
{
this->unregister_from_framework();
}
//____________________________________________________________________________//

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 )
{
@@ -168,8 +172,11 @@ unit_test_log_t::test_start( counter_t test_cases_amount )
current_logger_data.m_log_formatter->log_start( current_logger_data.stream(), test_cases_amount );
if( runtime_config::get<bool>( runtime_config::btrt_build_info ) )
current_logger_data.m_log_formatter->log_build_info( current_logger_data.stream() );
current_logger_data.m_log_formatter->log_build_info(
current_logger_data.stream(),
runtime_config::get<bool>( runtime_config::btrt_build_info ));
//current_logger_data.stream().flush();
current_logger_data.m_entry_in_progress = false;
}
@@ -261,6 +268,20 @@ unit_test_log_t::test_unit_aborted( test_unit const& tu )
}
}
void
unit_test_log_t::test_unit_timed_out( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( !current_logger_data.m_enabled || current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_timed_out(current_logger_data.stream(), tu );
}
}
//____________________________________________________________________________//
void
@@ -472,14 +493,14 @@ unit_test_log_t::log_entry_context( log_level l )
{
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), frame );
current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame );
}
}
}
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_enabled ) {
current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream() );
current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l );
}
}
}
@@ -523,6 +544,17 @@ unit_test_log_t::set_stream( output_format log_format, std::ostream& str )
}
}
std::ostream*
unit_test_log_t::get_stream( output_format log_format ) const
{
BOOST_TEST_FOREACH( unit_test_log_data_helper_impl&, current_logger_data, s_log_impl().m_log_formatter_data ) {
if( current_logger_data.m_format == log_format) {
return current_logger_data.m_stream;
}
}
return 0;
}
//____________________________________________________________________________//
void

View File

@@ -37,6 +37,7 @@
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <set>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -174,18 +175,34 @@ private:
std::set<std::string> m_labels;
};
struct framework_shutdown_helper {
~framework_shutdown_helper() {
try {
framework::shutdown();
}
catch(...) {
std::cerr << "Boost.Test shutdown exception caught" << std::endl;
}
}
};
} // namespace ut_detail
// ************************************************************************** //
// ************** unit_test_main ************** //
// ************************************************************************** //
int BOOST_TEST_DECL
unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
{
int result_code = 0;
ut_detail::framework_shutdown_helper shutdown_helper;
BOOST_TEST_I_TRY {
framework::init( init_func, argc, argv );
if( runtime_config::get<bool>( runtime_config::btrt_wait_for_debugger ) ) {
@@ -230,8 +247,6 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
framework::run();
results_reporter::make_report();
result_code = !runtime_config::get<bool>( runtime_config::btrt_result_code )
? boost::exit_success
: results_collector.results( framework::master_test_suite().p_id ).result_code();
@@ -249,14 +264,17 @@ unit_test_main( init_unit_test_func init_func, int argc, char* argv[] )
result_code = boost::exit_exception_failure;
}
BOOST_TEST_I_CATCH( std::logic_error, ex ) {
results_reporter::get_stream() << "Test setup error: " << ex.what() << std::endl;
result_code = boost::exit_exception_failure;
}
BOOST_TEST_I_CATCHALL() {
results_reporter::get_stream() << "Boost.Test framework internal error: unknown reason" << std::endl;
result_code = boost::exit_exception_failure;
}
framework::shutdown();
return result_code;
}

View File

@@ -29,16 +29,19 @@
namespace boost {
namespace unit_test {
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(unit_test_monitor_t)
// ************************************************************************** //
// ************** unit_test_monitor ************** //
// ************************************************************************** //
unit_test_monitor_t::error_level
unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned timeout )
unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned long int timeout_microseconds )
{
BOOST_TEST_I_TRY {
p_catch_system_errors.value = runtime_config::get<bool>( runtime_config::btrt_catch_sys_errors );
p_timeout.value = timeout;
p_timeout.value = timeout_microseconds;
p_auto_start_dbg.value = runtime_config::get<bool>( runtime_config::btrt_auto_start_dbg );
p_use_alt_stack.value = runtime_config::get<bool>( runtime_config::btrt_use_alt_stack );
p_detect_fp_exceptions.value = runtime_config::get<bool>( runtime_config::btrt_detect_fp_except );
@@ -47,7 +50,7 @@ unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
framework::test_unit_aborted( framework::current_test_case() );
framework::test_unit_aborted( framework::current_test_unit() );
// translate execution_exception::error_code to error_level
switch( ex.code() ) {

View File

@@ -43,7 +43,6 @@
#include <boost/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#include <boost/test/detail/enable_warnings.hpp>
#include <boost/optional.hpp>
#include <boost/cstdlib.hpp>
// STL
@@ -112,7 +111,7 @@ register_parameters( rt::parameters_store& store )
rt::description = "Automatically attaches debugger in case of system level failure (signal).",
rt::env_var = "BOOST_TEST_AUTO_START_DBG",
rt::help = "Option " + btrt_auto_start_dbg + " specifies whether Boost.Test should attempt "
rt::help = "Specifies whether Boost.Test should attempt "
"to attach a debugger when fatal system error occurs. At the moment this feature "
"is only available on a few selected platforms: Win32 and *nix. There is a "
"default debugger configured for these platforms. You can manually configure "
@@ -145,7 +144,7 @@ register_parameters( rt::parameters_store& store )
rt::option build_info( btrt_build_info, (
rt::description = "Displays library build information.",
rt::env_var = "BOOST_TEST_BUILD_INFO",
rt::help = "Option " + btrt_build_info + " displays library build information, including: platform, "
rt::help = "Displays library build information, including: platform, "
"compiler, STL version and Boost version."
));
@@ -164,7 +163,7 @@ register_parameters( rt::parameters_store& store )
#else
true,
#endif
rt::help = "If option " + btrt_catch_sys_errors + " has value no the frameworks does not attempt to catch "
rt::help = "If option " + btrt_catch_sys_errors + " has value 'no' the frameworks does not attempt to catch "
"asynchronous system failure events (signals on *NIX platforms or structured exceptions on Windows). "
" Default value is "
#ifdef BOOST_TEST_DEFAULTS_TO_CORE_DUMP
@@ -183,9 +182,9 @@ register_parameters( rt::parameters_store& store )
rt::option color_output( btrt_color_output, (
rt::description = "Enables color output of the framework log and report messages.",
rt::env_var = "BOOST_TEST_COLOR_OUTPUT",
rt::help = "The framework is able to produce color output on systems which supports it. "
"To enable this behavior set this option to yes. By default the framework "
"does not produces color output."
rt::default_value = true,
rt::help = "Produces color output for logs, reports and help. "
"Defaults to true. "
));
color_output.add_cla_id( "--", btrt_color_output, "=", true );
@@ -197,7 +196,7 @@ register_parameters( rt::parameters_store& store )
rt::option detect_fp_except( btrt_detect_fp_except, (
rt::description = "Enables/disables floating point exceptions traps.",
rt::env_var = "BOOST_TEST_DETECT_FP_EXCEPTIONS",
rt::help = "Option " + btrt_detect_fp_except + " enables/disables hardware traps for the floating "
rt::help = "Enables/disables hardware traps for the floating "
"point exceptions (if supported on your platfrom)."
));
@@ -212,7 +211,7 @@ register_parameters( rt::parameters_store& store )
rt::default_value = 1L,
rt::optional_value = 1L,
rt::value_hint = "<alloc order number>",
rt::help = "Parameter " + btrt_detect_mem_leaks + " enables/disables memory leaks detection. "
rt::help = "Enables/disables memory leaks detection. "
"This parameter has optional long integer value. The default value is 1, which "
"enables the memory leak detection. The value 0 disables memory leak detection. "
"Any value N greater than 1 is treated as leak allocation number and tells the "
@@ -242,9 +241,9 @@ register_parameters( rt::parameters_store& store )
( "DOT", OF_DOT )
,
#endif
rt::help = "Parameter " + btrt_list_content + " instructs the framework to list the content "
"of the test module instead of executing the test cases. Parameter accepts "
"optional string value indicating the format of the output. Currently the "
rt::help = "Lists the test suites and cases "
"of the test module instead of executing the test cases. The format of the "
"desired output can be passed to the command. Currently the "
"framework supports two formats: human readable format (HRF) and dot graph "
"format (DOT). If value is omitted HRF value is assumed."
));
@@ -285,7 +284,7 @@ register_parameters( rt::parameters_store& store )
( "JUNIT", OF_JUNIT )
,
#endif
rt::help = "Parameter " + btrt_log_format + " allows to set the frameowrk's log format to one "
rt::help = "Set the frameowrk's log format to one "
"of the formats supplied by the framework. The only acceptable values for this "
"parameter are the names of the output formats supplied by the framework. By "
"default the framework uses human readable format (HRF) for testing log. This "
@@ -300,7 +299,7 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
rt::enum_parameter<unit_test::log_level> log_level( btrt_log_level, (
rt::description = "Specifies log level.",
rt::description = "Specifies the logging level of the test execution.",
rt::env_var = "BOOST_TEST_LOG_LEVEL",
rt::default_value = log_all_errors,
rt::enum_values<unit_test::log_level>::value =
@@ -333,8 +332,8 @@ register_parameters( rt::parameters_store& store )
( "nothing" , log_nothing )
,
#endif
rt::help = "Parameter " + btrt_log_level + " allows to set the framework's log level. "
"Log level defines the verbosity of testing log produced by a testing "
rt::help = "Set the framework's log level. "
"The log level defines the verbosity of the testing logs produced by a test "
"module. The verbosity ranges from a complete log, when all assertions "
"(both successful and failing) are reported, all notifications about "
"test units start and finish are included, to an empty log when nothing "
@@ -348,11 +347,11 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
rt::parameter<std::string> log_sink( btrt_log_sink, (
rt::description = "Specifies log sink: stdout(default), stderr or file name.",
rt::description = "Specifies log sink: stdout (default), stderr or file name.",
rt::env_var = "BOOST_TEST_LOG_SINK",
rt::value_hint = "<stderr|stdout|file name>",
rt::help = "Parameter " + btrt_log_sink + " allows to set the log sink - location "
"where we report the log to, thus it allows to easily redirect the "
rt::help = "Sets the log sink - the location "
"where Boost.Test writes the logs of the test execution. It allows to easily redirect the "
"test logs to file or standard streams. By default testing log is "
"directed to standard output."
));
@@ -380,9 +379,8 @@ register_parameters( rt::parameters_store& store )
( "XML", OF_XML )
,
#endif
rt::help = "Parameter " + btrt_output_format + " combines an effect of " + btrt_report_format +
" and " + btrt_log_format + " parameters. This parameter has higher priority "
"than either one of them. In other words if this parameter is specified "
rt::help = "Combines an effect of " + btrt_report_format +
" and " + btrt_log_format + " parameters. If this parameter is specified, "
"it overrides the value of other two parameters. This parameter does not "
"have a default value. The only acceptable values are string names of "
"output formats: HRF - human readable format and XML - XML formats for "
@@ -398,9 +396,12 @@ register_parameters( rt::parameters_store& store )
rt::parameter<std::string,rt::REPEATABLE_PARAM> combined_logger( btrt_combined_logger, (
rt::description = "Specifies log level and sink for one or several log format",
rt::env_var = "BOOST_TEST_LOGGER",
rt::value_hint = "log_format:log_level:log_sink",
rt::help = "Parameter " + btrt_combined_logger + " allows to specify the logger type, level and sink\n"
"in one command."
rt::value_hint = "log_format,log_level,log_sink[:log_format,log_level,log_sink]",
rt::help = "Specify one or more logging definition, which include the logger type, level and sink. "
"The log format, level and sink follow the same format as for the argument '--" + btrt_log_format +
"', '--" + btrt_log_level + "' and '--" + btrt_log_sink + "' respetively. "
"This command can take several logging definition separated by a ':', or be repeated "
"on the command line."
));
combined_logger.add_cla_id( "--", btrt_combined_logger, "=" );
@@ -415,14 +416,14 @@ register_parameters( rt::parameters_store& store )
rt::default_value = 0U,
rt::optional_value = 1U,
rt::value_hint = "<seed>",
rt::help = "Parameter " + btrt_random_seed + " instructs the framework to execute the "
"test cases in random order. This parameter accepts optional unsigned "
"integer argument. By default test cases are executed in some specific "
"order defined by order of test units in test files and dependency between "
"test units. If parameter is specified without the argument value testing "
rt::help = "Instructs the framework to execute the "
"test cases in random order. This parameter accepts an optional unsigned "
"integer argument. If parameter is specified without the argument value testing "
"order is randomized based on current time. Alternatively you can specify "
"any positive value greater than 1 and it will be used as random seed for "
"the run."
"the run. "
"By default, the test cases are executed in an "
"order defined by their declaration and the optional dependencies among the test units."
));
random_seed.add_cla_id( "--", btrt_random_seed, "=" );
@@ -431,7 +432,7 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
rt::enum_parameter<unit_test::output_format> report_format( btrt_report_format, (
rt::description = "Specifies report format.",
rt::description = "Specifies the test report format.",
rt::env_var = "BOOST_TEST_REPORT_FORMAT",
rt::default_value = OF_CLF,
rt::enum_values<unit_test::output_format>::value =
@@ -448,7 +449,7 @@ register_parameters( rt::parameters_store& store )
( "XML", OF_XML )
,
#endif
rt::help = "Parameter " + btrt_report_format + " allows to set the framework's report format "
rt::help = "Set the framework's report format "
"to one of the formats supplied by the framework. The only acceptable values "
"for this parameter are the names of the output formats. By default the framework "
"uses human readable format (HRF) for results reporting. Alternatively you can "
@@ -463,7 +464,7 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
rt::enum_parameter<unit_test::report_level> report_level( btrt_report_level, (
rt::description = "Specifies report level.",
rt::description = "Specifies test report level.",
rt::env_var = "BOOST_TEST_REPORT_LEVEL",
rt::default_value = CONFIRMATION_REPORT,
rt::enum_values<unit_test::report_level>::value =
@@ -482,9 +483,9 @@ register_parameters( rt::parameters_store& store )
( "no", NO_REPORT )
,
#endif
rt::help = "Parameter " + btrt_report_level + " allows to set the verbosity level of the "
"testing result report generated by the framework. Use value 'no' to "
"eliminate the results report completely."
rt::help = "Set the verbosity level of the "
"result report generated by the testing framework. Use value 'no' to "
"disable the results report completely."
));
report_level.add_cla_id( "--", btrt_report_level, "=" );
@@ -512,10 +513,10 @@ register_parameters( rt::parameters_store& store )
rt::description = "Specifies report sink: stderr(default), stdout or file name.",
rt::env_var = "BOOST_TEST_REPORT_SINK",
rt::value_hint = "<stderr|stdout|file name>",
rt::help = "Parameter " + btrt_report_sink + " allows to set the result report sink - "
"the location where the framework writes the result report to, thus it "
"allows to easily redirect the result report to a file or a standard "
"stream. By default the testing result report is directed to the "
rt::help = "Sets the result report sink - "
"the location where the framework writes the result report to. "
"The sink may be a a file or a standard "
"stream. The default is 'stderr': the "
"standard error stream."
));
@@ -541,13 +542,13 @@ register_parameters( rt::parameters_store& store )
///////////////////////////////////////////////
rt::parameter<std::string,rt::REPEATABLE_PARAM> tests_to_run( btrt_run_filters, (
rt::description = "Filters, which test units to include or exclude from test module execution.",
rt::description = "Filters which tests to execute.",
rt::env_var = "BOOST_TEST_RUN_FILTERS",
rt::value_hint = "<test unit filter>",
rt::help = "Parameter " + btrt_run_filters + " allows to filter which test units to execute during "
"testing. The framework supports both 'selection filters', which allow to select "
rt::help = "Filters which test units to execute. "
"The framework supports both 'selection filters', which allow to select "
"which test units to enable from the set of available test units, and 'disabler "
"filters', which allow to disable some test units. The __UTF__ also supports "
"filters', which allow to disable some test units. Boost.test also supports "
"enabling/disabling test units at compile time. These settings identify the default "
"set of test units to run. Parameter " + btrt_run_filters + " is used to change this default. "
"This parameter is repeatable, so you can specify more than one filter if necessary."
@@ -576,8 +577,8 @@ register_parameters( rt::parameters_store& store )
rt::option show_progress( btrt_show_progress, (
rt::description = "Turns on progress display.",
rt::env_var = "BOOST_TEST_SHOW_PROGRESS",
rt::help = "Parameter " + btrt_show_progress + " instructs the framework to display test progress "
"information. By default the test progress is not shown."
rt::help = "Instructs the framework to display the progress of the tests. "
"This feature is turned off by default."
));
show_progress.add_cla_id( "--", btrt_show_progress, "=" );
@@ -590,9 +591,9 @@ register_parameters( rt::parameters_store& store )
rt::description = "Turns on/off usage of an alternative stack for signal handling.",
rt::env_var = "BOOST_TEST_USE_ALT_STACK",
rt::default_value = true,
rt::help = "Parameter " + btrt_use_alt_stack + " instructs the framework to use alternative "
"stack for signals processing, on platforms where they are supported. The feature "
"is enabled by default, but can be disabled using this parameter."
rt::help = "Instructs the framework to use an alternative "
"stack for operating system's signals handling (on platforms where this is supported). "
"The feature is enabled by default, but can be disabled using this command line switch."
));
use_alt_stack.add_cla_id( "--", btrt_use_alt_stack, "=", true );
@@ -603,9 +604,9 @@ register_parameters( rt::parameters_store& store )
rt::option wait_for_debugger( btrt_wait_for_debugger, (
rt::description = "Forces test module to wait for button to be pressed before starting test run.",
rt::env_var = "BOOST_TEST_WAIT_FOR_DEBUGGER",
rt::help = "Parameter " + btrt_wait_for_debugger + " instructs the framework to pause before starting "
"test units execution, so that you can attach a debugger to running test module. By "
"default this parameters turned off."
rt::help = "Instructs the framework to pause before starting "
"test units execution, so that you can attach a debugger to the test module process. "
"This feature is turned off by default."
));
wait_for_debugger.add_cla_id( "--", btrt_wait_for_debugger, "=" );
@@ -618,10 +619,10 @@ register_parameters( rt::parameters_store& store )
rt::description = "Help for framework parameters.",
rt::optional_value = std::string(),
rt::value_hint = "<parameter name>",
rt::help = "Parameter " + btrt_help + " displays help on the framework's parameters. "
rt::help = "Displays help on the framework's parameters. "
"The parameter accepts an optional argument value. If present, an argument value is "
"interpreted as a parameter name (name guessing works as well, so for example "
"--help=rand displays help on the parameter random). If the parameter name is unknown "
"'--help=rand' displays help on the parameter 'random'). If the parameter name is unknown "
"or ambiguous error is reported. If argument value is absent, a summary of all "
"framework's parameter is displayed."
));
@@ -675,17 +676,26 @@ init( int& argc, char** argv )
// Set arguments to default values if defined and perform all the validations
rt::finalize_arguments( s_parameters_store, s_arguments_store );
// check if colorized output is enabled
bool use_color = true;
if( s_arguments_store.has(btrt_color_output ) ) {
use_color = runtime_config::get<bool>(runtime_config::btrt_color_output);
}
// Report help if requested
if( runtime_config::get<bool>( btrt_version ) ) {
parser->version( std::cerr );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
else if( runtime_config::get<bool>( btrt_usage ) ) {
parser->usage( std::cerr );
parser->usage( std::cerr, runtime::cstring(), use_color );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}
else if( s_arguments_store.has( btrt_help ) ) {
parser->help( std::cerr, s_parameters_store, runtime_config::get<std::string>( btrt_help ) );
parser->help(std::cerr,
s_parameters_store,
runtime_config::get<std::string>( btrt_help ),
use_color );
BOOST_TEST_I_THROW( framework::nothing_to_test( boost::exit_success ) );
}

View File

@@ -63,16 +63,18 @@ xml_log_formatter::log_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
xml_log_formatter::log_build_info( std::ostream& ostr )
xml_log_formatter::log_build_info( std::ostream& ostr, bool log_build_info )
{
ostr << "<BuildInfo"
<< " platform" << utils::attr_value() << BOOST_PLATFORM
<< " compiler" << utils::attr_value() << BOOST_COMPILER
<< " stl" << utils::attr_value() << BOOST_STDLIB
<< " boost=\"" << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << '\"'
<< "/>";
if( log_build_info ) {
ostr << "<BuildInfo"
<< " platform" << utils::attr_value() << BOOST_PLATFORM
<< " compiler" << utils::attr_value() << BOOST_COMPILER
<< " stl" << utils::attr_value() << BOOST_STDLIB
<< " boost=\"" << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << '\"'
<< "/>";
}
}
//____________________________________________________________________________//
@@ -199,7 +201,7 @@ xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
//____________________________________________________________________________//
void
xml_log_formatter::entry_context_finish( std::ostream& ostr )
xml_log_formatter::entry_context_finish( std::ostream& ostr, log_level )
{
ostr << BOOST_TEST_L( "</Context>" );
}
@@ -207,7 +209,7 @@ xml_log_formatter::entry_context_finish( std::ostream& ostr )
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
xml_log_formatter::log_entry_context( std::ostream& ostr, log_level, const_string context_descr )
{
ostr << BOOST_TEST_L( "<Frame>" ) << utils::cdata() << context_descr << BOOST_TEST_L( "</Frame>" );
}

View File

@@ -59,6 +59,8 @@ xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream&
descr = "passed";
else if( tr.p_skipped )
descr = "skipped";
else if( tr.p_timed_out )
descr = "timed-out";
else if( tr.p_aborted )
descr = "aborted";
else
@@ -70,14 +72,18 @@ xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream&
<< " assertions_passed" << utils::attr_value() << tr.p_assertions_passed
<< " assertions_failed" << utils::attr_value() << tr.p_assertions_failed
<< " warnings_failed" << utils::attr_value() << tr.p_warnings_failed
<< " expected_failures" << utils::attr_value() << tr.p_expected_failures;
<< " expected_failures" << utils::attr_value() << tr.p_expected_failures
;
if( tu.p_type == TUT_SUITE ) {
ostr << " test_cases_passed" << utils::attr_value() << tr.p_test_cases_passed
<< " test_cases_passed_with_warnings" << utils::attr_value() << tr.p_test_cases_warned
<< " test_cases_failed" << utils::attr_value() << tr.p_test_cases_failed
<< " test_cases_skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " test_cases_aborted" << utils::attr_value() << tr.p_test_cases_aborted;
<< " test_cases_aborted" << utils::attr_value() << tr.p_test_cases_aborted
<< " test_cases_timed_out" << utils::attr_value() << tr.p_test_cases_timed_out
<< " test_suites_timed_out"<< utils::attr_value() << tr.p_test_suites_timed_out
;
}
ostr << '>';

View File

@@ -23,6 +23,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_main.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>

View File

@@ -5,6 +5,7 @@
// See http://www.boost.org/libs/test for the library home page.
//
//
//!@file
//!@brief Included (vs. linked) version of Unit Test Framework
// ***************************************************************************
@@ -24,6 +25,7 @@
#include <boost/test/impl/progress_monitor.ipp>
#include <boost/test/impl/results_collector.ipp>
#include <boost/test/impl/results_reporter.ipp>
#include <boost/test/impl/test_framework_init_observer.ipp>
#include <boost/test/impl/test_tools.ipp>
#include <boost/test/impl/test_tree.ipp>
#include <boost/test/impl/unit_test_log.ipp>
@@ -31,7 +33,6 @@
#include <boost/test/impl/unit_test_monitor.ipp>
#include <boost/test/impl/unit_test_parameters.ipp>
#include <boost/test/impl/xml_log_formatter.ipp>
#include <boost/test/impl/junit_log_formatter.ipp>
#include <boost/test/impl/xml_report_formatter.ipp>
#include <boost/test/unit_test.hpp>

View File

@@ -31,6 +31,9 @@
#ifndef BOOST_TEST_MINIMAL_HPP_071894GER
#define BOOST_TEST_MINIMAL_HPP_071894GER
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "Boost.Test minimal is deprecated. Please convert to the header only variant of Boost.Test." )
#define BOOST_CHECK(exp) \
( (exp) \
? static_cast<void>(0) \

View File

@@ -36,7 +36,7 @@ public:
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount );
void log_finish( std::ostream& );
void log_build_info( std::ostream& );
void log_build_info( std::ostream&, bool );
void test_unit_start( std::ostream&, test_unit const& tu );
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed );
@@ -51,8 +51,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
void log_entry_context( std::ostream&, const_string );
void entry_context_finish( std::ostream& );
void log_entry_context( std::ostream&, log_level l, const_string );
void entry_context_finish( std::ostream&, log_level l );
protected:
virtual void print_prefix( std::ostream&, const_string file, std::size_t line );

View File

@@ -101,12 +101,13 @@ public:
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount );
void log_finish( std::ostream& );
void log_build_info( std::ostream& );
void log_build_info( std::ostream&, bool );
void test_unit_start( std::ostream&, test_unit const& tu );
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed );
void test_unit_skipped( std::ostream&, test_unit const& tu, const_string reason );
void test_unit_aborted( std::ostream& os, test_unit const& tu );
void test_unit_timed_out( std::ostream& os, test_unit const& tu);
void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex );
void log_exception_finish( std::ostream& );
@@ -118,8 +119,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
void log_entry_context( std::ostream&, const_string );
void entry_context_finish( std::ostream& );
void log_entry_context( std::ostream&, log_level, const_string );
void entry_context_finish( std::ostream&, log_level );
//! Discards changes in the log level
virtual void set_log_level(log_level ll)

View File

@@ -39,7 +39,7 @@ public:
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount );
void log_finish( std::ostream& );
void log_build_info( std::ostream& );
void log_build_info( std::ostream&, bool );
void test_unit_start( std::ostream&, test_unit const& tu );
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed );
@@ -54,8 +54,8 @@ public:
void log_entry_finish( std::ostream& );
void entry_context_start( std::ostream&, log_level );
void log_entry_context( std::ostream&, const_string );
void entry_context_finish( std::ostream& );
void log_entry_context( std::ostream&, log_level, const_string );
void entry_context_finish( std::ostream&, log_level );
private:
// Data members

View File

@@ -14,6 +14,7 @@
// Boost.Test
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/utils/string_cast.hpp>
// Boost
#include <boost/type_traits/remove_reference.hpp>
@@ -65,6 +66,7 @@ public:
, m_tc_line( tc_line )
, m_par_begin( par_begin )
, m_par_end( par_end )
, m_index( 0 )
{}
virtual test_unit* next() const
@@ -72,9 +74,10 @@ public:
if( m_par_begin == m_par_end )
return (test_unit*)0;
test_unit* res = new test_case( m_tc_name, m_tc_file, m_tc_line, boost::bind( m_test_func, *m_par_begin ) );
test_unit* res = new test_case( m_tc_name + "_" + utils::string_cast(m_index), m_tc_file, m_tc_line, boost::bind( m_test_func, *m_par_begin ) );
++m_par_begin;
++m_index;
return res;
}
@@ -87,6 +90,7 @@ private:
std::size_t m_tc_line;
mutable ParamIter m_par_begin;
ParamIter m_par_end;
mutable std::size_t m_index;
};
//____________________________________________________________________________//

View File

@@ -14,7 +14,6 @@
// Boost.Test
#include <boost/test/tree/observer.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
// STL
#include <iosfwd> // for std::ostream&
@@ -31,7 +30,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
/// @{
@@ -41,7 +40,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
@@ -49,7 +48,7 @@ public:
void set_stream( std::ostream& );
/// @}
private:
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( progress_monitor_t )
}; // progress_monitor_t

View File

@@ -21,7 +21,6 @@
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -63,6 +62,7 @@ public:
(test_results)
(results_collect_helper) ) bool_prop;
counter_prop p_test_suites; //!< Number of test suites
counter_prop p_assertions_passed; //!< Number of successful assertions
counter_prop p_assertions_failed; //!< Number of failing assertions
counter_prop p_warnings_failed; //!< Number of warnings
@@ -72,13 +72,25 @@ public:
counter_prop p_test_cases_failed; //!< Number of failing test cases
counter_prop p_test_cases_skipped; //!< Number of skipped test cases
counter_prop p_test_cases_aborted; //!< Number of aborted test cases
counter_prop p_test_cases_timed_out; //!< Number of timed out test cases
counter_prop p_test_suites_timed_out; //!< Number of timed out test suites
counter_prop p_duration_microseconds; //!< Duration of the test in microseconds
bool_prop p_aborted; //!< Indicates that the test unit execution has been aborted
bool_prop p_skipped; //!< Indicates that the test unit execution has been skipped
bool_prop p_timed_out; //!< Indicates that the test unit has timed out
/// Returns true if test unit passed
bool passed() const;
/// Returns true if test unit skipped
///
/// 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;
/// Produces result code for the test unit execution
///
/// This methhod return one of the result codes defined in @c boost/cstdlib.hpp
@@ -106,7 +118,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 );
@@ -115,18 +127,19 @@ public:
virtual void test_unit_finish( test_unit const&, unsigned long );
virtual void test_unit_skipped( test_unit const&, const_string );
virtual void test_unit_aborted( test_unit const& );
virtual void test_unit_timed_out( test_unit const& );
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
///
/// @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

@@ -0,0 +1,61 @@
// (c) Copyright Raffi Enficiaud 2017.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
/// @file
/// @brief Defines an observer that monitors the init of the unit test framework
// ***************************************************************************
#ifndef BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
#define BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER
// Boost.Test
#include <boost/test/tree/observer.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
/// @brief Monitors the init of the framework
///
/// This class collects the state of the init/termination of the unit test framework.
///
/// @see boost::unit_test::test_observer
class BOOST_TEST_DECL framework_init_observer_t : public test_observer {
public:
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;
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( framework_init_observer_t )
};
BOOST_TEST_SINGLETON_INST( framework_init_observer )
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER

View File

@@ -277,7 +277,7 @@ public:
}
void report( std::ostream& ostr ) const
{
ostr << tt_detail::print_helper( m_value );
ostr << tt_detail::print_helper( value() );
}
// Mutating operators
@@ -309,8 +309,11 @@ public:
private:
template<typename U>
static void format_message( wrap_stringstream& ostr, U const& v ) { ostr << "[(bool)" << v << " is false]"; }
static void format_message( wrap_stringstream& /*ostr*/, bool /*v*/ ) {}
static void format_message( wrap_stringstream& ostr, U const& v )
{
ostr << "['" << tt_detail::print_helper(v) << "' evaluates to false]";
}
static void format_message( wrap_stringstream& /*ostr*/, bool /*v*/ ) {}
static void format_message( wrap_stringstream& /*ostr*/, assertion_result const& /*v*/ ) {}
// Data members

View File

@@ -20,6 +20,7 @@
// Boost
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/decay.hpp>
@@ -38,6 +39,15 @@ namespace assertion {
template<typename T>
struct specialized_compare : public mpl::false_ {};
template <typename T>
struct is_c_array : public mpl::false_ {};
template<typename T, std::size_t N>
struct is_c_array<T [N]> : public mpl::true_ {};
template<typename T, std::size_t N>
struct is_c_array<T (&)[N]> : public mpl::true_ {};
#define BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE(Col) \
namespace boost { namespace test_tools { namespace assertion { \
template<> \
@@ -55,17 +65,21 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
&& unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
assertion_result ar( true );
typename Lhs::const_iterator first1 = lhs.begin();
typename Rhs::const_iterator first2 = rhs.begin();
typename Lhs::const_iterator last1 = lhs.end();
typename Rhs::const_iterator last2 = rhs.end();
std::size_t pos = 0;
typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
typename t_Lhs_iterator::const_iterator first1 = t_Lhs_iterator::begin(lhs);
typename t_Rhs_iterator::const_iterator first2 = t_Rhs_iterator::begin(rhs);
typename t_Lhs_iterator::const_iterator last1 = t_Lhs_iterator::end(lhs);
typename t_Rhs_iterator::const_iterator last2 = t_Rhs_iterator::end(rhs);
std::size_t pos = 0;
for( ; (first1 != last1) && (first2 != last2); ++first1, ++first2, ++pos ) {
assertion_result const& element_ar = OP::eval(*first1, *first2);
@@ -113,8 +127,7 @@ template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
(!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
(!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
(unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
@@ -122,8 +135,8 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
return lexicographic_compare<OP, can_be_equal, prefer_shorter>(
boost::unit_test::basic_cstring<lhs_char_type>(lhs),
boost::unit_test::basic_cstring<rhs_char_type>(rhs));
lhs_char_type(lhs),
rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -135,23 +148,27 @@ lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
unit_test::is_forward_iterable<Lhs>::value && unit_test::is_forward_iterable<Rhs>::value,
unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
&& unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
assertion_result ar( true );
if( lhs.size() != rhs.size() ) {
if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) ) {
ar = false;
ar.message() << "\nCollections size mismatch: " << lhs.size() << " != " << rhs.size();
ar.message() << "\nCollections size mismatch: " << t_Lhs_iterator::size(lhs) << " != " << t_Rhs_iterator::size(rhs);
return ar;
}
typename Lhs::const_iterator left = lhs.begin();
typename Rhs::const_iterator right = rhs.begin();
std::size_t pos = 0;
typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
std::size_t pos = 0;
for( ; pos < lhs.size(); ++left, ++right, ++pos ) {
for( ; pos < t_Lhs_iterator::size(lhs); ++left, ++right, ++pos ) {
assertion_result const element_ar = OP::eval( *left, *right );
if( element_ar )
continue;
@@ -171,16 +188,15 @@ element_compare( Lhs const& lhs, Rhs const& rhs )
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
(!unit_test::is_forward_iterable<Lhs>::value && unit_test::is_cstring<Lhs>::value) ||
(!unit_test::is_forward_iterable<Rhs>::value && unit_test::is_cstring<Rhs>::value),
(unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
element_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type;
typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
return element_compare<OP>(boost::unit_test::basic_cstring<lhs_char_type>(lhs),
boost::unit_test::basic_cstring<rhs_char_type>(rhs));
return element_compare<OP>(lhs_char_type(lhs),
rhs_char_type(rhs));
}
//____________________________________________________________________________//
@@ -193,14 +209,17 @@ template <typename OP, typename Lhs, typename Rhs>
inline assertion_result
non_equality_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
assertion_result ar( true );
if( lhs.size() != rhs.size() )
if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) )
return ar;
typename Lhs::const_iterator left = lhs.begin();
typename Rhs::const_iterator right = rhs.begin();
typename Lhs::const_iterator end = lhs.end();
typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
typename t_Lhs_iterator::const_iterator end = t_Lhs_iterator::end(lhs);
for( ; left != end; ++left, ++right ) {
if( OP::eval( *left, *right ) )
@@ -367,22 +386,34 @@ compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*
#define DEFINE_COLLECTION_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
unit_test::is_forward_iterable<Lhs>::value \
&& !unit_test::is_cstring<Lhs>::value \
&& unit_test::is_forward_iterable<Rhs>::value \
&& !unit_test::is_cstring<Rhs>::value>::type> { \
unit_test::is_forward_iterable<Lhs>::value \
&& !unit_test::is_cstring_comparable<Lhs>::value \
&& unit_test::is_forward_iterable<Rhs>::value \
&& !unit_test::is_cstring_comparable<Rhs>::value>::type> { \
public: \
typedef assertion_result result_type; \
typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator_helper; \
typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator_helper; \
\
typedef name<Lhs, Rhs> OP; \
typedef typename \
mpl::if_c<is_same<typename decay<Lhs>::type, \
typename decay<Rhs>::type>::value, \
typename cctraits<OP>::is_specialized, \
mpl::false_>::type is_specialized; \
\
typedef name<typename Lhs::value_type, \
typename Rhs::value_type> elem_op; \
typedef typename \
mpl::if_c< \
mpl::or_< \
typename is_c_array<Lhs>::type, \
typename is_c_array<Rhs>::type \
>::value, \
mpl::true_, \
typename \
mpl::if_c<is_same<typename decay<Lhs>::type, \
typename decay<Rhs>::type>::value, \
typename cctraits<OP>::is_specialized, \
mpl::false_>::type \
>::type is_specialized; \
\
typedef name<typename t_Lhs_iterator_helper::value_type, \
typename t_Rhs_iterator_helper::value_type \
> elem_op; \
\
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs) \

View File

@@ -17,6 +17,20 @@
// Boost.Test
#include <boost/test/utils/lazy_ostream.hpp>
#include <boost/test/detail/pp_variadic.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -47,13 +61,30 @@ private:
::boost::unit_test::framework::add_context( BOOST_TEST_LAZY_MSG( context_descr ) , false ) \
/**/
#define BOOST_TEST_INFO_SCOPE( context_descr ) \
::boost::test_tools::tt_detail::context_frame BOOST_JOIN( context_frame_, __LINE__ ) = \
::boost::test_tools::tt_detail::context_frame(BOOST_TEST_LAZY_MSG( context_descr ) ) \
/**/
//____________________________________________________________________________//
#define BOOST_TEST_CONTEXT( context_descr ) \
if( ::boost::test_tools::tt_detail::context_frame BOOST_JOIN( context_frame_, __LINE__ ) = \
::boost::test_tools::tt_detail::context_frame( BOOST_TEST_LAZY_MSG( context_descr ) ) ) \
#define BOOST_CONTEXT_PARAM(r, ctx, i, context_descr) \
if( ::boost::test_tools::tt_detail::context_frame BOOST_PP_CAT(ctx, i) = \
::boost::test_tools::tt_detail::context_frame(BOOST_TEST_LAZY_MSG( context_descr ) ) ) \
/**/
#define BOOST_CONTEXT_PARAMS( params ) \
BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONTEXT_PARAM, \
BOOST_JOIN( context_frame_, __LINE__ ), \
params) \
/**/
#define BOOST_TEST_CONTEXT( ... ) \
BOOST_CONTEXT_PARAMS( BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
/**/
//____________________________________________________________________________//
} // namespace tt_detail

View File

@@ -37,8 +37,8 @@ namespace op {
#define DEFINE_CSTRING_COMPARISON( oper, name, rev ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
( unit_test::is_cstring<Lhs>::value \
&& unit_test::is_cstring<Rhs>::value) \
( unit_test::is_cstring_comparable<Lhs>::value \
&& unit_test::is_cstring_comparable<Rhs>::value) \
>::type > \
{ \
typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type; \
@@ -46,13 +46,14 @@ struct name<Lhs,Rhs,typename boost::enable_if_c< \
public: \
typedef assertion_result result_type; \
\
typedef name<lhs_char_type, rhs_char_type> elem_op; \
typedef name< \
typename lhs_char_type::value_type, \
typename rhs_char_type::value_type> elem_op; \
\
static bool \
eval( Lhs const& lhs, Rhs const& rhs) \
{ \
return unit_test::basic_cstring<lhs_char_type>(lhs) oper \
unit_test::basic_cstring<rhs_char_type>(rhs); \
return lhs_char_type(lhs) oper rhs_char_type(rhs); \
} \
\
template<typename PrevExprType> \

View File

@@ -18,7 +18,6 @@
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/workaround.hpp>
// Boost
#include <boost/mpl/or.hpp>
@@ -28,6 +27,8 @@
#include <boost/type_traits/is_abstract.hpp>
#include <boost/type_traits/has_left_shift.hpp>
#include <ios>
#include <iostream>
#include <limits>
#if !defined(BOOST_NO_CXX11_NULLPTR)
@@ -166,8 +167,11 @@ struct BOOST_TEST_DECL print_log_value<wchar_t const*> {
#if !defined(BOOST_NO_CXX11_NULLPTR)
template<>
struct BOOST_TEST_DECL print_log_value<std::nullptr_t> {
void operator()( std::ostream& ostr, std::nullptr_t t );
struct print_log_value<std::nullptr_t> {
// declaration and definition is here because of #12969 https://svn.boost.org/trac10/ticket/12969
void operator()( std::ostream& ostr, std::nullptr_t /*t*/ ) {
ostr << "nullptr";
}
};
#endif

View File

@@ -197,9 +197,11 @@ fraction_tolerance( percent_tolerance_t<FPT> tolerance )
/*!@brief Predicate for comparing floating point numbers
*
* This predicate is used to compare floating point numbers. In addition the comparison produces maximum
* related differnce, which can be used to generate detailed error message
* related difference, which can be used to generate detailed error message
* The methods for comparing floating points are detailed in the documentation. The method is chosen
* by the @ref boost::math::fpc::strength given at construction.
*
* This predicate is not suitable for comparing to 0 or to infinity.
*/
template<typename FPT>
class close_at_tolerance {

View File

@@ -20,6 +20,7 @@
// Boost
#include <boost/type_traits/common_type.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -38,22 +39,19 @@ namespace op {
template<typename OP>
struct fpctraits {
static const bool cmp_direct = true;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::NE<Lhs,Rhs> > {
static const bool cmp_direct = false;
// indicate if we should perform the operation with a "logical OR"
// with the "equality under tolerance".
static const bool equality_logical_disjunction = true;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::LT<Lhs,Rhs> > {
static const bool cmp_direct = false;
static const bool equality_logical_disjunction = false;
};
template <typename Lhs, typename Rhs>
struct fpctraits<op::GT<Lhs,Rhs> > {
static const bool cmp_direct = false;
static const bool equality_logical_disjunction = false;
};
//____________________________________________________________________________//
@@ -62,48 +60,30 @@ struct fpctraits<op::GT<Lhs,Rhs> > {
// ************** set of overloads to select correct fpc algo ************** //
// ************************************************************************** //
// we really only care about EQ vs NE. All other comparisons use direct first
// and then need EQ. For example a < b (tolerance t) IFF a < b OR a == b (tolerance t)
// and then need EQ. For example a <= b (tolerance t) IFF a <= b OR a == b (tolerance t)
template <typename FPT, typename Lhs, typename Rhs, typename OP>
inline assertion_result
compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* )
compare_fpv( Lhs const& lhs, Rhs const& rhs, OP* cmp_operator)
{
fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
assertion_result ar( P( lhs, rhs ) );
if( !ar )
ar.message() << "Relative difference exceeds tolerance ["
<< P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
return ar;
}
//____________________________________________________________________________//
template <typename FPT, typename OP>
inline assertion_result
compare_fpv_near_zero( FPT const& fpv, OP* )
{
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
assertion_result ar( P( fpv ) );
if( !ar )
ar.message() << "Absolute value exceeds tolerance [|" << fpv << "| > "<< fpc_tolerance<FPT>() << ']';
return ar;
bool result = cmp_operator->eval_direct(lhs, rhs);
if(fpctraits<OP>::equality_logical_disjunction) {
return result || compare_fpv<FPT>(lhs, rhs, (op::EQ<Lhs, Rhs>*)0);
}
return result && compare_fpv<FPT>(lhs, rhs, (op::NE<Lhs, Rhs>*)0);
}
//____________________________________________________________________________//
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
compare_fpv_near_zero( FPT const& fpv, op::EQ<Lhs,Rhs>* )
{
fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
fpc::small_with_tolerance<FPT> P( fpc_tolerance<FPT>() );
assertion_result ar( !P( lhs, rhs ) );
assertion_result ar( P( fpv ) );
if( !ar )
ar.message() << "Relative difference is within tolerance ["
<< P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
ar.message() << "Absolute value exceeds tolerance [|" << fpv << "| > "<< fpc_tolerance<FPT>() << ']';
return ar;
}
@@ -126,34 +106,48 @@ compare_fpv_near_zero( FPT const& fpv, op::NE<Lhs,Rhs>* )
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
compare_fpv( Lhs const& lhs, Rhs const& rhs, op::LT<Lhs,Rhs>* )
compare_fpv( Lhs const& lhs, Rhs const& rhs, op::EQ<Lhs,Rhs>* )
{
return lhs >= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
}
if( lhs == 0 ) {
return compare_fpv_near_zero<FPT>( rhs, (op::EQ<Lhs,Rhs>*)0 );
}
else if( rhs == 0) {
return compare_fpv_near_zero<FPT>( lhs, (op::EQ<Lhs,Rhs>*)0 );
}
else {
fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_STRONG );
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
compare_fpv_near_zero( FPT const& fpv, op::LT<Lhs,Rhs>* )
{
return fpv >= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
assertion_result ar( P( lhs, rhs ) );
if( !ar )
ar.message() << "Relative difference exceeds tolerance ["
<< P.tested_rel_diff() << " > " << P.fraction_tolerance() << ']';
return ar;
}
}
//____________________________________________________________________________//
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
compare_fpv( Lhs const& lhs, Rhs const& rhs, op::GT<Lhs,Rhs>* )
compare_fpv( Lhs const& lhs, Rhs const& rhs, op::NE<Lhs,Rhs>* )
{
return lhs <= rhs ? assertion_result( false ) : compare_fpv<FPT>( lhs, rhs, (op::NE<Lhs,Rhs>*)0 );
}
if( lhs == 0 ) {
return compare_fpv_near_zero<FPT>( rhs, (op::NE<Lhs,Rhs>*)0 );
}
else if( rhs == 0 ) {
return compare_fpv_near_zero<FPT>( lhs, (op::NE<Lhs,Rhs>*)0 );
}
else {
fpc::close_at_tolerance<FPT> P( fpc_tolerance<FPT>(), fpc::FPC_WEAK );
template <typename FPT, typename Lhs, typename Rhs>
inline assertion_result
compare_fpv_near_zero( FPT const& fpv, op::GT<Lhs,Rhs>* )
{
return fpv <= 0 ? assertion_result( false ) : compare_fpv_near_zero( fpv, (op::NE<Lhs,Rhs>*)0 );
}
assertion_result ar( !P( lhs, rhs ) );
if( !ar )
ar.message() << "Relative difference is within tolerance ["
<< P.tested_rel_diff() << " < " << fpc_tolerance<FPT>() << ']';
return ar;
}
}
//____________________________________________________________________________//
@@ -161,7 +155,12 @@ compare_fpv_near_zero( FPT const& fpv, op::GT<Lhs,Rhs>* )
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
(fpc::tolerance_based<Lhs>::value && \
fpc::tolerance_based<Rhs>::value)>::type> { \
fpc::tolerance_based<Rhs>::value) || \
(fpc::tolerance_based<Lhs>::value && \
boost::is_arithmetic<Rhs>::value) || \
(boost::is_arithmetic<Lhs>::value && \
fpc::tolerance_based<Rhs>::value) \
>::type> { \
public: \
typedef typename common_type<Lhs,Rhs>::type FPT; \
typedef name<Lhs,Rhs> OP; \
@@ -177,22 +176,13 @@ public: \
static assertion_result \
eval( Lhs const& lhs, Rhs const& rhs ) \
{ \
if( lhs == 0 ) \
if( fpc_tolerance<FPT>() == FPT(0) \
|| (std::numeric_limits<Lhs>::has_infinity \
&& (lhs == std::numeric_limits<Lhs>::infinity())) \
|| (std::numeric_limits<Rhs>::has_infinity \
&& (rhs == std::numeric_limits<Rhs>::infinity()))) \
{ \
return compare_fpv_near_zero( rhs, (OP*)0 ); \
} \
\
if( rhs == 0 ) \
{ \
return compare_fpv_near_zero( lhs, (OP*)0 ); \
} \
\
bool direct_res = eval_direct( lhs, rhs ); \
\
if( (direct_res && fpctraits<OP>::cmp_direct) || \
fpc_tolerance<FPT>() == FPT(0) ) \
{ \
return direct_res; \
return eval_direct( lhs, rhs ); \
} \
\
return compare_fpv<FPT>( lhs, rhs, (OP*)0 ); \
@@ -227,4 +217,3 @@ BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_FPV_COMPARISON )
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_FPC_OP_HPP_050915GER

View File

@@ -114,7 +114,7 @@ inline assertion_result equal_impl( char const* left, char* right ) { return equ
inline assertion_result equal_impl( char* left, char* right ) { return equal_impl( static_cast<char const*>(left), static_cast<char const*>(right) ); }
#if !defined( BOOST_NO_CWCHAR )
assertion_result BOOST_TEST_DECL equal_impl( wchar_t const* left, wchar_t const* right );
BOOST_TEST_DECL assertion_result equal_impl( wchar_t const* left, wchar_t const* right );
inline assertion_result equal_impl( wchar_t* left, wchar_t const* right ) { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }
inline assertion_result equal_impl( wchar_t const* left, wchar_t* right ) { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }
inline assertion_result equal_impl( wchar_t* left, wchar_t* right ) { return equal_impl( static_cast<wchar_t const*>(left), static_cast<wchar_t const*>(right) ); }

View File

@@ -20,6 +20,8 @@
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
@@ -95,7 +97,7 @@ do {
//____________________________________________________________________________//
#define BOOST_CHECK_THROW_IMPL( S, E, P, postfix, TL ) \
#define BOOST_CHECK_THROW_IMPL( S, E, P, postfix, TL ) \
do { \
try { \
BOOST_TEST_PASSPOINT(); \
@@ -103,9 +105,9 @@ do {
BOOST_TEST_TOOL_IMPL( 2, false, "exception " BOOST_STRINGIZE(E) " expected but not raised", \
TL, CHECK_MSG, _ ); \
} catch( E const& ex ) { \
::boost::unit_test::ut_detail::ignore_unused_variable_warning( ex ); \
BOOST_TEST_TOOL_IMPL( 2, P, \
"exception \"" BOOST_STRINGIZE( E )"\" raised as expected" postfix, \
boost::ignore_unused( ex ); \
BOOST_TEST_TOOL_IMPL( 2, P, \
"exception \"" BOOST_STRINGIZE( E )"\" raised as expected" postfix, \
TL, CHECK_MSG, _ ); \
} \
} while( ::boost::test_tools::tt_detail::dummy_cond() ) \

View File

@@ -37,9 +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 );
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,7 @@
#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>
// Boost
#include <boost/shared_ptr.hpp>
@@ -46,35 +44,45 @@ 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();
void stack();
std::vector<base_ptr> get_lazy_decorators() const;
// singleton pattern without ctor
BOOST_TEST_SINGLETON_CONS_NO_CTOR( collector_t )
private:
BOOST_TEST_SINGLETON_CONS( collector )
// Class invariant: minimal size is 1.
collector_t() : m_tu_decorators_stack(1) {}
// Data members
std::vector<base_ptr> m_tu_decorators;
std::vector< std::vector<base_ptr> > m_tu_decorators_stack;
};
// ************************************************************************** //
// ************** decorator::base ************** //
// ************** decorator::base ************** //
// ************************************************************************** //
class BOOST_TEST_DECL base {
public:
// composition interface
collector& operator*() const;
virtual collector_t& operator*() const;
// application interface
virtual void apply( test_unit& tu ) = 0;
@@ -86,6 +94,30 @@ protected:
virtual ~base() {}
};
// ************************************************************************** //
// ************** decorator::stack_decorator ************** //
// ************************************************************************** //
//!@ A decorator that creates a new stack in the collector
//!
//! This decorator may be used in places where the currently accumulated decorators
//! in the collector should be applied to lower levels of the hierarchy rather
//! than the current one. This is for instance for dataset test cases, where the
//! macro does not let the user specify decorators for the underlying generated tests
//! (but rather on the main generator function), applying the stack_decorator at the
//! parent level lets us consume the decorator at the underlying test cases level.
class BOOST_TEST_DECL stack_decorator : public decorator::base {
public:
explicit stack_decorator() {}
virtual collector_t& operator*() const;
private:
// decorator::base interface
virtual void apply( test_unit& tu );
virtual base_ptr clone() const { return base_ptr(new stack_decorator()); }
};
// ************************************************************************** //
// ************** decorator::label ************** //
// ************************************************************************** //

View File

@@ -5,11 +5,8 @@
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision: 74640 $
//
// Description : defines fixture interface and object makers
/// @file
/// Defines fixture interface and object makers
// ***************************************************************************
#ifndef BOOST_TEST_TREE_FIXTURE_HPP_100311GER
@@ -22,6 +19,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/function/function0.hpp>
#include <boost/utility/declval.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -45,6 +43,83 @@ public:
typedef shared_ptr<test_unit_fixture> test_unit_fixture_ptr;
// ************************************************************************** //
// ************** fixture helper functions ************** //
// ************************************************************************** //
namespace impl_fixture {
#if defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
template<typename U, void (U::*)()> struct fixture_detect {};
template<typename T>
struct has_setup {
private:
template<typename U> static char Test(fixture_detect<U, &U::setup>*);
template<typename U> static int Test(...);
public:
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
template<typename T>
struct has_teardown {
private:
template<typename U> static char Test(fixture_detect<U, &U::teardown>*);
template<typename U> static int Test(...);
public:
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
#else
template<typename U> struct fixture_detect { typedef char type; };
template<typename T>
struct has_setup {
private:
template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().setup())>::type;
template<typename U> static int Test(...);
public:
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
template<typename T>
struct has_teardown {
private:
template<typename U> static auto Test(U*) -> typename fixture_detect<decltype(boost::declval<U>().teardown())>::type;
template<typename U> static int Test(...);
public:
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
#endif
template <bool has_setup = false>
struct call_setup { template <class U> void operator()(U& ) { } };
template <>
struct call_setup<true> { template <class U> void operator()(U& u) { u.setup(); } };
template <bool has_teardown = false>
struct call_teardown { template <class U> void operator()(U& ) { } };
template <>
struct call_teardown<true> { template <class U> void operator()(U& u) { u.teardown(); } };
}
//! Calls the fixture "setup" if detected by the compiler, otherwise does nothing.
template <class U>
void setup_conditional(U& u) {
return impl_fixture::call_setup<impl_fixture::has_setup<U>::value>()(u);
}
//! Calls the fixture "teardown" if detected by the compiler, otherwise does nothing.
template <class U>
void teardown_conditional(U& u) {
return impl_fixture::call_teardown<impl_fixture::has_teardown<U>::value>()(u);
}
// ************************************************************************** //
// ************** class_based_fixture ************** //
// ************************************************************************** //
@@ -57,8 +132,8 @@ public:
private:
// Fixture interface
virtual void setup() { m_inst.reset( new F( m_arg ) ); }
virtual void teardown() { m_inst.reset(); }
virtual void setup() { m_inst.reset( new F( m_arg ) ); setup_conditional(*m_inst); }
virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;
@@ -75,8 +150,8 @@ public:
private:
// Fixture interface
virtual void setup() { m_inst.reset( new F ); }
virtual void teardown() { m_inst.reset(); }
virtual void setup() { m_inst.reset( new F ); setup_conditional(*m_inst); }
virtual void teardown() { teardown_conditional(*m_inst); m_inst.reset(); }
// Data members
scoped_ptr<F> m_inst;

View File

@@ -17,6 +17,7 @@
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/tree/observer.hpp>
#include <boost/test/tree/fixture.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -26,14 +27,53 @@
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** global_configuration ************** //
// ************************************************************************** //
class BOOST_TEST_DECL global_configuration : public test_observer {
public:
// Constructor
global_configuration();
/// Unregisters the global fixture from the framework
///
/// This is called by the framework at shutdown time
void unregister_from_framework();
// Dtor
virtual ~global_configuration();
// Happens after the framework global observer init has been done
virtual int priority() { return 1; }
private:
bool registered;
};
// ************************************************************************** //
// ************** 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();
/// Unregisters the global fixture from the framework
///
/// This is called by the framework at shutdown time
void unregister_from_framework();
// Dtor
virtual ~global_fixture();
private:
bool registered;
};
//____________________________________________________________________________//
@@ -41,14 +81,48 @@ public:
namespace ut_detail {
template<typename F>
struct global_fixture_impl : public global_fixture {
struct global_configuration_impl : public global_configuration {
// Constructor
global_fixture_impl() : m_fixture( 0 ) {}
global_configuration_impl() : m_configuration_observer( 0 ) {
}
// test observer interface
virtual void test_start( counter_t ) { m_fixture = new F; }
virtual void test_finish() { delete m_fixture; m_fixture = 0; }
virtual void test_aborted() { delete m_fixture; m_fixture = 0; }
virtual void test_start( counter_t ) {
m_configuration_observer = new F;
}
// test observer interface
virtual void test_finish() {
if(m_configuration_observer) {
delete m_configuration_observer;
m_configuration_observer = 0;
}
}
private:
// Data members
F* m_configuration_observer;
};
template<typename F>
struct global_fixture_impl : public global_fixture {
// Constructor
global_fixture_impl() : m_fixture( 0 ) {
}
// test fixture interface
virtual void setup() {
m_fixture = new F;
setup_conditional(*m_fixture);
}
// test fixture interface
virtual void teardown() {
if(m_fixture) {
teardown_conditional(*m_fixture);
}
delete m_fixture;
m_fixture = 0;
}
private:
// Data members

View File

@@ -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.
@@ -74,6 +72,12 @@ public:
virtual void test_unit_skipped( test_unit const& tu, const_string ) { test_unit_skipped( tu ); }
virtual void test_unit_skipped( test_unit const& ) {} ///< backward compatibility
//! Called when the test timed out
//!
//! This function is called to signal that a test unit (case or suite) timed out.
//! A valid test unit is available through boost::unit_test::framework::current_test_unit
virtual void test_unit_timed_out( test_unit const& ) {}
//! Called when a test unit indicates a fatal error.
//!
//! A fatal error happens when
@@ -81,14 +85,8 @@ public:
//! - an unexpected exception is caught by the Boost.Test framework
virtual void test_unit_aborted( test_unit const& ) {}
virtual void assertion_result( unit_test::assertion_result ar )
virtual void assertion_result( unit_test::assertion_result /* ar */ )
{
switch( ar ) {
case AR_PASSED: assertion_result( true ); break;
case AR_FAILED: assertion_result( false ); break;
case AR_TRIGGERED: break;
default: break;
}
}
//! Called when an exception is intercepted
@@ -98,11 +96,11 @@ 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:
//! Deprecated
virtual void assertion_result( bool /* passed */ ) {}
BOOST_TEST_PROTECTED_VIRTUAL ~test_observer() {}
};

View File

@@ -16,7 +16,7 @@
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/workaround.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/class_properties.hpp>
@@ -29,6 +29,10 @@
#include <boost/mpl/identity.hpp>
#include <boost/type.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/type_traits/is_rvalue_reference.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/function/function0.hpp>
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
@@ -41,6 +45,12 @@
#include <string> // for std::string
#include <list> // for std::list
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
#include <type_traits>
#include <boost/mpl/is_sequence.hpp>
#endif
#include <boost/test/detail/suppress_warnings.hpp>
@@ -64,7 +74,7 @@ public:
// ************** generate_test_case_4_type ************** //
// ************************************************************************** //
template<typename Generator,typename TestCaseTemplate>
template<typename Generator, typename TestCaseTemplate>
struct generate_test_case_4_type {
explicit generate_test_case_4_type( const_string tc_name, const_string tc_file, std::size_t tc_line, Generator& G )
: m_test_case_name( tc_name )
@@ -84,8 +94,16 @@ struct generate_test_case_4_type {
#else
full_name += BOOST_CURRENT_FUNCTION;
#endif
if( boost::is_const<TestType>::value )
typedef typename boost::remove_reference<TestType>::type TestTypewoRef;
if( boost::is_const<TestTypewoRef>::value )
full_name += "_const";
if( boost::is_volatile<TestTypewoRef>::value )
full_name += "_volatile";
if( boost::is_rvalue_reference<TestType>::value )
full_name += "_refref";
else if( boost::is_lvalue_reference<TestType>::value )
full_name += "_ref";
full_name += '>';
m_holder.m_test_cases.push_back( new test_case( ut_detail::normalize_test_case_name( full_name ),
@@ -106,17 +124,8 @@ private:
// ************** test_case_template ************** //
// ************************************************************************** //
template<typename TestCaseTemplate,typename TestTypesList>
class template_test_case_gen : public test_unit_generator {
class template_test_case_gen_base : public test_unit_generator {
public:
// Constructor
template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
{
typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,TestCaseTemplate> single_test_gen;
mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, tc_file, tc_line, *this ) );
}
virtual test_unit* next() const
{
if( m_test_cases.empty() )
@@ -132,6 +141,57 @@ public:
mutable std::list<test_unit*> m_test_cases;
};
template<typename TestCaseTemplate,typename TestTypesList, typename enabler = void>
class template_test_case_gen : public template_test_case_gen_base {
public:
// Constructor
template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
{
typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,TestCaseTemplate> single_test_gen;
mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, tc_file, tc_line, *this ) );
}
};
// Describing template test cases with tuples
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && \
!defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<typename TestCaseTemplate,
template <class ...> class C,
typename... parameter_pack>
class template_test_case_gen<
TestCaseTemplate,
C<parameter_pack...>,
typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type >
: public template_test_case_gen_base {
template<typename F>
void for_each(F &f)
{
auto l = { (f(mpl::identity<parameter_pack>()), 0)... };
(void)l; // silence warning
}
public:
// Constructor
template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
{
using this_type = template_test_case_gen<
TestCaseTemplate,
C<parameter_pack...>,
typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type>;
using single_test_gen = generate_test_case_4_type<this_type, TestCaseTemplate>;
single_test_gen op( tc_name, tc_file, tc_line, *this );
this->for_each(op);
}
};
#endif /* C++11 variadic, type alias */
} // namespace ut_detail
} // unit_test
} // namespace boost

View File

@@ -20,6 +20,7 @@
#include <boost/test/tree/decorator.hpp>
#include <boost/test/tree/fixture.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tools/assertion_result.hpp>
@@ -42,7 +43,7 @@ namespace boost {
namespace unit_test {
namespace framework {
class state;
class state;
}
// ************************************************************************** //
@@ -175,11 +176,21 @@ 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_t& decorators );
//! Removes a test from the test suite.
void remove( test_unit_id id );
//! Generates all the delayed test_units from the generators
void generate( );
//! Check for duplicates name in test cases
//!
//! Raises a setup_error if there are duplicates
void check_for_duplicate_test_cases();
// access methods
test_unit_id get( const_string tu_name ) const;
@@ -199,6 +210,8 @@ protected:
test_unit_id_list m_children;
children_per_rank m_ranked_children; ///< maps child sibling rank to list of children with that rank
std::vector< std::pair<boost::shared_ptr<test_unit_generator>, std::vector<decorator::base_ptr> > > m_generators; /// lazy evaluation
};
// ************************************************************************** //
@@ -206,12 +219,17 @@ protected:
// ************************************************************************** //
class BOOST_TEST_DECL master_test_suite_t : public test_suite {
public:
private:
master_test_suite_t();
master_test_suite_t(const master_test_suite_t&); // undefined
master_test_suite_t& operator=(master_test_suite_t const &); // undefined
public:
// Data members
int argc;
char** argv;
friend BOOST_TEST_DECL master_test_suite_t& boost::unit_test::framework::master_test_suite();
};
// ************************************************************************** //

View File

@@ -22,7 +22,6 @@
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/utils/wrap_stringstream.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
#include <boost/test/utils/lazy_ostream.hpp>
// Boost
@@ -109,7 +108,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 );
@@ -120,10 +119,11 @@ public:
virtual void test_unit_finish( test_unit const&, unsigned long elapsed );
virtual void test_unit_skipped( test_unit const&, const_string );
virtual void test_unit_aborted( test_unit const& );
virtual void test_unit_timed_out( test_unit const& );
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
@@ -137,6 +137,13 @@ public:
//! @par Since Boost 1.62
void set_stream( output_format, std::ostream& );
//! Returns a pointer to the stream associated to specific logger
//!
//! @note Returns a null pointer if the format is not found
//! @par Since Boost 1.67
std::ostream* get_stream( output_format ) const;
//! Sets the threshold level for all loggers/formatters.
//!
//! This will override the log level of all loggers, whether enabled or not.
@@ -214,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

@@ -139,8 +139,9 @@ public:
/// Invoked when Unit Test Framework build information is requested
///
/// @param[in] os output stream to write a messages into
virtual void log_build_info( std::ostream& os ) = 0;
/// @param[in] os output stream to write a messages into
/// @param[in] log_build_info indicates if build info should be logged or not
virtual void log_build_info( std::ostream& os, bool log_build_info = true ) = 0;
// @}
// @name Test unit start/finish
@@ -176,6 +177,10 @@ public:
/// Invoked when a test unit is aborted
virtual void test_unit_aborted( std::ostream& /* os */, test_unit const& /* tu */) {}
/// Invoked when a test unit times-out
virtual void test_unit_timed_out( std::ostream& /* os */, test_unit const& /* tu */) {}
// @}
// @name Uncaught exception report
@@ -248,7 +253,7 @@ public:
// @name Log entry context report
/// Invoked by Unit Test Framework to start log entry context report
//
/// Unit Test Framework logs for failed assertions and uncaught exceptions context if one was defined by a test module.
/// Context consists of multiple "scopes" identified by description messages assigned by the test module using
/// BOOST_TEST_INFO/BOOST_TEST_CONTEXT statements.
@@ -258,18 +263,20 @@ public:
virtual void entry_context_start( std::ostream& os, log_level l ) = 0;
/// Invoked by Unit Test Framework to report log entry context "scope" description
//
/// Each "scope" description is reported by separate call to log_entry_context.
/// @param[in] os output stream to write a messages into
/// @param[in] l entry log_level, to be used to fine tune the message
/// @param[in] value context "scope" description
/// @see log_entry_start, entry_context_finish
virtual void log_entry_context( std::ostream& os, const_string value ) = 0;
virtual void log_entry_context( std::ostream& os, log_level l, const_string value ) = 0;
/// Invoked by Unit Test Framework to finish log entry context report
///
/// @param[in] os output stream to write a messages into
/// @param[in] l entry log_level, to be used to fine tune the message
/// @see log_entry_start, entry_context_context
virtual void entry_context_finish( std::ostream& os ) = 0;
virtual void entry_context_finish( std::ostream& os, log_level l ) = 0;
// @}
// @name Log level management

View File

@@ -17,7 +17,6 @@
// Boost.Test
#include <boost/test/execution_monitor.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
@@ -30,11 +29,13 @@ 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,
precondition_failure = -1,
/// Indicates a failure to prepare the unit test (eg. fixture). Does not
/// account for tests skipped because of parent tests failed/skipped.
test_setup_failure = -1,
unexpected_exception = -2,
os_exception = -3,
os_timeout = -4,
@@ -44,9 +45,10 @@ public:
static bool is_critical_error( error_level e ) { return e <= fatal_error; }
// monitor method
error_level execute_and_translate( boost::function<void ()> const& func, unsigned timeout = 0 );
// timeout is expressed in seconds
error_level execute_and_translate( boost::function<void ()> const& func, unsigned long int timeout_microseconds = 0 );
private:
// singleton pattern
BOOST_TEST_SINGLETON_CONS( unit_test_monitor_t )
};

View File

@@ -19,6 +19,9 @@
#include <boost/test/utils/runtime/argument.hpp>
#include <boost/make_shared.hpp>
// Boost
#include <boost/function/function0.hpp>
// STL
#include <iostream>
#include <fstream>
@@ -96,24 +99,39 @@ BOOST_TEST_DECL bool save_pattern();
class stream_holder {
public:
// Constructor
explicit stream_holder( std::ostream& default_stream = std::cout)
explicit stream_holder( std::ostream& default_stream = std::cout )
: m_stream( &default_stream )
{
}
void setup( const const_string& stream_name )
void setup( const const_string& stream_name,
boost::function<void ()> const &cleaner_callback = boost::function<void ()>() )
{
if(stream_name.empty())
return;
if( stream_name == "stderr" )
if( stream_name == "stderr" ) {
m_stream = &std::cerr;
else if( stream_name == "stdout" )
if(cleaner_callback) {
m_cleaner = boost::make_shared<callback_cleaner>(cleaner_callback);
}
else {
m_cleaner.reset();
}
}
else if( stream_name == "stdout" ) {
m_stream = &std::cout;
if (cleaner_callback) {
m_cleaner = boost::make_shared<callback_cleaner>(cleaner_callback);
}
else {
m_cleaner.reset();
}
}
else {
m_file = boost::make_shared<std::ofstream>();
m_file->open( std::string(stream_name.begin(), stream_name.end()).c_str() );
m_stream = m_file.get();
m_cleaner = boost::make_shared<callback_cleaner>(cleaner_callback);
m_cleaner->m_file.open( std::string(stream_name.begin(), stream_name.end()).c_str() );
m_stream = &m_cleaner->m_file;
}
}
@@ -121,9 +139,22 @@ public:
std::ostream& ref() const { return *m_stream; }
private:
struct callback_cleaner {
callback_cleaner(boost::function<void ()> cleaner_callback)
: m_cleaner_callback(cleaner_callback)
, m_file() {
}
~callback_cleaner() {
if( m_cleaner_callback )
m_cleaner_callback();
}
boost::function<void ()> m_cleaner_callback;
std::ofstream m_file;
};
// Data members
boost::shared_ptr<std::ofstream> m_file;
std::ostream* m_stream;
boost::shared_ptr<callback_cleaner> m_cleaner;
std::ostream* m_stream;
};
} // namespace runtime_config

View File

@@ -32,10 +32,12 @@
// ************** Non-auto (explicit) test case interface ************** //
// ************************************************************************** //
#define BOOST_TEST_CASE( test_function ) \
#define BOOST_TEST_CASE_NAME( test_function, test_name ) \
boost::unit_test::make_test_case( boost::function<void ()>(test_function), \
BOOST_TEST_STRINGIZE( test_function ), \
test_name , \
__FILE__, __LINE__ )
#define BOOST_TEST_CASE( test_function ) \
BOOST_TEST_CASE_NAME(test_function, BOOST_TEST_STRINGIZE( test_function) )
#define BOOST_CLASS_TEST_CASE( test_function, tc_instance ) \
boost::unit_test::make_test_case( (test_function), \
BOOST_TEST_STRINGIZE( test_function ), \
@@ -63,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
@@ -143,11 +145,15 @@ struct test_name : public F { void test_method(); }; \
\
static void BOOST_AUTO_TC_INVOKER( test_name )() \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture entry."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor"); \
test_name t; \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture setup"); \
boost::unit_test::setup_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
t.test_method(); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture teardown"); \
boost::unit_test::teardown_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor"); \
} \
\
struct BOOST_AUTO_TC_UNIQUE_ID( test_name ) {}; \
@@ -163,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
@@ -229,11 +235,15 @@ struct BOOST_AUTO_TC_INVOKER( test_name ) { \
template<typename TestType> \
static void run( boost::type<TestType>* = 0 ) \
{ \
BOOST_TEST_CHECKPOINT('"' << #test_name <<"\" fixture entry."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor"); \
test_name<TestType> t; \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" entry."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture setup"); \
boost::unit_test::setup_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
t.test_method(); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" exit."); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture teardown");\
boost::unit_test::teardown_conditional(t); \
BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor"); \
} \
}; \
\
@@ -241,7 +251,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() \
@@ -290,6 +300,22 @@ void BOOST_JOIN( name, _impl )( boost::type<type_name>* ) \
// ************************************************************************** //
#define BOOST_GLOBAL_FIXTURE( F ) \
static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
/**/
// ************************************************************************** //
// ************** BOOST_TEST_GLOBAL_CONFIGURATION ************** //
// ************************************************************************** //
#define BOOST_TEST_GLOBAL_CONFIGURATION( F ) \
static boost::unit_test::ut_detail::global_configuration_impl<F> BOOST_JOIN( gf_, F ) \
/**/
// ************************************************************************** //
// ************** BOOST_TEST_GLOBAL_FIXTURE ************** //
// ************************************************************************** //
#define BOOST_TEST_GLOBAL_FIXTURE( F ) \
static boost::unit_test::ut_detail::global_fixture_impl<F> BOOST_JOIN( gf_, F ) \
/**/
@@ -298,8 +324,8 @@ 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& \
BOOST_TEST_APPEND_UNIQUE_ID(decorator_collector) = D; \
static boost::unit_test::decorator::collector_t const& \
BOOST_TEST_APPEND_UNIQUE_ID(decorator_collector) BOOST_ATTRIBUTE_UNUSED = D; \
/**/
// ************************************************************************** //
@@ -322,7 +348,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
@@ -339,7 +365,7 @@ typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;
#define BOOST_AUTO_TU_REGISTRAR( test_name ) \
static boost::unit_test::ut_detail::auto_test_unit_registrar \
BOOST_TEST_APPEND_UNIQUE_ID( BOOST_JOIN( test_name, _registrar ) ) \
BOOST_TEST_APPEND_UNIQUE_ID( BOOST_JOIN( test_name, _registrar ) ) BOOST_ATTRIBUTE_UNUSED \
/**/
#define BOOST_AUTO_TC_INVOKER( test_name ) BOOST_JOIN( test_name, _invoker )
#define BOOST_AUTO_TC_UNIQUE_ID( test_name ) BOOST_JOIN( test_name, _id )

View File

@@ -15,10 +15,16 @@
// STL
#include <utility>
#include <algorithm> // std::find
#include <functional> // std::bind1st
#include <functional> // std::bind1st or std::bind
#include <boost/test/detail/suppress_warnings.hpp>
#ifdef BOOST_NO_CXX98_BINDERS
#define BOOST_TEST_BIND1ST(F,A) std::bind( (F), (A), std::placeholders::_1 )
#else
#define BOOST_TEST_BIND1ST(F,A) std::bind1st( (F), (A) )
#endif
//____________________________________________________________________________//
namespace boost {
@@ -109,7 +115,7 @@ find_first_not_of( ForwardIterator1 first1, ForwardIterator1 last1,
Predicate pred )
{
while( first1 != last1 ) {
if( std::find_if( first2, last2, std::bind1st( pred, *first1 ) ) == last2 )
if( std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *first1 ) ) == last2 )
break;
++first1;
}
@@ -159,9 +165,9 @@ find_last_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ) {}
while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ) {}
return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//
@@ -206,9 +212,9 @@ find_last_not_of( BidirectionalIterator1 first1, BidirectionalIterator1 last1,
return last1;
BidirectionalIterator1 it1 = last1;
while( --it1 != first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) != last2 ) {}
while( --it1 != first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) != last2 ) {}
return it1 == first1 && std::find_if( first2, last2, std::bind1st( pred, *it1 ) ) == last2 ? last1 : it1;
return it1 == first1 && std::find_if( first2, last2, BOOST_TEST_BIND1ST( pred, *it1 ) ) == last2 ? last1 : it1;
}
//____________________________________________________________________________//

View File

@@ -39,12 +39,12 @@ namespace unit_test {
// ************************************************************************** //
template<typename CharT>
class basic_cstring {
class BOOST_SYMBOL_VISIBLE basic_cstring {
typedef basic_cstring<CharT> self_type;
public:
// Subtypes
typedef ut_detail::bcs_char_traits<CharT> traits_type;
typedef typename ut_detail::bcs_char_traits<CharT>::std_string std_string;
typedef typename traits_type::std_string std_string;
typedef CharT value_type;
typedef typename remove_cv<value_type>::type value_ret_type;
@@ -60,8 +60,8 @@ public:
// !! should also present reverse_iterator, const_reverse_iterator
#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
enum npos_type { npos = static_cast<size_type>(-1) };
#if !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) && !defined(__DCC__)
BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
#else
// IBM/VisualAge version 6 is not able to handle enums larger than 4 bytes.
// But size_type is 8 bytes in 64bit mode.
@@ -72,6 +72,7 @@ public:
// Constructors; default copy constructor is generated by compiler
basic_cstring();
basic_cstring( basic_cstring const & );
basic_cstring( std_string const& s );
basic_cstring( pointer s );
template<typename LenType>
@@ -162,15 +163,20 @@ private:
// Data members
iterator m_begin;
iterator m_end;
static CharT null;
};
//____________________________________________________________________________//
template<typename CharT>
CharT basic_cstring<CharT>::null = 0;
//____________________________________________________________________________//
template<typename CharT>
inline typename basic_cstring<CharT>::pointer
basic_cstring<CharT>::null_str()
{
static CharT null = 0;
return &null;
}
@@ -186,6 +192,16 @@ basic_cstring<CharT>::basic_cstring()
//____________________________________________________________________________//
template<typename CharT>
inline
basic_cstring<CharT>::basic_cstring(basic_cstring const & s)
: m_begin( s.m_begin )
, m_end( s.m_end )
{
}
//____________________________________________________________________________//
template<typename CharT>
inline
basic_cstring<CharT>::basic_cstring( std_string const& s )

View File

@@ -16,13 +16,13 @@
#ifndef BOOST_TEST_UTILS_BASIC_CSTRING_FWD_HPP
#define BOOST_TEST_UTILS_BASIC_CSTRING_FWD_HPP
#include <boost/detail/workaround.hpp>
#include <boost/test/detail/config.hpp>
namespace boost {
namespace unit_test {
template<typename CharT> class basic_cstring;
template<typename CharT> class BOOST_SYMBOL_VISIBLE basic_cstring;
typedef basic_cstring<char const> const_string;
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590041))
typedef const_string literal_string;
@@ -37,4 +37,3 @@ typedef char const* const c_literal_string;
} // namespace boost
#endif // BOOST_TEST_UTILS_BASIC_CSTRING_FWD_HPP

View File

@@ -76,9 +76,13 @@ case_ins_eq( basic_cstring<CharT> x, basic_cstring<CharT> y )
// ************************************************************************** //
template<class CharT>
class case_ins_less : public std::binary_function<basic_cstring<CharT>,basic_cstring<CharT>,bool>
class case_ins_less
{
public:
typedef bool result_type;
typedef basic_cstring<CharT> first_argument_type;
typedef basic_cstring<CharT> second_argument_type;
bool operator()( basic_cstring<CharT> x, basic_cstring<CharT> y ) const
{
return x.size() != y.size()

View File

@@ -26,7 +26,6 @@
// Boost
#include <boost/type.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/test/detail/workaround.hpp>
#include <boost/type_traits/is_const.hpp>

View File

@@ -23,6 +23,7 @@
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring_fwd.hpp>
#include <string>
//____________________________________________________________________________//
@@ -51,19 +52,36 @@ struct is_cstring_impl<char*> : public mpl::true_ {};
template<>
struct is_cstring_impl<wchar_t*> : public mpl::true_ {};
template <typename T, bool is_cstring = is_cstring_impl<typename boost::decay<T>::type>::value >
struct deduce_cstring_impl;
template <typename T, bool is_cstring >
struct deduce_cstring_impl<T&, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
template <typename T, bool is_cstring >
struct deduce_cstring_impl<T const, is_cstring> : public deduce_cstring_impl<T, is_cstring>{};
template <typename T>
struct deduce_cstring_impl {
struct deduce_cstring_impl<T, true> {
typedef typename boost::add_const<
typename boost::remove_pointer<
typename boost::decay<T>::type
>::type
>::type type;
>::type U;
typedef boost::unit_test::basic_cstring<U> type;
};
template <typename T>
struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
// const is required here
typedef typename boost::add_const<T>::type type;
struct deduce_cstring_impl< T, false > {
typedef typename
boost::remove_const<
typename boost::remove_reference<T>::type
>::type type;
};
template <typename T>
struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> >, false > {
typedef boost::unit_test::basic_cstring<typename boost::add_const<T>::type> type;
};
} // namespace ut_detail
@@ -71,8 +89,17 @@ struct deduce_cstring_impl< std::basic_string<T, std::char_traits<T> > > {
template<typename T>
struct is_cstring : public ut_detail::is_cstring_impl<typename decay<T>::type> {};
template<typename T, bool is_cstring = is_cstring<typename boost::decay<T>::type>::value >
struct is_cstring_comparable: public mpl::false_ {};
template<typename T>
struct is_cstring< std::basic_string<T, std::char_traits<T> > > : public mpl::true_ {};
struct is_cstring_comparable< T, true > : public mpl::true_ {};
template<typename T>
struct is_cstring_comparable< std::basic_string<T, std::char_traits<T> >, false > : public mpl::true_ {};
template<typename T>
struct is_cstring_comparable< boost::unit_test::basic_cstring<T>, false > : public mpl::true_ {};
template <class T>
struct deduce_cstring {
@@ -80,7 +107,7 @@ struct deduce_cstring {
boost::remove_const<
typename boost::remove_reference<T>::type
>::type U;
typedef typename ut_detail::deduce_cstring_impl<U>::type type;
typedef typename ut_detail::deduce_cstring_impl<typename boost::decay<U>::type>::type type;
};
} // namespace unit_test

View File

@@ -16,8 +16,8 @@
defined(BOOST_NO_CXX11_NULLPTR) || \
defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES)
// some issues with boost.config
#if !defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER < 170061030 /* VC2012 upd 5 */
// this feature works with VC2012 upd 5 while BOOST_NO_CXX11_TRAILING_RESULT_TYPES is defined
#if !defined(BOOST_MSVC) || BOOST_MSVC_FULL_VER < 170061232 /* VC2012 upd 5 */
#define BOOST_TEST_FWD_ITERABLE_CXX03
#endif
#endif
@@ -35,6 +35,7 @@
#else
// Boost
#include <boost/static_assert.hpp>
#include <boost/utility/declval.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_reference.hpp>
@@ -51,6 +52,9 @@
namespace boost {
namespace unit_test {
template<typename T>
struct is_forward_iterable;
// ************************************************************************** //
// ************** is_forward_iterable ************** //
// ************************************************************************** //
@@ -65,6 +69,9 @@ struct is_forward_iterable<T const> : public is_forward_iterable<T> {};
template<typename T>
struct is_forward_iterable<T&> : public is_forward_iterable<T> {};
template<typename T, std::size_t N>
struct is_forward_iterable< T [N] > : public mpl::true_ {};
template<typename T, typename A>
struct is_forward_iterable< std::vector<T, A> > : public mpl::true_ {};
@@ -86,6 +93,7 @@ struct is_forward_iterable< std::string > : public mpl::true_ {};
namespace ut_detail {
// SFINAE helper
template<typename T>
struct is_present : public mpl::true_ {};
@@ -110,7 +118,7 @@ template <class T>
struct has_member_begin {
private:
struct nil_t {};
template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().begin());
template<typename U> static auto test( U* ) -> decltype(std::begin(boost::declval<U&>())); // does not work with boost::begin
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
@@ -122,7 +130,7 @@ template <class T>
struct has_member_end {
private:
struct nil_t {};
template<typename U> static auto test( U* ) -> decltype(boost::declval<U>().end());
template<typename U> static auto test( U* ) -> decltype(std::end(boost::declval<U&>())); // does not work with boost::end
template<typename> static nil_t test( ... );
public:
static bool const value = !std::is_same< decltype(test<T>( nullptr )), nil_t>::value;
@@ -134,24 +142,36 @@ template <class T, class enabled = void>
struct is_forward_iterable_impl : std::false_type {
};
//____________________________________________________________________________//
template <class T>
struct is_forward_iterable_impl<
T,
typename std::enable_if<
is_present<typename T::const_iterator>::value &&
is_present<typename T::value_type>::value &&
has_member_size<T>::value &&
has_member_begin<T>::value &&
has_member_end<T>::value &&
!is_cstring<T>::value
has_member_begin<T>::value &&
has_member_end<T>::value
>::type
> : std::true_type
{};
//____________________________________________________________________________//
template <class T, class enabled = void>
struct is_container_forward_iterable_impl : std::false_type {
};
template <class T>
struct is_container_forward_iterable_impl<
T,
typename std::enable_if<
is_present<typename T::const_iterator>::value &&
is_present<typename T::value_type>::value &&
has_member_size<T>::value &&
is_forward_iterable_impl<T>::value
>::type
> : is_forward_iterable_impl<T>
{};
//____________________________________________________________________________//
} // namespace ut_detail
/*! Indicates that a specific type implements the forward iterable concept. */
@@ -163,8 +183,84 @@ struct is_forward_iterable {
enum { value = is_fwd_it_t::value };
};
/*! Indicates that a specific type implements the forward iterable concept. */
template<typename T>
struct is_container_forward_iterable {
typedef typename std::remove_reference<T>::type T_ref;
typedef ut_detail::is_container_forward_iterable_impl<T_ref> is_fwd_it_t;
typedef mpl::bool_<is_fwd_it_t::value> type;
enum { value = is_fwd_it_t::value };
};
#endif /* defined(BOOST_TEST_FWD_ITERABLE_CXX03) */
//! Helper structure for accessing the content of a container or an array
template <typename T, bool is_forward_iterable = is_forward_iterable<T>::value >
struct bt_iterator_traits;
template <typename T>
struct bt_iterator_traits< T, true >{
BOOST_STATIC_ASSERT((is_forward_iterable<T>::value));
#if defined(BOOST_TEST_FWD_ITERABLE_CXX03) || \
(defined(BOOST_MSVC) && (BOOST_MSVC_FULL_VER <= 170061232))
typedef typename T::const_iterator const_iterator;
typedef typename std::iterator_traits<const_iterator>::value_type value_type;
#else
typedef decltype(boost::declval<
typename boost::add_const<
typename boost::remove_reference<T>::type
>::type>().begin()) const_iterator;
typedef typename std::iterator_traits<const_iterator>::value_type value_type;
#endif /* BOOST_TEST_FWD_ITERABLE_CXX03 */
static const_iterator begin(T const& container) {
return container.begin();
}
static const_iterator end(T const& container) {
return container.end();
}
#if defined(BOOST_TEST_FWD_ITERABLE_CXX03) || \
(defined(BOOST_MSVC) && (BOOST_MSVC_FULL_VER <= 170061232))
static std::size_t
size(T const& container) {
return container.size();
}
#else
static std::size_t
size(T const& container) {
return size(container,
std::integral_constant<bool, ut_detail::has_member_size<T>::value>());
}
private:
static std::size_t
size(T const& container, std::true_type) { return container.size(); }
static std::size_t
size(T const& container, std::false_type) { return std::distance(begin(container), end(container)); }
#endif /* BOOST_TEST_FWD_ITERABLE_CXX03 */
};
template <typename T, std::size_t N>
struct bt_iterator_traits< T [N], true > {
typedef typename boost::add_const<T>::type T_const;
typedef typename boost::add_pointer<T_const>::type const_iterator;
typedef T value_type;
static const_iterator begin(T_const (&array)[N]) {
return &array[0];
}
static const_iterator end(T_const (&array)[N]) {
return &array[N];
}
static std::size_t size(T_const (&)[N]) {
return N;
}
};
} // namespace unit_test
} // namespace boost

View File

@@ -28,11 +28,11 @@
namespace boost {
namespace unit_test {
class lazy_ostream {
class BOOST_TEST_DECL lazy_ostream {
public:
virtual ~lazy_ostream() {}
static lazy_ostream& instance() { static lazy_ostream inst; return inst; }
static lazy_ostream& instance() { return inst; }
friend std::ostream& operator<<( std::ostream& ostr, lazy_ostream const& o ) { return o( ostr ); }
@@ -47,6 +47,7 @@ protected:
private:
// Data members
bool m_empty;
static lazy_ostream inst;
};
//____________________________________________________________________________//

View File

@@ -72,7 +72,7 @@ struct is_named_param_pack<named_parameter_combine<NP,Rest> > : public mpl::true
// ************** param_type ************** //
// ************************************************************************** //
/// param_type<Params,Keyword,Default>::type is is the type of the parameter
/// param_type<Params,Keyword,Default>::type is the type of the parameter
/// corresponding to the Keyword (if parameter is present) or Default
template<typename NP, typename Keyword, typename DefaultType=void>
@@ -91,7 +91,7 @@ struct param_type<named_parameter_combine<NP,Rest>,Keyword,DefaultType>
// ************** has_param ************** //
// ************************************************************************** //
/// has_param<Params,Keyword>::value is true id Params has parameter corresponding
/// has_param<Params,Keyword>::value is true if Params has parameter corresponding
/// to the Keyword
template<typename NP, typename Keyword>

View File

@@ -17,6 +17,7 @@
// C Runtime
#include <cstddef>
#include <boost/test/detail/config.hpp>
namespace boost {
namespace rtti {
@@ -30,7 +31,7 @@ typedef std::ptrdiff_t id_t;
namespace rtti_detail {
template<typename T>
struct rttid_holder {
struct BOOST_TEST_DECL rttid_holder {
static id_t id() { return reinterpret_cast<id_t>( &inst() ); }
private:
@@ -44,7 +45,7 @@ private:
//____________________________________________________________________________//
template<typename T>
inline id_t
BOOST_TEST_DECL inline id_t
type_id()
{
return rtti_detail::rttid_holder<T>::id();

View File

@@ -18,6 +18,7 @@
// Boost.Test Runtime parameters
#include <boost/test/utils/runtime/errors.hpp>
#include <boost/test/utils/runtime/argument.hpp>
#include <boost/test/utils/runtime/modifier.hpp>
// Boost.Test
#include <boost/test/utils/basic_cstring/io.hpp>

View File

@@ -17,6 +17,7 @@
// Boost.Test Runtime parameters
#include <boost/test/utils/runtime/fwd.hpp>
#include <cstring>
#include <boost/test/detail/suppress_warnings.hpp>

View File

@@ -109,12 +109,12 @@ struct parameter_trie {
// ************** runtime::cla::report_foreing_token ************** //
// ************************************************************************** //
static void
static void
report_foreing_token( cstring program_name, cstring token )
{
std::cerr << "Boost.Test WARNING: token \"" << token << "\" does not correspond to the Boost.Test argument \n"
<< " and should be placed after all Boost.Test arguments and the -- separator.\n"
<< " For example: " << program_name << " --random -- " << token << "\n";
<< " For example: " << program_name << " --random -- " << token << "\n";
}
} // namespace rt_cla_detail
@@ -203,7 +203,7 @@ public:
if( negative_form ) {
BOOST_TEST_I_ASSRT( found_id.m_negatable,
format_error( found_param->p_name )
format_error( found_param->p_name )
<< "Parameter tag " << found_id.m_tag << " is not negatable." );
curr_token.trim_left( m_negation_prefix.size() );
@@ -211,13 +211,18 @@ public:
curr_token.trim_left( name.size() );
bool should_go_to_next = true;
cstring value;
// Skip validations if parameter has optional value and we are at the end of token
if( !value_separator.is_empty() || !found_param->p_has_optional_value ) {
// we are given a separator or there is no optional value
// Validate and skip value separator in the input
BOOST_TEST_I_ASSRT( found_id.m_value_separator == value_separator,
format_error( found_param->p_name )
format_error( found_param->p_name )
<< "Invalid separator for the parameter "
<< found_param->p_name
<< " in the argument " << tr.current_token() );
@@ -237,6 +242,40 @@ public:
<< found_param->p_name
<< " in the argument " << tr.current_token() );
}
else if( (value_separator.is_empty() && found_id.m_value_separator.empty()) ) {
// Deduce value source
value = curr_token;
if( value.is_empty() ) {
tr.next_token(); // tokenization broke the value, we check the next one
if(!found_param->p_has_optional_value) {
// there is no separator and there is no optional value
// we look for the value on the next token
// example "-t XXXX" (no default)
// and we commit this value as being the passed value
value = tr.current_token();
}
else {
// there is no separator and the value is optional
// we check the next token
// example "-c" (defaults to true)
// and commit this as the value if this is not a token
cstring value_check = tr.current_token();
cstring prefix_test, name_test, value_separator_test;
bool negative_form_test;
if( validate_token_format( value_check, prefix_test, name_test, value_separator_test, negative_form_test )
&& m_param_trie[prefix_test]) {
// this is a token, we consume what we have
should_go_to_next = false;
}
else {
// this is a value, we commit it
value = value_check;
}
}
}
}
// Validate against argument duplication
BOOST_TEST_I_ASSRT( !res.has( found_param->p_name ) || found_param->p_repeatable,
@@ -248,7 +287,9 @@ public:
// Produce argument value
found_param->produce_argument( value, negative_form, res );
tr.next_token();
if(should_go_to_next) {
tr.next_token();
}
}
// generate the remainder and return it's size
@@ -273,7 +314,7 @@ public:
<< BOOST_VERSION % 100 ;
ostr << " with ";
#if defined(BOOST_TEST_INCLUDED)
ostr << "single header inclusion of";
ostr << "header-only inclusion of";
#elif defined(BOOST_TEST_DYN_LINK)
ostr << "dynamic linking to";
#else
@@ -287,57 +328,119 @@ public:
}
void
usage( std::ostream& ostr, cstring param_name = cstring() )
usage(std::ostream& ostr,
cstring param_name = cstring(),
bool use_color = true)
{
namespace utils = unit_test::utils;
namespace ut_detail = unit_test::ut_detail;
if( !param_name.is_empty() ) {
basic_param_ptr param = locate_parameter( m_param_trie[help_prefix], param_name, "" ).second;
param->usage( ostr, m_negation_prefix );
}
else {
ostr << "Usage: " << m_program_name << " [Boost.Test argument]... ";
if( !m_end_of_param_indicator.empty() )
ostr << m_end_of_param_indicator << " [custom test module argument]...";
ostr << "\n";
ostr << "\n The program '" << m_program_name << "' is a Boost.Test module containing unit tests.";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::ORIGINAL );
ostr << "\n\n Usage\n ";
}
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << m_program_name << " [Boost.Test argument]... ";
}
if( !m_end_of_param_indicator.empty() ) {
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::YELLOW );
ostr << '[' << m_end_of_param_indicator << " [custom test module argument]...]";
}
}
ostr << "\nFor detailed help on Boost.Test parameters use:\n"
<< " " << m_program_name << " --help\n"
<< "or\n"
<< " " << m_program_name << " --help=<parameter name>\n";
ostr << "\n\n Use\n ";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << m_program_name << " --help";
}
ostr << "\n or ";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << m_program_name << " --help=<parameter name>";
}
ostr << "\n for detailed help on Boost.Test parameters.\n";
}
void
help( std::ostream& ostr, parameters_store const& parameters, cstring param_name )
help(std::ostream& ostr,
parameters_store const& parameters,
cstring param_name,
bool use_color = true)
{
namespace utils = unit_test::utils;
namespace ut_detail = unit_test::ut_detail;
if( !param_name.is_empty() ) {
basic_param_ptr param = locate_parameter( m_param_trie[help_prefix], param_name, "" ).second;
param->help( ostr, m_negation_prefix );
param->help( ostr, m_negation_prefix, use_color);
return;
}
ostr << "Usage: " << m_program_name << " [Boost.Test argument]... ";
if( !m_end_of_param_indicator.empty() )
ostr << m_end_of_param_indicator << " [custom test module argument]...";
usage(ostr, cstring(), use_color);
ostr << "\n\nBoost.Test arguments correspond to parameters listed below. "
"All parameters are optional. You can use specify parameter value either "
"as a command line argument or as a value of corresponding environment "
"variable. In case if argument for the same parameter is specified in both "
"places, command line is taking precedence. Command line argument format "
"supports parameter name guessing, so you can use any unambiguous "
"prefix to identify a parameter.";
if( !m_end_of_param_indicator.empty() )
ostr << " All the arguments after the " << m_end_of_param_indicator << " are ignored by the Boost.Test.";
ostr << "\n\n";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::ORIGINAL );
ostr << " Command line flags:\n";
}
runtime::commandline_pretty_print(
ostr,
" ",
"The command line flags of Boost.Test are listed below. "
"All parameters are optional. You can specify parameter value either "
"as a command line argument or as a value of its corresponding environment "
"variable. If a flag is specified as a command line argument and an environment variable "
"at the same time, the command line takes precedence. "
"The command line argument "
"support name guessing, and works with shorter names as long as those are not ambiguous."
);
ostr << "\n\nBoost.Test supports following parameters:\n";
BOOST_TEST_FOREACH( parameters_store::storage_type::value_type const&, v, parameters.all() ) {
basic_param_ptr param = v.second;
param->usage( ostr, m_negation_prefix );
if( !m_end_of_param_indicator.empty() ) {
ostr << "\n\n All the arguments after the '";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::YELLOW );
ostr << m_end_of_param_indicator;
}
ostr << "' are ignored by Boost.Test.";
}
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::ORIGINAL );
ostr << "\n\n Environment variables:\n";
}
runtime::commandline_pretty_print(
ostr,
" ",
"Every argument listed below may also be set by a corresponding environment"
"variable. For an argument '--argument_x=<value>', the corresponding "
"environment variable is 'BOOST_TEST_ARGUMENT_X=value"
);
ostr << "\n\n The following parameters are supported:\n";
BOOST_TEST_FOREACH(
parameters_store::storage_type::value_type const&,
v,
parameters.all() )
{
basic_param_ptr param = v.second;
ostr << "\n";
param->usage( ostr, m_negation_prefix, use_color);
}
ostr << "\nUse --help=<parameter name> to display detailed help for specific parameter.\n";
}
private:

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,13 +55,13 @@ 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 {}
};
class input_error : public param_error {
class BOOST_SYMBOL_VISIBLE input_error : public param_error {
protected:
explicit input_error( cstring param_name ) : param_error( param_name ) {}
~input_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 {}
@@ -86,7 +86,7 @@ public:
{
this->msg.append( val );
return reinterpret_cast<Derived&&>(*this);
return static_cast<Derived&&>(*this);
}
//____________________________________________________________________________//
@@ -96,7 +96,7 @@ public:
{
this->msg.append( unit_test::utils::string_cast( val ) );
return reinterpret_cast<Derived&&>(*this);
return static_cast<Derived&&>(*this);
}
//____________________________________________________________________________//
@@ -133,7 +133,7 @@ public:
// ************************************************************************** //
#define SPECIFIC_EX_TYPE( type, base ) \
class type : public specific_param_error<type,base> { \
class BOOST_SYMBOL_VISIBLE type : public specific_param_error<type,base> { \
public: \
explicit type( cstring param_name = cstring() ) \
: specific_param_error<type,base>( param_name ) \
@@ -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 )
@@ -171,7 +171,7 @@ public:
std::vector<cstring> m_amb_candidates;
};
class unrecognized_param : public specific_param_error<unrecognized_param, input_error> {
class BOOST_SYMBOL_VISIBLE unrecognized_param : public specific_param_error<unrecognized_param, input_error> {
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
explicit unrecognized_param( std::vector<cstring>&& type_candidates )

View File

@@ -20,6 +20,7 @@
// Boost.Test
#include <boost/test/utils/named_params.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/suppress_warnings.hpp>

View File

@@ -24,9 +24,10 @@
// Boost.Test
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/utils/foreach.hpp>
#include <boost/test/utils/setcolor.hpp>
// Boost
#include <boost/function/function2.hpp>
#include <boost/function.hpp>
#include <boost/algorithm/cxx11/all_of.hpp>
// STL
@@ -37,6 +38,40 @@
namespace boost {
namespace runtime {
inline
std::ostream& commandline_pretty_print(
std::ostream& ostr,
std::string const& prefix,
std::string const& to_print) {
const int split_at = 80;
std::string::size_type current = 0;
while(current < to_print.size()) {
// discards spaces at the beginning
std::string::size_type startpos = to_print.find_first_not_of(" \t\n", current);
current += startpos - current;
bool has_more_lines = (current + split_at) < to_print.size();
if(has_more_lines) {
std::string::size_type endpos = to_print.find_last_of(" \t\n", current + split_at);
std::string sub(to_print.substr(current, endpos - current));
ostr << prefix << sub;
ostr << "\n";
current += endpos - current;
}
else
{
ostr << prefix << to_print.substr(current, split_at);
current += split_at;
}
}
return ostr;
}
// ************************************************************************** //
// ************** runtime::parameter_cla_id ************** //
// ************************************************************************** //
@@ -142,23 +177,37 @@ public:
virtual void produce_default( arguments_store& store ) const = 0;
/// interfaces for help message reporting
virtual void usage( std::ostream& ostr, cstring negation_prefix_ )
virtual void usage( std::ostream& ostr, cstring negation_prefix_, bool use_color = true )
{
ostr << "Parameter: " << p_name << '\n';
if( !p_description.empty() )
ostr << ' ' << p_description << '\n';
namespace utils = unit_test::utils;
namespace ut_detail = unit_test::ut_detail;
//
ostr << " ";
{
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << p_name;
}
ostr << '\n';
if( !p_description.empty() ) {
commandline_pretty_print(ostr, " ", p_description) << '\n';
}
ostr << " Command line formats:\n";
BOOST_TEST_FOREACH( parameter_cla_id const&, id, cla_ids() ) {
if( id.m_prefix == help_prefix )
continue;
ostr << " " << id.m_prefix;
if( id.m_negatable )
cla_name_help( ostr, id.m_tag, negation_prefix_ );
else
cla_name_help( ostr, id.m_tag, "" );
ostr << " " << id.m_prefix;
if( id.m_negatable )
cla_name_help( ostr, id.m_tag, negation_prefix_, use_color );
else
cla_name_help( ostr, id.m_tag, "", use_color );
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::YELLOW );
bool optional_value_ = false;
if( p_has_optional_value ) {
@@ -166,6 +215,7 @@ public:
ostr << '[';
}
if( id.m_value_separator.empty() )
ostr << ' ';
else {
@@ -179,16 +229,16 @@ public:
ostr << '\n';
}
if( !p_env_var.empty() )
ostr << " Environment variable: " << p_env_var << '\n';
}
virtual void help( std::ostream& ostr, cstring negation_prefix_ )
virtual void help( std::ostream& ostr, cstring negation_prefix_, bool use_color = true )
{
usage( ostr, negation_prefix_ );
usage( ostr, negation_prefix_, use_color );
if( !p_help.empty() )
ostr << '\n' << p_help << '\n';
if( !p_help.empty() ) {
ostr << '\n';
commandline_pretty_print(ostr, " ", p_help);
}
}
protected:
@@ -220,7 +270,7 @@ protected:
private:
/// interface for usage/help customization
virtual void cla_name_help( std::ostream& ostr, cstring cla_tag, cstring /* negation_prefix_ */) const
virtual void cla_name_help( std::ostream& ostr, cstring cla_tag, cstring /*negation_prefix_*/, bool /*use_color*/ = true) const
{
ostr << cla_tag;
}
@@ -337,12 +387,16 @@ private:
{
m_arg_factory.produce_default( p_name, store );
}
virtual void cla_name_help( std::ostream& ostr, cstring cla_tag, cstring negation_prefix_ ) const
virtual void cla_name_help( std::ostream& ostr, cstring cla_tag, cstring negation_prefix_, bool use_color = true ) const
{
if( negation_prefix_.is_empty() )
ostr << cla_tag;
else
ostr << '[' << negation_prefix_ << ']' << cla_tag;
namespace utils = unit_test::utils;
namespace ut_detail = unit_test::ut_detail;
if( !negation_prefix_.is_empty() ) {
BOOST_TEST_SCOPE_SETCOLOR( use_color, ostr, term_attr::BRIGHT, term_color::YELLOW );
ostr << '[' << negation_prefix_ << ']';
}
ostr << cla_tag;
}
virtual void value_help( std::ostream& ostr ) const
{

View File

@@ -18,12 +18,23 @@
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/core/ignore_unused.hpp>
// STL
#include <iostream>
#include <cstdio>
#include <boost/test/detail/suppress_warnings.hpp>
#ifdef _WIN32
#include <windows.h>
#if defined(__MINGW32__) && !defined(COMMON_LVB_UNDERSCORE)
// mingw badly mimicking windows.h
#define COMMON_LVB_UNDERSCORE 0x8000
#endif
#endif
//____________________________________________________________________________//
namespace boost {
@@ -64,57 +75,244 @@ struct term_color { enum _ {
// ************** setcolor ************** //
// ************************************************************************** //
#ifndef _WIN32
class setcolor {
public:
// Constructor
explicit setcolor( term_attr::_ attr = term_attr::NORMAL,
explicit setcolor( bool is_color_output = false,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: m_is_color_output(is_color_output)
{
m_command_size = std::sprintf( m_control_command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40 );
m_command_size = std::sprintf( m_control_command, "%c[%c;3%c;4%cm",
0x1B,
static_cast<char>(attr + '0'),
static_cast<char>(fg + '0'),
static_cast<char>(bg + '0'));
}
friend std::ostream&
operator<<( std::ostream& os, setcolor const& sc )
{
return os.write( sc.m_control_command, sc.m_command_size );
if (sc.m_is_color_output && (&os == &std::cout || &os == &std::cerr)) {
return os.write( sc.m_control_command, sc.m_command_size );
}
return os;
}
private:
// Data members
bool m_is_color_output;
char m_control_command[13];
int m_command_size;
};
#else
class setcolor {
protected:
void set_console_color(std::ostream& os, WORD *attributes = NULL) const {
if (!m_is_color_output) {
return;
}
DWORD console_type;
if (&os == &std::cout) {
console_type = STD_OUTPUT_HANDLE;
}
else if (&os == &std::cerr) {
console_type = STD_ERROR_HANDLE;
}
else {
return;
}
HANDLE hConsole = GetStdHandle(console_type);
if(hConsole == INVALID_HANDLE_VALUE || hConsole == NULL )
return;
if(attributes != NULL) {
SetConsoleTextAttribute(hConsole, *attributes);
return;
}
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
saved_attributes = consoleInfo.wAttributes;
WORD fg_attr = 0;
switch(m_fg)
{
case term_color::WHITE:
fg_attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case term_color::BLACK:
fg_attr = 0;
break;
case term_color::RED:
fg_attr = FOREGROUND_RED;
break;
case term_color::GREEN:
fg_attr = FOREGROUND_GREEN;
break;
case term_color::CYAN:
fg_attr = FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case term_color::MAGENTA:
fg_attr = FOREGROUND_RED | FOREGROUND_BLUE;
break;
case term_color::BLUE:
fg_attr = FOREGROUND_BLUE;
break;
case term_color::YELLOW:
fg_attr = FOREGROUND_RED | FOREGROUND_GREEN;
break;
case term_color::ORIGINAL:
default:
fg_attr = saved_attributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
}
WORD bg_attr = 0;
switch(m_bg)
{
case term_color::BLACK:
bg_attr = 0;
break;
case term_color::WHITE:
bg_attr = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
break;
case term_color::RED:
bg_attr = BACKGROUND_RED;
break;
case term_color::GREEN:
bg_attr = BACKGROUND_GREEN;
break;
case term_color::BLUE:
bg_attr = BACKGROUND_BLUE;
break;
case term_color::ORIGINAL:
default:
bg_attr = saved_attributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
break;
}
WORD text_attr = 0;
switch(m_attr)
{
case term_attr::BRIGHT:
text_attr = FOREGROUND_INTENSITY;
break;
case term_attr::UNDERLINE:
text_attr = COMMON_LVB_UNDERSCORE;
break;
default:
break;
}
SetConsoleTextAttribute(hConsole, fg_attr | bg_attr | text_attr);
return;
}
public:
// Constructor
explicit setcolor(
bool is_color_output = false,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: m_is_color_output(is_color_output)
, m_attr(attr)
, m_fg(fg)
, m_bg(bg)
{}
friend std::ostream&
operator<<( std::ostream& os, setcolor const& sc )
{
sc.set_console_color(os);
return os;
}
private:
bool m_is_color_output;
term_attr::_ m_attr;
term_color::_ m_fg;
term_color::_ m_bg;
protected:
// Data members
mutable WORD saved_attributes;
};
#endif
// ************************************************************************** //
// ************** scope_setcolor ************** //
// ************************************************************************** //
#ifndef _WIN32
struct scope_setcolor {
scope_setcolor() : m_os( 0 ) {}
explicit scope_setcolor( std::ostream& os,
explicit scope_setcolor( bool is_color_output,
std::ostream& os,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: m_os( &os )
, m_is_color_output( is_color_output )
{
os << setcolor( attr, fg, bg );
os << setcolor( is_color_output, attr, fg, bg );
}
~scope_setcolor()
{
if( m_os )
*m_os << setcolor();
*m_os << setcolor( m_is_color_output );
}
private:
scope_setcolor(const scope_setcolor& r);
scope_setcolor& operator=(const scope_setcolor& r);
// Data members
std::ostream* m_os;
bool m_is_color_output;
};
#define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
utils::scope_setcolor const& sc = is_color_output \
? utils::scope_setcolor( os, utils::attr, utils::color ) \
: utils::scope_setcolor(); \
ut_detail::ignore_unused_variable_warning( sc ) \
#else
struct scope_setcolor : setcolor {
scope_setcolor() : m_os( 0 ) {}
explicit scope_setcolor(
bool is_color_output,
std::ostream& os,
term_attr::_ attr = term_attr::NORMAL,
term_color::_ fg = term_color::ORIGINAL,
term_color::_ bg = term_color::ORIGINAL )
: setcolor(is_color_output, attr, fg, bg)
, m_os( &os )
{
os << *this;
}
~scope_setcolor()
{
if (m_os) {
set_console_color(*m_os, &this->saved_attributes);
}
}
private:
scope_setcolor(const scope_setcolor& r);
scope_setcolor& operator=(const scope_setcolor& r);
// Data members
std::ostream* m_os;
};
#endif
#define BOOST_TEST_SCOPE_SETCOLOR( is_color_output, os, attr, color ) \
utils::scope_setcolor const sc(is_color_output, os, utils::attr, utils::color); \
boost::ignore_unused( sc ) \
/**/
} // namespace utils

View File

@@ -0,0 +1,164 @@
// (C) Copyright Raffi Enficiaud 2019.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// Description : timer and elapsed types
// ***************************************************************************
#ifndef BOOST_TEST_UTILS_TIMER_HPP
#define BOOST_TEST_UTILS_TIMER_HPP
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <utility>
#include <ctime>
# if defined(_WIN32) || defined(__CYGWIN__)
# define BOOST_TEST_TIMER_WINDOWS_API
# elif defined(__MACH__)// && !defined(CLOCK_MONOTONIC)
# // we compile for all macs the same, CLOCK_MONOTONIC introduced in 10.12
# define BOOST_TEST_TIMER_MACH_API
# else
# define BOOST_TEST_TIMER_POSIX_API
# if !defined(CLOCK_MONOTONIC)
# error "CLOCK_MONOTONIC not defined"
# endif
# endif
# if defined(BOOST_TEST_TIMER_WINDOWS_API)
# include <windows.h>
# elif defined(BOOST_TEST_TIMER_MACH_API)
# include <mach/mach_time.h>
//# include <mach/mach.h> /* host_get_clock_service, mach_... */
# else
# include <sys/time.h>
# endif
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::clock_t; using ::clock; }
# endif
namespace boost {
namespace unit_test {
namespace timer {
struct elapsed_time
{
typedef boost::int_least64_t nanosecond_type;
nanosecond_type wall;
nanosecond_type system;
void clear() {
wall = 0;
system = 0;
}
};
inline double
microsecond_wall_time( elapsed_time const& elapsed )
{
return elapsed.wall / 1E3;
}
inline double
second_wall_time( elapsed_time const& elapsed )
{
return elapsed.wall / 1E9;
}
namespace details {
#if defined(BOOST_TEST_TIMER_WINDOWS_API)
elapsed_time::nanosecond_type get_tick_freq() {
LARGE_INTEGER freq;
::QueryPerformanceFrequency( &freq );
return static_cast<elapsed_time::nanosecond_type>(freq.QuadPart);
}
#elif defined(BOOST_TEST_TIMER_MACH_API)
std::pair<elapsed_time::nanosecond_type, elapsed_time::nanosecond_type> get_time_base() {
mach_timebase_info_data_t timebase;
if(mach_timebase_info(&timebase) == 0)
return std::pair<elapsed_time::nanosecond_type, elapsed_time::nanosecond_type>(timebase.numer, timebase.denom);
return std::pair<elapsed_time::nanosecond_type, elapsed_time::nanosecond_type>(0, 1);
}
#endif
}
//! Simple timing class
//!
//! This class measures the wall clock time.
class timer
{
public:
timer()
{
restart();
}
void restart()
{
_start_time_clock = std::clock();
#if defined(BOOST_TEST_TIMER_WINDOWS_API)
::QueryPerformanceCounter(&_start_time_wall);
#elif defined(BOOST_TEST_TIMER_MACH_API)
_start_time_wall = mach_absolute_time();
#else
if( ::clock_gettime( CLOCK_MONOTONIC, &_start_time_wall ) != 0 )
{
_start_time_wall.tv_nsec = -1;
_start_time_wall.tv_sec = -1;
}
#endif
}
// return elapsed time in seconds
elapsed_time elapsed() const
{
typedef elapsed_time::nanosecond_type nanosecond_type;
static const double clock_to_nano_seconds = 1E9 / CLOCKS_PER_SEC;
elapsed_time return_value;
// processor / system time
return_value.system = static_cast<nanosecond_type>(double(std::clock() - _start_time_clock) * clock_to_nano_seconds);
#if defined(BOOST_TEST_TIMER_WINDOWS_API)
static const nanosecond_type tick_per_sec = details::get_tick_freq();
LARGE_INTEGER end_time;
::QueryPerformanceCounter(&end_time);
return_value.wall = static_cast<nanosecond_type>(((end_time.QuadPart - _start_time_wall.QuadPart) * 1E9) / tick_per_sec);
#elif defined(BOOST_TEST_TIMER_MACH_API)
static std::pair<nanosecond_type, nanosecond_type> timebase = details::get_time_base();
nanosecond_type clock = mach_absolute_time() - _start_time_wall;
return_value.wall = static_cast<nanosecond_type>((clock * timebase.first) / timebase.second);
#else
struct timespec end_time;
if( ::clock_gettime( CLOCK_MONOTONIC, &end_time ) == 0 )
{
return_value.wall = static_cast<nanosecond_type>((end_time.tv_sec - _start_time_wall.tv_sec) * 1E9 + (end_time.tv_nsec - _start_time_wall.tv_nsec));
}
#endif
return return_value;
}
private:
std::clock_t _start_time_clock;
#if defined(BOOST_TEST_TIMER_WINDOWS_API)
LARGE_INTEGER _start_time_wall;
#elif defined(BOOST_TEST_TIMER_MACH_API)
elapsed_time::nanosecond_type _start_time_wall;
#else
struct timespec _start_time_wall;
#endif
};
//____________________________________________________________________________//
} // namespace timer
} // namespace unit_test
} // namespace boost
#endif // BOOST_TEST_UTILS_TIMER_HPP

View File

@@ -1,79 +0,0 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : simple helpers for creating cusom output manipulators
// ***************************************************************************
#ifndef BOOST_TEST_UTILS_TRIVIAL_SIGNLETON_HPP
#define BOOST_TEST_UTILS_TRIVIAL_SIGNLETON_HPP
// Boost.Test
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
// Boost
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** singleton ************** //
// ************************************************************************** //
template<typename Derived>
class singleton {
public:
static Derived& instance() { static Derived the_inst; return the_inst; }
BOOST_DELETED_FUNCTION(singleton(singleton const&))
BOOST_DELETED_FUNCTION(singleton& operator=(singleton const&))
protected:
BOOST_DEFAULTED_FUNCTION(singleton(), {})
BOOST_DEFAULTED_FUNCTION(~singleton(), {})
};
//____________________________________________________________________________//
#define BOOST_TEST_SINGLETON_CONS( type ) \
friend class boost::unit_test::singleton<type>; \
type() {} \
/**/
#if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
#define BOOST_TEST_SINGLETON_INST( inst ) \
template class unit_test::singleton< BOOST_JOIN( inst, _t ) > ; \
namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); }
#elif defined(__APPLE_CC__) && defined(__GNUC__) && __GNUC__ < 4
#define BOOST_TEST_SINGLETON_INST( inst ) \
static BOOST_JOIN( inst, _t)& inst = BOOST_JOIN (inst, _t)::instance();
#else
#define BOOST_TEST_SINGLETON_INST( inst ) \
namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance(); }
#endif
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UTILS_TRIVIAL_SIGNLETON_HPP

View File

@@ -16,6 +16,7 @@
#define BOOST_TEST_UTILS_XML_PRINTER_HPP
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
#include <boost/test/utils/custom_manip.hpp>
#include <boost/test/utils/foreach.hpp>
@@ -26,6 +27,7 @@
// STL
#include <iostream>
#include <map>
#include <boost/test/detail/suppress_warnings.hpp>