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)
5
6// See http://www.boost.org/libs/test for the library home page.
7//
8///@ file
9/// Defines template_test_case_gen
10// ***************************************************************************
11
12#ifndef BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER
13#define BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER
14
15// Boost.Test
16#include <boost/test/detail/config.hpp>
17#include <boost/test/detail/global_typedef.hpp>
18#include <boost/test/detail/fwd_decl.hpp>
19#include <boost/test/tree/test_unit.hpp>
20
21#include <boost/test/utils/class_properties.hpp>
22#include <boost/test/tree/observer.hpp>
23#include <boost/test/utils/algorithm.hpp>
24
25
26// Boost
27#include <boost/shared_ptr.hpp>
28#include <boost/mpl/for_each.hpp>
29#include <boost/mpl/identity.hpp>
30#include <boost/type.hpp>
31#include <boost/type_traits/is_const.hpp>
32#include <boost/type_traits/is_volatile.hpp>
33#include <boost/type_traits/is_lvalue_reference.hpp>
34#include <boost/type_traits/is_rvalue_reference.hpp>
35#include <boost/type_traits/remove_reference.hpp>
36#include <boost/function/function0.hpp>
37
38#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
39# include <boost/current_function.hpp>
40#else
41# include <boost/core/demangle.hpp>
42#endif
43
44// STL
45#include <string> // for std::string
46#include <list> // for std::list
47
48#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
49 !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS)
50 #include <type_traits>
51 #include <boost/mpl/is_sequence.hpp>
52#endif
53
54#include <boost/test/detail/suppress_warnings.hpp>
55
56
57//____________________________________________________________________________//
58
59namespace boost {
60namespace unit_test {
61namespace ut_detail {
62
63// ************************************************************************** //
64// ************** test_case_template_invoker ************** //
65// ************************************************************************** //
66
67template<typename TestCaseTemplate,typename TestType>
68class test_case_template_invoker {
69public:
70 void operator()() { TestCaseTemplate::run( (boost::type<TestType>*)0 ); }
71};
72
73// ************************************************************************** //
74// ************** generate_test_case_4_type ************** //
75// ************************************************************************** //
76
77template<typename Generator, typename TestCaseTemplate>
78struct generate_test_case_4_type {
79 explicit generate_test_case_4_type( const_string tc_name, const_string tc_file, std::size_t tc_line, Generator& G )
80 : m_test_case_name( tc_name )
81 , m_test_case_file( tc_file )
82 , m_test_case_line( tc_line )
83 , m_holder( G )
84 {}
85
86 template<typename TestType>
87 void operator()( mpl::identity<TestType> )
88 {
89 std::string full_name;
90 assign_op( target&: full_name, src: m_test_case_name, 0 );
91 full_name += '<';
92#if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
93 full_name += boost::core::demangle(name: typeid(TestType).name()); // same as execution_monitor.ipp
94#else
95 full_name += BOOST_CURRENT_FUNCTION;
96#endif
97
98 // replacing ',' by ', ' first, and then removing any double space
99 static const std::string to_replace[] = { "class ", "struct ", ",", " ", " <", " >"};
100 static const std::string replacement[] = { "", "" , ", ", " ", "<" , ">"};
101
102 full_name = unit_test::utils::replace_all_occurrences_of(
103 str: full_name,
104 first1: to_replace, last1: to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
105 first2: replacement, last2: replacement + sizeof(replacement)/sizeof(replacement[0]));
106
107 typedef typename boost::remove_reference<TestType>::type TestTypewoRef;
108 if( boost::is_const<TestTypewoRef>::value )
109 full_name += "_const";
110 if( boost::is_volatile<TestTypewoRef>::value )
111 full_name += "_volatile";
112 if( boost::is_rvalue_reference<TestType>::value )
113 full_name += "_refref";
114 else if( boost::is_lvalue_reference<TestType>::value )
115 full_name += "_ref";
116
117 full_name += '>';
118
119 m_holder.m_test_cases.push_back( new test_case( ut_detail::normalize_test_case_name( tu_name: full_name ),
120 m_test_case_file,
121 m_test_case_line,
122 test_case_template_invoker<TestCaseTemplate,TestType>() ) );
123 }
124
125private:
126 // Data members
127 const_string m_test_case_name;
128 const_string m_test_case_file;
129 std::size_t m_test_case_line;
130 Generator& m_holder;
131};
132
133// ************************************************************************** //
134// ************** test_case_template ************** //
135// ************************************************************************** //
136
137class template_test_case_gen_base : public test_unit_generator {
138public:
139 test_unit* next() const BOOST_OVERRIDE
140 {
141 if( m_test_cases.empty() )
142 return 0;
143
144 test_unit* res = m_test_cases.front();
145 m_test_cases.pop_front();
146
147 return res;
148 }
149
150 // Data members
151 mutable std::list<test_unit*> m_test_cases;
152};
153
154template<typename TestCaseTemplate,typename TestTypesList, typename enabler = void>
155class template_test_case_gen : public template_test_case_gen_base {
156public:
157 // Constructor
158 template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
159 {
160 typedef generate_test_case_4_type<template_test_case_gen<TestCaseTemplate,TestTypesList>,TestCaseTemplate> single_test_gen;
161
162 mpl::for_each<TestTypesList,mpl::make_identity<mpl::_> >( single_test_gen( tc_name, tc_file, tc_line, *this ) );
163 }
164};
165
166// Describing template test cases with tuples
167#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
168 !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && \
169 !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
170
171template<typename TestCaseTemplate,
172 template <class ...> class C,
173 typename... parameter_pack>
174class template_test_case_gen<
175 TestCaseTemplate,
176 C<parameter_pack...>,
177 typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type >
178 : public template_test_case_gen_base {
179
180 template<typename F>
181 void for_each(F &f)
182 {
183 auto l = { (f(mpl::identity<parameter_pack>()), 0)... };
184 (void)l; // silence warning
185 }
186
187public:
188 // Constructor
189 template_test_case_gen( const_string tc_name, const_string tc_file, std::size_t tc_line )
190 {
191 using this_type = template_test_case_gen<
192 TestCaseTemplate,
193 C<parameter_pack...>,
194 typename std::enable_if<!boost::mpl::is_sequence<C<parameter_pack...>>::value>::type>;
195 using single_test_gen = generate_test_case_4_type<this_type, TestCaseTemplate>;
196
197 single_test_gen op( tc_name, tc_file, tc_line, *this );
198
199 this->for_each(op);
200 }
201};
202
203#endif /* C++11 variadic, type alias */
204
205} // namespace ut_detail
206} // unit_test
207} // namespace boost
208
209#include <boost/test/detail/enable_warnings.hpp>
210
211#endif // BOOST_TEST_TREE_TEST_CASE_TEMPLATE_HPP_091911GER
212

source code of include/boost/test/tree/test_case_template.hpp