1
0
mirror of https://git.suyu.dev/suyu/suyu synced 2025-09-11 00:36:35 -05:00

Initial commit

This commit is contained in:
Crimson-Hawk
2024-03-05 16:42:40 +08:00
commit f1e4595ebf
39576 changed files with 7006612 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
CRTLinkage: dynamic
LibraryLinkage: dynamic

View File

@@ -0,0 +1,8 @@
Package: boost-test
Version: 1.79.0
Depends: boost-algorithm, boost-assert, boost-bind, boost-build, boost-config, boost-core, boost-detail, boost-exception, boost-function, boost-io, boost-iterator, boost-modular-build-helper, boost-mpl, boost-numeric-conversion, boost-optional, boost-preprocessor, boost-smart-ptr, boost-static-assert, boost-type-traits, boost-utility, boost-vcpkg-helpers, vcpkg-cmake
Architecture: x64-windows
Multi-Arch: same
Abi: 4b372770143aa5260ae586dd2f86f09e6dd6d8db0b088e00a26f947eb4695589
Description: Boost test module
Type: Port

View File

@@ -0,0 +1,21 @@
// (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 Deprecated header.
//! @deprecated Use @c boost/test/unit_test.hpp instead.
// ***************************************************************************
#ifndef BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER
#define BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/unit_test.hpp>" )
#include <boost/test/unit_test.hpp>
#endif // BOOST_TEST_AUTO_UNIT_TEST_HPP_071894GER

View File

@@ -0,0 +1,50 @@
// (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 common dataset macros
// ***************************************************************************
#ifndef BOOST_TEST_DATA_CONFIG_HPP_112611GER
#define BOOST_TEST_DATA_CONFIG_HPP_112611GER
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/detail/throw_exception.hpp>
// STL
#include <stdexcept> // for std::logic_error
// availability on features: preprocessed by doxygen
#if defined(BOOST_NO_CXX11_HDR_RANDOM) || defined(BOOST_TEST_DOXYGEN_DOC__)
//! Defined when the random dataset feature is not available
#define BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE
#endif
#if defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
//! Defined when grid composition of datasets is not available
#define BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE
//! Defined when zip composition of datasets is not available
#define BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE
#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 ) )
#define BOOST_TEST_DS_ASSERT( cond, msg ) BOOST_TEST_I_ASSRT( cond, std::logic_error( msg ) )
#endif // BOOST_TEST_DATA_CONFIG_HPP_112611GER

View File

@@ -0,0 +1,19 @@
// (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 dataset interfaces
// ***************************************************************************
#ifndef BOOST_TEST_DATA_DATASET_HPP_102211GER
#define BOOST_TEST_DATA_DATASET_HPP_102211GER
// Boost.Test
#include <boost/test/data/monomorphic.hpp>
#endif // BOOST_TEST_DATA_DATASET_HPP_102211GER

View File

@@ -0,0 +1,117 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
/// @file
/// Defines for_each_sample algorithm
// ***************************************************************************
#ifndef BOOST_TEST_DATA_FOR_EACH_SAMPLE_HPP_102211GER
#define BOOST_TEST_DATA_FOR_EACH_SAMPLE_HPP_102211GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/size.hpp>
#include <boost/test/data/index_sequence.hpp>
#include <boost/test/data/monomorphic/sample_merge.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
// STL
#include <tuple>
#include <boost/test/detail/suppress_warnings.hpp>
// needed for std::min
#include <algorithm>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
// ************************************************************************** //
// ************** data::invoke_action ************** //
// ************************************************************************** //
template<typename Action, typename T>
inline void
invoke_action( Action const& action, T && arg, std::false_type /* is_tuple */ )
{
action( std::forward<T>(arg) );
}
//____________________________________________________________________________//
template<typename Action, typename T, std::size_t ...I>
inline void
invoke_action_impl( Action const& action,
T && args,
index_sequence<I...> const& )
{
action( std::get<I>(std::forward<T>(args))... );
}
//____________________________________________________________________________//
template<typename Action, typename T>
inline void
invoke_action( Action const& action, T&& args, std::true_type /* is_tuple */ )
{
invoke_action_impl( action,
std::forward<T>(args),
typename make_index_sequence< 0,
std::tuple_size<typename std::decay<T>::type>::value
>::type{} );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** for_each_sample ************** //
// ************************************************************************** //
template<typename DataSet, typename Action>
inline typename std::enable_if<monomorphic::is_dataset<DataSet>::value,void>::type
for_each_sample( DataSet const & samples,
Action const& act,
data::size_t number_of_samples = BOOST_TEST_DS_INFINITE_SIZE )
{
data::size_t size = (std::min)( samples.size(), number_of_samples );
BOOST_TEST_DS_ASSERT( !size.is_inf(), "Dataset has infinite size. Please specify the number of samples" );
auto it = samples.begin();
while( size-- > 0 ) {
invoke_action( act,
*it,
typename monomorphic::ds_detail::is_tuple<decltype(*it)>::type());
++it;
}
}
//____________________________________________________________________________//
template<typename DataSet, typename Action>
inline typename std::enable_if<!monomorphic::is_dataset<DataSet>::value,void>::type
for_each_sample( DataSet && samples,
Action const& act,
data::size_t number_of_samples = BOOST_TEST_DS_INFINITE_SIZE )
{
data::for_each_sample( data::make( std::forward<DataSet>(samples) ),
act,
number_of_samples );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_FOR_EACH_SAMPLE_HPP_102211GER

View File

@@ -0,0 +1,67 @@
// (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
/// Defines c++14 index_sequence implementation
// ***************************************************************************
#ifndef BOOST_TEST_DATA_INDEX_SEQUENCE_HPP
#define BOOST_TEST_DATA_INDEX_SEQUENCE_HPP
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
// ************************************************************************** //
// ************** data::index_sequence ************** //
// ************************************************************************** //
template <std::size_t... Ns>
struct index_sequence {};
template<typename IS1, typename IS2>
struct merge_index_sequence;
template <std::size_t... Ns1, std::size_t... Ns2>
struct merge_index_sequence<index_sequence<Ns1...>, index_sequence<Ns2...>> {
typedef index_sequence<Ns1..., Ns2...> type;
};
template <std::size_t B, std::size_t E, typename Enabler = void>
struct make_index_sequence {
typedef typename merge_index_sequence<typename make_index_sequence<B,(B+E)/2>::type,
typename make_index_sequence<(B+E)/2,E>::type>::type type;
};
template <std::size_t B, std::size_t E>
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;
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_INDEX_SEQUENCE_HPP

View File

@@ -0,0 +1,28 @@
// (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 Monomorphic dataset interfaces
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_HPP_102211GER
#define BOOST_TEST_DATA_MONOMORPHIC_HPP_102211GER
// Boost.Test
#include <boost/test/data/monomorphic/array.hpp>
#include <boost/test/data/monomorphic/collection.hpp>
#include <boost/test/data/monomorphic/initializer_list.hpp>
#include <boost/test/data/monomorphic/generate.hpp>
#include <boost/test/data/monomorphic/generators.hpp>
#include <boost/test/data/monomorphic/grid.hpp>
#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

@@ -0,0 +1,83 @@
// (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
///Defines monomorphic dataset based on C type arrays
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_ARRAY_HPP_121411GER
#define BOOST_TEST_DATA_MONOMORPHIC_ARRAY_HPP_121411GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** array ************** //
// ************************************************************************** //
/// Dataset view of a C array
template<typename T>
class array {
public:
typedef T sample;
static const int arity = 1;
typedef T const* iterator;
// Constructor
array( T const* arr_, std::size_t size_ )
: m_arr( arr_ )
, m_size( size_ )
{}
// dataset interface
data::size_t size() const { return m_size; }
iterator begin() const { return m_arr; }
private:
// Data members
T const* m_arr;
std::size_t m_size;
};
//____________________________________________________________________________//
//! An array dataset is a dataset
template<typename T>
struct is_dataset<array<T>> : mpl::true_ {};
} // namespace monomorphic
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename T, std::size_t size>
inline monomorphic::array<typename boost::remove_const<T>::type>
make( T (&a)[size] )
{
return monomorphic::array<typename boost::remove_const<T>::type>( a, size );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_ARRAY_HPP_121411GER

View File

@@ -0,0 +1,91 @@
// (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
///Defines monomorphic dataset based on forward iterable sequence
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_COLLECTION_HPP_102211GER
#define BOOST_TEST_DATA_MONOMORPHIC_COLLECTION_HPP_102211GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** collection ************** //
// ************************************************************************** //
//!@brief Dataset from a forward iterable container (collection)
//!
//! This dataset is applicable to any container implementing a forward iterator. Note that
//! container with one element will be considered as singletons.
//! This dataset is constructible with the @ref boost::unit_test::data::make function.
template<typename C>
class collection {
typedef typename boost::decay<C>::type col_type;
public:
typedef typename col_type::value_type sample;
static const int arity = 1;
typedef typename col_type::const_iterator iterator;
//! Constructor consumed a temporary collection or stores a reference
explicit collection( C&& col ) : m_col( std::forward<C>(col) ) {}
//! Move constructor
collection( collection&& c ) : m_col( std::forward<C>( c.m_col ) ) {}
//! Returns the underlying collection
C const& col() const { return m_col; }
//! dataset interface
data::size_t size() const { return m_col.size(); }
iterator begin() const { return m_col.begin(); }
private:
// Data members
C m_col;
};
//____________________________________________________________________________//
//! A collection from a forward iterable container is a dataset.
template<typename C>
struct is_dataset<collection<C>> : mpl::true_ {};
} // namespace monomorphic
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename C>
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) );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_COLLECTION_HPP_102211GER

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:
static const int 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

@@ -0,0 +1,222 @@
// (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
/// Forward declares monomorphic datasets interfaces
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_FWD_HPP_102212GER
#define BOOST_TEST_DATA_MONOMORPHIC_FWD_HPP_102212GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/size.hpp>
#include <boost/test/utils/is_forward_iterable.hpp>
// Boost
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/mpl/bool.hpp>
// STL
#include <tuple>
#include <boost/test/detail/suppress_warnings.hpp>
// STL
#include <initializer_list>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
#if !defined(BOOST_TEST_DOXYGEN_DOC__)
template<typename T>
class singleton;
template<typename C>
class collection;
template<typename T>
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
// ************************************************************************** //
// ************** monomorphic::is_dataset ************** //
// ************************************************************************** //
//! Helper metafunction indicating if the specified type is a dataset.
template<typename DataSet>
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> {};
//____________________________________________________________________________//
//! A const dataset is a 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
// ************************************************************************** //
// ************** data::make ************** //
// ************************************************************************** //
//! @brief Creates a dataset from a value, a collection or an array
//!
//! This function has several overloads:
//! @code
//! // returns ds if ds is already a dataset
//! template <typename DataSet> DataSet make(DataSet&& ds);
//!
//! // creates a singleton dataset, for non forward iterable and non dataset type T
//! // (a C string is not considered as a sequence).
//! template <typename T> monomorphic::singleton<T> make(T&& v);
//! monomorphic::singleton<char*> make( char* str );
//! monomorphic::singleton<char const*> make( char const* str );
//!
//! // creates a collection dataset, for forward iterable and non dataset type C
//! template <typename C> monomorphic::collection<C> make(C && c);
//!
//! // creates an array dataset
//! template<typename T, std::size_t size> monomorphic::array<T> make( T (&a)[size] );
//! @endcode
template<typename DataSet>
inline typename std::enable_if<monomorphic::is_dataset<DataSet>::value,DataSet>::type
make(DataSet&& ds)
{
return std::forward<DataSet>( ds );
}
//____________________________________________________________________________//
// warning: doxygen is apparently unable to handle @overload from different files, so if the overloads
// below are not declared with @overload in THIS file, they do not appear in the documentation.
//! @overload boost::unit_test::data::make()
template<typename T>
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
make( T&& v );
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename C>
inline typename std::enable_if<is_container_forward_iterable<C>::value,monomorphic::collection<C>>::type
make( C&& c );
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename T, std::size_t size>
inline monomorphic::array< typename boost::remove_const<T>::type >
make( T (&a)[size] );
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
inline monomorphic::singleton<char*>
make( char* str );
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
inline monomorphic::singleton<char const*>
make( char const* str );
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename T>
inline monomorphic::init_list<T>
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.
template<typename DataSet>
struct make {
typedef decltype( data::make( declval<DataSet>() ) ) type;
};
} // namespace result_of
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_FWD_HPP_102212GER

View File

@@ -0,0 +1,111 @@
// (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
/// Defines generic interface for monomorphic dataset based on generator
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATE_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATE_HPP_112011GER
// Boost.Test
#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>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** generated_by ************** //
// ************************************************************************** //
/*!@brief Generators interface
*
* This class implements the dataset concept over a generator. Examples of generators are:
* - xrange_t
* - random_t
*
* The generator concept is the following:
* - the type of the generated samples is given by field @c sample
* - the member function @c capacity should return the size of the collection being generated (potentially infinite)
* - the member function @c next should change the state of the generator to the next generated value
* - the member function @c reset should put the state of the object in the same state as right after its instanciation
*/
template<typename Generator>
class generated_by {
public:
typedef typename Generator::sample sample;
static const int arity = 1;
struct iterator {
// Constructor
explicit iterator( Generator& gen )
: m_gen( &gen )
{
if(m_gen->capacity() > 0) {
m_gen->reset();
++*this;
}
}
// forward iterator interface
sample const& operator*() const { return m_curr_sample; }
void operator++() { m_curr_sample = m_gen->next(); }
private:
// Data members
Generator* m_gen;
sample m_curr_sample;
};
typedef Generator generator_type;
// Constructor
explicit generated_by( Generator&& G )
: m_generator( std::forward<Generator>(G) )
{}
// Move constructor
generated_by( generated_by&& rhs )
: m_generator( std::forward<Generator>(rhs.m_generator) )
{}
//! Size of the underlying dataset
data::size_t size() const { return m_generator.capacity(); }
//! Iterator on the beginning of the dataset
iterator begin() const { return iterator( boost::ref(const_cast<Generator&>(m_generator)) ); }
private:
// Data members
Generator m_generator;
};
//____________________________________________________________________________//
//! A generated dataset is a dataset.
template<typename Generator>
struct is_dataset<generated_by<Generator>> : mpl::true_ {};
} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATE_HPP_112011GER

View File

@@ -0,0 +1,20 @@
// (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
///Defines 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>
#include <boost/test/data/monomorphic/generators/random.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_HPP_112011GER

View File

@@ -0,0 +1,39 @@
// (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
/// Keywords used in generator interfaces
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_KEYWORDS_HPP_101512GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_KEYWORDS_HPP_101512GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/utils/named_params.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace {
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
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_KEYWORDS_HPP_101512GER

View File

@@ -0,0 +1,198 @@
// (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 Random generator
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER
// Boost.Test
#include <boost/test/data/config.hpp>
#if !defined(BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
#include <boost/test/data/monomorphic/generate.hpp>
#include <boost/test/data/monomorphic/generators/keywords.hpp>
// STL
#include <random>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace {
nfp::keyword<struct seed_t> seed;
nfp::keyword<struct distribution_t> distribution;
nfp::keyword<struct engine_t> engine;
} // local namespace
namespace monomorphic {
namespace ds_detail {
template<typename SampleType>
struct default_distribution {
typedef typename mpl::if_<std::is_integral<SampleType>,
std::uniform_int_distribution<SampleType>,
std::uniform_real_distribution<SampleType>>::type type;
};
} // namespace ds_detail
// ************************************************************************** //
// ************** random_t ************** //
// ************************************************************************** //
/*!@brief Generator for the random sequences
*
* This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing
* a random number generator.
*/
template<typename SampleType = double,
typename DistributionType = typename ds_detail::default_distribution<SampleType>::type,
typename EngineType = std::default_random_engine>
class random_t {
public:
typedef SampleType sample;
typedef DistributionType distr_type;
typedef EngineType engine_type;
random_t()
: m_distribution()
, m_engine( std::random_device()() )
{}
explicit random_t( distr_type&& d )
: m_distribution( std::forward<distr_type>(d) )
, m_engine( std::random_device()() ){}
random_t( engine_type&& e, distr_type&& d )
: m_distribution( std::forward<distr_type>(d) )
, m_engine( std::forward<engine_type>(e) ){}
// Generator interface
data::size_t capacity() const { return BOOST_TEST_DS_INFINITE_SIZE; }
SampleType next()
{
return m_distribution( m_engine );
}
void reset() {}
//! Sets the seed of the pseudo-random number engine.
template<typename SeedType>
void seed( SeedType&& seed ) { m_engine.seed( std::forward<SeedType>( seed ) ); }
private:
// Data members
DistributionType m_distribution;
EngineType m_engine;
};
//____________________________________________________________________________//
} // namespace monomorphic
//! @brief Returns an infinite sequence of random numbers.
//!
//! The following overloads are available:
//! @code
//! auto d = random();
//! auto d = random(begin, end);
//! auto d = random(params);
//! @endcode
//!
//!
//! - The first overload uses the default distribution, which is uniform and which elements
//! are @c double type (the values are in [0, 1) ).
//! - The second overload generates numbers in the given interval. The distribution is uniform (in [begin, end)
//! for real numbers, and in [begin, end] for integers). The type of the distribution is deduced from the type
//! of the @c begin and @c end parameters.
//! - The third overload generates numbers using the named parameter inside @c params , which are:
//! - @c distribution: the distribution used. In this overload, since the type of the samples cannot be deduced,
//! the samples are of type @c double and the distribution is uniform real in [0, 1).
//! - @c seed: the seed for generating the values
//! - @c engine: the random number generator engine
//!
//! The function returns an object that implements the dataset API.
//! @note This function is available only for C++11 capable compilers.
inline monomorphic::generated_by< monomorphic::random_t<>> random()
{
return monomorphic::generated_by<monomorphic::random_t<>>( monomorphic::random_t<>() );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::random()
template<typename SampleType>
inline monomorphic::generated_by< monomorphic::random_t<SampleType>>
random( SampleType begin, SampleType end )
{
typedef monomorphic::random_t<SampleType> Gen;
typedef typename Gen::distr_type distr_type;
return monomorphic::generated_by<Gen>( Gen( distr_type(begin,end) ) );
}
//____________________________________________________________________________//
namespace ds_detail {
template<typename Params>
struct random_gen_type {
typedef typename nfp::param_type<Params,decltype(distribution),std::uniform_real_distribution<>>::type distr_type;
typedef typename nfp::param_type<Params,decltype(engine),std::default_random_engine>::type engine_type;
typedef typename distr_type::result_type sample_type;
typedef monomorphic::random_t<sample_type,distr_type,engine_type> type;
};
}
/// @overload boost::unit_test::data::random()
template<typename Params>
inline monomorphic::generated_by<typename ds_detail::random_gen_type<Params>::type>
random( Params const& params )
{
typedef typename ds_detail::random_gen_type<Params>::type Gen;
typedef typename Gen::distr_type distr_type;
typedef typename Gen::engine_type engine_type;
std::random_device rd;
engine_type E;
// engine_type E( rd );
if( params.has(engine) )
E = params[engine];
distr_type D;
if( params.has(distribution) )
D = params[distribution];
Gen G( std::move(E), std::move(D) );
if( params.has(seed) )
G.seed( params[seed] );
return monomorphic::generated_by<Gen>( std::move(G) );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_NO_RANDOM_DATASET_AVAILABLE
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_RANDOM_HPP_101512GER

View File

@@ -0,0 +1,224 @@
// (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
///Defines range generator
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
#define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/generators/keywords.hpp>
#include <boost/test/data/monomorphic/generate.hpp>
// Boost
#include <boost/optional.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_unsigned.hpp>
// STL
#include <limits>
#include <cmath>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** monomorphic::xrange_t ************** //
// ************************************************************************** //
/*!@brief Generator for the range sequences
*
* This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing
* a range like sequence of numbers.
*/
template<typename SampleType, typename StepType=SampleType>
class xrange_t {
public:
typedef SampleType sample;
xrange_t( SampleType const& begin_, StepType const& step_, data::size_t size_ )
: m_begin( begin_ )
, m_curr( begin_ )
, m_step( step_ )
, m_index( 0 )
, m_size( size_ )
{}
// Generator interface
data::size_t capacity() const { return m_size; }
SampleType next()
{
if( m_index == m_size )
return m_curr;
SampleType res = m_curr;
m_curr += m_step;
++m_index;
return res;
}
void reset()
{
m_curr = m_begin;
m_index = 0;
}
private:
// Data members
SampleType m_begin;
SampleType m_curr;
StepType m_step;
data::size_t m_index;
data::size_t m_size;
};
//____________________________________________________________________________//
namespace ds_detail {
template<typename SampleType, typename StepType=SampleType>
struct make_xrange {
static StepType abs( StepType s, boost::true_type* ) { return s; }
static StepType abs( StepType s, boost::false_type* ) { return std::abs(s); }
typedef xrange_t<SampleType, StepType> range_gen;
template<typename Params>
static generated_by<range_gen>
_( Params const& params )
{
SampleType begin_val = params.has( data::begin ) ? params[data::begin] : SampleType();
optional<SampleType> end_val = params.has( data::end ) ? params[data::end] : optional<SampleType>();
StepType step_val = params.has( data::step ) ? params[data::step] : 1;
BOOST_TEST_DS_ASSERT( step_val != 0, "Range step can't be zero" );
data::size_t size;
if( !end_val.is_initialized() )
size = BOOST_TEST_DS_INFINITE_SIZE;
else {
BOOST_TEST_DS_ASSERT( (step_val < 0) ^ (begin_val < *end_val), "Invalid step direction" );
SampleType abs_distance = step_val < 0 ? begin_val - *end_val : *end_val-begin_val;
StepType abs_step = make_xrange::abs(step_val, (typename boost::is_unsigned<StepType>::type*)0 );
std::size_t s = static_cast<std::size_t>(abs_distance/abs_step);
if( static_cast<SampleType>(s*abs_step) < abs_distance )
s++;
size = s;
}
return generated_by<range_gen>( range_gen( begin_val, step_val, size ) );
}
};
} // namespace ds_detail
} // namespace monomorphic
//____________________________________________________________________________//
//! Creates a range (sequence) dataset.
//!
//! The following overloads are available:
//! @code
//! auto d = xrange();
//! auto d = xrange(end_val);
//! auto d = xrange(end_val, param);
//! auto d = xrange(begin_val, end_val);
//! auto d = xrange(begin_val, end_val, step_val);
//! auto d = xrange(param);
//! @endcode
//!
//! - @c begin_val indicates the start of the sequence (default to 0).
//! - @c end_val is the end of the sequence. If ommited, the dataset has infinite size.\n
//! - @c step_val is the step between two consecutive elements of the sequence, and defaults to 1.\n
//! - @c param is the named parameters that describe the sequence. The following parameters are accepted:
//! - @c begin: same meaning @c begin_val
//! - @c end: same meaning as @c end_val
//! - @c step: same meaning as @c step_val
//!
//!
//! The returned value is an object that implements the dataset API.
//!
//! @note the step size cannot be null, and it should be positive if @c begin_val < @c end_val, negative otherwise.
template<typename SampleType, typename Params>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( Params const& params )
{
return monomorphic::ds_detail::make_xrange<SampleType>::_( params );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::xrange()
template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( SampleType const& end_val )
{
return monomorphic::ds_detail::make_xrange<SampleType>::_( data::end=end_val );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::xrange()
template<typename SampleType, typename Params>
inline typename enable_if_c<nfp::is_named_param_pack<Params>::value,
monomorphic::generated_by<monomorphic::xrange_t<SampleType>>>::type
xrange( SampleType const& end_val, Params const& params )
{
return monomorphic::ds_detail::make_xrange<SampleType>::_(( params, data::end=end_val ));
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::xrange()
template<typename SampleType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( SampleType const& begin_val, SampleType const& end_val )
{
return monomorphic::ds_detail::make_xrange<SampleType>::_((
data::begin=begin_val,
data::end=end_val ));
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::xrange()
template<typename SampleType,typename StepType>
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val )
{
return monomorphic::ds_detail::make_xrange<SampleType,StepType>::_((
data::begin=begin_val,
data::end=end_val,
data::step=step_val ));
}
//____________________________________________________________________________//
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER

View File

@@ -0,0 +1,185 @@
// (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
/// Defines monomorphic dataset n+m dimentional *. Samples in this
/// dataset is grid of elements in DataSet1 and DataSet2. There will be total
/// |DataSet1| * |DataSet2| samples
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER
#define BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER
// Boost.Test
#include <boost/test/data/config.hpp>
#if !defined(BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
#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>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** grid ************** //
// ************************************************************************** //
//! Implements the dataset resulting from a cartesian product/grid operation on datasets.
//!
//! The arity of the resulting dataset is the sum of the arity of its operands.
template<typename DataSet1, typename DataSet2>
class grid {
typedef typename boost::decay<DataSet1>::type dataset1_decay;
typedef typename boost::decay<DataSet2>::type dataset2_decay;
typedef typename dataset1_decay::iterator dataset1_iter;
typedef typename dataset2_decay::iterator dataset2_iter;
public:
struct iterator {
// Constructor
explicit iterator( dataset1_iter iter1, DataSet2 const& ds2 )
: m_iter1( std::move( iter1 ) )
, m_iter2( std::move( ds2.begin() ) )
, m_ds2( &ds2 )
, m_ds2_pos( 0 )
{}
using iterator_sample = decltype(
sample_merge( *std::declval<dataset1_iter>(),
*std::declval<dataset2_iter>()) );
// forward iterator interface
auto operator*() const -> iterator_sample {
return sample_merge( *m_iter1, *m_iter2 );
}
void operator++()
{
++m_ds2_pos;
if( m_ds2_pos != m_ds2->size() )
++m_iter2;
else {
m_ds2_pos = 0;
++m_iter1;
m_iter2 = std::move( m_ds2->begin() );
}
}
private:
// Data members
dataset1_iter m_iter1;
dataset2_iter m_iter2;
dataset2_decay const* m_ds2;
data::size_t m_ds2_pos;
};
public:
static const int arity = boost::decay<DataSet1>::type::arity + boost::decay<DataSet2>::type::arity;
//! Constructor
grid( DataSet1&& ds1, DataSet2&& ds2 )
: m_ds1( std::forward<DataSet1>( ds1 ) )
, m_ds2( std::forward<DataSet2>( ds2 ) )
{}
//! Move constructor
grid( grid&& j )
: m_ds1( std::forward<DataSet1>( j.m_ds1 ) )
, m_ds2( std::forward<DataSet2>( j.m_ds2 ) )
{}
// dataset interface
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:
// Data members
DataSet1 m_ds1;
DataSet2 m_ds2;
};
//____________________________________________________________________________//
// A grid dataset is a dataset
template<typename DataSet1, typename DataSet2>
struct is_dataset<grid<DataSet1,DataSet2>> : mpl::true_ {};
//____________________________________________________________________________//
namespace result_of {
/// Result type of the grid operation on dataset.
template<typename DS1Gen, typename DS2Gen>
struct grid {
typedef monomorphic::grid<typename DS1Gen::type,typename DS2Gen::type> type;
};
} // namespace result_of
//____________________________________________________________________________//
//! Grid operation
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::grid<mpl::identity<DataSet1>,mpl::identity<DataSet2>>
>::type
operator*( DataSet1&& ds1, DataSet2&& ds2 )
{
return grid<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ), std::forward<DataSet2>( ds2 ) );
}
//____________________________________________________________________________//
//! @overload boost::unit_test::data::operator*
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && !is_dataset<DataSet2>::value,
result_of::grid<mpl::identity<DataSet1>,data::result_of::make<DataSet2>>
>::type
operator*( DataSet1&& ds1, DataSet2&& ds2 )
{
return std::forward<DataSet1>(ds1) * data::make(std::forward<DataSet2>(ds2));
}
//____________________________________________________________________________//
//! @overload boost::unit_test::data::operator*
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<!is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::grid<data::result_of::make<DataSet1>,mpl::identity<DataSet2>>
>::type
operator*( DataSet1&& ds1, DataSet2&& ds2 )
{
return data::make(std::forward<DataSet1>(ds1)) * std::forward<DataSet2>(ds2);
}
} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_NO_GRID_COMPOSITION_AVAILABLE
#endif // BOOST_TEST_DATA_MONOMORPHIC_GRID_HPP_101512GER

View File

@@ -0,0 +1,159 @@
// (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
///Defines monomorphic dataset based on C++11 initializer_list template
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_INITIALIZATION_LIST_HPP_091515GER
#define BOOST_TEST_DATA_MONOMORPHIC_INITIALIZATION_LIST_HPP_091515GER
// Boost.Test
#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>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** initializer_list ************** //
// ************************************************************************** //
/// 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:
static const int arity = 1;
typedef typename std::vector<T>::const_iterator iterator;
//! 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(); }
iterator begin() const { return m_data.begin(); }
private:
// Data members
std::vector<T> m_data;
};
//! Specialization of init_list for type bool
template <>
class init_list<bool> {
public:
typedef bool sample;
static const int arity = 1;
//! 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
struct non_proxy_iterator {
std::vector<bool>::const_iterator iterator;
non_proxy_iterator(std::vector<bool>::const_iterator &&it)
: iterator(std::forward<std::vector<bool>::const_iterator>(it))
{}
bool operator*() const {
return *iterator;
}
non_proxy_iterator& operator++() {
++iterator;
return *this;
}
};
typedef non_proxy_iterator iterator;
//! 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;
};
//____________________________________________________________________________//
//! An array dataset is a dataset
template<typename T>
struct is_dataset<init_list<T>> : mpl::true_ {};
} // namespace monomorphic
//____________________________________________________________________________//
//! @overload boost::unit_test::data::make()
template<typename T>
inline monomorphic::init_list<T>
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
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_INITIALIZATION_LIST_HPP_091515GER

