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 
15 namespace Catch {
16 
17 template<typename C>
18 class MethodTestCase : public SharedImpl<ITestCase> {
19 
20 public:
MethodTestCase(void (C::* method)())21     MethodTestCase( void (C::*method)() ) : m_method( method ) {}
22 
invoke() const23     virtual void invoke() const {
24         C obj;
25         (obj.*m_method)();
26     }
27 
28 private:
~MethodTestCase()29     virtual ~MethodTestCase() {}
30 
31     void (C::*m_method)();
32 };
33 
34 typedef void(*TestFunction)();
35 
36 struct NameAndDesc {
NameAndDescCatch::NameAndDesc37     NameAndDesc( const char* _name = "", const char* _description= "" )
38     : name( _name ), description( _description )
39     {}
40 
41     const char* name;
42     const char* description;
43 };
44 
45 void registerTestCase
46     (   ITestCase* testCase,
47         char const* className,
48         NameAndDesc const& nameAndDesc,
49         SourceLineInfo const& lineInfo );
50 
51 struct AutoReg {
52 
53     AutoReg
54         (   TestFunction function,
55             SourceLineInfo const& lineInfo,
56             NameAndDesc const& nameAndDesc );
57 
58     template<typename C>
AutoRegCatch::AutoReg59     AutoReg
60         (   void (C::*method)(),
61             char const* className,
62             NameAndDesc const& nameAndDesc,
63             SourceLineInfo const& lineInfo ) {
64 
65         registerTestCase
66             (   new MethodTestCase<C>( method ),
67                 className,
68                 nameAndDesc,
69                 lineInfo );
70     }
71 
72     ~AutoReg();
73 
74 private:
75     AutoReg( AutoReg const& );
76     void operator= ( AutoReg const& );
77 };
78 
79 void registerTestCaseFunction
80     (   TestFunction function,
81         SourceLineInfo const& lineInfo,
82         NameAndDesc const& nameAndDesc );
83 
84 } // end namespace Catch
85 
86 #ifdef CATCH_CONFIG_VARIADIC_MACROS
87     ///////////////////////////////////////////////////////////////////////////////
88     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
89         static void TestName(); \
90         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
91         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } /* NOLINT */ \
92         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
93         static void TestName()
94     #define INTERNAL_CATCH_TESTCASE( ... ) \
95         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
96 
97     ///////////////////////////////////////////////////////////////////////////////
98     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
99         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
100         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \
101         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
102 
103     ///////////////////////////////////////////////////////////////////////////////
104     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
105         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
106         namespace{ \
107             struct TestName : ClassName{ \
108                 void test(); \
109             }; \
110             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \
111         } \
112         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
113         void TestName::test()
114     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
115         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
116 
117     ///////////////////////////////////////////////////////////////////////////////
118     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
119         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
120         Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); /* NOLINT */ \
121         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
122 
123 #else
124     ///////////////////////////////////////////////////////////////////////////////
125     #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
126         static void TestName(); \
127         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
128         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); } /* NOLINT */ \
129         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
130         static void TestName()
131     #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
132         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
133 
134     ///////////////////////////////////////////////////////////////////////////////
135     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
136         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
137         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /* NOLINT */ \
138         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
139 
140     ///////////////////////////////////////////////////////////////////////////////
141     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
142         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
143         namespace{ \
144             struct TestCaseName : ClassName{ \
145                 void test(); \
146             }; \
147             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); /* NOLINT */ \
148         } \
149         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
150         void TestCaseName::test()
151     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
152         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
153 
154     ///////////////////////////////////////////////////////////////////////////////
155     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
156         CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
157         Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); /* NOLINT */ \
158         CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
159 
160 #endif
161 
162 #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
163