123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- // (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
|