View File

@@ -0,0 +1,162 @@
// (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
//! Defines dataset join operation
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER
#define BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER
// Boost.Test
#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>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** join ************** //
// ************************************************************************** //
//! Defines a new dataset from the concatenation of two datasets
//!
//! The size of the resulting dataset is the sum of the two underlying datasets. The arity of the datasets
//! should match.
template<typename DataSet1, typename DataSet2>
class join {
typedef typename boost::decay<DataSet1>::type dataset1_decay;
typedef typename boost::decay<DataSet2>::type dataset2_decay;
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:
static const int 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 )
: m_it1( std::move( it1 ) )
, m_it2( std::move( it2 ) )
, m_first_size( first_size )
{}
// forward iterator interface
// 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
dataset1_iter m_it1;
dataset2_iter m_it2;
data::size_t m_first_size;
};
//! Constructor
join( DataSet1&& ds1, DataSet2&& ds2 )
: m_ds1( std::forward<DataSet1>( ds1 ) )
, m_ds2( std::forward<DataSet2>( ds2 ) )
{}
//! Move constructor
join( join&& j )
: m_ds1( std::forward<DataSet1>( j.m_ds1 ) )
, m_ds2( std::forward<DataSet2>( j.m_ds2 ) )
{}
//! dataset interface
data::size_t size() const { return m_ds1.size() + m_ds2.size(); }
iterator begin() const { return iterator( m_ds1.begin(), m_ds2.begin(), m_ds1.size() ); }
private:
// Data members
DataSet1 m_ds1;
DataSet2 m_ds2;
};
//____________________________________________________________________________//
// A joined dataset is a dataset.
template<typename DataSet1, typename DataSet2>
struct is_dataset<join<DataSet1,DataSet2>> : mpl::true_ {};
//____________________________________________________________________________//
namespace result_of {
//! Result type of the join operation on datasets.
template<typename DataSet1Gen, typename DataSet2Gen>
struct join {
typedef monomorphic::join<typename DataSet1Gen::type,typename DataSet2Gen::type> type;
};
} // namespace result_of
//____________________________________________________________________________//
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::join<mpl::identity<DataSet1>,mpl::identity<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
return join<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ), std::forward<DataSet2>( ds2 ) );
}
//____________________________________________________________________________//
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && !is_dataset<DataSet2>::value,
result_of::join<mpl::identity<DataSet1>,data::result_of::make<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
return std::forward<DataSet1>( ds1 ) + data::make( std::forward<DataSet2>( ds2 ) );
}
//____________________________________________________________________________//
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<!is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::join<data::result_of::make<DataSet1>,mpl::identity<DataSet2>>
>::type
operator+( DataSet1&& ds1, DataSet2&& ds2 )
{
return data::make( std::forward<DataSet1>(ds1) ) + std::forward<DataSet2>( ds2 );
}
} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_JOIN_HPP_112711GER

View File

@@ -0,0 +1,103 @@
// (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
/// Defines helper routines and types for merging monomorphic samples
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP
#define BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/index_sequence.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
//____________________________________________________________________________//
namespace ds_detail {
template <class T>
struct is_tuple : std::false_type {};
template <class ...T>
struct is_tuple<std::tuple<T...>> : std::true_type {};
template <class T>
struct is_tuple<T&&> : is_tuple<typename std::decay<T>::type> {};
template <class T>
struct is_tuple<T&> : is_tuple<typename std::decay<T>::type> {};
template<typename T>
inline auto as_tuple_impl_xvalues( T const & arg, std::false_type /* is_rvalue_ref */ )
-> decltype(std::tuple<T const&>(arg)) {
//return std::tuple<T const&>(arg);
return std::forward_as_tuple(arg);
}
template<typename T>
inline auto as_tuple_impl_xvalues( T && arg, std::true_type /* is_rvalue_ref */ )
-> decltype(std::make_tuple(std::forward<T>(arg))) {
return std::make_tuple(std::forward<T>(arg));
}
template<typename T>
inline auto as_tuple_impl( T && arg, std::false_type /* is_tuple = nullptr */ )
-> decltype(as_tuple_impl_xvalues(std::forward<T>(arg),
typename std::is_rvalue_reference<T&&>::type())) {
return as_tuple_impl_xvalues(std::forward<T>(arg),
typename std::is_rvalue_reference<T&&>::type());
}
//____________________________________________________________________________//
template<typename T>
inline T &&
as_tuple_impl(T && arg, std::true_type /* is_tuple */ ) {
return std::forward<T>(arg);
}
template<typename T>
inline auto as_tuple( T && arg )
-> decltype( as_tuple_impl(std::forward<T>(arg),
typename ds_detail::is_tuple<T>::type()) ) {
return as_tuple_impl(std::forward<T>(arg),
typename ds_detail::is_tuple<T>::type());
}
//____________________________________________________________________________//
} // namespace ds_detail
template<typename T1, typename T2>
inline auto
sample_merge( T1 && a1, T2 && a2 )
-> decltype( std::tuple_cat(ds_detail::as_tuple(std::forward<T1>(a1)),
ds_detail::as_tuple(std::forward<T2>(a2)) ) ) {
return std::tuple_cat(ds_detail::as_tuple(std::forward<T1>(a1)),
ds_detail::as_tuple(std::forward<T2>(a2)));
}
} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_SAMPLE_MERGE_HPP

View File

@@ -0,0 +1,121 @@
// (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
/// Defines single element monomorphic dataset
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_SINGLETON_HPP_102211GER
#define BOOST_TEST_DATA_MONOMORPHIC_SINGLETON_HPP_102211GER
// Boost.Test
#include <boost/test/data/config.hpp>
#include <boost/test/data/monomorphic/fwd.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** singleton ************** //
// ************************************************************************** //
/// Models a single element data set
template<typename T>
class singleton {
private:
typedef typename boost::decay<T>::type sample;
public:
static const int arity = 1;
struct iterator {
// Constructor
explicit iterator( singleton<T> const* owner )
: m_owner( owner )
{}
// forward iterator interface
sample const& operator*() const { return m_owner->value(); }
void operator++() {}
private:
singleton<T> const* m_owner;
};
//! Constructor
explicit singleton( T&& value ) : m_value( std::forward<T>( value ) ) {}
//! Move constructor
singleton( singleton&& s ) : m_value( std::forward<T>( s.m_value ) ) {}
//! Value access method
T const& value() const { return m_value; }
//! dataset interface
data::size_t size() const { return 1; }
iterator begin() const { return iterator( this ); }
private:
// Data members
T m_value;
};
//____________________________________________________________________________//
// a singleton is a dataset
template<typename T>
struct is_dataset<singleton<T>> : mpl::true_ {};
//____________________________________________________________________________//
} // namespace monomorphic
/// @overload boost::unit_test::data::make()
template<typename T>
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>
>::type
make( T&& v )
{
return monomorphic::singleton<T>( std::forward<T>( v ) );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::make
inline monomorphic::singleton<char*>
make( char* str )
{
return monomorphic::singleton<char*>( std::move(str) );
}
//____________________________________________________________________________//
/// @overload boost::unit_test::data::make
inline monomorphic::singleton<char const*>
make( char const* str )
{
return monomorphic::singleton<char const*>( std::move(str) );
}
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_MONOMORPHIC_SINGLETON_HPP_102211GER

View File

@@ -0,0 +1,188 @@
// (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
/// Defines monomorphic dataset based on zipping of 2 other monomorphic datasets
// ***************************************************************************
#ifndef BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER
#define BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER
// Boost.Test
#include <boost/test/data/config.hpp>
#if !defined(BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE) || defined(BOOST_TEST_DOXYGEN_DOC__)
#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>
namespace boost {
namespace unit_test {
namespace data {
namespace monomorphic {
// ************************************************************************** //
// ************** zip ************** //
// ************************************************************************** //
//! Zip datasets
//!
//! A zip of two datasets is a dataset whose arity is the sum of the operand datasets arity. The size is given by
//! the function creating the instance (see @c operator^ on datasets).
template<typename DataSet1, typename DataSet2>
class zip {
typedef typename boost::decay<DataSet1>::type dataset1_decay;
typedef typename boost::decay<DataSet2>::type dataset2_decay;
typedef typename dataset1_decay::iterator dataset1_iter;
typedef typename dataset2_decay::iterator dataset2_iter;
public:
static const int arity = dataset1_decay::arity + dataset2_decay::arity;
struct iterator {
// Constructor
explicit iterator( dataset1_iter iter1, dataset2_iter iter2 )
: m_iter1( std::move( iter1 ) )
, m_iter2( std::move( iter2 ) )
{}
using iterator_sample = decltype(
sample_merge( *std::declval<dataset1_iter>(),
*std::declval<dataset2_iter>()) );
// forward iterator interface
auto operator*() const -> iterator_sample {
return sample_merge( *m_iter1, *m_iter2 );
}
void operator++() { ++m_iter1; ++m_iter2; }
private:
// Data members
dataset1_iter m_iter1;
dataset2_iter m_iter2;
};
//! Constructor
//!
//! The datasets are moved and not copied.
zip( DataSet1&& ds1, DataSet2&& ds2/*, data::size_t size*/ )
: m_ds1( std::forward<DataSet1>( ds1 ) )
, m_ds2( std::forward<DataSet2>( ds2 ) )
//, 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 )
{}
// dataset interface
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;
//! 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" );
}
};
//____________________________________________________________________________//
//! Zipped datasets results in a dataset.
template<typename DataSet1, typename DataSet2>
struct is_dataset<zip<DataSet1,DataSet2>> : mpl::true_ {};
//____________________________________________________________________________//
namespace result_of {
//! Result type of the zip operator.
template<typename DS1Gen, typename DS2Gen>
struct zip {
typedef monomorphic::zip<typename DS1Gen::type,typename DS2Gen::type> type;
};
} // namespace result_of
//____________________________________________________________________________//
//! Overload operator for zip support
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::zip<mpl::identity<DataSet1>,mpl::identity<DataSet2>>
>::type
operator^( DataSet1&& ds1, DataSet2&& ds2 )
{
return zip<DataSet1,DataSet2>( std::forward<DataSet1>( ds1 ),
std::forward<DataSet2>( ds2 )/*,
ds_detail::zip_size( ds1, ds2 )*/ );
}
//____________________________________________________________________________//
//! @overload boost::unit_test::data::monomorphic::operator^()
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<is_dataset<DataSet1>::value && !is_dataset<DataSet2>::value,
result_of::zip<mpl::identity<DataSet1>,data::result_of::make<DataSet2>>
>::type
operator^( DataSet1&& ds1, DataSet2&& ds2 )
{
return std::forward<DataSet1>( ds1 ) ^ data::make( std::forward<DataSet2>( ds2 ) );
}
//____________________________________________________________________________//
//! @overload boost::unit_test::data::monomorphic::operator^()
template<typename DataSet1, typename DataSet2>
inline typename boost::lazy_enable_if_c<!is_dataset<DataSet1>::value && is_dataset<DataSet2>::value,
result_of::zip<data::result_of::make<DataSet1>,mpl::identity<DataSet2>>
>::type
operator^( DataSet1&& ds1, DataSet2&& ds2 )
{
return data::make( std::forward<DataSet1>( ds1 ) ) ^ std::forward<DataSet2>( ds2 );
}
} // namespace monomorphic
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_NO_ZIP_COMPOSITION_AVAILABLE
#endif // BOOST_TEST_DATA_MONOMORPHIC_ZIP_HPP_102211GER

View File

@@ -0,0 +1,145 @@
// (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 simple dataset size abstraction (can be infinite)
// ***************************************************************************
#ifndef BOOST_TEST_DATA_SIZE_HPP_102211GER
#define BOOST_TEST_DATA_SIZE_HPP_102211GER
// Boost.Test
#include <boost/test/data/config.hpp>
// STL
#include <iosfwd>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
// ************************************************************************** //
// ************** size_t ************** //
// ************************************************************************** //
//! Utility for handling the size of a datasets
class size_t {
struct dummy { void nonnull() {} };
typedef void (dummy::*safe_bool)();
public:
// Constructors
size_t( std::size_t s = 0 ) : m_value( s ), m_infinity( false ) {}
explicit size_t( bool ) : m_value( 0 ), m_infinity( true ) {}
template<typename T>
size_t( T v ) : m_value( static_cast<std::size_t>(v) ), m_infinity( false ) {}
// Access methods
std::size_t value() const { return m_value; }
bool is_inf() const { return m_infinity; }
operator safe_bool() const { return is_inf() || m_value != 0 ? &dummy::nonnull : 0; }
// Unary operators
data::size_t operator--() { if( !is_inf() ) m_value--; return *this; }
data::size_t operator--(int) { data::size_t res(*this); if( !is_inf() ) m_value--; return res; }
data::size_t operator++() { if( !is_inf() ) m_value++; return *this; }
data::size_t operator++(int) { data::size_t res(*this); if( !is_inf() ) m_value++; return res; }
// Binary operators
data::size_t& operator+=( std::size_t rhs ) { if( !is_inf() ) m_value += rhs; return *this; }
data::size_t& operator+=( data::size_t rhs )
{
if( !is_inf() ) {
if( rhs.is_inf() )
*this = rhs;
else
m_value += rhs.value();
}
return *this;
}
data::size_t& operator-=( std::size_t rhs ) { if( !is_inf() ) m_value -= rhs; return *this; }
data::size_t& operator-=( data::size_t rhs )
{
if( !is_inf() ) {
if( value() < rhs.value() )
m_value = 0;
else
m_value -= rhs.value();
}
return *this;
}
private:
// Data members
std::size_t m_value;
bool m_infinity;
};
namespace { const data::size_t BOOST_TEST_DS_INFINITE_SIZE( true ); }
//____________________________________________________________________________//
// Binary operators
inline bool operator>(data::size_t lhs, std::size_t rhs) { return lhs.is_inf() || (lhs.value() > rhs); }
inline bool operator>(std::size_t lhs, data::size_t rhs) { return !rhs.is_inf() && (lhs > rhs.value()); }
inline bool operator>(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() ^ rhs.is_inf() ? lhs.is_inf() : lhs.value() > rhs.value(); }
inline bool operator>=(data::size_t lhs, std::size_t rhs ) { return lhs.is_inf() || (lhs.value() >= rhs); }
inline bool operator>=(std::size_t lhs, data::size_t rhs) { return !rhs.is_inf() && (lhs >= rhs.value()); }
inline bool operator>=(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() ^ rhs.is_inf() ? lhs.is_inf() : lhs.value() >= rhs.value(); }
inline bool operator<(data::size_t lhs, std::size_t rhs) { return !lhs.is_inf() && (lhs.value() < rhs); }
inline bool operator<(std::size_t lhs, data::size_t rhs) { return rhs.is_inf() || (lhs < rhs.value()); }
inline bool operator<(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() ^ rhs.is_inf() ? rhs.is_inf() : lhs.value() < rhs.value(); }
inline bool operator<=(data::size_t lhs, std::size_t rhs) { return !lhs.is_inf() && (lhs.value() <= rhs); }
inline bool operator<=(std::size_t lhs, data::size_t rhs) { return rhs.is_inf() || (lhs <= rhs.value()); }
inline bool operator<=(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() ^ rhs.is_inf() ? rhs.is_inf() : lhs.value() <= rhs.value(); }
inline bool operator==(data::size_t lhs, std::size_t rhs) { return !lhs.is_inf() && (lhs.value() == rhs); }
inline bool operator==(std::size_t lhs, data::size_t rhs) { return !rhs.is_inf() && (lhs == rhs.value()); }
inline bool operator==(data::size_t lhs, data::size_t rhs) { return !(lhs.is_inf() ^ rhs.is_inf()) && lhs.value() == rhs.value(); }
inline bool operator!=(data::size_t lhs, std::size_t rhs) { return lhs.is_inf() || (lhs.value() != rhs); }
inline bool operator!=(std::size_t lhs, data::size_t rhs) { return rhs.is_inf() || (lhs != rhs.value()); }
inline bool operator!=(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() ^ rhs.is_inf() || lhs.value() != rhs.value(); }
inline data::size_t operator+(data::size_t lhs, std::size_t rhs) { return lhs.is_inf() ? lhs : data::size_t( lhs.value()+rhs ); }
inline data::size_t operator+(std::size_t lhs, data::size_t rhs) { return rhs.is_inf() ? rhs : data::size_t( lhs+rhs.value() ); }
inline data::size_t operator+(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() || rhs.is_inf() ? data::size_t(true) : data::size_t( lhs.value()+rhs.value() ); }
inline data::size_t operator*(data::size_t lhs, std::size_t rhs) { return lhs.is_inf() ? lhs : data::size_t( lhs.value()*rhs ); }
inline data::size_t operator*(std::size_t lhs, data::size_t rhs) { return rhs.is_inf() ? rhs : data::size_t( lhs*rhs.value() ); }
inline data::size_t operator*(data::size_t lhs, data::size_t rhs) { return lhs.is_inf() || rhs.is_inf() ? data::size_t(true) : data::size_t( lhs.value()*rhs.value() ); }
//____________________________________________________________________________//
template<typename CharT1, typename Tr>
inline std::basic_ostream<CharT1,Tr>&
operator<<( std::basic_ostream<CharT1,Tr>& os, data::size_t const& s )
{
if( s.is_inf() )
os << "infinity";
else
os << s.value();
return os;
}
//____________________________________________________________________________//
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_SIZE_HPP_102211GER

View File

@@ -0,0 +1,345 @@
// (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 test case family based on data generator
// ***************************************************************************
#ifndef BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
#define BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
// Boost.Test
#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>
#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/bind/bind.hpp>
#include <boost/type_traits/is_copy_constructible.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
#endif
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace data {
namespace ds_detail {
// ************************************************************************** //
// ************** seed ************** //
// ************************************************************************** //
struct seed {
template<typename DataSet>
typename data::result_of::make<DataSet>::type
operator->*( DataSet&& ds ) const
{
return data::make( std::forward<DataSet>( ds ) );
}
};
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
!defined(BOOST_NO_CXX11_DECLTYPE) && \
!defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
!defined(BOOST_NO_CXX11_SMART_PTR)
#define BOOST_TEST_DATASET_VARIADIC
template <class T>
struct parameter_holder {
std::shared_ptr<T> value;
parameter_holder(T && value_)
: value(std::make_shared<T>(std::move(value_)))
{}
operator T const&() const {
return *value;
}
};
template <class T>
parameter_holder<typename std::remove_reference<T>::type>
boost_bind_rvalue_holder_helper_impl(T&& value, boost::false_type /* is copy constructible */) {
return parameter_holder<typename std::remove_reference<T>::type>(std::forward<T>(value));
}
template <class T>
T&& boost_bind_rvalue_holder_helper_impl(T&& value, boost::true_type /* is copy constructible */) {
return std::forward<T>(value);
}
template <class T>
auto boost_bind_rvalue_holder_helper(T&& value)
-> decltype(boost_bind_rvalue_holder_helper_impl(
std::forward<T>(value),
typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type()))
{
// need to use boost::is_copy_constructible because std::is_copy_constructible is broken on MSVC12
return boost_bind_rvalue_holder_helper_impl(
std::forward<T>(value),
typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type());
}
#endif
// ************************************************************************** //
// ************** test_case_gen ************** //
// ************************************************************************** //
template<typename TestCase,typename DataSet>
class test_case_gen : public test_unit_generator {
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_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 )
{}
test_case_gen( test_case_gen&& gen )
: 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 )
, m_test_cases( std::move(gen.m_test_cases) )
{}
#else
test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
: 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 )
{}
#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;
test_unit* res = m_test_cases.front();
m_test_cases.pop_front();
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 \
{ \
m_test_cases.push_back( new test_case( genTestCaseName(), m_tc_file, m_tc_line, \
boost::bind( &TestCase::template test_method<BOOST_PP_ENUM_PARAMS(arity,Arg)>,\
BOOST_PP_ENUM_PARAMS(arity, arg) ) ) ); \
} \
BOOST_PP_REPEAT_FROM_TO(1, BOOST_TEST_DATASET_MAX_ARITY, TC_MAKE, _)
#else
template<typename ...Arg>
void operator()(Arg&& ... arg) const
{
m_test_cases.push_back(
new test_case( genTestCaseName(),
m_tc_file,
m_tc_line,
std::bind( &TestCase::template test_method<Arg...>,
boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
}
#endif
private:
std::string genTestCaseName() const
{
return "_" + utils::string_cast(m_tc_index++);
}
// 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;
mutable std::size_t m_tc_index;
mutable std::list<test_unit*> m_test_cases;
};
//____________________________________________________________________________//
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename TestCase,typename 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 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>
test_case_gen<TestCase,DataSet>
make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
{
return test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, ds );
}
#endif
//____________________________________________________________________________//
} // namespace ds_detail
// ************************************************************************** //
// ************** BOOST_DATA_TEST_CASE ************** //
// ************************************************************************** //
#define BOOST_DATA_TEST_CASE_PARAM(r, _, i, param) (BOOST_PP_CAT(Arg, i) const& param)
#define BOOST_DATA_TEST_CONTEXT(r, _, param) << BOOST_STRINGIZE(param) << " = " << boost::test_tools::tt_detail::print_helper(param) << "; "
#define BOOST_DATA_TEST_CASE_PARAMS( params ) \
BOOST_PP_SEQ_ENUM( \
BOOST_PP_SEQ_FOR_EACH_I(BOOST_DATA_TEST_CASE_PARAM, _, params)) \
/**/
#define BOOST_DATA_TEST_CASE_IMPL(arity, F, test_name, dataset, params) \
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_CONTEXT( "" \
BOOST_PP_SEQ_FOR_EACH(BOOST_DATA_TEST_CONTEXT, _, params)) \
{ \
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::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< \
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_t::instance() ); \
\
BOOST_AUTO_TEST_SUITE_END() \
\
template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
void BOOST_PP_CAT(test_name, case)::_impl( \
BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
/**/
#define BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, ... ) \
BOOST_DATA_TEST_CASE_IMPL( BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
F, test_name, dataset, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
/**/
#define BOOST_DATA_TEST_CASE_NO_PARAMS( F, test_name, dataset ) \
BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, sample ) \
/**/
#if BOOST_PP_VARIADICS_MSVC
#define BOOST_DATA_TEST_CASE( ... ) \
BOOST_PP_CAT( \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__), ) \
/**/
#define BOOST_DATA_TEST_CASE_F( F, ... ) \
BOOST_PP_CAT( \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
F, __VA_ARGS__), ) \
/**/
#else
#define BOOST_DATA_TEST_CASE( ... ) \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__) \
/**/
#define BOOST_DATA_TEST_CASE_F( F, ... ) \
BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
BOOST_DATA_TEST_CASE_NO_PARAMS, \
BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
F, __VA_ARGS__) \
/**/
#endif
} // namespace data
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DATA_TEST_CASE_HPP_102211GER

View File

@@ -0,0 +1,138 @@
// (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 defines portable debug interfaces
//!
//! Intended to standardize interface of programs with debuggers
// ***************************************************************************
#ifndef BOOST_TEST_DEBUG_API_HPP_112006GER
#define BOOST_TEST_DEBUG_API_HPP_112006GER
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
// Boost
#include <boost/function/function1.hpp>
// STL
#include <string>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
/// Contains debugger and debug C Runtime interfaces
namespace debug {
/// @defgroup DebuggerInterface Debugger and debug C Runtime portable interfaces
/// @{
/// These interfaces are intended to be used by application to:
/// - check if we are running under debugger
/// - attach the debugger to itself
///
/// Unfortunately these actions differ widely between different debuggers available in a field. These interface present generalized standard form of
/// performing these actions. Implementation depends a lot on the environment application is running in and thus there are several custom implementations
/// supported by the Boost.Test
///
/// In addition here you find interfaces for memory leaks detection and reporting.
///
/// All these interfaces are defined in namespace boost::debug
// ************************************************************************** //
/// Checks if programs runs under debugger
/// @returns true if current process is under debugger. False otherwise
// ************************************************************************** //
bool BOOST_TEST_DECL under_debugger();
// ************************************************************************** //
/// Cause program to break execution in debugger at call point
// ************************************************************************** //
void BOOST_TEST_DECL debugger_break();
// ************************************************************************** //
/// Collection of data, which is used by debugger starter routine
// ************************************************************************** //
struct dbg_startup_info {
long pid; ///< pid of a program to attach to
bool break_or_continue; ///< what to do after debugger is attached
unit_test::const_string binary_path; ///< path to executable for current process
unit_test::const_string display; ///< if debugger has a GUI, which display to use (on UNIX)
unit_test::const_string init_done_lock; ///< path to a uniquely named lock file, which is used to pause current application while debugger is being initialized
};
/// Signature of debugger starter routine. Takes an instance of dbg_startup_into as only argument
typedef boost::function<void (dbg_startup_info const&)> dbg_starter;
// ************************************************************************** //
/// Specifies which debugger to use when attaching and optionally what routine to use to start that debugger
/// There are many different debuggers available for different platforms. Some of them also can be used in a different setups/configuratins.
/// For example, gdb can be used in plain text mode, inside ddd, inside (x)emacs or in a separate xterm window.
/// Boost.Test identifies each configuration with unique string.
/// Also different debuggers configurations require different routines which is specifically tailored to start that debugger configuration.
/// Boost.Test comes with set of predefined configuration names and corresponding routines for these configurations:
/// - TODO
///
/// You can use this routine to select which one of the predefined debugger configurations to use in which case you do not need to provide starter
/// routine (the one provided by Boost.Test will be used). You can also use this routine to select your own debugger by providing unique configuration
/// id and starter routine for this configuration.
///
/// @param[in] dbg_id Unique id for debugger configuration (for example, gdb)
/// @param[in] s Optional starter routine for selected configuration (use only you want to define your own configuration)
/// @returns Id of previously selected debugger configuration
std::string BOOST_TEST_DECL set_debugger( unit_test::const_string dbg_id, dbg_starter s = dbg_starter() );
// ************************************************************************** //
/// Attaches debugger to the current process
/// Using currently selected debugger, this routine attempts to attach the debugger to this process.
/// @param[in] break_or_continue tells what we wan to do after the debugger is attached. If true - process execution breaks
/// in the point in invocation of this function. Otherwise execution continues, but now it is
/// under the debugger
/// @returns true if debugger successfully attached. False otherwise
// ************************************************************************** //
bool BOOST_TEST_DECL attach_debugger( bool break_or_continue = true );
// ************************************************************************** //
/// Switches on/off memory leaks detection
/// On platforms where memory leak detection is possible inside of running application (at the moment this is only Windows family) you can
/// switch this feature on and off using this interface. In addition you can specify the name of the file to write a report into. Otherwise
/// the report is going to be generated in standard error stream.
/// @param[in] on_off boolean switch
/// @param[in] report_file file, where the report should be directed to
// ************************************************************************** //
void BOOST_TEST_DECL detect_memory_leaks( bool on_off, unit_test::const_string report_file = unit_test::const_string() );
// ************************************************************************** //
/// Causes program to break execution in debugger at specific allocation point
/// On some platforms/memory managers (at the moment only on Windows/Visual Studio) one can tell a C Runtime to break
/// on specific memory allocation. This can be used in combination with memory leak detection (which reports leaked memory
/// allocation number) to locate the place where leak initiated.
/// @param[in] mem_alloc_order_num Specific memory allocation number
// ************************************************************************** //
void BOOST_TEST_DECL break_memory_alloc( long mem_alloc_order_num );
} // namespace debug
/// @}
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif

