Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / test / tree / test_case_template.hpp
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( full_name, m_test_case_name, 0 );
91         full_name += '<';
92 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
93         full_name += boost::core::demangle(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             full_name,
104             to_replace, to_replace + sizeof(to_replace)/sizeof(to_replace[0]),
105             replacement, 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( 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     virtual test_unit* next() const
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