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 | |
59 | namespace boost { |
60 | namespace unit_test { |
61 | namespace ut_detail { |
62 | |
63 | // ************************************************************************** // |
64 | // ************** test_case_template_invoker ************** // |
65 | // ************************************************************************** // |
66 | |
67 | template<typename TestCaseTemplate,typename TestType> |
68 | class test_case_template_invoker { |
69 | public: |
70 | void operator()() { TestCaseTemplate::run( (boost::type<TestType>*)0 ); } |
71 | }; |
72 | |
73 | // ************************************************************************** // |
74 | // ************** generate_test_case_4_type ************** // |
75 | // ************************************************************************** // |
76 | |
77 | template<typename Generator, typename TestCaseTemplate> |
78 | struct 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 | |
125 | private: |
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 | |
137 | class template_test_case_gen_base : public test_unit_generator { |
138 | public: |
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 | |
154 | template<typename TestCaseTemplate,typename TestTypesList, typename enabler = void> |
155 | class template_test_case_gen : public template_test_case_gen_base { |
156 | public: |
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 | |
171 | template<typename TestCaseTemplate, |
172 | template <class ...> class C, |
173 | typename... parameter_pack> |
174 | class 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 | |
187 | public: |
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 | |