View File

@@ -0,0 +1,24 @@
// (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 user's config for Boost.Test debugging support
//!
//! This file is intended to be edited by end user to specify varios macros, which configure debugger interface
//! Alterntively you can set these parameters in your own sources/makefiles
// ***************************************************************************
#ifndef BOOST_TEST_DEBUG_CONFIG_HPP_112006GER
#define BOOST_TEST_DEBUG_CONFIG_HPP_112006GER
// ';' separated list of supported debuggers
// #define BOOST_TEST_DBG_LIST gdb;dbx
// maximum size of /proc/pid/stat file
// #define BOOST_TEST_STAT_LINE_MAX
#endif

View File

@@ -0,0 +1,170 @@
// (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 a central place for global configuration switches
// ***************************************************************************
#ifndef BOOST_TEST_CONFIG_HPP_071894GER
#define BOOST_TEST_CONFIG_HPP_071894GER
// Boost
#include <boost/config.hpp> // compilers workarounds
#include <boost/detail/workaround.hpp>
#if defined(_WIN32) && !defined(BOOST_DISABLE_WIN32) && \
(!defined(__COMO__) && !defined(__MWERKS__) && \
!defined(__GNUC__) && !defined(BOOST_EMBTC) || \
BOOST_WORKAROUND(__MWERKS__, >= 0x3000))
# define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif
#if defined(__COMO__) && defined(_MSC_VER)
// eh.h uses type_info without declaring it.
class type_info;
# define BOOST_SEH_BASED_SIGNAL_HANDLING
#endif
//____________________________________________________________________________//
#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x570)) || \
BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
(defined __sgi && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(730)))
# define BOOST_TEST_SHIFTED_LINE
#endif
//____________________________________________________________________________//
#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32))
# define BOOST_TEST_CALL_DECL __cdecl
#else
# define BOOST_TEST_CALL_DECL /**/
#endif
//____________________________________________________________________________//
#if !defined(BOOST_NO_STD_LOCALE) && !defined(__MWERKS__)
# define BOOST_TEST_USE_STD_LOCALE 1
#endif
//____________________________________________________________________________//
#if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x570) || \
BOOST_WORKAROUND( __COMO__, <= 0x433 ) || \
BOOST_WORKAROUND( __INTEL_COMPILER, <= 800 ) || \
defined(__sgi) && _COMPILER_VERSION <= 730 || \
BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \
defined(__DECCXX) || \
defined(__DMC__)
# define BOOST_TEST_NO_PROTECTED_USING
#endif
//____________________________________________________________________________//
#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
#define BOOST_TEST_PROTECTED_VIRTUAL
#else
#define BOOST_TEST_PROTECTED_VIRTUAL virtual
#endif
//____________________________________________________________________________//
#if !defined(BOOST_BORLANDC) && !BOOST_WORKAROUND( __SUNPRO_CC, < 0x5100 )
#define BOOST_TEST_SUPPORT_TOKEN_ITERATOR 1
#endif
//____________________________________________________________________________//
// 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
#if defined(BOOST_TEST_DYN_LINK)
# define BOOST_TEST_ALTERNATIVE_INIT_API
# ifdef BOOST_TEST_SOURCE
# define BOOST_TEST_DECL BOOST_SYMBOL_EXPORT BOOST_SYMBOL_VISIBLE
# else
# define BOOST_TEST_DECL BOOST_SYMBOL_IMPORT BOOST_SYMBOL_VISIBLE
# endif // BOOST_TEST_SOURCE
#else
# if defined(BOOST_TEST_INCLUDED)
# define BOOST_TEST_DECL
# else
# define BOOST_TEST_DECL BOOST_SYMBOL_VISIBLE
# endif
#endif
#if !defined(BOOST_TEST_MAIN) && defined(BOOST_AUTO_TEST_MAIN)
#define BOOST_TEST_MAIN BOOST_AUTO_TEST_MAIN
#endif
#if !defined(BOOST_TEST_MAIN) && defined(BOOST_TEST_MODULE)
#define BOOST_TEST_MAIN BOOST_TEST_MODULE
#endif
#ifndef BOOST_PP_VARIADICS /* we can change this only if not already defined */
#ifdef __PGI
#define BOOST_PP_VARIADICS 1
#endif
#if BOOST_CLANG
#define BOOST_PP_VARIADICS 1
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 4 * 10000 + 8 * 100)
#define BOOST_PP_VARIADICS 1
#endif
#if defined(__NVCC__)
#define BOOST_PP_VARIADICS 1
#endif
#endif /* ifndef BOOST_PP_VARIADICS */
// some versions of VC exibit a manifest error with this BOOST_UNREACHABLE_RETURN
#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
# define BOOST_TEST_UNREACHABLE_RETURN(x) return x
#else
# define BOOST_TEST_UNREACHABLE_RETURN(x) BOOST_UNREACHABLE_RETURN(x)
#endif
//____________________________________________________________________________//
// string_view support
//____________________________________________________________________________//
// note the code should always be compatible with compiled version of boost.test
// using a pre-c++17 compiler
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
#define BOOST_TEST_STRING_VIEW
#endif
#endif // BOOST_TEST_CONFIG_HPP_071894GER

View File

@@ -0,0 +1,36 @@
// (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 enable previously suppressed warnings
// ***************************************************************************
#ifdef BOOST_MSVC
# pragma warning(default: 4511) // copy constructor can't not be generated
# pragma warning(default: 4512) // assignment operator can't not be generated
# pragma warning(default: 4100) // unreferenced formal parameter
# pragma warning(default: 4996) // <symbol> was declared deprecated
# pragma warning(default: 4355) // 'this' : used in base member initializer list
# pragma warning(default: 4706) // assignment within conditional expression
# pragma warning(default: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
# pragma warning(default: 4127) // conditional expression is constant
# pragma warning(default: 4290) // C++ exception specification ignored except to ...
# pragma warning(default: 4180) // qualifier applied to function type has no meaning; ignored
# pragma warning(default: 4275) // non dll-interface class ... used as base for dll-interface class ...
# pragma warning(default: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
# pragma warning(default: 4511) // 'class' : copy constructor could not be generated
# pragma warning(pop)
#endif
#if defined(BOOST_CLANG) && (BOOST_CLANG == 1)
#pragma clang diagnostic pop
#endif
#if defined(BOOST_GCC) && (BOOST_GCC >= 4 * 10000 + 6 * 100)
# pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,47 @@
// (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 forward eclarations for Boost.Test data types
// ***************************************************************************
#ifndef BOOST_TEST_FWD_DECL_HPP_011605GER
#define BOOST_TEST_FWD_DECL_HPP_011605GER
namespace boost {
class execution_monitor;
class execution_exception;
namespace unit_test {
class test_unit;
class test_case;
class test_suite;
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;
class unit_test_log_t;
class unit_test_log_formatter;
struct log_entry_data;
struct log_checkpoint_data;
class lazy_ostream;
} // namespace unit_test
} // namespace boost
#endif // BOOST_TEST_FWD_DECL_HPP_011605GER

View File

@@ -0,0 +1,149 @@
// (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 some trivial global typedefs
// ***************************************************************************
#ifndef BOOST_TEST_GLOBAL_TYPEDEF_HPP_021005GER
#define BOOST_TEST_GLOBAL_TYPEDEF_HPP_021005GER
#include <boost/test/utils/basic_cstring/basic_cstring.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 ) )
#define BOOST_TEST_EMPTY_STRING BOOST_TEST_L( "" )
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
typedef unsigned long counter_t;
//____________________________________________________________________________//
enum report_level { INV_REPORT_LEVEL, CONFIRMATION_REPORT, SHORT_REPORT, DETAILED_REPORT, NO_REPORT };
//____________________________________________________________________________//
//! Indicates the output format for the loggers or the test tree printing
enum output_format { OF_INVALID,
OF_CLF, ///< compiler log format
OF_XML, ///< XML format for report and log,
OF_JUNIT, ///< JUNIT format for report and log,
OF_CUSTOM_LOGGER, ///< User specified logger.
OF_DOT ///< dot format for output content
};
//____________________________________________________________________________//
enum test_unit_type { TUT_CASE = 0x01, TUT_SUITE = 0x10, TUT_ANY = 0x11 };
//____________________________________________________________________________//
enum assertion_result { AR_FAILED, AR_PASSED, AR_TRIGGERED };
//____________________________________________________________________________//
typedef unsigned long test_unit_id;
const test_unit_id INV_TEST_UNIT_ID = 0xFFFFFFFF;
const test_unit_id MAX_TEST_CASE_ID = 0xFFFFFFFE;
const test_unit_id MIN_TEST_CASE_ID = 0x00010000;
const test_unit_id MAX_TEST_SUITE_ID = 0x0000FF00;
const test_unit_id MIN_TEST_SUITE_ID = 0x00000001;
//____________________________________________________________________________//
namespace ut_detail {
inline test_unit_type
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
// helper templates to prevent ODR violations
template<class T>
struct static_constant {
static T value;
};
template<class T>
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
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_GLOBAL_TYPEDEF_HPP_021005GER

View File

@@ -0,0 +1,42 @@
// (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 shared definition for unit test log levels
// ***************************************************************************
#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 {
// ************************************************************************** //
// ************** log levels ************** //
// ************************************************************************** //
// each log level includes all subsequent higher loging levels
enum BOOST_TEST_ENUM_SYMBOL_VISIBLE log_level {
invalid_log_level = -1,
log_successful_tests = 0,
log_test_units = 1,
log_messages = 2,
log_warnings = 3,
log_all_errors = 4, // reported by unit test macros
log_cpp_exception_errors = 5, // uncaught C++ exceptions
log_system_errors = 6, // including timeouts, signals, traps
log_fatal_errors = 7, // including unit test macros or
// fatal system errors
log_nothing = 8
};
} // namespace unit_test
} // namespace boost
#endif // BOOST_TEST_LOG_LEVEL_HPP_011605GER

View File

@@ -0,0 +1,49 @@
// (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 few helpers for working with variadic macros
// ***************************************************************************
#ifndef BOOST_TEST_PP_VARIADIC_HPP_021515GER
#define BOOST_TEST_PP_VARIADIC_HPP_021515GER
// Boost
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/comparison/equal.hpp>
#include <boost/preprocessor/variadic/size.hpp>
//____________________________________________________________________________//
#if BOOST_PP_VARIADICS
#if BOOST_PP_VARIADICS_MSVC
# define BOOST_TEST_INVOKE_VARIADIC( tool, ... ) BOOST_PP_CAT( tool (__VA_ARGS__), )
#else
# define BOOST_TEST_INVOKE_VARIADIC( tool, ... ) tool (__VA_ARGS__)
#endif
//____________________________________________________________________________//
/// if sizeof(__VA_ARGS__) == N: F1(__VA_ARGS__)
/// else: F2(__VA_ARGS__)
#define BOOST_TEST_INVOKE_IF_N_ARGS( N, F1, F2, ... ) \
BOOST_TEST_INVOKE_VARIADIC( \
BOOST_PP_IIF( \
BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), N), \
F1, \
F2), \
__VA_ARGS__ ) \
/**/
//____________________________________________________________________________//
#endif /* BOOST_PP_VARIADICS */
#endif // BOOST_TEST_PP_VARIADIC_HPP_021515GER
// EOF

View File

@@ -0,0 +1,41 @@
// (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 suppress some warnings
// ***************************************************************************
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4511) // copy constructor can't not be generated
# pragma warning(disable: 4512) // assignment operator can't not be generated
# pragma warning(disable: 4100) // unreferenced formal parameter
# pragma warning(disable: 4996) // <symbol> was declared deprecated
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
# pragma warning(disable: 4706) // assignment within conditional expression
# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B'
# pragma warning(disable: 4127) // conditional expression is constant
# pragma warning(disable: 4290) // C++ exception specification ignored except to ...
# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored
# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ...
# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated
#endif
#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"
// # pragma GCC diagnostic ignored "-Wattributes"
#endif

View File

@@ -0,0 +1,71 @@
// (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 wrappers, which allows to build Boost.Test with no exception
// ***************************************************************************
#ifndef BOOST_TEST_DETAIL_THROW_EXCEPTION_HPP
#define BOOST_TEST_DETAIL_THROW_EXCEPTION_HPP
// Boost
#include <boost/config.hpp> // BOOST_NO_EXCEPTIONS
#ifdef BOOST_NO_EXCEPTIONS
// C RUNTIME
#include <stdlib.h>
#endif
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace ut_detail {
#ifdef BOOST_NO_EXCEPTIONS
template<typename E>
BOOST_NORETURN inline void
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;)
#define BOOST_TEST_I_CATCH0( T ) if(0)
#define BOOST_TEST_I_CATCHALL() if(0)
#define BOOST_TEST_I_RETHROW
#else
template<typename E>
BOOST_NORETURN inline void
throw_exception(E const& e) { throw e; }
#define BOOST_TEST_I_TRY try
#define BOOST_TEST_I_CATCH( T, var ) catch( T const& var )
#define BOOST_TEST_I_CATCH0( T ) catch( T const& )
#define BOOST_TEST_I_CATCHALL() catch(...)
#define BOOST_TEST_I_RETHROW throw
#endif
//____________________________________________________________________________//
#define BOOST_TEST_I_THROW( E ) unit_test::ut_detail::throw_exception( E )
#define BOOST_TEST_I_ASSRT( cond, ex ) if( cond ) {} else BOOST_TEST_I_THROW( ex )
} // namespace ut_detail
} // namespace unit_test
} // namespace boost
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_DETAIL_THROW_EXCEPTION_HPP

View File

@@ -0,0 +1,584 @@
// (C) Copyright Gennadiy Rozental 2001.
// (C) Copyright Beman Dawes 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 Defines public interface of the Execution Monitor and related classes
// ***************************************************************************
#ifndef BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
#define BOOST_TEST_EXECUTION_MONITOR_HPP_071894GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/utils/class_properties.hpp>
// Boost
#include <boost/shared_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/type.hpp>
#include <boost/cstdlib.hpp>
#include <boost/function/function0.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
// for the FP constants and control routines
#include <float.h>
#ifndef EM_INVALID
#define EM_INVALID _EM_INVALID
#endif
#ifndef EM_DENORMAL
#define EM_DENORMAL _EM_DENORMAL
#endif
#ifndef EM_ZERODIVIDE
#define EM_ZERODIVIDE _EM_ZERODIVIDE
#endif
#ifndef EM_OVERFLOW
#define EM_OVERFLOW _EM_OVERFLOW
#endif
#ifndef EM_UNDERFLOW
#define EM_UNDERFLOW _EM_UNDERFLOW
#endif
#ifndef MCW_EM
#define MCW_EM _MCW_EM
#endif
#else // based on ISO C standard
#if !defined(BOOST_NO_FENV_H)
#include <boost/detail/fenv.hpp>
#endif
#endif
#if defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
//! Indicates tha the floating point exception handling is supported
//! through SEH
#define BOOST_TEST_FPE_SUPPORT_WITH_SEH__
#elif !defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE)
#if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \
defined(__GLIBC__) && defined(__USE_GNU) && \
!(defined(__UCLIBC__) || defined(__nios2__) || defined(__microblaze__))
//! Indicates that floating point exception handling is supported for the
//! non SEH version of it, for the GLIBC extensions only
// see discussions on the related topic: https://svn.boost.org/trac/boost/ticket/11756
#define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
#endif
#endif
// Additional macro documentations not being generated without this hack
#ifdef BOOST_TEST_DOXYGEN_DOC__
//! Disables the support of the alternative stack
//! during the compilation of the Boost.test framework. This is especially useful
//! in case it is not possible to detect the lack of alternative stack support for
//! your compiler (for instance, ESXi).
#define BOOST_TEST_DISABLE_ALT_STACK
#endif
//____________________________________________________________________________//
namespace boost {
/// @defgroup ExecutionMonitor Function Execution Monitor
/// @{
/// @section Intro Introduction
/// Sometimes we need to call a function and make sure that no user or system originated exceptions are being thrown by it. Uniform exception reporting
/// is also may be convenient. That's the purpose of the Boost.Test's Execution Monitor.
///
/// The Execution Monitor is a lower-level component of the Boost Test Library. It is the base for implementing all other Boost.Test components, but also
/// can be used standalone to get controlled execution of error-prone functions with a uniform error notification. The Execution Monitor calls a user-supplied
/// function in a controlled environment, relieving users from messy error detection.
///
/// The Execution Monitor usage is demonstrated in the example exec_mon_example.
///
/// @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.
///
/// @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,
/// in monitored environment that should prevent any undesirable exceptions to propagate out of function call and produce consistent result report for all outcomes.
/// The Execution Monitor is able to produce informative report for all standard C++ exceptions and intrinsic types. All other exceptions are reported as unknown.
/// If you prefer different message for your exception type or need to perform any action, the Execution Monitor supports custom exception translators.
/// There are several other parameters of the monitored environment can be configured by setting appropriate properties of the Execution Monitor.
///
/// All symbols in the Execution Monitor implementation are located in the namespace boost. To use the Execution Monitor you need to:
/// -# include @c boost/test/execution_monitor.hpp
/// -# Make an instance of execution_monitor.
/// -# Optionally register custom exception translators for exception classes which require special processing.
///
/// @subsection FuncExec Monitored function execution
///
/// The class execution_monitor can monitor functions with the following signatures:
/// - int ()
/// - void ()
///
/// This function is expected to be self sufficient part of your application. You can't pass any arguments to this function directly. Instead you
/// should bind them into executable nullary function using bind function (either standard or boost variant). Neither you can return any other value,
/// but an integer result code. If necessary you can bind output parameters by reference or use some other more complicated nullary functor, which
/// maintains state. This includes class methods, static class methods etc.
///
/// To start the monitored function, invoke the method execution_monitor::execute and pass the monitored function as an argument. If the call succeeds,
/// the method returns the result code produced by the monitored function. If any of the following conditions occur:
/// - Uncaught C++ exception
/// - Hardware or software signal, trap, or other exception
/// - Timeout reached
/// - Debug assert event occurred (under Microsoft Visual C++ or compatible compiler)
///
/// then the method throws the execution_exception. The exception contains unique error_code value identifying the error condition and the detailed message
/// that can be used to report the error.
///
/// @subsection Reporting Errors reporting and translation
///
/// If you need to report an error inside monitored function execution you have to throw an exception. Do not use the execution_exception - it's not intended
/// to be used for this purpose. The simplest choice is to use one of the following C++ types as an exception:
/// - C string
/// - std:string
/// - any exception class in std::exception hierarchy
/// - boost::exception
///
/// execution_monitor will catch and report these types of exceptions. If exception is thrown which is unknown to execution_monitor, it can only
/// report the fact of the exception. So in case if you prefer to use your own exception types or can't govern what exceptions are generated by monitored
/// function and would like to see proper error message in a report, execution_monitor can be configured with custom "translator" routine, which will have
/// a chance to either record the fact of the exception itself or translate it into one of standard exceptions and rethrow (or both). The translator routine
/// is registered per exception type and is invoked when exception of this class (or one inherited from it) is thrown inside monitored routine. You can
/// register as many independent translators as you like. See execution_monitor::register_exception_translator specification for requirements on translator
/// function.
///
/// Finally, if you need to abort the monitored function execution without reporting any errors, you can throw an exception execution_aborted. As a result
/// the execution is aborted and zero result code is produced by the method execution_monitor::execute.
///
/// @subsection Parameters Supported parameters
///
/// The Execution Monitor behavior is configurable through the set of parameters (properties) associated with the instance of the monitor. See execution_monitor
/// specification for a list of supported parameters and their semantic.
// ************************************************************************** //
// ************** detail::translator_holder_base ************** //
// ************************************************************************** //
namespace detail {
class translator_holder_base;
typedef boost::shared_ptr<translator_holder_base> translator_holder_base_ptr;
class BOOST_TEST_DECL translator_holder_base {
protected:
typedef boost::unit_test::const_string const_string;
public:
// Constructor
translator_holder_base( translator_holder_base_ptr next, const_string tag )
: m_next( next )
, m_tag( std::string() + tag )
{
}
// Destructor
virtual ~translator_holder_base() {}
// translator holder interface
// invokes the function F inside the try/catch guarding against specific exception
virtual int operator()( boost::function<int ()> const& F ) = 0;
// erases specific translator holder from the chain
translator_holder_base_ptr erase( translator_holder_base_ptr this_, const_string tag )
{
if( m_next )
m_next = m_next->erase( m_next, tag );
return m_tag == tag ? m_next : this_;
}
#ifndef BOOST_NO_RTTI
virtual translator_holder_base_ptr erase( translator_holder_base_ptr this_, std::type_info const& ) = 0;
template<typename ExceptionType>
translator_holder_base_ptr erase( translator_holder_base_ptr this_, boost::type<ExceptionType>* = 0 )
{
if( m_next )
m_next = m_next->erase<ExceptionType>( m_next );
return erase( this_, typeid(ExceptionType) );
}
#endif
protected:
// Data members
translator_holder_base_ptr m_next;
std::string m_tag;
};
} // namespace detail
// ************************************************************************** //
/// @class execution_exception
/// @brief This class is used to report any kind of an failure during execution of a monitored function inside of execution_monitor
///
/// The instance of this class is thrown out of execution_monitor::execute invocation when failure is detected. Regardless of a kind of failure occurred
/// the instance will provide a uniform way to catch and report it.
///
/// One important design rationale for this class is that we should be ready to work after fatal memory corruptions or out of memory conditions. To facilitate
/// 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_SYMBOL_VISIBLE execution_exception {
typedef boost::unit_test::const_string const_string;
public:
/// These values are sometimes used as program return codes.
/// The particular values have been chosen to avoid conflicts with
/// commonly used program return codes: values < 100 are often user
/// assigned, values > 255 are sometimes used to report system errors.
/// Gaps in values allow for orderly expansion.
///
/// @note(1) Only uncaught C++ exceptions are treated as errors.
/// If a function catches a C++ exception, it never reaches
/// the execution_monitor.
///
/// The implementation decides what is a system_fatal_error and what is
/// just a system_exception. Fatal errors are so likely to have corrupted
/// machine state (like a stack overflow or addressing exception) that it
/// is unreasonable to continue execution.
///
/// @note(2) These errors include Unix signals and Windows structured
/// exceptions. They are often initiated by hardware traps.
enum error_code {
no_error = 0, ///< for completeness only; never returned
user_error = 200, ///< user reported non-fatal error
cpp_exception_error = 205, ///< see note (1) above
system_error = 210, ///< see note (2) above
timeout_error = 215, ///< only detectable on certain platforms
user_fatal_error = 220, ///< user reported fatal error
system_fatal_error = 225 ///< see note (2) above
};
/// 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
const_string m_function; ///< Function name
};
/// @name Constructors
/// Constructs instance based on message, location and error code
/// @param[in] ec error code
/// @param[in] what_msg error message
/// @param[in] location error location
execution_exception( error_code ec, const_string what_msg, location const& location );
/// @name Access methods
/// Exception error code
error_code code() const { return m_error_code; }
/// Exception message
const_string what() const { return m_what; }
/// Exception location
location const& where() const { return m_location; }
///@}
private:
// Data members
error_code m_error_code;
const_string m_what;
location m_location;
}; // execution_exception
// ************************************************************************** //
/// @brief Function execution monitor
/// This class is used to uniformly detect and report an occurrence of several types of signals and exceptions, reducing various
/// errors to a uniform execution_exception that is returned to a caller.
///
/// The execution_monitor behavior can be customized through a set of public parameters (properties) associated with the execution_monitor instance.
/// All parameters are implemented as public unit_test::readwrite_property data members of the class execution_monitor.
// ************************************************************************** //
class BOOST_TEST_DECL execution_monitor {
typedef boost::unit_test::const_string const_string;
public:
/// Default constructor initializes all execution monitor properties
execution_monitor();
/// Should monitor catch system errors.
///
/// The @em p_catch_system_errors property is a boolean flag (default value is true) specifying whether or not execution_monitor should trap system
/// errors/system level exceptions/signals, which would cause program to crash in a regular case (without execution_monitor).
/// Set this property to false, for example, if you wish to force coredump file creation. The Unit Test Framework provides a
/// runtime parameter @c \-\-catch_system_errors=yes to alter the behavior in monitored test cases.
unit_test::readwrite_property<bool> p_catch_system_errors;
/// Should monitor try to attach debugger in case of caught system error.
///
/// The @em p_auto_start_dbg property is a boolean flag (default value is false) specifying whether or not execution_monitor should try to attach debugger
/// in case system error is caught.
unit_test::readwrite_property<bool> p_auto_start_dbg;
/// Specifies the seconds that elapse before a timer_error occurs.
///
/// 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.
///
/// The @em p_use_alt_stack property is a boolean flag (default value is false) specifying whether or not execution_monitor should use an alternative stack
/// for the sigaction based signal catching. When enabled the signals are delivered to the execution_monitor on a stack different from current execution
/// stack, which is safer in case if it is corrupted by monitored function. For more details on alternative stack handling see appropriate manuals.
unit_test::readwrite_property<bool> p_use_alt_stack;
/// Should monitor try to detect hardware floating point exceptions (!= 0), and which specific exception to catch.
///
/// The @em p_detect_fp_exceptions property is a boolean flag (default value is false) specifying whether or not execution_monitor should install hardware
/// traps for the floating point exception on platforms where it's supported.
unit_test::readwrite_property<unsigned> p_detect_fp_exceptions;
// @name Monitoring entry points
/// @brief Execution monitor entry point for functions returning integer value
///
/// This method executes supplied function F inside a try/catch block and also may include other unspecified platform dependent error detection code.
///
/// This method throws an execution_exception on an uncaught C++ exception, a hardware or software signal, trap, or other user exception.
///
/// @note execute() doesn't consider it an error for F to return a non-zero value.
/// @param[in] F Function to monitor
/// @returns value returned by function call F().
/// @see vexecute
int execute( boost::function<int ()> const& F );
/// @brief Execution monitor entry point for functions returning void
///
/// This method is semantically identical to execution_monitor::execute, but doesn't produce any result code.
/// @param[in] F Function to monitor
/// @see execute
void vexecute( boost::function<void ()> const& F );
// @}
// @name Exception translator registration
/// @brief Registers custom (user supplied) exception translator
/// This method template registers a translator for an exception type specified as a first template argument. For example
/// @code
/// void myExceptTr( MyException const& ex ) { /*do something with the exception here*/}
/// em.register_exception_translator<MyException>( myExceptTr );
/// @endcode
/// The translator should be any unary function/functor object which accepts MyException const&. This can be free standing function
/// or bound class method. The second argument is an optional string tag you can associate with this translator routine. The only reason
/// to specify the tag is if you plan to erase the translator eventually. This can be useful in scenario when you reuse the same
/// execution_monitor instance to monitor different routines and need to register a translator specific to the routine being monitored.
/// While it is possible to erase the translator based on an exception type it was registered for, tag string provides simpler way of doing this.
/// @tparam ExceptionType type of the exception we register a translator for
/// @tparam ExceptionTranslator type of the translator we register for this exception
/// @param[in] tr translator function object with the signature <em> void (ExceptionType const&)</em>
/// @param[in] tag tag associated with this translator
template<typename ExceptionType, typename ExceptionTranslator>
void register_exception_translator( ExceptionTranslator const& tr, const_string tag = const_string(), boost::type<ExceptionType>* = 0 );
/// @brief Erases custom exception translator based on a tag
/// Use the same tag as the one used during translator registration
/// @param[in] tag tag associated with translator you wants to erase
void erase_exception_translator( const_string tag )
{
m_custom_translators = m_custom_translators->erase( m_custom_translators, tag );
}
#ifndef BOOST_NO_RTTI
/// @brief Erases custom exception translator based on an exception type
///
/// tparam ExceptionType Exception type for which you want to erase the translator
template<typename ExceptionType>
void erase_exception_translator( boost::type<ExceptionType>* = 0 )
{
m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
}
//@}
#endif
private:
// implementation helpers
int catch_signals( boost::function<int ()> const& F );
// Data members
detail::translator_holder_base_ptr m_custom_translators;
boost::scoped_array<char> m_alt_stack;
}; // execution_monitor
// ************************************************************************** //
// ************** detail::translator_holder ************** //
// ************************************************************************** //
namespace detail {
template<typename ExceptionType, typename ExceptionTranslator>
class translator_holder : public translator_holder_base
{
public:
explicit translator_holder( ExceptionTranslator const& tr, translator_holder_base_ptr& next, const_string tag = const_string() )
: translator_holder_base( next, tag ), m_translator( tr ) {}
// translator holder interface
int operator()( boost::function<int ()> const& F ) BOOST_OVERRIDE
{
BOOST_TEST_I_TRY {
return m_next ? (*m_next)( F ) : F();
}
BOOST_TEST_I_CATCH( ExceptionType, e ) {
m_translator( e );
return boost::exit_exception_failure;
}
}
#ifndef BOOST_NO_RTTI
translator_holder_base_ptr erase( translator_holder_base_ptr this_, std::type_info const& ti ) BOOST_OVERRIDE
{
return ti == typeid(ExceptionType) ? m_next : this_;
}
#endif
private:
// Data members
ExceptionTranslator m_translator;
};
} // namespace detail
template<typename ExceptionType, typename ExceptionTranslator>
void
execution_monitor::register_exception_translator( ExceptionTranslator const& tr, const_string tag, boost::type<ExceptionType>* )
{
m_custom_translators.reset(
new detail::translator_holder<ExceptionType,ExceptionTranslator>( tr, m_custom_translators, tag ) );
}
// ************************************************************************** //
/// @class execution_aborted
/// @brief This is a trivial default constructible class. Use it to report graceful abortion of a monitored function execution.
// ************************************************************************** //
struct BOOST_SYMBOL_VISIBLE execution_aborted {};
// ************************************************************************** //
// ************** system_error ************** //
// ************************************************************************** //
class system_error {
public:
// Constructor
explicit system_error( char const* exp );
long const p_errno;
char const* const p_failed_exp;
};
//!@internal
#define BOOST_TEST_SYS_ASSERT( cond ) BOOST_TEST_I_ASSRT( cond, ::boost::system_error( BOOST_STRINGIZE( exp ) ) )
// ************************************************************************** //
// **************Floating point exception management interface ************** //
// ************************************************************************** //
namespace fpe {
enum masks {
BOOST_FPE_OFF = 0,
#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__) /* *** */
BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE,
BOOST_FPE_INEXACT = EM_INEXACT,
BOOST_FPE_INVALID = EM_INVALID,
BOOST_FPE_OVERFLOW = EM_OVERFLOW,
BOOST_FPE_UNDERFLOW = EM_UNDERFLOW|EM_DENORMAL,
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)
BOOST_FPE_DIVBYZERO = FE_DIVBYZERO,
#else
BOOST_FPE_DIVBYZERO = BOOST_FPE_OFF,
#endif
#if defined(FE_INEXACT)
BOOST_FPE_INEXACT = FE_INEXACT,
#else
BOOST_FPE_INEXACT = BOOST_FPE_OFF,
#endif
#if defined(FE_INVALID)
BOOST_FPE_INVALID = FE_INVALID,
#else
BOOST_FPE_INVALID = BOOST_FPE_OFF,
#endif
#if defined(FE_OVERFLOW)
BOOST_FPE_OVERFLOW = FE_OVERFLOW,
#else
BOOST_FPE_OVERFLOW = BOOST_FPE_OFF,
#endif
#if defined(FE_UNDERFLOW)
BOOST_FPE_UNDERFLOW = FE_UNDERFLOW,
#else
BOOST_FPE_UNDERFLOW = BOOST_FPE_OFF,
#endif
#if defined(FE_ALL_EXCEPT)
BOOST_FPE_ALL = FE_ALL_EXCEPT,
#else
BOOST_FPE_ALL = BOOST_FPE_OFF,
#endif
#endif /* *** */
BOOST_FPE_INV = BOOST_FPE_ALL+1
};
//____________________________________________________________________________//
// return the previous set of enabled exceptions when successful, and BOOST_FPE_INV otherwise
unsigned BOOST_TEST_DECL enable( unsigned mask );
unsigned BOOST_TEST_DECL disable( unsigned mask );
//____________________________________________________________________________//
} // namespace fpe
///@}
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif

