1 /*
2  *  Created by Phil on 18/10/2010.
3  *  Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  */
8 #ifndef TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
9 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
10 
11 #include "catch_common.h"
12 #include "catch_interfaces_testcase.h"
13 #include "catch_compiler_capabilities.h"
14 #include "catch_stringref.h"
15 #include "catch_preprocessor.hpp"
16 #include "catch_meta.hpp"
17 
18 namespace Catch {
19 
20 template<typename C>
21 class TestInvokerAsMethod : public ITestInvoker {
22     void (C::*m_testAsMethod)();
23 public:
TestInvokerAsMethod(void (C::* testAsMethod)())24     TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
25 
invoke()26     void invoke() const override {
27         C obj;
28         (obj.*m_testAsMethod)();
29     }
30 };
31 
32 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
33 
34 template<typename C>
35 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
36     return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
37 }
38 
39 struct NameAndTags {
40     NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
41     StringRef name;
42     StringRef tags;
43 };
44 
45 struct AutoReg : NonCopyable {
46     AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
47     ~AutoReg();
48 };
49 
50 } // end namespace Catch
51 
52 #if defined(CATCH_CONFIG_DISABLE)
53     #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
54         static void TestName()
55     #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
56         namespace{                        \
57             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
58                 void test();              \
59             };                            \
60         }                                 \
61         void TestName::test()
62     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... )  \
63         INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
64     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... )    \
65         namespace{                                                                                  \
66             namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                      \
67             INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
68         }                                                                                           \
69         }                                                                                           \
70         INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
71 
72     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
73         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
74             INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
75     #else
76         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
77             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
78     #endif
79 
80     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
81         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
82             INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
83     #else
84         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
85             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
86     #endif
87 
88     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
89         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
90             INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
91     #else
92         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
93             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
94     #endif
95 
96     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
97         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
98             INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
99     #else
100         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
101             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
102     #endif
103 #endif
104 
105     ///////////////////////////////////////////////////////////////////////////////
106     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
107         static void TestName(); \
108         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
109         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
110         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
111         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
112         static void TestName()
113     #define INTERNAL_CATCH_TESTCASE( ... ) \
114         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
115 
116     ///////////////////////////////////////////////////////////////////////////////
117     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
118         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
119         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
120         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
121         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
122 
123     ///////////////////////////////////////////////////////////////////////////////
124     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
125         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
126         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
127         namespace{ \
128             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
129                 void test(); \
130             }; \
131             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
132         } \
133         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
134         void TestName::test()
135     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
136         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
137 
138     ///////////////////////////////////////////////////////////////////////////////
139     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
140         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
141         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
142         Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
143         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
144 
145     ///////////////////////////////////////////////////////////////////////////////
146     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
147         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
148         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
149         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
150         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
151         INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
152         namespace {\
153         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
154             INTERNAL_CATCH_TYPE_GEN\
155             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
156             INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
157             template<typename...Types> \
158             struct TestName{\
159                 TestName(){\
160                     int index = 0;                                    \
161                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
162                     using expander = int[];\
163                     (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
164                 }\
165             };\
166             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
167             TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
168             return 0;\
169         }();\
170         }\
171         }\
172         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
173         INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
174 
175 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
176     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
177         INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
178 #else
179     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
180         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
181 #endif
182 
183 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
184     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
185         INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
186 #else
187     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
188         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
189 #endif
190 
191     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
192         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                      \
193         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
194         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS                \
195         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS              \
196         template<typename TestType> static void TestFuncName();       \
197         namespace {\
198         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                     \
199             INTERNAL_CATCH_TYPE_GEN                                                  \
200             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))         \
201             template<typename... Types>                               \
202             struct TestName {                                         \
203                 void reg_tests() {                                          \
204                     int index = 0;                                    \
205                     using expander = int[];                           \
206                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
207                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
208                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
209                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\
210                 }                                                     \
211             };                                                        \
212             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
213                 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
214                 TestInit t;                                           \
215                 t.reg_tests();                                        \
216                 return 0;                                             \
217             }();                                                      \
218         }                                                             \
219         }                                                             \
220         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
221         template<typename TestType>                                   \
222         static void TestFuncName()
223 
224 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
225     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
226         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__)
227 #else
228     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
229         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) )
230 #endif
231 
232 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
233     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
234         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__)
235 #else
236     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
237         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
238 #endif
239 
240     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
241         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
242         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
243         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
244         template<typename TestType> static void TestFunc();       \
245         namespace {\
246         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
247         INTERNAL_CATCH_TYPE_GEN\
248         template<typename... Types>                               \
249         struct TestName {                                         \
250             void reg_tests() {                                          \
251                 int index = 0;                                    \
252                 using expander = int[];                           \
253                 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
254             }                                                     \
255         };\
256         static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
257                 using TestInit = typename convert<TestName, TmplList>::type; \
258                 TestInit t;                                           \
259                 t.reg_tests();                                        \
260                 return 0;                                             \
261             }();                                                      \
262         }}\
263         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
264         template<typename TestType>                                   \
265         static void TestFunc()
266 
267     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
268         INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList )
269 
270 
271     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
272         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
273         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
274         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
275         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
276         namespace {\
277         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
278             INTERNAL_CATCH_TYPE_GEN\
279             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
280             INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
281             INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
282             template<typename...Types> \
283             struct TestNameClass{\
284                 TestNameClass(){\
285                     int index = 0;                                    \
286                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
287                     using expander = int[];\
288                     (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
289                 }\
290             };\
291             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
292                 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
293                 return 0;\
294         }();\
295         }\
296         }\
297         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
298         INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
299 
300 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
301     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
302         INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
303 #else
304     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
305         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
306 #endif
307 
308 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
309     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
310         INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
311 #else
312     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
313         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
314 #endif
315 
316     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
317         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
318         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
319         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
320         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
321         template<typename TestType> \
322             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
323                 void test();\
324             };\
325         namespace {\
326         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
327             INTERNAL_CATCH_TYPE_GEN                  \
328             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
329             template<typename...Types>\
330             struct TestNameClass{\
331                 void reg_tests(){\
332                     int index = 0;\
333                     using expander = int[];\
334                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
335                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
336                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
337                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \
338                 }\
339             };\
340             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
341                 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
342                 TestInit t;\
343                 t.reg_tests();\
344                 return 0;\
345             }(); \
346         }\
347         }\
348         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
349         template<typename TestType> \
350         void TestName<TestType>::test()
351 
352 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
353     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
354         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
355 #else
356     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
357         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
358 #endif
359 
360 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
361     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
362         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
363 #else
364     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
365         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
366 #endif
367 
368     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
369         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
370         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
371         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
372         template<typename TestType> \
373         struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
374             void test();\
375         };\
376         namespace {\
377         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
378             INTERNAL_CATCH_TYPE_GEN\
379             template<typename...Types>\
380             struct TestNameClass{\
381                 void reg_tests(){\
382                     int index = 0;\
383                     using expander = int[];\
384                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
385                 }\
386             };\
387             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
388                 using TestInit = typename convert<TestNameClass, TmplList>::type;\
389                 TestInit t;\
390                 t.reg_tests();\
391                 return 0;\
392             }(); \
393         }}\
394         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
395         template<typename TestType> \
396         void TestName<TestType>::test()
397 
398 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
399         INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList )
400 
401 
402 #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
403