1 // (C) Copyright Gennadiy Rozental 2001.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
6 // See http://www.boost.org/libs/test for the library home page.
9 //!@brief test case family based on data generator
10 // ***************************************************************************
12 #ifndef BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
13 #define BOOST_TEST_DATA_TEST_CASE_HPP_102211GER
16 #include <boost/test/data/config.hpp>
17 #include <boost/test/data/dataset.hpp>
18 #include <boost/test/data/for_each_sample.hpp>
19 #include <boost/test/tree/test_unit.hpp>
22 #include <boost/preprocessor/repetition/enum_params.hpp>
23 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
24 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
26 #include <boost/preprocessor/variadic/to_seq.hpp>
27 #include <boost/preprocessor/variadic/size.hpp>
28 #include <boost/preprocessor/cat.hpp>
29 #include <boost/preprocessor/seq/for_each_i.hpp>
30 #include <boost/preprocessor/seq/for_each.hpp>
31 #include <boost/preprocessor/seq/enum.hpp>
32 #include <boost/preprocessor/control/iif.hpp>
33 #include <boost/preprocessor/comparison/equal.hpp>
35 #include <boost/bind.hpp>
36 #include <boost/type_traits/is_copy_constructible.hpp>
38 #include <boost/test/tools/detail/print_helper.hpp>
39 #include <boost/test/utils/string_cast.hpp>
44 #include <boost/test/detail/suppress_warnings.hpp>
46 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
47 && !defined(BOOST_TEST_DATASET_MAX_ARITY)
48 # define BOOST_TEST_DATASET_MAX_ARITY 10
51 //____________________________________________________________________________//
59 // ************************************************************************** //
60 // ************** seed ************** //
61 // ************************************************************************** //
64 template<typename DataSet>
65 typename data::result_of::make<DataSet>::type
66 operator->*( DataSet&& ds ) const
68 return data::make( std::forward<DataSet>( ds ) );
73 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
74 !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
75 !defined(BOOST_NO_CXX11_DECLTYPE) && \
76 !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
77 !defined(BOOST_NO_CXX11_SMART_PTR)
79 #define BOOST_TEST_DATASET_VARIADIC
81 struct parameter_holder {
82 std::shared_ptr<T> value;
84 parameter_holder(T && value_)
85 : value(std::make_shared<T>(std::move(value_)))
88 operator T const&() const {
94 parameter_holder<typename std::remove_reference<T>::type>
95 boost_bind_rvalue_holder_helper_impl(T&& value, boost::false_type /* is copy constructible */) {
96 return parameter_holder<typename std::remove_reference<T>::type>(std::forward<T>(value));
100 T&& boost_bind_rvalue_holder_helper_impl(T&& value, boost::true_type /* is copy constructible */) {
101 return std::forward<T>(value);
105 auto boost_bind_rvalue_holder_helper(T&& value)
106 -> decltype(boost_bind_rvalue_holder_helper_impl(
107 std::forward<T>(value),
108 typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type()))
110 // need to use boost::is_copy_constructible because std::is_copy_constructible is broken on MSVC12
111 return boost_bind_rvalue_holder_helper_impl(
112 std::forward<T>(value),
113 typename boost::is_copy_constructible<typename std::remove_reference<T>::type>::type());
119 // ************************************************************************** //
120 // ************** test_case_gen ************** //
121 // ************************************************************************** //
123 template<typename TestCase,typename DataSet>
124 class test_case_gen : public test_unit_generator {
127 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
128 test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
129 : m_dataset( std::forward<DataSet>( ds ) )
130 , m_generated( false )
131 , m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
132 , m_tc_file( tc_file )
133 , m_tc_line( tc_line )
136 test_case_gen( test_case_gen&& gen )
137 : m_dataset( std::move( gen.m_dataset ) )
138 , m_generated( gen.m_generated )
139 , m_tc_name( gen.m_tc_name )
140 , m_tc_file( gen.m_tc_file )
141 , m_tc_line( gen.m_tc_line )
142 , m_tc_index( gen.m_tc_index )
143 , m_test_cases( std::move(gen.m_test_cases) )
146 test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
148 , m_generated( false )
149 , m_tc_name( ut_detail::normalize_test_case_name( tc_name ) )
150 , m_tc_file( tc_file )
151 , m_tc_line( tc_line )
157 virtual test_unit* next() const
160 data::for_each_sample( m_dataset, *this );
164 if( m_test_cases.empty() )
167 test_unit* res = m_test_cases.front();
168 m_test_cases.pop_front();
174 #if !defined(BOOST_TEST_DATASET_VARIADIC)
175 // see BOOST_TEST_DATASET_MAX_ARITY to increase the default supported arity
176 // there is also a limit on boost::bind
177 #define TC_MAKE(z,arity,_) \
178 template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
179 void operator()( BOOST_PP_ENUM_BINARY_PARAMS(arity, Arg, const& arg) ) const \
181 m_test_cases.push_back( new test_case( genTestCaseName(), m_tc_file, m_tc_line, \
182 boost::bind( &TestCase::template test_method<BOOST_PP_ENUM_PARAMS(arity,Arg)>,\
183 BOOST_PP_ENUM_PARAMS(arity, arg) ) ) ); \
186 BOOST_PP_REPEAT_FROM_TO(1, BOOST_TEST_DATASET_MAX_ARITY, TC_MAKE, _)
188 template<typename ...Arg>
189 void operator()(Arg&& ... arg) const
191 m_test_cases.push_back(
192 new test_case( genTestCaseName(),
195 std::bind( &TestCase::template test_method<Arg...>,
196 boost_bind_rvalue_holder_helper(std::forward<Arg>(arg))...)));
201 std::string genTestCaseName() const
203 return "_" + utils::string_cast(m_tc_index++);
208 mutable bool m_generated;
209 std::string m_tc_name;
210 const_string m_tc_file;
211 std::size_t m_tc_line;
212 mutable std::size_t m_tc_index;
213 mutable std::list<test_unit*> m_test_cases;
216 //____________________________________________________________________________//
218 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
219 template<typename TestCase,typename DataSet>
220 boost::shared_ptr<test_unit_generator> //test_case_gen<TestCase,DataSet>
221 make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet&& ds )
223 return boost::shared_ptr<test_unit_generator>(new test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, std::forward<DataSet>(ds) ));
226 template<typename TestCase,typename DataSet>
227 test_case_gen<TestCase,DataSet>
228 make_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line, DataSet const& ds )
230 return test_case_gen<TestCase,DataSet>( tc_name, tc_file, tc_line, ds );
234 //____________________________________________________________________________//
236 } // namespace ds_detail
238 // ************************************************************************** //
239 // ************** BOOST_DATA_TEST_CASE ************** //
240 // ************************************************************************** //
242 #define BOOST_DATA_TEST_CASE_PARAM(r, _, i, param) (BOOST_PP_CAT(Arg, i) const& param)
243 #define BOOST_DATA_TEST_CONTEXT(r, _, param) << BOOST_STRINGIZE(param) << " = " << boost::test_tools::tt_detail::print_helper(param) << "; "
245 #define BOOST_DATA_TEST_CASE_PARAMS( params ) \
247 BOOST_PP_SEQ_FOR_EACH_I(BOOST_DATA_TEST_CASE_PARAM, _, params)) \
250 #define BOOST_DATA_TEST_CASE_IMPL(arity, F, test_name, dataset, params) \
251 struct BOOST_PP_CAT(test_name, case) : public F { \
252 template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
253 static void test_method( BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
255 BOOST_TEST_CONTEXT( "" \
256 BOOST_PP_SEQ_FOR_EACH(BOOST_DATA_TEST_CONTEXT, _, params)) \
258 BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture ctor");\
259 BOOST_PP_CAT(test_name, case) t; \
260 BOOST_TEST_CHECKPOINT('"' \
261 << #test_name << "\" fixture setup"); \
262 boost::unit_test::setup_conditional(t); \
263 BOOST_TEST_CHECKPOINT('"' << #test_name << "\" test entry"); \
264 t._impl(BOOST_PP_SEQ_ENUM(params)); \
265 BOOST_TEST_CHECKPOINT('"' \
266 << #test_name << "\" fixture teardown"); \
267 boost::unit_test::teardown_conditional(t); \
268 BOOST_TEST_CHECKPOINT('"' << #test_name << "\" fixture dtor");\
272 template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
273 void _impl(BOOST_DATA_TEST_CASE_PARAMS( params )); \
276 BOOST_AUTO_TEST_SUITE( test_name, \
277 *boost::unit_test::decorator::stack_decorator()) \
279 BOOST_AUTO_TU_REGISTRAR( BOOST_PP_CAT(test_name, case) )( \
280 boost::unit_test::data::ds_detail::make_test_case_gen< \
281 BOOST_PP_CAT(test_name, case)>( \
282 BOOST_STRINGIZE( test_name ), \
283 __FILE__, __LINE__, \
284 boost::unit_test::data::ds_detail::seed{} ->* dataset ), \
285 boost::unit_test::decorator::collector_t::instance() ); \
287 BOOST_AUTO_TEST_SUITE_END() \
289 template<BOOST_PP_ENUM_PARAMS(arity, typename Arg)> \
290 void BOOST_PP_CAT(test_name, case)::_impl( \
291 BOOST_DATA_TEST_CASE_PARAMS( params ) ) \
294 #define BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, ... ) \
295 BOOST_DATA_TEST_CASE_IMPL( BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
296 F, test_name, dataset, \
297 BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
299 #define BOOST_DATA_TEST_CASE_NO_PARAMS( F, test_name, dataset ) \
300 BOOST_DATA_TEST_CASE_WITH_PARAMS( F, test_name, dataset, sample ) \
303 #if BOOST_PP_VARIADICS_MSVC
305 #define BOOST_DATA_TEST_CASE( ... ) \
307 BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
308 BOOST_DATA_TEST_CASE_NO_PARAMS, \
309 BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
310 BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__), ) \
313 #define BOOST_DATA_TEST_CASE_F( F, ... ) \
315 BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
316 BOOST_DATA_TEST_CASE_NO_PARAMS, \
317 BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
323 #define BOOST_DATA_TEST_CASE( ... ) \
324 BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
325 BOOST_DATA_TEST_CASE_NO_PARAMS, \
326 BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
327 BOOST_AUTO_TEST_CASE_FIXTURE, __VA_ARGS__) \
330 #define BOOST_DATA_TEST_CASE_F( F, ... ) \
331 BOOST_PP_IIF(BOOST_PP_EQUAL(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),2), \
332 BOOST_DATA_TEST_CASE_NO_PARAMS, \
333 BOOST_DATA_TEST_CASE_WITH_PARAMS) ( \
339 } // namespace unit_test
342 #include <boost/test/detail/enable_warnings.hpp>
344 #endif // BOOST_TEST_DATA_TEST_CASE_HPP_102211GER