View File

@@ -0,0 +1,18 @@
// (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 Deprecated header
//! @deprecated Use boost/test/tools/floating_point_comparison.hpp instead
// ***************************************************************************
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/tools/floating_point_comparison.hpp>" )
// Boost.Test
#include <boost/test/tools/floating_point_comparison.hpp>

View File

@@ -0,0 +1,307 @@
// (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 Defines Unit Test Framework mono-state interfaces.
//! The framework interfaces are based on Monostate design pattern.
// ***************************************************************************
#ifndef BOOST_TEST_FRAMEWORK_HPP_020805GER
#define BOOST_TEST_FRAMEWORK_HPP_020805GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/detail/throw_exception.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
// STL
#include <stdexcept>
//____________________________________________________________________________//
namespace boost {
/// Main namespace for the Unit Test Framework interfaces and implementation
namespace unit_test {
// ************************************************************************** //
// ************** init_unit_test_func ************** //
// ************************************************************************** //
/// Test module initialization routine signature
/// Different depending on whether BOOST_TEST_ALTERNATIVE_INIT_API is defined or not
#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
typedef bool (*init_unit_test_func)();
#else
typedef test_suite* (*init_unit_test_func)( int, char* [] );
#endif
// ************************************************************************** //
// ************** framework ************** //
// ************************************************************************** //
/// Namespace of the Unit Test Framework mono-state
namespace framework {
/// @name Unit Test Framework initialization and shutdown
/// @{
/// @brief This function performs initialization of the framework mono-state.
///
/// It needs to be called every time before the test is started.
/// @param[in] init_func test module initialization routine
/// @param[in] argc command line arguments collection
/// @param[in] argv command line arguments collection
BOOST_TEST_DECL void init( init_unit_test_func init_func, int argc, char* argv[] );
/// This function applies all the decorators and figures out default run status. This argument facilitates an
/// ability of the test cases to prepare some other test units (primarily used internally for self testing).
/// @param[in] tu Optional id of the test unit representing root of test tree. If absent, master test suite is used
BOOST_TEST_DECL void finalize_setup_phase( test_unit_id tu = INV_TEST_UNIT_ID);
/// This function returns true when testing is in progress (setup is finished).
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();
/// @}
/// @name Test unit registration
/// @{
/// Provides both read and write access to current "leaf" auto test suite during the test unit registration phase.
///
/// During auto-registration phase the framework maintain a FIFO queue of test units being registered. New test units become children
/// of the current "leaf" test suite and if this is test suite it is pushed back into queue and becomes a new leaf.
/// When test suite registration is completed, a test suite is popped from the back of the queue. Only automatically registered test suites
/// should be added to this queue. Master test suite is always a zero element in this queue, so if no other test suites are registered
/// all test cases are added to master test suite.
/// This function facilitates all three possible actions:
/// - if no argument are provided it returns the current queue leaf test suite
/// - if test suite is provided and no second argument are set, test suite is added to the queue
/// - if no test suite are provided and last argument is false, the semantic of this function is similar to queue pop: last element is popped from the queue
/// @param[in] ts test suite to push back to the queue
/// @param[in] push_or_pop should we push ts to the queue or pop leaf test suite instead
/// @returns a reference to the currently active/"leaf" test suite
BOOST_TEST_DECL test_suite& current_auto_test_suite( test_suite* ts = 0, bool push_or_pop = true );
/// This function add new test case into the global collection of test units the framework aware of.
/// This function also assignes unique test unit id for every test case. Later on one can use this id to locate
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in] tc test case to register
BOOST_TEST_DECL void register_test_unit( test_case* tc );
/// This function add new test suite into the global collection of test units the framework aware of.
/// This function also assignes unique test unit id for every test suite. Later on one can use this id to locate
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in] ts test suite to register
BOOST_TEST_DECL void register_test_unit( test_suite* ts );
/// This function removes the test unit from the collection of known test units and destroys the test unit object.
/// This function also assigns unique test unit id for every test case. Later on one can use this id to located
/// the test case if necessary. This is the way for the framework to maintain weak references between test units.
/// @param[in] tu test unit to deregister
BOOST_TEST_DECL void deregister_test_unit( test_unit* tu );
// This function clears up the framework mono-state.
/// After this call the framework can be reinitialized to perform a second test run during the same program lifetime.
BOOST_TEST_DECL void clear();
/// @}
/// @name Test observer registration
/// @{
/// Adds new test execution observer object into the framework's list of test observers.
/// Observer lifetime should exceed the the testing execution timeframe
/// @param[in] to test observer object to add
BOOST_TEST_DECL void register_observer( test_observer& to );
/// 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
struct BOOST_TEST_DECL context_generator {
context_generator() : m_curr_frame( 0 ) {}
/// Is there any context?
bool is_empty() const;
/// Give me next frame; empty - last frame
const_string next() const;
private:
// Data members
mutable unsigned m_curr_frame;
};
/// Records context frame message.
/// Some context frames are sticky - they can only explicitly cleared by specifying context id. Other (non sticky) context frames cleared after every assertion.
/// @param[in] context_descr context frame message
/// @param[in] sticky is this sticky frame or not
/// @returns id of the newly created frame
BOOST_TEST_DECL int add_context( lazy_ostream const& context_descr, bool sticky );
/// Erases context frame (when test exits context scope)
/// If context_id is passed clears that specific context frame identified by this id, otherwise clears all non sticky contexts.
BOOST_TEST_DECL void clear_context( int context_id = -1 );
/// Produces an instance of small "delegate" object, which facilitates access to collected context.
BOOST_TEST_DECL context_generator get_context();
/// @}
/// @name Access to registered test units.
/// @{
/// This function provides access to the master test suite.
/// There is only only master test suite per test module.
/// @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.
/// @see current_test_case_id
BOOST_TEST_DECL test_case const& current_test_case();
/// This function provides an access to an id of the test case currently being executed.
/// This function safer than current_test_case, cause if wont throw if no test case is being executed.
/// @see current_test_case
BOOST_TEST_DECL test_unit_id current_test_case_id(); /* safe version of above */
/// This function provides access to a test unit by id and type combination. It will throw if no test unit located.
/// @param[in] tu_id id of a test unit to locate
/// @param[in] tu_type type of a test unit to locate
/// @returns located test unit
BOOST_TEST_DECL test_unit& get( test_unit_id tu_id, test_unit_type tu_type );
/// This function template provides access to a typed test unit by id
/// It will throw if you specify incorrect test unit type
/// @tparam UnitType compile time type of test unit to get (test_suite or test_case)
/// @param id id of test unit to get
template<typename UnitType>
inline UnitType& get( test_unit_id id )
{
return static_cast<UnitType&>( get( id, static_cast<test_unit_type>(UnitType::type) ) );
}
///@}
/// @name Test initiation interface
/// @{
/// Initiates test execution
/// This function is used to start the test execution from a specific "root" test unit.
/// If no root provided, test is started from master test suite. This second argument facilitates an ability of the test cases to
/// start some other test units (primarily used internally for self testing).
/// @param[in] tu Optional id of the test unit or test unit itself from which the test is started. If absent, master test suite is used
/// @param[in] continue_test true == continue test if it was already started, false == restart the test from scratch regardless
BOOST_TEST_DECL void run( test_unit_id tu = INV_TEST_UNIT_ID, bool continue_test = true );
/// Initiates test execution. Same as other overload
BOOST_TEST_DECL void run( test_unit const* tu, bool continue_test = true );
/// @}
/// @name Test events dispatchers
/// @{
/// Reports results of assertion to all test observers
BOOST_TEST_DECL void assertion_result( unit_test::assertion_result ar );
/// Reports uncaught exception to all test observers
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 {
// exclusively for self test
BOOST_TEST_DECL void setup_for_execution( test_unit const& );
BOOST_TEST_DECL void setup_loggers( );
// Helper for setting the name of the master test suite globally
struct BOOST_TEST_DECL master_test_suite_name_setter {
master_test_suite_name_setter( const_string name );
};
} // namespace impl
// ************************************************************************** //
// ************** framework errors ************** //
// ************************************************************************** //
/// This exception type is used to report internal Boost.Test framework errors.
struct BOOST_TEST_DECL internal_error : public std::runtime_error {
internal_error( const_string m ) : std::runtime_error( std::string( m.begin(), m.size() ) ) {}
};
//____________________________________________________________________________//
/// This exception type is used to report test module setup errors.
struct BOOST_TEST_DECL setup_error : public std::runtime_error {
setup_error( const_string m ) : std::runtime_error( std::string( m.begin(), m.size() ) ) {}
};
#define BOOST_TEST_SETUP_ASSERT( cond, msg ) BOOST_TEST_I_ASSRT( cond, unit_test::framework::setup_error( msg ) )
//____________________________________________________________________________//
struct nothing_to_test {
explicit nothing_to_test( int rc ) : m_result_code( rc ) {}
int m_result_code;
};
//____________________________________________________________________________//
} // namespace framework
} // unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_HPP_020805GER

View File

@@ -0,0 +1,293 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implements compiler like Log formatter
// ***************************************************************************
#ifndef BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
#define BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER
// Boost.Test
#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/lazy_ostream.hpp>
// Boost
#include <boost/version.hpp>
// STL
#include <iostream>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
// ************************************************************************** //
// ************** compiler_log_formatter ************** //
// ************************************************************************** //
namespace {
std::string
test_phase_identifier()
{
return framework::test_in_progress() ? framework::current_test_unit().full_name() : std::string( "Test setup" );
}
} // local namespace
//____________________________________________________________________________//
void
compiler_log_formatter::log_start( std::ostream& output, counter_t test_cases_amount )
{
m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
if( test_cases_amount > 0 )
output << "Running " << test_cases_amount << " test "
<< (test_cases_amount > 1 ? "cases" : "case") << "...\n";
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_finish( std::ostream& ostr )
{
ostr.flush();
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_build_info( std::ostream& output, bool log_build_info )
{
if(log_build_info) {
output << "Platform: " << BOOST_PLATFORM << '\n'
<< "Compiler: " << BOOST_COMPILER << '\n'
<< "STL : " << BOOST_STDLIB << '\n'
<< "Boost : " << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << std::endl;
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::test_unit_start( std::ostream& output, test_unit const& tu )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::BLUE );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Entering test " << tu.p_type_name << " \"" << tu.p_name << "\"" << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::test_unit_finish( std::ostream& output, test_unit const& tu, unsigned long elapsed )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::BLUE );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Leaving test " << tu.p_type_name << " \"" << tu.p_name << "\"";
if( elapsed > 0 ) {
output << "; testing time: ";
if( elapsed % 1000 == 0 )
output << elapsed/1000 << "ms";
else
output << elapsed << "us";
}
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::test_unit_skipped( std::ostream& output, test_unit const& tu, const_string reason )
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::YELLOW );
print_prefix( output, tu.p_file_name, tu.p_line_num );
output << "Test " << tu.p_type_name << " \"" << tu.full_name() << "\"" << " is skipped because " << reason << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_exception_start( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
print_prefix( output, loc.m_file_name, loc.m_line_num );
{
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::UNDERLINE, term_color::RED );
output << "fatal error: in \"" << (loc.m_function.is_empty() ? test_phase_identifier() : loc.m_function ) << "\": "
<< ex.what();
}
if( !checkpoint_data.m_file_name.is_empty() ) {
output << '\n';
print_prefix( output, checkpoint_data.m_file_name, checkpoint_data.m_line_num );
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, output, term_attr::BRIGHT, term_color::CYAN );
output << "last checkpoint";
if( !checkpoint_data.m_message.empty() )
output << ": " << checkpoint_data.m_message;
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_exception_finish( std::ostream& output )
{
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_start( std::ostream& output, log_entry_data const& entry_data, log_entry_types let )
{
using namespace utils;
switch( let ) {
case BOOST_UTL_ET_INFO:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::GREEN, term_color::ORIGINAL, &m_color_state);
output << "info: ";
break;
case BOOST_UTL_ET_MESSAGE:
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::CYAN, term_color::ORIGINAL, &m_color_state);
break;
case BOOST_UTL_ET_WARNING:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::YELLOW, term_color::ORIGINAL, &m_color_state);
output << "warning: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::BRIGHT, term_color::RED, term_color::ORIGINAL, &m_color_state);
output << "error: in \"" << test_phase_identifier() << "\": ";
break;
case BOOST_UTL_ET_FATAL_ERROR:
print_prefix( output, entry_data.m_file_name, entry_data.m_line_num );
output << setcolor( m_color_output, term_attr::UNDERLINE, term_color::RED, term_color::ORIGINAL, &m_color_state);
output << "fatal error: in \"" << test_phase_identifier() << "\": ";
break;
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_value( std::ostream& output, const_string value )
{
output << value;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_value( std::ostream& output, lazy_ostream const& value )
{
output << value;
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_finish( std::ostream& output )
{
if( m_color_output )
output << utils::setcolor(m_color_output, &m_color_state);
output << std::endl;
}
//____________________________________________________________________________//
void
compiler_log_formatter::print_prefix( std::ostream& output, const_string file_name, std::size_t line_num )
{
if( !file_name.empty() ) {
#ifdef __APPLE_CC__
// Xcode-compatible logging format, idea by Richard Dingwall at
// <http://richarddingwall.name/2008/06/01/using-the-boost-unit-test-framework-with-xcode-3/>.
output << file_name << ':' << line_num << ": ";
#else
output << file_name << '(' << line_num << "): ";
#endif
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::entry_context_start( std::ostream& output, log_level l )
{
if( l == log_messages ) {
output << "\n[context:";
}
else {
output << (l == log_successful_tests ? "\nAssertion" : "\nFailure" ) << " occurred in a following context:";
}
}
//____________________________________________________________________________//
void
compiler_log_formatter::entry_context_finish( std::ostream& output, log_level l )
{
if( l == log_messages ) {
output << "]";
}
output.flush();
}
//____________________________________________________________________________//
void
compiler_log_formatter::log_entry_context( std::ostream& output, log_level /*l*/, const_string context_descr )
{
output << "\n " << context_descr;
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,136 @@
// (C) Copyright Gennadiy Rozental 2001.
// (C) Copyright Beman Dawes 1995-2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : main function implementation for Program Executon Monitor
// ***************************************************************************
#ifndef BOOST_TEST_CPP_MAIN_IPP_012205GER
#define BOOST_TEST_CPP_MAIN_IPP_012205GER
// Boost.Test
#include <boost/test/execution_monitor.hpp>
#include <boost/test/detail/config.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
// Boost
#include <boost/cstdlib.hpp> // for exit codes
#include <boost/config.hpp> // for workarounds
// STL
#include <iostream>
#include <cstdlib> // std::getenv
#include <cstring> // std::strerror
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::getenv; using ::strerror; }
#endif
namespace {
struct cpp_main_caller {
cpp_main_caller( int (*cpp_main_func)( int argc, char* argv[] ), int argc, char** argv )
: m_cpp_main_func( cpp_main_func )
, m_argc( argc )
, m_argv( argv ) {}
int operator()() { return (*m_cpp_main_func)( m_argc, m_argv ); }
private:
// Data members
int (*m_cpp_main_func)( int argc, char* argv[] );
int m_argc;
char** m_argv;
};
} // local namespace
// ************************************************************************** //
// ************** prg_exec_monitor_main ************** //
// ************************************************************************** //
namespace boost {
int BOOST_TEST_DECL
prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char* argv[] )
{
int result = 0;
BOOST_TEST_I_TRY {
boost::unit_test::const_string p( std::getenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS" ) );
::boost::execution_monitor ex_mon;
ex_mon.p_catch_system_errors.value = p != "no";
result = ex_mon.execute( cpp_main_caller( cpp_main, argc, argv ) );
if( result == 0 )
result = ::boost::exit_success;
else if( result != ::boost::exit_success ) {
std::cout << "\n**** error return code: " << result << std::endl;
result = ::boost::exit_failure;
}
}
BOOST_TEST_I_CATCH( ::boost::execution_exception, exex ) {
std::cout << "\n**** exception(" << exex.code() << "): " << exex.what() << std::endl;
result = ::boost::exit_exception_failure;
}
BOOST_TEST_I_CATCH( ::boost::system_error, ex ) {
std::cout << "\n**** failed to initialize execution monitor."
<< "\n**** expression at fault: " << ex.p_failed_exp
<< "\n**** error(" << ex.p_errno << "): " << std::strerror( ex.p_errno ) << std::endl;
result = ::boost::exit_exception_failure;
}
if( result != ::boost::exit_success ) {
std::cerr << "******** errors detected; see standard output for details ********" << std::endl;
}
else {
// Some prefer a confirming message when all is well, while others don't
// like the clutter. Use an environment variable to avoid command
// line argument modifications; for use in production programs
// that's a no-no in some organizations.
::boost::unit_test::const_string p( std::getenv( "BOOST_PRG_MON_CONFIRM" ) );
if( p != "no" ) {
std::cerr << std::flush << "no errors detected" << std::endl;
}
}
return result;
}
} // namespace boost
#if !defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
// ************************************************************************** //
// ************** main function for tests using lib ************** //
// ************************************************************************** //
int cpp_main( int argc, char* argv[] ); // prototype for user's cpp_main()
int BOOST_TEST_CALL_DECL
main( int argc, char* argv[] )
{
return ::boost::prg_exec_monitor_main( &cpp_main, argc, argv );
}
//____________________________________________________________________________//
#endif // !BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_CPP_MAIN_IPP_012205GER

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,218 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : plain report formatter definition
// ***************************************************************************
#ifndef BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
#define BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER
// Boost.Test
#include <boost/test/output/plain_report_formatter.hpp>
#include <boost/test/utils/custom_manip.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/setcolor.hpp>
// STL
#include <iomanip>
#include <boost/config/no_tr1/cmath.hpp>
#include <iostream>
#include <boost/test/detail/suppress_warnings.hpp>
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::log10; }
# endif
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
namespace {
typedef utils::custom_manip<struct quote_t> quote;
template<typename T>
inline std::ostream&
operator<<( utils::custom_printer<quote> const& p, T const& value )
{
*p << '"' << value << '"';
return *p;
}
//____________________________________________________________________________//
void
print_stat_value( std::ostream& ostr, counter_t v, counter_t indent, counter_t total, const_string name, const_string res )
{
if( v == 0 )
return;
if( total > 0 )
ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << name << ( v != 1 ? "s" : "" )
<< " out of " << total << ' ' << res << '\n';
else
ostr << std::setw( static_cast<int>(indent) ) << "" << v << ' ' << res << ' ' << name << ( v != 1 ? "s" : "" ) << '\n';
}
//____________________________________________________________________________//
} // local namespace
// ************************************************************************** //
// ************** plain_report_formatter ************** //
// ************************************************************************** //
void
plain_report_formatter::results_report_start( std::ostream& ostr )
{
m_indent = 0;
m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
ostr << '\n';
}
//____________________________________________________________________________//
void
plain_report_formatter::results_report_finish( std::ostream& ostr )
{
ostr.flush();
}
//____________________________________________________________________________//
void
plain_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream& ostr )
{
test_results const& tr = results_collector.results( tu.p_id );
const_string descr;
if( tr.passed() )
descr = "has passed";
else if( tr.p_skipped )
descr = "was skipped";
else if( tr.p_timed_out )
descr = "has timed out";
else if( tr.p_aborted )
descr = "was aborted";
else
descr = "has failed";
ostr << std::setw( static_cast<int>(m_indent) ) << ""
<< "Test " << tu.p_type_name << ' ' << quote() << tu.full_name() << ' ' << descr;
if( tr.p_skipped ) {
ostr << "\n";
m_indent += 2;
return;
}
// aborted test case within failed ones, timed-out TC exclusive with failed/aborted
counter_t total_assertions = tr.p_assertions_passed + tr.p_assertions_failed;
counter_t total_tc = tr.p_test_cases_passed + tr.p_test_cases_warned + tr.p_test_cases_failed + tr.p_test_cases_skipped + tr.p_test_cases_timed_out;
if( total_assertions > 0 || total_tc > 0 || tr.p_warnings_failed > 0)
ostr << " with:";
ostr << '\n';
m_indent += 2;
print_stat_value( ostr, tr.p_test_cases_passed , m_indent, total_tc , "test case", "passed" );
print_stat_value( ostr, tr.p_test_cases_warned , m_indent, total_tc , "test case", "passed with warnings" );
print_stat_value( ostr, tr.p_test_cases_failed , m_indent, total_tc , "test case", "failed" );
print_stat_value( ostr, tr.p_test_cases_timed_out, m_indent, total_tc , "test case", "timed-out" );
print_stat_value( ostr, tr.p_test_suites_timed_out, m_indent, tr.p_test_suites, "test suite", "timed-out" );
print_stat_value( ostr, tr.p_test_cases_skipped, m_indent, total_tc , "test case", "skipped" );
print_stat_value( ostr, tr.p_test_cases_aborted, m_indent, total_tc , "test case", "aborted" );
print_stat_value( ostr, tr.p_assertions_passed , m_indent, total_assertions, "assertion", "passed" );
print_stat_value( ostr, tr.p_assertions_failed , m_indent, total_assertions, "assertion", "failed" );
print_stat_value( ostr, tr.p_warnings_failed , m_indent, 0 , "warning" , "failed" );
print_stat_value( ostr, tr.p_expected_failures , m_indent, 0 , "failure" , "expected" );
ostr << '\n';
}
//____________________________________________________________________________//
void
plain_report_formatter::test_unit_report_finish( test_unit const&, std::ostream& )
{
m_indent -= 2;
}
//____________________________________________________________________________//
void
plain_report_formatter::do_confirmation_report( test_unit const& tu, std::ostream& ostr )
{
test_results const& tr = results_collector.results( tu.p_id );
if( tr.passed() ) {
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, ostr, term_attr::BRIGHT, term_color::GREEN );
ostr << "*** No errors detected\n";
return;
}
BOOST_TEST_SCOPE_SETCOLOR( m_color_output, ostr, term_attr::BRIGHT, term_color::RED );
if( tr.p_skipped ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was skipped"
<< "; see standard output for details\n";
return;
}
if( tr.p_timed_out ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " has timed out"
<< "; see standard output for details\n";
return;
}
if( tr.p_aborted ) {
ostr << "*** The test " << tu.p_type_name << ' ' << quote() << tu.full_name() << " was aborted"
<< "; see standard output for details\n";
}
if( tr.p_assertions_failed == 0 ) {
if( !tr.p_aborted )
ostr << "*** Errors were detected in the test " << tu.p_type_name << ' ' << quote() << tu.full_name()
<< "; see standard output for details\n";
return;
}
counter_t num_failures = tr.p_assertions_failed;
ostr << "*** " << num_failures << " failure" << ( num_failures != 1 ? "s are" : " is" ) << " detected";
if( tr.p_expected_failures > 0 )
ostr << " (" << tr.p_expected_failures << " failure" << ( tr.p_expected_failures != 1 ? "s are" : " is" ) << " expected)";
ostr << " in the test " << tu.p_type_name << " " << quote() << tu.full_name() << "\n";
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PLAIN_REPORT_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,189 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implements simple text based progress monitor
// ***************************************************************************
#ifndef BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
#define BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER
// Boost.Test
#include <boost/test/progress_monitor.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/setcolor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/test_case_counter.hpp>
#include <boost/test/tree/traverse.hpp>
// Boost
#include <boost/scoped_ptr.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** progress_monitor ************** //
// ************************************************************************** //
struct progress_display {
progress_display( counter_t expected_count, std::ostream& os )
: m_os(os)
, m_count( 0 )
, m_expected_count( expected_count )
, m_next_tic_count( 0 )
, m_tic( 0 )
{
m_os << "\n0% 10 20 30 40 50 60 70 80 90 100%"
<< "\n|----|----|----|----|----|----|----|----|----|----|"
<< std::endl;
if( !m_expected_count )
m_expected_count = 1; // prevent divide by zero
}
unsigned long operator+=( unsigned long increment )
{
if( (m_count += increment) < m_next_tic_count )
return m_count;
// use of floating point ensures that both large and small counts
// work correctly. static_cast<>() is also used several places
// to suppress spurious compiler warnings.
unsigned int tics_needed = static_cast<unsigned int>(
(static_cast<double>(m_count)/m_expected_count)*50.0 );
do {
m_os << '*' << std::flush;
} while( ++m_tic < tics_needed );
m_next_tic_count = static_cast<unsigned long>((m_tic/50.0) * m_expected_count);
if( m_count == m_expected_count ) {
if( m_tic < 51 )
m_os << '*';
m_os << std::endl;
}
return m_count;
}
unsigned long operator++() { return operator+=( 1 ); }
unsigned long count() const { return m_count; }
private:
BOOST_DELETED_FUNCTION(progress_display(progress_display const&))
BOOST_DELETED_FUNCTION(progress_display& operator=(progress_display const&))
std::ostream& m_os; // may not be present in all imps
unsigned long m_count;
unsigned long m_expected_count;
unsigned long m_next_tic_count;
unsigned int m_tic;
};
namespace {
struct progress_monitor_impl {
// Constructor
progress_monitor_impl()
: m_stream( &std::cout )
, m_color_output( false )
{
}
std::ostream* m_stream;
scoped_ptr<progress_display> m_progress_display;
bool m_color_output;
};
progress_monitor_impl& s_pm_impl() { static progress_monitor_impl the_inst; return the_inst; }
#define PM_SCOPED_COLOR() \
BOOST_TEST_SCOPE_SETCOLOR( s_pm_impl().m_color_output, *s_pm_impl().m_stream, term_attr::BRIGHT, term_color::MAGENTA )
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL(progress_monitor_t)
//____________________________________________________________________________//
void
progress_monitor_t::test_start( counter_t test_cases_amount, test_unit_id )
{
s_pm_impl().m_color_output = runtime_config::get<bool>( runtime_config::btrt_color_output );
PM_SCOPED_COLOR();
s_pm_impl().m_progress_display.reset( new progress_display( test_cases_amount, *s_pm_impl().m_stream ) );
}
//____________________________________________________________________________//
void
progress_monitor_t::test_aborted()
{
PM_SCOPED_COLOR();
(*s_pm_impl().m_progress_display) += s_pm_impl().m_progress_display->count();
}
//____________________________________________________________________________//
void
progress_monitor_t::test_unit_finish( test_unit const& tu, unsigned long )
{
PM_SCOPED_COLOR();
if( tu.p_type == TUT_CASE )
++(*s_pm_impl().m_progress_display);
}
//____________________________________________________________________________//
void
progress_monitor_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
PM_SCOPED_COLOR();
test_case_counter tcc;
traverse_test_tree( tu, tcc );
(*s_pm_impl().m_progress_display) += tcc.p_count;
}
//____________________________________________________________________________//
void
progress_monitor_t::set_stream( std::ostream& ostr )
{
s_pm_impl().m_stream = &ostr;
}
//____________________________________________________________________________//
#undef PM_SCOPED_COLOR
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PROGRESS_MONITOR_IPP_020105GER

View File

@@ -0,0 +1,349 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
/// @file
/// Test results collecting facility.
///
// ***************************************************************************
#ifndef BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
#define BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER
// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/test_case_counter.hpp>
#include <boost/test/tree/traverse.hpp>
// Boost
#include <boost/cstdlib.hpp>
// STL
#include <map>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** test_results ************** //
// ************************************************************************** //
test_results::test_results()
{
clear();
}
//____________________________________________________________________________//
bool
test_results::passed() const
{
// if it is skipped, it is not passed. However, if any children is not failed/aborted
// then their skipped status is not taken into account.
return !p_skipped &&
p_test_cases_failed == 0 &&
p_assertions_failed <= p_expected_failures &&
// p_test_cases_skipped == 0 &&
!p_timed_out &&
p_test_cases_timed_out == 0 &&
!aborted();
}
//____________________________________________________________________________//
bool
test_results::aborted() const
{
return p_aborted;
}
//____________________________________________________________________________//
bool
test_results::skipped() const
{
return p_skipped;
}
//____________________________________________________________________________//
int
test_results::result_code() const
{
return passed() ? exit_success
: ( (p_assertions_failed > p_expected_failures || p_skipped || p_timed_out || p_test_cases_timed_out )
? exit_test_failure
: exit_exception_failure );
}
//____________________________________________________________________________//
void
test_results::operator+=( test_results const& tr )
{
p_test_suites.value += tr.p_test_suites;
p_assertions_passed.value += tr.p_assertions_passed;
p_assertions_failed.value += tr.p_assertions_failed;
p_warnings_failed.value += tr.p_warnings_failed;
p_test_cases_passed.value += tr.p_test_cases_passed;
p_test_cases_warned.value += tr.p_test_cases_warned;
p_test_cases_failed.value += tr.p_test_cases_failed;
p_test_cases_skipped.value += tr.p_test_cases_skipped;
p_test_cases_aborted.value += tr.p_test_cases_aborted;
p_test_cases_timed_out.value += tr.p_test_cases_timed_out;
p_test_suites_timed_out.value += tr.p_test_suites_timed_out;
p_duration_microseconds.value += tr.p_duration_microseconds;
}
//____________________________________________________________________________//
void
test_results::clear()
{
p_test_suites.value = 0;
p_assertions_passed.value = 0;
p_assertions_failed.value = 0;
p_warnings_failed.value = 0;
p_expected_failures.value = 0;
p_test_cases_passed.value = 0;
p_test_cases_warned.value = 0;
p_test_cases_failed.value = 0;
p_test_cases_skipped.value = 0;
p_test_cases_aborted.value = 0;
p_test_cases_timed_out.value = 0;
p_test_suites_timed_out.value = 0;
p_duration_microseconds.value= 0;
p_aborted.value = false;
p_skipped.value = false;
p_timed_out.value = false;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** results_collector ************** //
// ************************************************************************** //
namespace {
struct results_collector_impl {
std::map<test_unit_id,test_results> m_results_store;
};
results_collector_impl& s_rc_impl() { static results_collector_impl the_inst; return the_inst; }
// deletes the entries of results_collector_impl
class clear_subtree_result : public test_tree_visitor {
public:
clear_subtree_result(results_collector_impl& store)
: m_store( store )
{}
private:
bool visit( test_unit const& tu) BOOST_OVERRIDE
{
typedef std::map<test_unit_id,test_results>::iterator iterator;
iterator found = m_store.m_results_store.find(tu.p_id);
if(found != m_store.m_results_store.end()) {
m_store.m_results_store.erase( found );
}
return true;
}
results_collector_impl& m_store;
};
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( results_collector_t )
//____________________________________________________________________________//
void
results_collector_t::test_start( counter_t, test_unit_id id )
{
// deletes the results under id only
clear_subtree_result tree_clear(s_rc_impl());
traverse_test_tree( id, tree_clear );
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_start( test_unit const& tu )
{
// init test_results entry
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.clear();
tr.p_expected_failures.value = tu.p_expected_failures;
}
//____________________________________________________________________________//
class results_collect_helper : public test_tree_visitor {
public:
explicit results_collect_helper( test_results& tr, test_unit const& ts ) : m_tr( tr ), m_ts( ts ) {}
void visit( test_case const& tc ) BOOST_OVERRIDE
{
test_results const& tr = results_collector.results( tc.p_id );
m_tr += tr;
if( tr.passed() ) {
if( tr.p_warnings_failed )
m_tr.p_test_cases_warned.value++;
else
m_tr.p_test_cases_passed.value++;
}
else if( tr.p_timed_out ) {
m_tr.p_test_cases_timed_out.value++;
}
else if( tr.p_skipped || !tc.is_enabled() ) {
m_tr.p_test_cases_skipped.value++;
}
else {
if( tr.p_aborted )
m_tr.p_test_cases_aborted.value++;
m_tr.p_test_cases_failed.value++;
}
}
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
if( m_ts.p_id == ts.p_id )
return true;
m_tr += results_collector.results( ts.p_id );
m_tr.p_test_suites.value++;
if( results_collector.results( ts.p_id ).p_timed_out )
m_tr.p_test_suites_timed_out.value++;
return false;
}
private:
// Data members
test_results& m_tr;
test_unit const& m_ts;
};
//____________________________________________________________________________//
void
results_collector_t::test_unit_finish( test_unit const& tu, unsigned long elapsed_in_microseconds )
{
test_results & tr = s_rc_impl().m_results_store[tu.p_id];
if( tu.p_type == TUT_SUITE ) {
results_collect_helper ch( tr, tu );
traverse_test_tree( tu, ch, true ); // true to ignore the status: we need to count the skipped/disabled tests
}
else {
bool num_failures_match = tr.p_aborted || tr.p_assertions_failed >= tr.p_expected_failures;
if( !num_failures_match )
BOOST_TEST_FRAMEWORK_MESSAGE( "Test case " << tu.full_name() << " has fewer failures than expected" );
bool check_any_assertions = tr.p_aborted || (tr.p_assertions_failed != 0) || (tr.p_assertions_passed != 0);
if( !check_any_assertions )
BOOST_TEST_FRAMEWORK_MESSAGE( "Test case " << tu.full_name() << " did not check any assertions" );
}
tr.p_duration_microseconds.value = elapsed_in_microseconds;
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_skipped( test_unit const& tu, const_string /*reason*/ )
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.clear();
tr.p_skipped.value = true;
if( tu.p_type == TUT_SUITE ) {
test_case_counter tcc(true);
traverse_test_tree( tu, tcc, true ); // true because need to count the disabled tests/units
tr.p_test_cases_skipped.value = tcc.p_count;
}
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_timed_out(test_unit const& tu)
{
test_results& tr = s_rc_impl().m_results_store[tu.p_id];
tr.p_timed_out.value = true;
}
//____________________________________________________________________________//
void
results_collector_t::assertion_result( unit_test::assertion_result ar )
{
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
switch( ar ) {
case AR_PASSED: tr.p_assertions_passed.value++; break;
case AR_FAILED: tr.p_assertions_failed.value++; break;
case AR_TRIGGERED: tr.p_warnings_failed.value++; break;
}
if( tr.p_assertions_failed == 1 )
first_failed_assertion();
}
//____________________________________________________________________________//
void
results_collector_t::exception_caught( execution_exception const& ex)
{
test_results& tr = s_rc_impl().m_results_store[framework::current_test_case_id()];
tr.p_assertions_failed.value++;
if( ex.code() == execution_exception::timeout_error ) {
tr.p_timed_out.value = true;
}
}
//____________________________________________________________________________//
void
results_collector_t::test_unit_aborted( test_unit const& tu )
{
s_rc_impl().m_results_store[tu.p_id].p_aborted.value = true;
}
//____________________________________________________________________________//
test_results const&
results_collector_t::results( test_unit_id id ) const
{
return s_rc_impl().m_results_store[id];
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_COLLECTOR_IPP_021105GER

View File

@@ -0,0 +1,197 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : result reporting facilities
// ***************************************************************************
#ifndef BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
#define BOOST_TEST_RESULTS_REPORTER_IPP_020105GER
// Boost.Test
#include <boost/test/results_reporter.hpp>
#include <boost/test/results_collector.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/output/plain_report_formatter.hpp>
#include <boost/test/output/xml_report_formatter.hpp>
#include <boost/test/tree/visitor.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/tree/traverse.hpp>
// Boost
#include <boost/scoped_ptr.hpp>
#include <boost/io/ios_state.hpp>
typedef ::boost::io::ios_base_all_saver io_saver_type;
// STL
#include <iostream>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace results_reporter {
// ************************************************************************** //
// ************** result reporter implementation ************** //
// ************************************************************************** //
namespace {
struct results_reporter_impl : test_tree_visitor {
// Constructor
results_reporter_impl()
: m_stream( &std::cerr )
, m_stream_state_saver( new io_saver_type( std::cerr ) )
, m_report_level( CONFIRMATION_REPORT )
, m_formatter( new output::plain_report_formatter )
{}
// test tree visitor interface implementation
void visit( test_case const& tc ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_start( tc, *m_stream );
m_formatter->test_unit_report_finish( tc, *m_stream );
}
bool test_suite_start( test_suite const& ts ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_start( ts, *m_stream );
if( m_report_level == DETAILED_REPORT && !results_collector.results( ts.p_id ).p_skipped )
return true;
m_formatter->test_unit_report_finish( ts, *m_stream );
return false;
}
void test_suite_finish( test_suite const& ts ) BOOST_OVERRIDE
{
m_formatter->test_unit_report_finish( ts, *m_stream );
}
typedef scoped_ptr<io_saver_type> saver_ptr;
// Data members
std::ostream* m_stream;
saver_ptr m_stream_state_saver;
report_level m_report_level;
scoped_ptr<format> m_formatter;
};
results_reporter_impl& s_rr_impl() { static results_reporter_impl the_inst; return the_inst; }
} // local namespace
// ************************************************************************** //
// ************** report configuration ************** //
// ************************************************************************** //
void
set_level( report_level l )
{
if( l != INV_REPORT_LEVEL )
s_rr_impl().m_report_level = l;
}
//____________________________________________________________________________//
void
set_stream( std::ostream& ostr )
{
s_rr_impl().m_stream = &ostr;
s_rr_impl().m_stream_state_saver.reset( new io_saver_type( ostr ) );
}
//____________________________________________________________________________//
std::ostream&
get_stream()
{
return *s_rr_impl().m_stream;
}
//____________________________________________________________________________//
void
set_format( output_format rf )
{
switch( rf ) {
default:
case OF_CLF:
set_format( new output::plain_report_formatter );
break;
case OF_XML:
set_format( new output::xml_report_formatter );
break;
}
}
//____________________________________________________________________________//
void
set_format( results_reporter::format* f )
{
if( f )
s_rr_impl().m_formatter.reset( f );
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** report initiation ************** //
// ************************************************************************** //
void
make_report( report_level l, test_unit_id id )
{
if( l == INV_REPORT_LEVEL )
l = s_rr_impl().m_report_level;
if( l == NO_REPORT )
return;
if( id == INV_TEST_UNIT_ID )
id = framework::master_test_suite().p_id;
s_rr_impl().m_stream_state_saver->restore();
report_level bkup = s_rr_impl().m_report_level;
s_rr_impl().m_report_level = l;
s_rr_impl().m_formatter->results_report_start( *s_rr_impl().m_stream );
switch( l ) {
case CONFIRMATION_REPORT:
s_rr_impl().m_formatter->do_confirmation_report( framework::get<test_unit>( id ), *s_rr_impl().m_stream );
break;
case SHORT_REPORT:
case DETAILED_REPORT:
traverse_test_tree( id, s_rr_impl() );
break;
default:
break;
}
s_rr_impl().m_formatter->results_report_finish( *s_rr_impl().m_stream );
s_rr_impl().m_report_level = bkup;
}
//____________________________________________________________________________//
} // namespace results_reporter
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_REPORTER_IPP_020105GER

View File

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

View File

@@ -0,0 +1,65 @@
// (C) Copyright Gennadiy Rozental 2001.
// (C) Copyright Beman Dawes 1995-2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
/// @file
/// @brief Implements main function for Test Execution Monitor.
// ***************************************************************************
#ifndef BOOST_TEST_TEST_MAIN_IPP_012205GER
#define BOOST_TEST_TEST_MAIN_IPP_012205GER
// Boost.Test
#include <boost/test/framework.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test_suite.hpp>
// Boost
#include <boost/cstdlib.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
extern int test_main( int argc, char* argv[] ); // prototype for user's test_main()
struct test_main_caller {
test_main_caller( int argc, char** argv ) : m_argc( argc ), m_argv( argv ) {}
void operator()() {
int test_main_result = test_main( m_argc, m_argv );
// translate a test_main non-success return into a test error
BOOST_CHECK( test_main_result == 0 || test_main_result == boost::exit_success );
}
private:
// Data members
int m_argc;
char** m_argv;
};
// ************************************************************************** //
// ************** test main ************** //
// ************************************************************************** //
::boost::unit_test::test_suite*
init_unit_test_suite( int argc, char* argv[] ) {
using namespace ::boost::unit_test;
framework::master_test_suite().p_name.value = "Test Program";
framework::master_test_suite().add( BOOST_TEST_CASE( test_main_caller( argc, argv ) ) );
return 0;
}
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TEST_MAIN_IPP_012205GER

View File

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

View File

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

View File

@@ -0,0 +1,787 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implemets Unit Test Log
// ***************************************************************************
#ifndef BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER
// Boost.Test
#include <boost/test/unit_test_log.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
#include <boost/test/utils/foreach.hpp>
#include <boost/test/output/compiler_log_formatter.hpp>
#include <boost/test/output/xml_log_formatter.hpp>
#include <boost/test/output/junit_log_formatter.hpp>
// Boost
#include <boost/shared_ptr.hpp>
#include <boost/io/ios_state.hpp>
typedef ::boost::io::ios_base_all_saver io_saver_type;
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** entry_value_collector ************** //
// ************************************************************************** //
namespace ut_detail {
entry_value_collector const&
entry_value_collector::operator<<( lazy_ostream const& v ) const
{
unit_test_log << v;
return *this;
}
//____________________________________________________________________________//
entry_value_collector const&
entry_value_collector::operator<<( const_string v ) const
{
unit_test_log << v;
return *this;
}
//____________________________________________________________________________//
entry_value_collector::~entry_value_collector()
{
if( m_last )
unit_test_log << log::end();
}
//____________________________________________________________________________//
} // namespace ut_detail
// ************************************************************************** //
// ************** unit_test_log ************** //
// ************************************************************************** //
namespace {
// log data
struct unit_test_log_data_helper_impl {
typedef boost::shared_ptr<unit_test_log_formatter> formatter_ptr;
typedef boost::shared_ptr<io_saver_type> saver_ptr;
bool m_enabled;
output_format m_format;
std::ostream* m_stream;
saver_ptr m_stream_state_saver;
formatter_ptr m_log_formatter;
bool m_entry_in_progress;
unit_test_log_data_helper_impl(unit_test_log_formatter* p_log_formatter, output_format format, bool enabled = false)
: m_enabled( enabled )
, m_format( format )
, m_stream( &std::cout )
, m_stream_state_saver( new io_saver_type( std::cout ) )
, m_log_formatter()
, m_entry_in_progress( false )
{
m_log_formatter.reset(p_log_formatter);
m_log_formatter->set_log_level(log_all_errors);
}
// helper functions
std::ostream& stream()
{
return *m_stream;
}
log_level get_log_level() const
{
return m_log_formatter->get_log_level();
}
};
struct unit_test_log_impl {
// Constructor
unit_test_log_impl()
{
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::compiler_log_formatter, OF_CLF, true) ); // only this one is active by default,
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::xml_log_formatter, OF_XML, false) );
m_log_formatter_data.push_back( unit_test_log_data_helper_impl(new output::junit_log_formatter, OF_JUNIT, false) );
}
typedef std::vector<unit_test_log_data_helper_impl> v_formatter_data_t;
v_formatter_data_t m_log_formatter_data;
typedef std::vector<unit_test_log_data_helper_impl*> vp_formatter_data_t;
vp_formatter_data_t m_active_log_formatter_data;
// entry data
log_entry_data m_entry_data;
bool has_entry_in_progress() const {
for( vp_formatter_data_t::const_iterator it(m_active_log_formatter_data.begin()), ite(m_active_log_formatter_data.end());
it < ite;
++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.m_entry_in_progress )
return true;
}
return false;
}
// check point data
log_checkpoint_data m_checkpoint_data;
void set_checkpoint( const_string file, std::size_t line_num, const_string msg )
{
assign_op( m_checkpoint_data.m_message, msg, 0 );
m_checkpoint_data.m_file_name = file;
m_checkpoint_data.m_line_num = line_num;
}
};
unit_test_log_impl& s_log_impl() { static unit_test_log_impl the_inst; return the_inst; }
//____________________________________________________________________________//
void
log_entry_context( log_level l, unit_test_log_data_helper_impl& current_logger_data)
{
framework::context_generator const& context = framework::get_context();
if( context.is_empty() )
return;
const_string frame;
current_logger_data.m_log_formatter->entry_context_start( current_logger_data.stream(), l );
while( !(frame=context.next()).is_empty() )
{
current_logger_data.m_log_formatter->log_entry_context( current_logger_data.stream(), l, frame );
}
current_logger_data.m_log_formatter->entry_context_finish( current_logger_data.stream(), l );
}
//____________________________________________________________________________//
void
clear_entry_context()
{
framework::clear_context();
}
// convenience
typedef unit_test_log_impl::vp_formatter_data_t vp_logger_t;
typedef unit_test_log_impl::v_formatter_data_t v_logger_t;
} // local namespace
//____________________________________________________________________________//
BOOST_TEST_SINGLETON_CONS_IMPL( unit_test_log_t )
void
unit_test_log_t::configure( )
{
// configure is not test_start:
// test_start pushes the necessary log information when the test module is starting, and implies configure.
// configure: should be called each time the set of loggers, stream or configuration is changed.
s_log_impl().m_active_log_formatter_data.clear();
for( unit_test_log_impl::v_formatter_data_t::iterator it(s_log_impl().m_log_formatter_data.begin()),
ite(s_log_impl().m_log_formatter_data.end());
it < ite;
++it)
{
if( !it->m_enabled || it->get_log_level() == log_nothing )
continue;
s_log_impl().m_active_log_formatter_data.push_back(&*it);
it->m_entry_in_progress = false;
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_start( counter_t test_cases_amount, test_unit_id )
{
configure();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.m_log_formatter->log_start( current_logger_data.stream(), test_cases_amount );
current_logger_data.m_log_formatter->log_build_info(
current_logger_data.stream(),
runtime_config::get<bool>( runtime_config::btrt_build_info ));
//current_logger_data.stream().flush();
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_finish()
{
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.m_log_formatter->log_finish( current_logger_data.stream() );
current_logger_data.stream().flush();
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_aborted()
{
BOOST_TEST_LOG_ENTRY( log_messages ) << "Test is aborted";
}
//____________________________________________________________________________//
void
unit_test_log_t::test_unit_start( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_start( current_logger_data.stream(), tu );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_unit_finish( test_unit const& tu, unsigned long elapsed )
{
s_log_impl().m_checkpoint_data.clear();
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_finish( current_logger_data.stream(), tu, elapsed );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::test_unit_skipped( test_unit const& tu, const_string reason )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_skipped( current_logger_data.stream(), tu, reason );
}
}
void
unit_test_log_t::test_unit_aborted( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_aborted(current_logger_data.stream(), tu );
}
}
void
unit_test_log_t::test_unit_timed_out( test_unit const& tu )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.get_log_level() > log_test_units )
continue;
current_logger_data.m_log_formatter->test_unit_timed_out(current_logger_data.stream(), tu );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::exception_caught( execution_exception const& ex )
{
log_level l =
ex.code() <= execution_exception::cpp_exception_error ? log_cpp_exception_errors :
(ex.code() <= execution_exception::timeout_error ? log_system_errors
: log_fatal_errors );
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( l >= current_logger_data.get_log_level() ) {
current_logger_data.m_log_formatter->log_exception_start( current_logger_data.stream(), s_log_impl().m_checkpoint_data, ex );
log_entry_context( l, current_logger_data );
current_logger_data.m_log_formatter->log_exception_finish( current_logger_data.stream() );
}
}
clear_entry_context();
}
//____________________________________________________________________________//
void
unit_test_log_t::set_checkpoint( const_string file, std::size_t line_num, const_string msg )
{
s_log_impl().set_checkpoint( file, line_num, msg );
}
//____________________________________________________________________________//
char
set_unix_slash( char in )
{
return in == '\\' ? '/' : in;
}
unit_test_log_t&
unit_test_log_t::operator<<( log::begin const& b )
{
if( s_log_impl().has_entry_in_progress() )
*this << log::end();
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
current_logger_data.m_stream_state_saver->restore();
}
s_log_impl().m_entry_data.clear();
assign_op( s_log_impl().m_entry_data.m_file_name, b.m_file_name, 0 );
// normalize file name
std::transform( s_log_impl().m_entry_data.m_file_name.begin(), s_log_impl().m_entry_data.m_file_name.end(),
s_log_impl().m_entry_data.m_file_name.begin(),
&set_unix_slash );
s_log_impl().m_entry_data.m_line_num = b.m_line_num;
return *this;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( log::end const& )
{
if( s_log_impl().has_entry_in_progress() ) {
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
log_level l = s_log_impl().m_entry_data.m_level;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( current_logger_data.m_entry_in_progress ) {
if( l >= current_logger_data.get_log_level() ) {
log_entry_context( l, current_logger_data );
}
current_logger_data.m_log_formatter->log_entry_finish( current_logger_data.stream() );
}
current_logger_data.m_entry_in_progress = false;
}
}
clear_entry_context();
return *this;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( log_level l )
{
s_log_impl().m_entry_data.m_level = l;
return *this;
}
//____________________________________________________________________________//
ut_detail::entry_value_collector
unit_test_log_t::operator()( log_level l )
{
*this << l;
return ut_detail::entry_value_collector();
}
//____________________________________________________________________________//
bool
log_entry_start(unit_test_log_data_helper_impl &current_logger_data)
{
if( current_logger_data.m_entry_in_progress )
return true;
switch( s_log_impl().m_entry_data.m_level ) {
case log_successful_tests:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_INFO );
break;
case log_messages:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_MESSAGE );
break;
case log_warnings:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_WARNING );
break;
case log_all_errors:
case log_cpp_exception_errors:
case log_system_errors:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_ERROR );
break;
case log_fatal_errors:
current_logger_data.m_log_formatter->log_entry_start( current_logger_data.stream(), s_log_impl().m_entry_data,
unit_test_log_formatter::BOOST_UTL_ET_FATAL_ERROR );
break;
case log_nothing:
case log_test_units:
case invalid_log_level:
return false;
}
current_logger_data.m_entry_in_progress = true;
return true;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( const_string value )
{
if(value.empty()) {
return *this;
}
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() )
if( log_entry_start(current_logger_data) ) {
current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
}
}
return *this;
}
//____________________________________________________________________________//
unit_test_log_t&
unit_test_log_t::operator<<( lazy_ostream const& value )
{
if(value.empty()) {
return *this;
}
vp_logger_t& vloggers = s_log_impl().m_active_log_formatter_data;
for( vp_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = **it;
if( s_log_impl().m_entry_data.m_level >= current_logger_data.get_log_level() ) {
if( log_entry_start(current_logger_data) ) {
current_logger_data.m_log_formatter->log_entry_value( current_logger_data.stream(), value );
}
}
}
return *this;
}
//____________________________________________________________________________//
void
unit_test_log_t::set_stream( std::ostream& str )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
current_logger_data.m_stream = &str;
current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) );
}
}
//____________________________________________________________________________//
void
unit_test_log_t::set_stream( output_format log_format, std::ostream& str )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
current_logger_data.m_stream = &str;
current_logger_data.m_stream_state_saver.reset( new io_saver_type( str ) );
break;
}
}
}
std::ostream*
unit_test_log_t::get_stream( output_format log_format ) const
{
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
return current_logger_data.m_stream;
}
}
return 0;
}
//____________________________________________________________________________//
log_level
unit_test_log_t::set_threshold_level( log_level lev )
{
if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level )
return invalid_log_level;
log_level ret = log_nothing;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
ret = (std::min)(ret, current_logger_data.m_log_formatter->get_log_level());
current_logger_data.m_log_formatter->set_log_level( lev );
}
return ret;
}
//____________________________________________________________________________//
log_level
unit_test_log_t::set_threshold_level( output_format log_format, log_level lev )
{
if( s_log_impl().has_entry_in_progress() || lev == invalid_log_level )
return invalid_log_level;
log_level ret = log_nothing;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
ret = current_logger_data.m_log_formatter->get_log_level();
current_logger_data.m_log_formatter->set_log_level( lev );
break;
}
}
return ret;
}
//____________________________________________________________________________//
void
unit_test_log_t::set_format( output_format log_format )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
current_logger_data.m_enabled = current_logger_data.m_format == log_format;
}
}
//____________________________________________________________________________//
void
unit_test_log_t::add_format( output_format log_format )
{
if( s_log_impl().has_entry_in_progress() )
return;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
current_logger_data.m_enabled = true;
break;
}
}
}
//____________________________________________________________________________//
unit_test_log_formatter*
unit_test_log_t::get_formatter( output_format log_format ) {
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for( v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
unit_test_log_data_helper_impl& current_logger_data = *it;
if( current_logger_data.m_format == log_format) {
return current_logger_data.m_log_formatter.get();
}
}
return 0;
}
void
unit_test_log_t::add_formatter( unit_test_log_formatter* the_formatter )
{
// remove only user defined logger
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
if( it->m_format == OF_CUSTOM_LOGGER) {
s_log_impl().m_log_formatter_data.erase(it);
break;
}
}
if( the_formatter ) {
s_log_impl().m_active_log_formatter_data.clear(); // otherwise dandling references
vloggers.push_back( unit_test_log_data_helper_impl(the_formatter, OF_CUSTOM_LOGGER, true) );
}
}
void
unit_test_log_t::set_formatter( unit_test_log_formatter* the_formatter )
{
if( s_log_impl().has_entry_in_progress() )
return;
// remove only user defined logger
log_level current_level = invalid_log_level;
std::ostream *current_stream = 0;
output_format previous_format = OF_INVALID;
v_logger_t& vloggers = s_log_impl().m_log_formatter_data;
for(v_logger_t::iterator it(vloggers.begin()), ite(vloggers.end()); it < ite; ++it)
{
if( it->m_enabled ) {
if( current_level == invalid_log_level || it->m_format < previous_format || it->m_format == OF_CUSTOM_LOGGER) {
current_level = it->get_log_level();
current_stream = &(it->stream());
previous_format = it->m_format;
}
}
}
if( the_formatter ) {
add_formatter(the_formatter);
set_format(OF_CUSTOM_LOGGER);
set_threshold_level(OF_CUSTOM_LOGGER, current_level);
set_stream(OF_CUSTOM_LOGGER, *current_stream);
}
configure();
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** unit_test_log_formatter ************** //
// ************************************************************************** //
void
unit_test_log_formatter::log_entry_value( std::ostream& ostr, lazy_ostream const& value )
{
log_entry_value( ostr, (wrap_stringstream().ref() << value).str() );
}
void
unit_test_log_formatter::set_log_level(log_level new_log_level)
{
m_log_level = new_log_level;
}
log_level
unit_test_log_formatter::get_log_level() const
{
return m_log_level;
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_LOG_IPP_012205GER

View File

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

View File

@@ -0,0 +1,78 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implements specific subclass of Executon Monitor used by Unit
// Test Framework to monitor test cases run.
// ***************************************************************************
#ifndef BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
#define BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER
// Boost.Test
#include <boost/test/unit_test_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/unit_test_parameters.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// singleton pattern
BOOST_TEST_SINGLETON_CONS_IMPL(unit_test_monitor_t)
// ************************************************************************** //
// ************** unit_test_monitor ************** //
// ************************************************************************** //
unit_test_monitor_t::error_level
unit_test_monitor_t::execute_and_translate( boost::function<void ()> const& func, unsigned long int timeout_microseconds )
{
BOOST_TEST_I_TRY {
p_catch_system_errors.value = runtime_config::get<bool>( runtime_config::btrt_catch_sys_errors );
p_timeout.value = timeout_microseconds;
p_auto_start_dbg.value = runtime_config::get<bool>( runtime_config::btrt_auto_start_dbg );
p_use_alt_stack.value = runtime_config::get<bool>( runtime_config::btrt_use_alt_stack );
p_detect_fp_exceptions.value = runtime_config::get<bool>( runtime_config::btrt_detect_fp_except );
vexecute( func );
}
BOOST_TEST_I_CATCH( execution_exception, ex ) {
framework::exception_caught( ex );
framework::test_unit_aborted( framework::current_test_unit() );
// translate execution_exception::error_code to error_level
switch( ex.code() ) {
case execution_exception::no_error: return test_ok;
case execution_exception::user_error: return unexpected_exception;
case execution_exception::cpp_exception_error: return unexpected_exception;
case execution_exception::system_error: return os_exception;
case execution_exception::timeout_error: return os_timeout;
case execution_exception::user_fatal_error:
case execution_exception::system_fatal_error: return fatal_error;
default: return unexpected_exception;
}
}
return test_ok;
}
//____________________________________________________________________________//
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_UNIT_TEST_MONITOR_IPP_012205GER

View File

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

View File

@@ -0,0 +1,225 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : implements OF_XML Log formatter
// ***************************************************************************
#ifndef BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
#define BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER
// Boost.Test
#include <boost/test/output/xml_log_formatter.hpp>
#include <boost/test/execution_monitor.hpp>
#include <boost/test/framework.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/utils/xml_printer.hpp>
// Boost
#include <boost/version.hpp>
// STL
#include <iostream>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
static const_string tu_type_name( test_unit const& tu )
{
return tu.p_type == TUT_CASE ? "TestCase" : "TestSuite";
}
// ************************************************************************** //
// ************** xml_log_formatter ************** //
// ************************************************************************** //
void
xml_log_formatter::log_start( std::ostream& ostr, counter_t )
{
ostr << "<TestLog>";
}
//____________________________________________________________________________//
void
xml_log_formatter::log_finish( std::ostream& ostr )
{
ostr << "</TestLog>";
}
//____________________________________________________________________________//
void
xml_log_formatter::log_build_info( std::ostream& ostr, bool log_build_info )
{
if( log_build_info ) {
ostr << "<BuildInfo"
<< " platform" << utils::attr_value() << BOOST_PLATFORM
<< " compiler" << utils::attr_value() << BOOST_COMPILER
<< " stl" << utils::attr_value() << BOOST_STDLIB
<< " boost=\"" << BOOST_VERSION/100000 << "."
<< BOOST_VERSION/100 % 1000 << "."
<< BOOST_VERSION % 100 << '\"'
<< "/>";
}
}
//____________________________________________________________________________//
void
xml_log_formatter::test_unit_start( std::ostream& ostr, test_unit const& tu )
{
ostr << "<" << tu_type_name( tu ) << " name" << utils::attr_value() << tu.p_name.get();
if( !tu.p_file_name.empty() )
ostr << BOOST_TEST_L( " file" ) << utils::attr_value() << tu.p_file_name
<< BOOST_TEST_L( " line" ) << utils::attr_value() << tu.p_line_num;
ostr << ">";
}
//____________________________________________________________________________//
void
xml_log_formatter::test_unit_finish( std::ostream& ostr, test_unit const& tu, unsigned long elapsed )
{
if( tu.p_type == TUT_CASE )
ostr << "<TestingTime>" << elapsed << "</TestingTime>";
ostr << "</" << tu_type_name( tu ) << ">";
}
//____________________________________________________________________________//
void
xml_log_formatter::test_unit_skipped( std::ostream& ostr, test_unit const& tu, const_string reason )
{
ostr << "<" << tu_type_name( tu )
<< " name" << utils::attr_value() << tu.p_name.get()
<< " skipped" << utils::attr_value() << "yes"
<< " reason" << utils::attr_value() << reason
<< "/>";
}
//____________________________________________________________________________//
void
xml_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
ostr << "<Exception file" << utils::attr_value() << loc.m_file_name
<< " line" << utils::attr_value() << loc.m_line_num;
if( !loc.m_function.is_empty() )
ostr << " function" << utils::attr_value() << loc.m_function;
ostr << ">" << utils::cdata() << ex.what();
if( !checkpoint_data.m_file_name.is_empty() ) {
ostr << "<LastCheckpoint file" << utils::attr_value() << checkpoint_data.m_file_name
<< " line" << utils::attr_value() << checkpoint_data.m_line_num
<< ">"
<< utils::cdata() << checkpoint_data.m_message
<< "</LastCheckpoint>";
}
}
//____________________________________________________________________________//
void
xml_log_formatter::log_exception_finish( std::ostream& ostr )
{
ostr << "</Exception>";
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_start( std::ostream& ostr, log_entry_data const& entry_data, log_entry_types let )
{
static literal_string xml_tags[] = { "Info", "Message", "Warning", "Error", "FatalError" };
m_curr_tag = xml_tags[let];
ostr << '<' << m_curr_tag
<< BOOST_TEST_L( " file" ) << utils::attr_value() << entry_data.m_file_name
<< BOOST_TEST_L( " line" ) << utils::attr_value() << entry_data.m_line_num
<< BOOST_TEST_L( "><![CDATA[" );
m_value_closed = false;
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_value( std::ostream& ostr, const_string value )
{
utils::print_escaped_cdata( ostr, value );
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_finish( std::ostream& ostr )
{
if( !m_value_closed ) {
ostr << BOOST_TEST_L( "]]>" );
m_value_closed = true;
}
ostr << BOOST_TEST_L( "</" ) << m_curr_tag << BOOST_TEST_L( ">" );
m_curr_tag.clear();
}
//____________________________________________________________________________//
void
xml_log_formatter::entry_context_start( std::ostream& ostr, log_level )
{
if( !m_value_closed ) {
ostr << BOOST_TEST_L( "]]>" );
m_value_closed = true;
}
ostr << BOOST_TEST_L( "<Context>" );
}
//____________________________________________________________________________//
void
xml_log_formatter::entry_context_finish( std::ostream& ostr, log_level )
{
ostr << BOOST_TEST_L( "</Context>" );
}
//____________________________________________________________________________//
void
xml_log_formatter::log_entry_context( std::ostream& ostr, log_level, const_string context_descr )
{
ostr << BOOST_TEST_L( "<Frame>" ) << utils::cdata() << context_descr << BOOST_TEST_L( "</Frame>" );
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_LOG_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,117 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : OF_XML report formatter
// ***************************************************************************
#ifndef BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
#define BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER
// Boost.Test
#include <boost/test/results_collector.hpp>
#include <boost/test/output/xml_report_formatter.hpp>
#include <boost/test/tree/test_unit.hpp>
#include <boost/test/utils/xml_printer.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
void
xml_report_formatter::results_report_start( std::ostream& ostr )
{
ostr << "<TestResult>";
}
//____________________________________________________________________________//
void
xml_report_formatter::results_report_finish( std::ostream& ostr )
{
ostr << "</TestResult>";
}
//____________________________________________________________________________//
void
xml_report_formatter::test_unit_report_start( test_unit const& tu, std::ostream& ostr )
{
test_results const& tr = results_collector.results( tu.p_id );
const_string descr;
if( tr.passed() )
descr = "passed";
else if( tr.p_skipped )
descr = "skipped";
else if( tr.p_timed_out )
descr = "timed-out";
else if( tr.p_aborted )
descr = "aborted";
else
descr = "failed";
ostr << '<' << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" )
<< " name" << utils::attr_value() << tu.p_name.get()
<< " result" << utils::attr_value() << descr
<< " assertions_passed" << utils::attr_value() << tr.p_assertions_passed
<< " assertions_failed" << utils::attr_value() << tr.p_assertions_failed
<< " warnings_failed" << utils::attr_value() << tr.p_warnings_failed
<< " expected_failures" << utils::attr_value() << tr.p_expected_failures
;
if( tu.p_type == TUT_SUITE ) {
ostr << " test_cases_passed" << utils::attr_value() << tr.p_test_cases_passed
<< " test_cases_passed_with_warnings" << utils::attr_value() << tr.p_test_cases_warned
<< " test_cases_failed" << utils::attr_value() << tr.p_test_cases_failed
<< " test_cases_skipped" << utils::attr_value() << tr.p_test_cases_skipped
<< " test_cases_aborted" << utils::attr_value() << tr.p_test_cases_aborted
<< " test_cases_timed_out" << utils::attr_value() << tr.p_test_cases_timed_out
<< " test_suites_timed_out"<< utils::attr_value() << tr.p_test_suites_timed_out
;
}
ostr << '>';
}
//____________________________________________________________________________//
void
xml_report_formatter::test_unit_report_finish( test_unit const& tu, std::ostream& ostr )
{
ostr << "</" << ( tu.p_type == TUT_CASE ? "TestCase" : "TestSuite" ) << '>';
}
//____________________________________________________________________________//
void
xml_report_formatter::do_confirmation_report( test_unit const& tu, std::ostream& ostr )
{
test_unit_report_start( tu, ostr );
test_unit_report_finish( tu, ostr );
}
//____________________________________________________________________________//
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_REPORT_FORMATTER_IPP_020105GER

View File

@@ -0,0 +1,21 @@
// (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 : included variant of Execution Monitor to be used independently
// ***************************************************************************
#ifndef BOOST_INCLUDED_EXECUTION_MONITOR_HPP_051410GER
#define BOOST_INCLUDED_EXECUTION_MONITOR_HPP_051410GER
#include <boost/test/impl/execution_monitor.ipp>
#include <boost/test/impl/debug.ipp>
#endif // BOOST_INCLUDED_EXECUTION_MONITOR_HPP_051410GER

View File

@@ -0,0 +1,25 @@
// (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 : included (vs. linked ) version of Program Execution Monitor
// ***************************************************************************
#ifndef BOOST_INCLUDED_PRG_EXEC_MONITOR_HPP_071894GER
#define BOOST_INCLUDED_PRG_EXEC_MONITOR_HPP_071894GER
#include <boost/test/impl/execution_monitor.ipp>
#include <boost/test/impl/debug.ipp>
#include <boost/test/impl/cpp_main.ipp>
#define BOOST_TEST_INCLUDED
#include <boost/test/prg_exec_monitor.hpp>
#endif // BOOST_INCLUDED_PRG_EXEC_MONITOR_HPP_071894GER

View File

@@ -0,0 +1,40 @@
// (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 Included (vs. linked) version of Test Execution Monitor
// ***************************************************************************
#ifndef BOOST_INCLUDED_TEST_EXEC_MONITOR_HPP_071894GER
#define BOOST_INCLUDED_TEST_EXEC_MONITOR_HPP_071894GER
#include <boost/test/impl/compiler_log_formatter.ipp>
#include <boost/test/impl/junit_log_formatter.ipp>
#include <boost/test/impl/debug.ipp>
#include <boost/test/impl/decorator.ipp>
#include <boost/test/impl/execution_monitor.ipp>
#include <boost/test/impl/framework.ipp>
#include <boost/test/impl/plain_report_formatter.ipp>
#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>
#include <boost/test/impl/unit_test_log.ipp>
#include <boost/test/impl/unit_test_main.ipp>
#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/xml_report_formatter.ipp>
#define BOOST_TEST_INCLUDED
#include <boost/test/test_exec_monitor.hpp>
#endif // BOOST_INCLUDED_TEST_EXEC_MONITOR_HPP_071894GER

View File

@@ -0,0 +1,40 @@
// (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 Included (vs. linked) version of Unit Test Framework
// ***************************************************************************
#ifndef BOOST_INCLUDED_UNIT_TEST_FRAMEWORK_HPP_071894GER
#define BOOST_INCLUDED_UNIT_TEST_FRAMEWORK_HPP_071894GER
#define BOOST_TEST_INCLUDED
#include <boost/test/impl/compiler_log_formatter.ipp>
#include <boost/test/impl/junit_log_formatter.ipp>
#include <boost/test/impl/debug.ipp>
#include <boost/test/impl/decorator.ipp>
#include <boost/test/impl/framework.ipp>
#include <boost/test/impl/execution_monitor.ipp>
#include <boost/test/impl/plain_report_formatter.ipp>
#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>
#include <boost/test/impl/unit_test_main.ipp>
#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/xml_report_formatter.ipp>
#include <boost/test/unit_test.hpp>
#endif // BOOST_INCLUDED_UNIT_TEST_FRAMEWORK_HPP_071894GER

View File

@@ -0,0 +1,16 @@
// (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
/// @deprecated
// ***************************************************************************
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/included/unit_test.hpp>" )
#include <boost/test/included/unit_test.hpp>

View File

@@ -0,0 +1,162 @@
// (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 Deprecated implementation of simple minimal testing
/// @deprecated
/// To convert to Unit Test Framework simply rewrite:
/// @code
/// #include <boost/test/minimal.hpp>
///
/// int test_main( int, char *[] )
/// {
/// ...
/// }
/// @endcode
/// as
/// @code
/// #include <boost/test/included/unit_test.hpp>
///
/// BOOST_AUTO_TEST_CASE(test_main)
/// {
/// ...
/// }
/// @endcode
// ***************************************************************************
#ifndef BOOST_TEST_MINIMAL_HPP_071894GER
#define BOOST_TEST_MINIMAL_HPP_071894GER
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/included/unit_test.hpp>" )
#if defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE( "Boost.Test minimal is deprecated. Please convert to the header only variant of Boost.Test." )
#endif
#define BOOST_CHECK(exp) \
( (exp) \
? static_cast<void>(0) \
: boost::minimal_test::report_error(#exp,__FILE__,__LINE__, BOOST_CURRENT_FUNCTION) )
#define BOOST_REQUIRE(exp) \
( (exp) \
? static_cast<void>(0) \
: boost::minimal_test::report_critical_error(#exp,__FILE__,__LINE__,BOOST_CURRENT_FUNCTION))
#define BOOST_ERROR( msg_ ) \
boost::minimal_test::report_error( (msg_),__FILE__,__LINE__, BOOST_CURRENT_FUNCTION, true )
#define BOOST_FAIL( msg_ ) \
boost::minimal_test::report_critical_error( (msg_),__FILE__,__LINE__, BOOST_CURRENT_FUNCTION, true )
//____________________________________________________________________________//
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/impl/execution_monitor.ipp>
#include <boost/test/impl/debug.ipp>
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
// Boost
#include <boost/cstdlib.hpp> // for exit codes
#include <boost/current_function.hpp> // for BOOST_CURRENT_FUNCTION
// STL
#include <iostream> // std::cerr, std::endl
#include <string> // std::string
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
int test_main( int argc, char* argv[] ); // prototype for users test_main()
namespace boost {
namespace minimal_test {
typedef boost::unit_test::const_string const_string;
inline unit_test::counter_t& errors_counter() { static unit_test::counter_t ec = 0; return ec; }
inline void
report_error( const char* msg, const char* file, int line, const_string func_name, bool is_msg = false )
{
++errors_counter();
std::cerr << file << "(" << line << "): ";
if( is_msg )
std::cerr << msg;
else
std::cerr << "test " << msg << " failed";
if( func_name != "(unknown)" )
std::cerr << " in function: '" << func_name << "'";
std::cerr << std::endl;
}
inline void
report_critical_error( const char* msg, const char* file, int line, const_string func_name, bool is_msg = false )
{
report_error( msg, file, line, func_name, is_msg );
throw boost::execution_aborted();
}
class caller {
public:
// constructor
caller( int argc, char** argv )
: m_argc( argc ), m_argv( argv ) {}
// execution monitor hook implementation
int operator()() { return test_main( m_argc, m_argv ); }
private:
// Data members
int m_argc;
char** m_argv;
}; // monitor
} // namespace minimal_test
} // namespace boost
//____________________________________________________________________________//
int BOOST_TEST_CALL_DECL main( int argc, char* argv[] )
{
using namespace boost::minimal_test;
try {
::boost::execution_monitor ex_mon;
int run_result = ex_mon.execute( caller( argc, argv ) );
BOOST_CHECK( run_result == 0 || run_result == boost::exit_success );
}
catch( boost::execution_exception const& exex ) {
if( exex.code() != boost::execution_exception::no_error )
BOOST_ERROR( (std::string( "exception \"" ) + exex.what() + "\" caught").c_str() );
std::cerr << "\n**** Testing aborted.";
}
if( boost::minimal_test::errors_counter() != 0 ) {
std::cerr << "\n**** " << errors_counter()
<< " error" << (errors_counter() > 1 ? "s" : "" ) << " detected\n";
return boost::exit_test_failure;
}
std::cout << "\n**** no errors detected\n";
return boost::exit_success;
}
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_MINIMAL_HPP_071894GER

View File

@@ -0,0 +1,73 @@
// (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 the formatter for the Human Readable Format (HRF)
// ***************************************************************************
#ifndef BOOST_TEST_COMPILER_LOG_FORMATTER_HPP_020105GER
#define BOOST_TEST_COMPILER_LOG_FORMATTER_HPP_020105GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/utils/setcolor.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
// ************************************************************************** //
// ************** compiler_log_formatter ************** //
// ************************************************************************** //
//!@brief Log formatter for the Human Readable Format (HRF) log format
class BOOST_TEST_DECL compiler_log_formatter : public unit_test_log_formatter {
public:
compiler_log_formatter() : m_color_output( false ), m_color_state() {}
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount ) BOOST_OVERRIDE;
void log_finish( std::ostream& ) BOOST_OVERRIDE;
void log_build_info( std::ostream&, bool ) BOOST_OVERRIDE;
void test_unit_start( std::ostream&, test_unit const& tu ) BOOST_OVERRIDE;
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) BOOST_OVERRIDE;
void test_unit_skipped( std::ostream&, test_unit const& tu, const_string reason ) BOOST_OVERRIDE;
void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ) BOOST_OVERRIDE;
void log_exception_finish( std::ostream& ) BOOST_OVERRIDE;
void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) BOOST_OVERRIDE;
void log_entry_value( std::ostream&, const_string value ) BOOST_OVERRIDE;
void log_entry_value( std::ostream&, lazy_ostream const& value ) BOOST_OVERRIDE;
void log_entry_finish( std::ostream& ) BOOST_OVERRIDE;
void entry_context_start( std::ostream&, log_level ) BOOST_OVERRIDE;
void log_entry_context( std::ostream&, log_level l, const_string ) BOOST_OVERRIDE;
void entry_context_finish( std::ostream&, log_level l ) BOOST_OVERRIDE;
protected:
virtual void print_prefix( std::ostream&, const_string file, std::size_t line );
// Data members
bool m_color_output;
utils::setcolor::state m_color_state;
};
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_COMPILER_LOG_FORMATTER_HPP_020105GER

View File

@@ -0,0 +1,168 @@
// (C) Copyright 2016 Raffi Enficiaud.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
///@file
///@brief Contains the definition of the Junit log formatter (OF_JUNIT)
// ***************************************************************************
#ifndef BOOST_TEST_JUNIT_LOG_FORMATTER__
#define BOOST_TEST_JUNIT_LOG_FORMATTER__
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/tree/test_unit.hpp>
//#include <boost/test/results_collector.hpp>
// STL
#include <cstddef> // std::size_t
#include <map>
#include <list>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
namespace junit_impl {
// helper for the JUnit logger
struct junit_log_helper
{
struct assertion_entry {
enum log_entry_t {
log_entry_info,
log_entry_error,
log_entry_failure
};
assertion_entry() : sealed(false)
{}
std::string logentry_message; // the message associated to the JUnit error/entry
std::string logentry_type; // the one that will get expanded in the final junit (failure, error)
std::string output; // additional information/message generated by the assertion
log_entry_t log_entry; // the type associated to the assertion (or error)
bool sealed; // indicates if the entry can accept additional information
};
std::list<std::string> system_out; // sysout: additional information
std::list<std::string> system_err; // syserr: additional information
std::string skipping_reason;
// list of failure, errors and messages (assertions message and the full log)
std::vector< assertion_entry > assertion_entries;
bool skipping;
junit_log_helper(): skipping(false)
{}
void clear() {
assertion_entries.clear();
system_out.clear();
system_err.clear();
skipping_reason.clear();
skipping = false;
}
};
}
// ************************************************************************** //
// ************** junit_log_formatter ************** //
// ************************************************************************** //
/// JUnit logger class
class junit_log_formatter : public unit_test_log_formatter {
public:
junit_log_formatter() : m_display_build_info(false)
{
// we log everything from the logger singleton point of view
// because we need to know about all the messages/commands going to the logger
// we decide what we put inside the logs internally
this->m_log_level = log_successful_tests;
m_log_level_internal = log_messages;
}
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount ) BOOST_OVERRIDE;
void log_finish( std::ostream& ) BOOST_OVERRIDE;
void log_build_info( std::ostream&, bool ) BOOST_OVERRIDE;
void test_unit_start( std::ostream&, test_unit const& tu ) BOOST_OVERRIDE;
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) BOOST_OVERRIDE;
void test_unit_skipped( std::ostream&, test_unit const& tu, const_string reason ) BOOST_OVERRIDE;
void test_unit_aborted( std::ostream& os, test_unit const& tu ) BOOST_OVERRIDE;
void test_unit_timed_out( std::ostream& os, test_unit const& tu) BOOST_OVERRIDE;
void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ) BOOST_OVERRIDE;
void log_exception_finish( std::ostream& ) BOOST_OVERRIDE;
void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) BOOST_OVERRIDE;
using unit_test_log_formatter::log_entry_value; // bring base class functions into overload set
void log_entry_value( std::ostream&, const_string value ) BOOST_OVERRIDE;
void log_entry_finish( std::ostream& ) BOOST_OVERRIDE;
void entry_context_start( std::ostream&, log_level ) BOOST_OVERRIDE;
void log_entry_context( std::ostream&, log_level, const_string ) BOOST_OVERRIDE;
void entry_context_finish( std::ostream&, log_level ) BOOST_OVERRIDE;
//! Discards changes in the log level
void set_log_level(log_level ll) BOOST_OVERRIDE
{
if(ll > log_successful_tests && ll < log_messages)
ll = log_successful_tests;
else if (ll > log_all_errors)
ll = log_all_errors;
this->m_log_level_internal = ll;
}
//! Instead of a regular stream, returns a file name corresponding to
//! the current master test suite. If the file already exists, adds an index
//! to it.
std::string get_default_stream_description() const BOOST_OVERRIDE;
private:
typedef std::map<test_unit_id, junit_impl::junit_log_helper> map_trace_t;
map_trace_t map_tests;
junit_impl::junit_log_helper runner_log_entry;
junit_impl::junit_log_helper& get_current_log_entry() {
if(list_path_to_root.empty())
return runner_log_entry;
map_trace_t::iterator it = map_tests.find(list_path_to_root.back());
return (it == map_tests.end() ? runner_log_entry : it->second);
}
std::list<test_unit_id> list_path_to_root;
bool m_display_build_info;
bool m_is_last_assertion_or_error; // true if failure, false if error
log_level m_log_level_internal;
friend class junit_result_helper;
};
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_JUNIT_LOG_FORMATTER__

View File

@@ -0,0 +1,59 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : plain report formatter implementation
// ***************************************************************************
#ifndef BOOST_TEST_PLAIN_REPORT_FORMATTER_HPP_020105GER
#define BOOST_TEST_PLAIN_REPORT_FORMATTER_HPP_020105GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/results_reporter.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
// ************************************************************************** //
// ************** plain_report_formatter ************** //
// ************************************************************************** //
class plain_report_formatter : public results_reporter::format {
public:
plain_report_formatter() : m_indent( 0 ), m_color_output( false ) {}
// Formatter interface
void results_report_start( std::ostream& ostr ) BOOST_OVERRIDE;
void results_report_finish( std::ostream& ostr ) BOOST_OVERRIDE;
void test_unit_report_start( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
void test_unit_report_finish( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
void do_confirmation_report( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
private:
// Data members
counter_t m_indent;
bool m_color_output;
};
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PLAIN_REPORT_FORMATTER_HPP_020105GER

View File

@@ -0,0 +1,72 @@
// (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 : contains OF_XML Log formatter definition
// ***************************************************************************
#ifndef BOOST_TEST_XML_LOG_FORMATTER_020105GER
#define BOOST_TEST_XML_LOG_FORMATTER_020105GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/unit_test_log_formatter.hpp>
// STL
#include <cstddef> // std::size_t
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
// ************************************************************************** //
// ************** xml_log_formatter ************** //
// ************************************************************************** //
class xml_log_formatter : public unit_test_log_formatter {
public:
// Formatter interface
void log_start( std::ostream&, counter_t test_cases_amount ) BOOST_OVERRIDE;
void log_finish( std::ostream& ) BOOST_OVERRIDE;
void log_build_info( std::ostream&, bool ) BOOST_OVERRIDE;
void test_unit_start( std::ostream&, test_unit const& tu ) BOOST_OVERRIDE;
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) BOOST_OVERRIDE;
void test_unit_skipped( std::ostream&, test_unit const& tu, const_string reason ) BOOST_OVERRIDE;
void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ) BOOST_OVERRIDE;
void log_exception_finish( std::ostream& ) BOOST_OVERRIDE;
void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) BOOST_OVERRIDE;
using unit_test_log_formatter::log_entry_value; // bring base class functions into overload set
void log_entry_value( std::ostream&, const_string value ) BOOST_OVERRIDE;
void log_entry_finish( std::ostream& ) BOOST_OVERRIDE;
void entry_context_start( std::ostream&, log_level ) BOOST_OVERRIDE;
void log_entry_context( std::ostream&, log_level, const_string ) BOOST_OVERRIDE;
void entry_context_finish( std::ostream&, log_level ) BOOST_OVERRIDE;
private:
// Data members
const_string m_curr_tag;
bool m_value_closed;
};
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_LOG_FORMATTER_020105GER

View File

@@ -0,0 +1,52 @@
// (C) Copyright Gennadiy Rozental 2001.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/test for the library home page.
//
// File : $RCSfile$
//
// Version : $Revision$
//
// Description : OF_XML report formatter implementation
// ***************************************************************************
#ifndef BOOST_TEST_XML_REPORT_FORMATTER_HPP_020105GER
#define BOOST_TEST_XML_REPORT_FORMATTER_HPP_020105GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/results_reporter.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace output {
// ************************************************************************** //
// ************** xml_report_formatter ************** //
// ************************************************************************** //
class xml_report_formatter : public results_reporter::format {
public:
// Formatter interface
void results_report_start( std::ostream& ostr ) BOOST_OVERRIDE;
void results_report_finish( std::ostream& ostr ) BOOST_OVERRIDE;
void test_unit_report_start( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
void test_unit_report_finish( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
void do_confirmation_report( test_unit const&, std::ostream& ostr ) BOOST_OVERRIDE;
};
} // namespace output
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_XML_REPORT_FORMATTER_HPP_020105GER

View File

@@ -0,0 +1,18 @@
// (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 Deprecated header.
//!@deprecated Use boost/test/tools/output_test_stream.hpp instead
// ***************************************************************************
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/tools/output_test_stream.hpp>" )
// Boost.Test
#include <boost/test/tools/output_test_stream.hpp>

View File

@@ -0,0 +1,176 @@
// (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 generators and helper macros for parameterized tests
// ***************************************************************************
#ifndef BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER
#define BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER
// Boost.Test
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/utils/string_cast.hpp>
// Boost
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/bind/bind.hpp>
#include <boost/function/function1.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
#define BOOST_PARAM_TEST_CASE( function, begin, end ) \
boost::unit_test::make_test_case( function, \
BOOST_TEST_STRINGIZE( function ), \
__FILE__, __LINE__, \
(begin), (end) ) \
/**/
#define BOOST_PARAM_CLASS_TEST_CASE( function, tc_instance, begin, end ) \
boost::unit_test::make_test_case( function, \
BOOST_TEST_STRINGIZE( function ), \
__FILE__, __LINE__, \
(tc_instance), \
(begin), (end) ) \
/**/
namespace boost {
namespace unit_test {
namespace ut_detail {
// ************************************************************************** //
// ************** param_test_case_generator ************** //
// ************************************************************************** //
template<typename ParamType, typename ParamIter>
class param_test_case_generator : public test_unit_generator {
public:
param_test_case_generator( boost::function<void (ParamType)> const& test_func,
const_string tc_name,
const_string tc_file,
std::size_t tc_line,
ParamIter par_begin,
ParamIter par_end )
: m_test_func( test_func )
, m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
, m_tc_file( tc_file )
, m_tc_line( tc_line )
, m_par_begin( par_begin )
, m_par_end( par_end )
, m_index( 0 )
{}
virtual test_unit* next() const
{
if( m_par_begin == m_par_end )
return (test_unit*)0;
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;
}
private:
// Data members
boost::function<void (ParamType)> m_test_func;
std::string m_tc_name;
const_string m_tc_file;
std::size_t m_tc_line;
mutable ParamIter m_par_begin;
ParamIter m_par_end;
mutable std::size_t m_index;
};
//____________________________________________________________________________//
template<typename UserTestCase,typename ParamType>
struct user_param_tc_method_invoker {
typedef void (UserTestCase::*test_method)( ParamType );
// Constructor
user_param_tc_method_invoker( shared_ptr<UserTestCase> inst, test_method test_method )
: m_inst( inst ), m_test_method( test_method ) {}
void operator()( ParamType p ) { ((*m_inst).*m_test_method)( p ); }
// Data members
shared_ptr<UserTestCase> m_inst;
test_method m_test_method;
};
//____________________________________________________________________________//
} // namespace ut_detail
template<typename ParamType, typename ParamIter>
inline ut_detail::param_test_case_generator<ParamType,ParamIter>
make_test_case( boost::function<void (ParamType)> const& test_func,
const_string tc_name,
const_string tc_file,
std::size_t tc_line,
ParamIter par_begin,
ParamIter par_end )
{
return ut_detail::param_test_case_generator<ParamType,ParamIter>( test_func, tc_name, tc_file, tc_line, par_begin, par_end );
}
//____________________________________________________________________________//
template<typename ParamType, typename ParamIter>
inline ut_detail::param_test_case_generator<
BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type,ParamIter>
make_test_case( void (*test_func)( ParamType ),
const_string tc_name,
const_string tc_file,
std::size_t tc_line,
ParamIter par_begin,
ParamIter par_end )
{
typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type param_value_type;
return ut_detail::param_test_case_generator<param_value_type,ParamIter>( test_func, tc_name, tc_file, tc_line, par_begin, par_end );
}
//____________________________________________________________________________//
template<typename UserTestCase,typename ParamType, typename ParamIter>
inline ut_detail::param_test_case_generator<
BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type,ParamIter>
make_test_case( void (UserTestCase::*test_method )( ParamType ),
const_string tc_name,
const_string tc_file,
std::size_t tc_line,
boost::shared_ptr<UserTestCase> const& user_test_case,
ParamIter par_begin,
ParamIter par_end )
{
typedef BOOST_DEDUCED_TYPENAME remove_const<BOOST_DEDUCED_TYPENAME remove_reference<ParamType>::type>::type param_value_type;
return ut_detail::param_test_case_generator<param_value_type,ParamIter>(
ut_detail::user_param_tc_method_invoker<UserTestCase,ParamType>( user_test_case, test_method ),
tc_name,
tc_file,
tc_line,
par_begin,
par_end );
}
//____________________________________________________________________________//
} // unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PARAMETERIZED_TEST_HPP_021102GER

View File

@@ -0,0 +1,18 @@
// (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 Deprecated header
/// @deprecated Use boost/test/tools/assertion_result.hpp instead
// ***************************************************************************
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/tools/assertion_result.hpp>" )
// Boost.Test
#include <boost/test/tools/assertion_result.hpp>

View File

@@ -0,0 +1,81 @@
// (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 Entry point for the end user into the Program Execution Monitor.
///
/// Use this header to forward declare function prg_exec_monitor_main and to automatically define a main
/// function for you. If you prefer to use your own main you are free to do so, but you need to define
/// BOOST_TEST_NO_MAIN before incuding this header. To initiate your main program body execution you
/// would use statement like this:
/// @code ::boost::prg_exec_monitor_main( &my_main, argc, argv ); @endcode
/// Also this header facilitate auto linking with the Program Execution Monitor library if this feature
/// is supported
// ***************************************************************************
#ifndef BOOST_PRG_EXEC_MONITOR_HPP_071894GER
#define BOOST_PRG_EXEC_MONITOR_HPP_071894GER
#include <boost/test/detail/config.hpp>
//____________________________________________________________________________//
// ************************************************************************** //
// ************** Auto Linking ************** //
// ************************************************************************** //
// Automatically link to the correct build variant where possible.
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_TEST_NO_LIB) && \
!defined(BOOST_TEST_SOURCE) && !defined(BOOST_TEST_INCLUDED)
# define BOOST_LIB_NAME boost_prg_exec_monitor
// If we're importing code from a dll, then tell auto_link.hpp about it:
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_TEST_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
// ************************************************************************** //
// ************** prg_exec_monitor_main ************** //
// ************************************************************************** //
namespace boost {
/// @brief Wrapper around the main function
///
/// Call this routine instead of your own main body implementation directly. This routine impements all the monitoring
/// functionality. THe monitor behavior is configurable by using the environment variable BOOST_TEST_CATCH_SYSTEM_ERRORS.
/// If set to string value "no", the monitor will not attempt to catch system errors (signals)
/// @param[in] cpp_main main function body. Should have the same signature as regular main function
/// @param[in] argc, argv command line arguments
int BOOST_TEST_DECL prg_exec_monitor_main( int (*cpp_main)( int argc, char* argv[] ), int argc, char* argv[] );
} // boost
#if defined(BOOST_TEST_DYN_LINK) && !defined(BOOST_TEST_NO_MAIN)
// ************************************************************************** //
// ************** main function for tests using dll ************** //
// ************************************************************************** //
// prototype for user's cpp_main()
int cpp_main( int argc, char* argv[] );
int BOOST_TEST_CALL_DECL
main( int argc, char* argv[] )
{
return ::boost::prg_exec_monitor_main( &cpp_main, argc, argv );
}
//____________________________________________________________________________//
#endif // BOOST_TEST_DYN_LINK && !BOOST_TEST_NO_MAIN
#endif // BOOST_PRG_EXEC_MONITOR_HPP_071894GER

View File

@@ -0,0 +1,65 @@
// (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 defines simple text based progress monitor
// ***************************************************************************
#ifndef BOOST_TEST_PROGRESS_MONITOR_HPP_020105GER
#define BOOST_TEST_PROGRESS_MONITOR_HPP_020105GER
// Boost.Test
#include <boost/test/tree/observer.hpp>
// STL
#include <iosfwd> // for std::ostream&
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
// ************************************************************************** //
// ************** progress_monitor ************** //
// ************************************************************************** //
/// 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:
/// @name Test observer interface
/// @{
void test_start( counter_t test_cases_amount, test_unit_id ) BOOST_OVERRIDE;
void test_aborted() BOOST_OVERRIDE;
void test_unit_finish( test_unit const&, unsigned long ) BOOST_OVERRIDE;
void test_unit_skipped( test_unit const&, const_string ) BOOST_OVERRIDE;
int priority() BOOST_OVERRIDE { return 4; }
/// @}
/// @name Configuration
/// @{
void set_stream( std::ostream& );
/// @}
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( progress_monitor_t )
}; // progress_monitor_t
BOOST_TEST_SINGLETON_INST( progress_monitor )
} // namespace unit_test
} // namespace boost
//____________________________________________________________________________//
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PROGRESS_MONITOR_HPP_020105GER

View File

@@ -0,0 +1,153 @@
// (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 Defines testing result collector components
///
/// Defines classes for keeping track (@ref test_results) and collecting
/// (@ref results_collector_t) the states of the test units.
// ***************************************************************************
#ifndef BOOST_TEST_RESULTS_COLLECTOR_HPP_071894GER
#define BOOST_TEST_RESULTS_COLLECTOR_HPP_071894GER
// Boost.Test
#include <boost/test/tree/observer.hpp>
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
namespace {
// ************************************************************************** //
/// First failed assertion debugger hook
///
/// This function is a placeholder where user can set a breakpoint in debugger to catch the
/// very first assertion failure in each test case
// ************************************************************************** //
inline void first_failed_assertion() {}
}
// ************************************************************************** //
/// @brief Collection of attributes constituting test unit results
///
/// This class is a collection of attributes describing a test result.
///
/// The attributes presented as public properties on
/// an instance of the class. In addition summary conclusion methods are presented to generate simple answer to pass/fail question
class BOOST_TEST_DECL test_results {
public:
test_results();
/// Type representing counter like public property
typedef BOOST_READONLY_PROPERTY( counter_t, (results_collector_t)
(test_results)
(results_collect_helper) ) counter_prop;
/// Type representing boolean like public property
typedef BOOST_READONLY_PROPERTY( bool, (results_collector_t)
(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
counter_prop p_expected_failures;
counter_prop p_test_cases_passed; //!< Number of successfull test cases
counter_prop p_test_cases_warned; //!< Number of warnings in test cases
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
/// @returns
/// - @c boost::exit_success on success,
/// - @c boost::exit_exception_failure in case test unit
/// was aborted for any reason (including uncaught exception)
/// - and @c boost::exit_test_failure otherwise
int result_code() const;
//! Combines the results of the current instance with another
//!
//! Only the counters are updated and the @c p_aborted and @c p_skipped are left unchanged.
void operator+=( test_results const& );
//! Resets the current state of the result
void clear();
};
// ************************************************************************** //
/// @brief Collects and combines the test results
///
/// This class collects and combines the results of the test unit during the execution of the
/// test tree. The results_collector_t::results() function combines the test results on a subtree
/// of the test tree.
///
/// @see boost::unit_test::test_observer
class BOOST_TEST_DECL results_collector_t : public test_observer {
public:
void test_start( counter_t, test_unit_id ) BOOST_OVERRIDE;
void test_unit_start( test_unit const& ) BOOST_OVERRIDE;
void test_unit_finish( test_unit const&, unsigned long ) BOOST_OVERRIDE;
void test_unit_skipped( test_unit const&, const_string ) BOOST_OVERRIDE;
void test_unit_aborted( test_unit const& ) BOOST_OVERRIDE;
void test_unit_timed_out( test_unit const& ) BOOST_OVERRIDE;
void assertion_result( unit_test::assertion_result ) BOOST_OVERRIDE;
void exception_caught( execution_exception const& ) BOOST_OVERRIDE;
int priority() BOOST_OVERRIDE { 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;
/// Singleton pattern
BOOST_TEST_SINGLETON_CONS( results_collector_t )
};
BOOST_TEST_SINGLETON_INST( results_collector )
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_COLLECTOR_HPP_071894GER

View File

@@ -0,0 +1,122 @@
// (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 defines testing result reporter interfaces
///
/// This file defines interfaces that are responsible for results reporting. Interface is presented in a form of
/// free standing function implemented in namespace result_reporter
// ***************************************************************************
#ifndef BOOST_TEST_RESULTS_REPORTER_HPP_021205GER
#define BOOST_TEST_RESULTS_REPORTER_HPP_021205GER
// Boost.Test
#include <boost/test/detail/global_typedef.hpp>
#include <boost/test/detail/fwd_decl.hpp>
// STL
#include <iosfwd> // for std::ostream&
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
/// Namespace for results reporter interfaces
namespace results_reporter {
// ************************************************************************** //
/// @brief Results report formatter interface
///
/// This is abstract interface for the report formatter used by results reporter routines.
/// You can define a custom formatter by implementing this interface and setting the formatter using set_format function.
/// This is usually done during test module initialization
// ************************************************************************** //
class BOOST_TEST_DECL format {
public:
// Destructor
virtual ~format() {}
virtual void results_report_start( std::ostream& ostr ) = 0;
virtual void results_report_finish( std::ostream& ostr ) = 0;
virtual void test_unit_report_start( test_unit const&, std::ostream& ostr ) = 0;
virtual void test_unit_report_finish( test_unit const&, std::ostream& ostr ) = 0;
virtual void do_confirmation_report( test_unit const&, std::ostream& ostr ) = 0;
};
// ************************************************************************** //
/// @name report configuration
// ************************************************************************** //
/// Sets reporting level
/// There are only four possible levels for results report:
/// - confirmation report (boost::unit_test::CONFIRMATION_REPORT). This report level only produces short confirmation
/// message about test module pass/fail status
/// - short report (boost::unit_test::SHORT_REPORT). This report level produces short summary report for failed/passed
/// assertions and test units.
/// - detailed report (boost::unit_test::DETAILED_REPORT). This report level produces detailed report per test unit for
/// passed/failed assertions and uncaught exceptions
/// - no report (boost::unit_test::NO_REPORT). This report level produces no results report. This is used for test modules
/// running as part of some kind of continues integration framework
/// @param[in] l report level
BOOST_TEST_DECL void set_level( report_level l );
/// Sets output stream for results reporting
/// By default std::cerr is used. Use this function to set a different stream. The framework
/// refers to the stream by reference, so you need to make sure the stream object lifetime exceeds the testing main scope.
BOOST_TEST_DECL void set_stream( std::ostream& );
/// Sets one of the predefined formats
/// The framework implements two results report formats:
/// - plain human readable format (boost::unit_test::OF_CLF)
/// - XML format (boost::unit_test::OF_XML)
/// @param[in] of one of the presefined enumeration values for output formats
BOOST_TEST_DECL void set_format( output_format of );
/// Sets custom report formatter
/// The framework takes ownership of the pointer passed as an argument. So this should be a pointer to
/// a heap allocated object
/// @param[in] f pointer to heap allocated instance of custom report formatter class
BOOST_TEST_DECL void set_format( results_reporter::format* f );
/// @brief Access to configured results reporter stream
///
/// Use this stream to report additional information abut test module execution
BOOST_TEST_DECL std::ostream& get_stream();
/// @}
// ************************************************************************** //
// ************** report initiation ************** //
// ************************************************************************** //
BOOST_TEST_DECL void make_report( report_level l = INV_REPORT_LEVEL, test_unit_id = INV_TEST_UNIT_ID );
inline void confirmation_report( test_unit_id id = INV_TEST_UNIT_ID )
{ make_report( CONFIRMATION_REPORT, id ); }
inline void short_report( test_unit_id id = INV_TEST_UNIT_ID )
{ make_report( SHORT_REPORT, id ); }
inline void detailed_report( test_unit_id id = INV_TEST_UNIT_ID )
{ make_report( DETAILED_REPORT, id ); }
} // namespace results_reporter
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_RESULTS_REPORTER_HPP_021205GER

View File

@@ -0,0 +1,17 @@
// (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 Deprecated header.
/// @deprecated Use @c boost/test/unit_test.hpp instead
// ***************************************************************************
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED( "<boost/test/unit_test.hpp>" )
#include <boost/test/unit_test.hpp>

View File

@@ -0,0 +1,53 @@
// (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 Deprecated implementation of Test Execution Monitor
///
/// To convert to Unit Test Framework simply rewrite:
/// @code
/// #include <boost/test/test_exec_monitor.hpp>
///
/// int test_main( int, char *[] )
/// {
/// ...
/// }
/// @endcode
/// as
/// @code
/// #include <boost/test/unit_test.hpp>
///
/// BOOST_AUTO_TEST_CASE(test_main)
/// {
/// ...
/// }
/// @endcode
/// and link with boost_unit_test_framework library *instead of* boost_test_exec_monitor
// ***************************************************************************
#ifndef BOOST_TEST_EXEC_MONITOR_HPP_071894GER
#define BOOST_TEST_EXEC_MONITOR_HPP_071894GER
// Boost.Test
#include <boost/test/test_tools.hpp>
//____________________________________________________________________________//
// ************************************************************************** //
// ************** Auto Linking ************** //
// ************************************************************************** //
// Automatically link to the correct build variant where possible.
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_TEST_NO_LIB) && \
!defined(BOOST_TEST_SOURCE) && !defined(BOOST_TEST_INCLUDED)
# define BOOST_LIB_NAME boost_test_exec_monitor
# include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_TEST_EXEC_MONITOR_HPP_071894GER

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:
framework_init_observer_t(): m_has_failure( false ) {}
void test_start( counter_t, test_unit_id ) BOOST_OVERRIDE;
void assertion_result( unit_test::assertion_result ) BOOST_OVERRIDE;
void exception_caught( execution_exception const& ) BOOST_OVERRIDE;
void test_aborted() BOOST_OVERRIDE;
int priority() BOOST_OVERRIDE { return 0; }
void clear();
/// Indicates if a failure has been recorded so far
bool has_failed( ) const;
private:
bool m_has_failure;
};
} // namespace unit_test
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_FRAMEWORK_INIT_OBSERVER_HPP_071894GER

View File

@@ -0,0 +1,68 @@
// (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 test tools compatibility header
///
/// This file is used to select the test tools implementation and includes all the necessary headers
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_HPP_111812GER
#define BOOST_TEST_TOOLS_HPP_111812GER
#include <boost/config.hpp>
// brings some compiler configuration like BOOST_PP_VARIADICS
#include <boost/test/detail/config.hpp>
#include <boost/preprocessor/config/config.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_MACROS) \
|| defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) \
|| defined(BOOST_NO_CXX11_DECLTYPE)
# define BOOST_TEST_MACRO_LIMITED_SUPPORT
#endif
// Boost.Test
// #define BOOST_TEST_NO_OLD_TOOLS
#if defined(BOOST_TEST_MACRO_LIMITED_SUPPORT) \
&& ( !BOOST_PP_VARIADICS \
|| !(__cplusplus >= 201103L) && defined(BOOST_NO_CXX11_VARIADIC_MACROS))
# define BOOST_TEST_NO_NEW_TOOLS
#endif
// #define BOOST_TEST_TOOLS_UNDER_DEBUGGER
// #define BOOST_TEST_TOOLS_DEBUGGABLE
#include <boost/test/tools/context.hpp>
#ifndef BOOST_TEST_NO_OLD_TOOLS
# include <boost/test/tools/old/interface.hpp>
# include <boost/test/tools/old/impl.hpp>
# include <boost/test/tools/detail/print_helper.hpp>
#endif
#ifndef BOOST_TEST_NO_NEW_TOOLS
# include <boost/test/tools/interface.hpp>
# include <boost/test/tools/assertion.hpp>
# include <boost/test/tools/fpc_op.hpp>
# include <boost/test/tools/collection_comparison_op.hpp>
# include <boost/test/tools/cstring_comparison_op.hpp>
# include <boost/test/tools/detail/fwd.hpp>
# include <boost/test/tools/detail/print_helper.hpp>
# include <boost/test/tools/detail/it_pair.hpp>
# include <boost/test/tools/detail/bitwise_manip.hpp>
# include <boost/test/tools/detail/tolerance_manip.hpp>
# include <boost/test/tools/detail/per_element_manip.hpp>
# include <boost/test/tools/detail/lexicographic_manip.hpp>
#endif
#endif // BOOST_TEST_TOOLS_HPP_111812GER

View File

@@ -0,0 +1,424 @@
// (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 Defines framework for automated assertion construction
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER
#define BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER
// Boost.Test
#include <boost/test/tools/assertion_result.hpp>
#include <boost/test/tools/detail/print_helper.hpp>
#include <boost/test/tools/detail/fwd.hpp>
// Boost
#include <boost/type.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/utility/declval.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
// STL
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#include <utility>
#endif
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
namespace assertion {
// ************************************************************************** //
// ************** assertion::operators ************** //
// ************************************************************************** //
// precedence 4: ->*, .*
// precedence 5: *, /, %
// precedence 6: +, -
// precedence 7: << , >>
// precedence 8: <, <=, > and >=
// precedence 9: == and !=
// precedence 10: bitwise AND
// precedence 11: bitwise XOR
// precedence 12: bitwise OR
// precedence 13: logical AND
// disabled
// precedence 14: logical OR
// disabled
// precedence 15: ternary conditional
// disabled
// precedence 16: = and OP= operators
// precedence 17: throw operator
// not supported
// precedence 18: comma
// not supported
namespace op {
#define BOOST_TEST_FOR_EACH_COMP_OP(action) \
action( < , LT, >=, GE ) \
action( <=, LE, > , GT ) \
action( > , GT, <=, LE ) \
action( >=, GE, < , LT ) \
action( ==, EQ, !=, NE ) \
action( !=, NE, ==, EQ ) \
/**/
//____________________________________________________________________________//
#ifndef BOOST_NO_CXX11_DECLTYPE
#define BOOST_TEST_FOR_EACH_CONST_OP(action)\
action(->*, MEMP, ->*, MEMP ) \
\
action( * , MUL , * , MUL ) \
action( / , DIV , / , DIV ) \
action( % , MOD , % , MOD ) \
\
action( + , ADD , + , ADD ) \
action( - , SUB , - , SUB ) \
\
action( <<, LSH , << , LSH ) \
action( >>, RSH , >> , RSH ) \
\
BOOST_TEST_FOR_EACH_COMP_OP(action) \
\
action( & , BAND, & , BAND ) \
action( ^ , XOR , ^ , XOR ) \
action( | , BOR , | , BOR ) \
/**/
#else
#define BOOST_TEST_FOR_EACH_CONST_OP(action)\
BOOST_TEST_FOR_EACH_COMP_OP(action) \
/**/
#endif
//____________________________________________________________________________//
#define BOOST_TEST_FOR_EACH_MUT_OP(action) \
action( = , SET , = , SET ) \
action( +=, IADD, += , IADD ) \
action( -=, ISUB, -= , ISUB ) \
action( *=, IMUL, *= , IMUL ) \
action( /=, IDIV, /= , IDIV ) \
action( %=, IMOD, %= , IMOD ) \
action(<<=, ILSH, <<=, ILSH ) \
action(>>=, IRSH, >>=, IRSH ) \
action( &=, IAND, &= , IAND ) \
action( ^=, IXOR, ^= , IXOR ) \
action( |=, IOR , |= , IOR ) \
/**/
//____________________________________________________________________________//
#ifndef BOOST_NO_CXX11_DECLTYPE
# define DEDUCE_RESULT_TYPE( oper ) \
decltype(boost::declval<Lhs>() oper boost::declval<Rhs>() ) optype; \
typedef typename boost::remove_reference<optype>::type \
/**/
#else
# define DEDUCE_RESULT_TYPE( oper ) bool
#endif
#define DEFINE_CONST_OPER_FWD_DECL( oper, name, rev, name_inverse ) \
template<typename Lhs, typename Rhs, \
typename Enabler=void> \
struct name; \
/**/
BOOST_TEST_FOR_EACH_CONST_OP( DEFINE_CONST_OPER_FWD_DECL )
#define DEFINE_CONST_OPER( oper, name, rev, name_inverse ) \
template<typename Lhs, typename Rhs, \
typename Enabler> \
struct name { \
typedef DEDUCE_RESULT_TYPE( oper ) result_type; \
typedef name_inverse<Lhs, Rhs> inverse; \
\
static result_type \
eval( Lhs const& lhs, Rhs const& rhs ) \
{ \
return lhs oper rhs; \
} \
\
template<typename PrevExprType> \
static void \
report( std::ostream& ostr, \
PrevExprType const& lhs, \
Rhs const& rhs) \
{ \
lhs.report( ostr ); \
ostr << revert() \
<< tt_detail::print_helper( rhs ); \
} \
\
static char const* forward() \
{ return " " #oper " "; } \
static char const* revert() \
{ return " " #rev " "; } \
}; \
/**/
BOOST_TEST_FOR_EACH_CONST_OP( DEFINE_CONST_OPER )
#undef DEDUCE_RESULT_TYPE
#undef DEFINE_CONST_OPER
//____________________________________________________________________________//
} // namespace op
// ************************************************************************** //
// ************** assertion::expression_base ************** //
// ************************************************************************** //
// Defines expression operators
template<typename Lhs, typename Rhs, typename OP> class binary_expr;
template<typename ExprType,typename ValType>
class expression_base {
public:
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T>
struct RhsT : remove_const<typename remove_reference<T>::type> {};
#define ADD_OP_SUPPORT( oper, name, _, _i ) \
template<typename T> \
binary_expr<ExprType,T, \
op::name<ValType,typename RhsT<T>::type> > \
operator oper( T&& rhs ) \
{ \
return binary_expr<ExprType,T, \
op::name<ValType,typename RhsT<T>::type> > \
( std::forward<ExprType>( \
*static_cast<ExprType*>(this) ), \
std::forward<T>(rhs) ); \
} \
/**/
#else
#define ADD_OP_SUPPORT( oper, name, _, _i ) \
template<typename T> \
binary_expr<ExprType,typename boost::decay<T const>::type, \
op::name<ValType,typename boost::decay<T const>::type> >\
operator oper( T const& rhs ) const \
{ \
typedef typename boost::decay<T const>::type Rhs; \
return binary_expr<ExprType,Rhs,op::name<ValType,Rhs> > \
( *static_cast<ExprType const*>(this), \
rhs ); \
} \
/**/
#endif
BOOST_TEST_FOR_EACH_CONST_OP( ADD_OP_SUPPORT )
#undef ADD_OP_SUPPORT
#ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS
// Disabled operators
template<typename T>
ExprType&
operator ||( T const& /*rhs*/ )
{
BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_OR_WITHIN_THIS_TESTING_TOOL, () );
return *static_cast<ExprType*>(this);
}
template<typename T>
ExprType&
operator &&( T const& /*rhs*/ )
{
BOOST_MPL_ASSERT_MSG(false, CANT_USE_LOGICAL_OPERATOR_AND_WITHIN_THIS_TESTING_TOOL, () );
return *static_cast<ExprType*>(this);
}
operator bool()
{
BOOST_MPL_ASSERT_MSG(false, CANT_USE_TERNARY_OPERATOR_WITHIN_THIS_TESTING_TOOL, () );
return false;
}
#endif
};
// ************************************************************************** //
// ************** assertion::value_expr ************** //
// ************************************************************************** //
// simple value expression
template<typename T>
class value_expr : public expression_base<value_expr<T>,typename remove_const<typename remove_reference<T>::type>::type> {
public:
// Public types
typedef T result_type;
// Constructor
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
value_expr( value_expr&& ve )
: m_value( std::forward<T>(ve.m_value) )
{}
explicit value_expr( T&& val )
: m_value( std::forward<T>(val) )
{}
#else
explicit value_expr( T const& val )
: m_value( val )
{}
#endif
// Specific expression interface
T const& value() const
{
return m_value;
}
void report( std::ostream& ostr ) const
{
ostr << tt_detail::print_helper( value() );
}
// Mutating operators
#define ADD_OP_SUPPORT( OPER, ID, _, _i)\
template<typename U> \
value_expr<T>& \
operator OPER( U const& rhs ) \
{ \
m_value OPER rhs; \
\
return *this; \
} \
/**/
BOOST_TEST_FOR_EACH_MUT_OP( ADD_OP_SUPPORT )
#undef ADD_OP_SUPPORT
// expression interface
assertion_result evaluate( bool no_message = false ) const
{
assertion_result res( value() );
if( no_message || res )
return res;
format_message( res.message(), value() );
return tt_detail::format_assertion_result( "", res.message().str() );
}
private:
template<typename U>
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
T m_value;
};
// ************************************************************************** //
// ************** assertion::binary_expr ************** //
// ************************************************************************** //
// binary expression
template<typename LExpr, typename Rhs, typename OP>
class binary_expr : public expression_base<binary_expr<LExpr,Rhs,OP>,typename OP::result_type> {
public:
// Public types
typedef typename OP::result_type result_type;
// Constructor
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
binary_expr( binary_expr&& be )
: m_lhs( std::forward<LExpr>(be.m_lhs) )
, m_rhs( std::forward<Rhs>(be.m_rhs) )
{}
binary_expr( LExpr&& lhs, Rhs&& rhs )
: m_lhs( std::forward<LExpr>(lhs) )
, m_rhs( std::forward<Rhs>(rhs) )
{}
#else
binary_expr( LExpr const& lhs, Rhs const& rhs )
: m_lhs( lhs )
, m_rhs( rhs )
{}
#endif
// Specific expression interface
result_type value() const
{
return OP::eval( m_lhs.value(), m_rhs );
}
void report( std::ostream& ostr ) const
{
return OP::report( ostr, m_lhs, m_rhs );
}
assertion_result evaluate( bool no_message = false ) const
{
assertion_result const expr_res( value() );
if( no_message || expr_res )
return expr_res;
wrap_stringstream buff;
report( buff.stream() );
return tt_detail::format_assertion_result( buff.stream().str(), expr_res.message() );
}
// To support custom manipulators
LExpr const& lhs() const { return m_lhs; }
Rhs const& rhs() const { return m_rhs; }
private:
// Data members
LExpr m_lhs;
Rhs m_rhs;
};
// ************************************************************************** //
// ************** assertion::seed ************** //
// ************************************************************************** //
// seed added ot the input expression to form an assertion expression
class seed {
public:
// ->* is highest precedence left to right operator
template<typename T>
value_expr<T>
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator->*( T&& v ) const
{
return value_expr<T>( std::forward<T>( v ) );
}
#else
operator->*( T const& v ) const
{
return value_expr<T>( v );
}
#endif
};
#undef BOOST_TEST_FOR_EACH_CONST_OP
} // namespace assertion
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_ASSERTION_HPP_100911GER

View File

@@ -0,0 +1,90 @@
// (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
/// Enhanced result for test predicate that include message explaining failure
// ***************************************************************************
#ifndef BOOST_TEST_PREDICATE_RESULT_HPP_012705GER
#define BOOST_TEST_PREDICATE_RESULT_HPP_012705GER
// Boost.Test
#include <boost/test/utils/class_properties.hpp>
#include <boost/test/utils/wrap_stringstream.hpp>
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
// Boost
#include <boost/shared_ptr.hpp>
#include <boost/detail/workaround.hpp>
// STL
#include <cstddef> // for std::size_t
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
// ************************************************************************** //
// ************** assertion_result ************** //
// ************************************************************************** //
//!@brief Type used for storing the result of an assertion.
class BOOST_TEST_DECL assertion_result {
//!@internal
typedef unit_test::const_string const_string;
//!@internal
struct dummy { void nonnull() {} };
//!@internal
typedef void (dummy::*safe_bool)();
public:
// Constructor
assertion_result( bool pv_ )
: p_predicate_value( pv_ )
{}
template<typename BoolConvertable>
assertion_result( BoolConvertable const& pv_ ) : p_predicate_value( !!pv_ ) {}
// Access methods
bool operator!() const { return !p_predicate_value; }
void operator=( bool pv_ ) { p_predicate_value.value = pv_; }
operator safe_bool() const { return !!p_predicate_value ? &dummy::nonnull : 0; }
// Public properties
BOOST_READONLY_PROPERTY( bool, (assertion_result) ) p_predicate_value;
// Access methods
bool has_empty_message() const { return !m_message; }
wrap_stringstream& message()
{
if( !m_message )
m_message.reset( new wrap_stringstream );
return *m_message;
}
const_string message() const { return !m_message ? const_string() : const_string( m_message->str() ); }
private:
// Data members
shared_ptr<wrap_stringstream> m_message;
};
typedef assertion_result predicate_result;
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_PREDICATE_RESULT_HPP_012705GER

View File

@@ -0,0 +1,458 @@
// (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 Collection comparison with enhanced reporting
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER
#define BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER
// Boost.Test
#include <boost/test/tools/assertion.hpp>
#include <boost/test/utils/is_forward_iterable.hpp>
#include <boost/test/utils/is_cstring.hpp>
// Boost
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
namespace assertion {
// ************************************************************************** //
// ************* selectors for specialized comparizon routines ************** //
// ************************************************************************** //
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<> \
struct specialized_compare<Col> : public mpl::true_ {}; \
}}} \
/**/
// ************************************************************************** //
// ************** lexicographic_compare ************** //
// ************************************************************************** //
namespace op {
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,
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
assertion_result ar( true );
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);
if( !can_be_equal && element_ar )
return ar; // a < b
assertion_result const& reverse_ar = OP::eval(*first2, *first1);
if( element_ar && !reverse_ar )
return ar; // a<=b and !(b<=a) => a < b => return true
if( element_ar || !reverse_ar ) {
continue; // (a<=b and b<=a) or (!(a<b) and !(b<a)) => a == b => keep looking
}
// !(a<=b) and b<=a => b < a => return false
ar = false;
ar.message() << "\nFailure at position " << pos << ":";
ar.message() << "\n - condition [" << tt_detail::print_helper(*first1) << OP::forward() << tt_detail::print_helper(*first2) << "] is false";
if(!element_ar.has_empty_message())
ar.message() << ": " << element_ar.message();
ar.message() << "\n - inverse condition [" << tt_detail::print_helper(*first2) << OP::forward() << tt_detail::print_helper(*first1) << "] is true";
if(!reverse_ar.has_empty_message())
ar.message() << ": " << reverse_ar.message();
return ar;
}
if( first1 != last1 ) {
if( prefer_shorter ) {
ar = false;
ar.message() << "\nFirst collection has extra trailing elements.";
}
}
else if( first2 != last2 ) {
if( !prefer_shorter ) {
ar = false;
ar.message() << "\nSecond collection has extra trailing elements.";
}
}
else if( !can_be_equal ) {
ar = false;
ar.message() << "\nCollections appear to be equal.";
}
return ar;
}
template <typename OP, bool can_be_equal, bool prefer_shorter,
typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
(unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
assertion_result>::type
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
typedef typename unit_test::deduce_cstring_transform<Lhs>::type lhs_char_type;
typedef typename unit_test::deduce_cstring_transform<Rhs>::type rhs_char_type;
return lexicographic_compare<OP, can_be_equal, prefer_shorter>(
lhs_char_type(lhs),
rhs_char_type(rhs));
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** equality_compare ************** //
// ************************************************************************** //
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,
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( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) ) {
ar = false;
ar.message() << "\nCollections size mismatch: " << t_Lhs_iterator::size(lhs) << " != " << t_Rhs_iterator::size(rhs);
return ar;
}
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 < t_Lhs_iterator::size(lhs); ++left, ++right, ++pos ) {
assertion_result const element_ar = OP::eval( *left, *right );
if( element_ar )
continue;
ar = false;
ar.message() << "\n - mismatch at position " << pos << ": ["
<< tt_detail::print_helper(*left)
<< OP::forward()
<< tt_detail::print_helper(*right)
<< "] is false";
if(!element_ar.has_empty_message())
ar.message() << ": " << element_ar.message();
}
return ar;
}
// In case string comparison is branching here
template <typename OP, typename Lhs, typename Rhs>
inline
typename boost::enable_if_c<
(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_transform<Lhs>::type lhs_char_type;
typedef typename unit_test::deduce_cstring_transform<Rhs>::type rhs_char_type;
return element_compare<OP>(lhs_char_type(lhs),
rhs_char_type(rhs));
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** non_equality_compare ************** //
// ************************************************************************** //
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( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) )
return ar;
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 ) )
return ar;
}
ar = false;
ar.message() << "\nCollections appear to be equal";
return ar;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** cctraits ************** //
// ************************************************************************** //
// set of collection comparison traits per comparison OP
template<typename OP>
struct cctraits;
template<typename Lhs, typename Rhs>
struct cctraits<op::EQ<Lhs, Rhs> > {
typedef specialized_compare<Lhs> is_specialized;
};
template<typename Lhs, typename Rhs>
struct cctraits<op::NE<Lhs, Rhs> > {
typedef specialized_compare<Lhs> is_specialized;
};
template<typename Lhs, typename Rhs>
struct cctraits<op::LT<Lhs, Rhs> > {
static const bool can_be_equal = false;
static const bool prefer_short = true;
typedef specialized_compare<Lhs> is_specialized;
};
template<typename Lhs, typename Rhs>
struct cctraits<op::LE<Lhs, Rhs> > {
static const bool can_be_equal = true;
static const bool prefer_short = true;
typedef specialized_compare<Lhs> is_specialized;
};
template<typename Lhs, typename Rhs>
struct cctraits<op::GT<Lhs, Rhs> > {
static const bool can_be_equal = false;
static const bool prefer_short = false;
typedef specialized_compare<Lhs> is_specialized;
};
template<typename Lhs, typename Rhs>
struct cctraits<op::GE<Lhs, Rhs> > {
static const bool can_be_equal = true;
static const bool prefer_short = false;
typedef specialized_compare<Lhs> is_specialized;
};
// ************************************************************************** //
// ************** compare_collections ************** //
// ************************************************************************** //
// Overloaded set of functions dispatching to specific implementation of comparison
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::EQ<L, R> >*, mpl::true_ )
{
return assertion::op::element_compare<op::EQ<L, R> >( lhs, rhs );
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::EQ<L, R> >*, mpl::false_ )
{
return lhs == rhs;
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::NE<L, R> >*, mpl::true_ )
{
return assertion::op::non_equality_compare<op::NE<L, R> >( lhs, rhs );
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::NE<L, R> >*, mpl::false_ )
{
return lhs != rhs;
}
//____________________________________________________________________________//
template <typename OP, typename Lhs, typename Rhs>
inline assertion_result
lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
{
return assertion::op::lexicographic_compare<OP, cctraits<OP>::can_be_equal, cctraits<OP>::prefer_short>( lhs, rhs );
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename OP>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<OP>*, mpl::true_ )
{
return lexicographic_compare<OP>( lhs, rhs );
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LT<L, R> >*, mpl::false_ )
{
return lhs < rhs;
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LE<L, R> >*, mpl::false_ )
{
return lhs <= rhs;
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GT<L, R> >*, mpl::false_ )
{
return lhs > rhs;
}
//____________________________________________________________________________//
template <typename Lhs, typename Rhs, typename L, typename R>
inline assertion_result
compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*, mpl::false_ )
{
return lhs >= rhs;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ********* specialization of comparison operators for collections ********* //
// ************************************************************************** //
#define DEFINE_COLLECTION_COMPARISON( oper, name, rev, name_inverse ) \
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_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 name_inverse<Lhs, Rhs> inverse; \
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< \
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) \
{ \
return assertion::op::compare_collections( lhs, rhs, \
(boost::type<elem_op>*)0, \
is_specialized() ); \
} \
\
template<typename PrevExprType> \
static void \
report( std::ostream&, \
PrevExprType const&, \
Rhs const& ) {} \
\
static char const* forward() \
{ return " " #oper " "; } \
static char const* revert() \
{ return " " #rev " "; } \
\
}; \
/**/
BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_COLLECTION_COMPARISON )
#undef DEFINE_COLLECTION_COMPARISON
//____________________________________________________________________________//
} // namespace op
} // namespace assertion
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER

View File

@@ -0,0 +1,96 @@
// (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: 74248 $
//
// Description : test tools context interfaces
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_CONTEXT_HPP_111712GER
#define BOOST_TEST_TOOLS_CONTEXT_HPP_111712GER
// 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>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
namespace tt_detail {
// ************************************************************************** //
// ************** context_frame ************** //
// ************************************************************************** //
struct BOOST_TEST_DECL context_frame {
explicit context_frame( ::boost::unit_test::lazy_ostream const& context_descr );
~context_frame();
operator bool();
private:
// Data members
int m_frame_id;
};
//____________________________________________________________________________//
#define BOOST_TEST_INFO( context_descr ) \
::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_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
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_CONTEXT_HPP_111712GER

View File

@@ -0,0 +1,91 @@
// (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 C string comparison with enhanced reporting
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_CSTRING_COMPARISON_OP_HPP_050815GER
#define BOOST_TEST_TOOLS_CSTRING_COMPARISON_OP_HPP_050815GER
// Boost.Test
#include <boost/test/tools/assertion.hpp>
#include <boost/test/utils/is_cstring.hpp>
#include <boost/test/utils/basic_cstring/compare.hpp>
// Boost
#include <boost/utility/enable_if.hpp>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
namespace assertion {
namespace op {
// ************************************************************************** //
// ************** string_compare ************** //
// ************************************************************************** //
#define DEFINE_CSTRING_COMPARISON( oper, name, rev, name_inverse ) \
template<typename Lhs,typename Rhs> \
struct name<Lhs,Rhs,typename boost::enable_if_c< \
( unit_test::is_cstring_comparable<Lhs>::value \
&& unit_test::is_cstring_comparable<Rhs>::value) \
>::type > \
{ \
typedef typename unit_test::deduce_cstring_transform<Lhs>::type lhs_char_type; \
typedef typename unit_test::deduce_cstring_transform<Rhs>::type rhs_char_type; \
public: \
typedef assertion_result result_type; \
typedef name_inverse<Lhs, Rhs> inverse; \
\
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 lhs_char_type(lhs) oper rhs_char_type(rhs); \
} \
\
template<typename PrevExprType> \
static void \
report( std::ostream& ostr, \
PrevExprType const& lhs, \
Rhs const& rhs) \
{ \
lhs.report( ostr ); \
ostr << revert() \
<< tt_detail::print_helper( rhs ); \
} \
\
static char const* forward() \
{ return " " #oper " "; } \
static char const* revert() \
{ return " " #rev " "; } \
}; \
/**/
BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_CSTRING_COMPARISON )
#undef DEFINE_CSTRING_COMPARISON
//____________________________________________________________________________//
} // namespace op
} // namespace assertion
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_CSTRING_COMPARISON_OP_HPP_050815GER

View File

@@ -0,0 +1,129 @@
// (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
//! Bitwise comparison manipulator implementation
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_DETAIL_BITWISE_MANIP_HPP_012705GER
#define BOOST_TEST_TOOLS_DETAIL_BITWISE_MANIP_HPP_012705GER
// Boost Test
#include <boost/test/tools/detail/fwd.hpp>
#include <boost/test/tools/detail/indirections.hpp>
#include <boost/test/tools/assertion_result.hpp>
#include <boost/test/tools/assertion.hpp>
// STL
#include <climits> // for CHAR_BIT
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
// ************************************************************************** //
// ************** bitwise comparison manipulator ************** //
// ************************************************************************** //
//! Bitwise comparison manipulator
//! This is a terminal for the expression
struct bitwise {};
//____________________________________________________________________________//
inline unit_test::lazy_ostream &
operator<<( unit_test::lazy_ostream &o, bitwise ) { return o; }
// needed for the lazy evaluation in lazy_ostream as bitwise is a terminal
inline std::ostream&
operator<<( std::ostream& o, bitwise ) { return o; }
//____________________________________________________________________________//
namespace tt_detail {
/*!@brief Bitwise comparison of two operands
*
* This class constructs an @ref assertion_result that contains precise bit comparison information.
* In particular the location of the mismatches (if any) are printed in the assertion result.
*/
template<typename Lhs, typename Rhs, typename E>
inline assertion_result
bitwise_compare(Lhs const& lhs, Rhs const& rhs, E const& expr )
{
assertion_result pr( true );
std::size_t left_bit_size = sizeof(Lhs)*CHAR_BIT;
std::size_t right_bit_size = sizeof(Rhs)*CHAR_BIT;
static Lhs const leftOne( 1 );
static Rhs const rightOne( 1 );
std::size_t total_bits = left_bit_size < right_bit_size ? left_bit_size : right_bit_size;
for( std::size_t counter = 0; counter < total_bits; ++counter ) {
if( (lhs & ( leftOne << counter )) != (rhs & (rightOne << counter)) ) {
if( pr ) {
pr.message() << " [";
expr.report( pr.message().stream() );
pr.message() << "]. Bitwise comparison failed";
pr = false;
}
pr.message() << "\nMismatch at position " << counter;
}
}
if( left_bit_size != right_bit_size ) {
if( pr ) {
pr.message() << " [";
expr.report( pr.message().stream() );
pr.message() << "]. Bitwise comparison failed";
pr = false;
}
pr.message() << "\nOperands bit sizes mismatch: " << left_bit_size << " != " << right_bit_size;
}
return pr;
}
//____________________________________________________________________________//
//! Returns an assertion_result using the bitwise comparison out of an expression
//!
//! This is used as a modifer of the normal operator<< on expressions to use the
//! bitwise comparison.
//!
//! @note Available only for compilers supporting the @c auto declaration.
template<typename T1, typename T2, typename T3, typename T4>
inline assertion_result
operator<<(assertion_evaluate_t<assertion::binary_expr<T1,T2,assertion::op::EQ<T3,T4> > > const& ae, bitwise )
{
return bitwise_compare( ae.m_e.lhs().value(), ae.m_e.rhs(), ae.m_e );
}
//____________________________________________________________________________//
inline assertion_type
operator<<( assertion_type const& , bitwise )
{
return assertion_type(CHECK_BUILT_ASSERTION);
}
//____________________________________________________________________________//
} // namespace tt_detail
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_DETAIL_BITWISE_MANIP_HPP_012705GER

View File

@@ -0,0 +1,121 @@
// (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: 74248 $
//
// Description : toolbox implementation types and forward declarations
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_DETAIL_FWD_HPP_012705GER
#define BOOST_TEST_TOOLS_DETAIL_FWD_HPP_012705GER
// Boost.Test
#include <boost/test/detail/config.hpp>
#include <boost/test/utils/basic_cstring/io.hpp>
// STL
#include <cstddef> // for std::size_t
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace unit_test {
class lazy_ostream;
} // namespace unit_test
namespace test_tools {
using unit_test::const_string;
class assertion_result;
//____________________________________________________________________________//
namespace tt_detail {
inline bool dummy_cond() { return false; }
// ************************************************************************** //
// ************** types of supported assertions ************** //
// ************************************************************************** //
//____________________________________________________________________________//
enum check_type {
CHECK_PRED,
CHECK_MSG,
CHECK_EQUAL,
CHECK_NE,
CHECK_LT,
CHECK_LE,
CHECK_GT,
CHECK_GE,
CHECK_CLOSE,
CHECK_CLOSE_FRACTION,
CHECK_SMALL,
CHECK_BITWISE_EQUAL,
CHECK_PRED_WITH_ARGS,
CHECK_EQUAL_COLL,
CHECK_BUILT_ASSERTION
};
//____________________________________________________________________________//
// ************************************************************************** //
// ************** levels of supported assertions ************** //
// ************************************************************************** //
enum tool_level {
WARN, CHECK, REQUIRE, PASS
};
//____________________________________________________________________________//
// ************************************************************************** //
// ************** Tools offline implementation ************** //
// ************************************************************************** //
BOOST_TEST_DECL bool
report_assertion( assertion_result const& pr, unit_test::lazy_ostream const& assertion_descr,
const_string file_name, std::size_t line_num,
tool_level tl, check_type ct,
std::size_t num_args, ... );
//____________________________________________________________________________//
BOOST_TEST_DECL assertion_result
format_assertion_result( const_string expr_val, const_string details );
//____________________________________________________________________________//
BOOST_TEST_DECL assertion_result
format_fpc_report( const_string expr_val, const_string details );
//____________________________________________________________________________//
BOOST_TEST_DECL bool
is_defined_impl( const_string symbol_name, const_string symbol_value );
//____________________________________________________________________________//
BOOST_TEST_DECL assertion_result
equal_impl( char const* left, char const* right );
//____________________________________________________________________________//
} // namespace tt_detail
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_DETAIL_FWD_HPP_012705GER

View File

@@ -0,0 +1,125 @@
// (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: 74248 $
//
// Description : inidiration interfaces to support manipulators and message output
// ***************************************************************************
#ifndef BOOST_TEST_TOOLS_DETAIL_INDIRECTIONS_HPP_112812GER
#define BOOST_TEST_TOOLS_DETAIL_INDIRECTIONS_HPP_112812GER
// Boost.Test
#include <boost/test/tools/detail/fwd.hpp>
#include <boost/test/tools/assertion_result.hpp>
#include <boost/test/utils/lazy_ostream.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
#include <boost/test/detail/suppress_warnings.hpp>
//____________________________________________________________________________//
namespace boost {
namespace test_tools {
namespace tt_detail {
struct assertion_evaluation_context
{
assertion_evaluation_context(bool has_report = false)
: m_has_report(has_report)
{}
bool m_has_report;
};
// ************************************************************************** //
// ************** assertion_evaluate indirection ************** //
// ************************************************************************** //
template<typename E>
struct assertion_evaluate_t {
typedef shared_ptr<assertion_evaluation_context> context_holder;
assertion_evaluate_t( E const& e ) : m_e( e ), m_evaluate( true )
{}
operator assertion_result() { return m_e.evaluate( m_evaluate ); }
assertion_evaluate_t<E>
stack_context(context_holder context) const {
assertion_evaluate_t<E> added_context(*this);
added_context.m_context_holder.push_back(context);
added_context.m_evaluate = !context->m_has_report;
return added_context;
}
E const& m_e;
std::list< context_holder > m_context_holder;
bool m_evaluate;
};
//____________________________________________________________________________//
template<typename E>
inline assertion_evaluate_t<E>
assertion_evaluate( E const& e ) { return assertion_evaluate_t<E>( e ); }
//____________________________________________________________________________//
template<typename E, typename T>
inline assertion_evaluate_t<E>
operator<<( assertion_evaluate_t<E> const& ae, T const& ) { return ae; }
//____________________________________________________________________________//
// ************************************************************************** //
// ************** assertion_text indirection ************** //
// ************************************************************************** //
inline unit_test::lazy_ostream const&
assertion_text( unit_test::lazy_ostream const& et, unit_test::lazy_ostream const& s) {
if(!s.empty())
return s;
return et;
}
//____________________________________________________________________________//
// ************************************************************************** //
// ************** assertion_evaluate indirection ************** //
// ************************************************************************** //
struct assertion_type {
assertion_type(check_type ct = CHECK_MSG) : m_check_type(ct)
{}
operator check_type() { return m_check_type; }
check_type m_check_type;
};
//____________________________________________________________________________//
template<typename T>
inline assertion_type
operator<<( assertion_type const& at, T const& ) { return at; }
//____________________________________________________________________________//
} // namespace tt_detail
} // namespace test_tools
} // namespace boost
#include <boost/test/detail/enable_warnings.hpp>
#endif // BOOST_TEST_TOOLS_DETAIL_INDIRECTIONS_HPP_112812GER

Some files were not shown because too many files have changed in this diff Show More