xref: /freebsd/contrib/googletest/googletest/include/gtest/gtest-typed-test.h (revision 5ca8c28cd8c725b81781201cfdb5f9969396f934)
1 // Copyright 2008 Google Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // IWYU pragma: private, include "gtest/gtest.h"
31 // IWYU pragma: friend gtest/.*
32 // IWYU pragma: friend gmock/.*
33 
34 #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
35 #define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
36 
37 // This header implements typed tests and type-parameterized tests.
38 
39 // Typed (aka type-driven) tests repeat the same test for types in a
40 // list.  You must know which types you want to test with when writing
41 // typed tests. Here's how you do it:
42 
43 #if 0
44 
45 // First, define a fixture class template.  It should be parameterized
46 // by a type.  Remember to derive it from testing::Test.
47 template <typename T>
48 class FooTest : public testing::Test {
49  public:
50   ...
51   typedef std::list<T> List;
52   static T shared_;
53   T value_;
54 };
55 
56 // Next, associate a list of types with the test suite, which will be
57 // repeated for each type in the list.  The typedef is necessary for
58 // the macro to parse correctly.
59 typedef testing::Types<char, int, unsigned int> MyTypes;
60 TYPED_TEST_SUITE(FooTest, MyTypes);
61 
62 // If the type list contains only one type, you can write that type
63 // directly without Types<...>:
64 //   TYPED_TEST_SUITE(FooTest, int);
65 
66 // Then, use TYPED_TEST() instead of TEST_F() to define as many typed
67 // tests for this test suite as you want.
68 TYPED_TEST(FooTest, DoesBlah) {
69   // Inside a test, refer to the special name TypeParam to get the type
70   // parameter.  Since we are inside a derived class template, C++ requires
71   // us to visit the members of FooTest via 'this'.
72   TypeParam n = this->value_;
73 
74   // To visit static members of the fixture, add the TestFixture::
75   // prefix.
76   n += TestFixture::shared_;
77 
78   // To refer to typedefs in the fixture, add the "typename
79   // TestFixture::" prefix.
80   typename TestFixture::List values;
81   values.push_back(n);
82   ...
83 }
84 
85 TYPED_TEST(FooTest, HasPropertyA) { ... }
86 
87 // TYPED_TEST_SUITE takes an optional third argument which allows to specify a
88 // class that generates custom test name suffixes based on the type. This should
89 // be a class which has a static template function GetName(int index) returning
90 // a string for each type. The provided integer index equals the index of the
91 // type in the provided type list. In many cases the index can be ignored.
92 //
93 // For example:
94 //   class MyTypeNames {
95 //    public:
96 //     template <typename T>
97 //     static std::string GetName(int) {
98 //       if (std::is_same<T, char>()) return "char";
99 //       if (std::is_same<T, int>()) return "int";
100 //       if (std::is_same<T, unsigned int>()) return "unsignedInt";
101 //     }
102 //   };
103 //   TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
104 
105 #endif  // 0
106 
107 // Type-parameterized tests are abstract test patterns parameterized
108 // by a type.  Compared with typed tests, type-parameterized tests
109 // allow you to define the test pattern without knowing what the type
110 // parameters are.  The defined pattern can be instantiated with
111 // different types any number of times, in any number of translation
112 // units.
113 //
114 // If you are designing an interface or concept, you can define a
115 // suite of type-parameterized tests to verify properties that any
116 // valid implementation of the interface/concept should have.  Then,
117 // each implementation can easily instantiate the test suite to verify
118 // that it conforms to the requirements, without having to write
119 // similar tests repeatedly.  Here's an example:
120 
121 #if 0
122 
123 // First, define a fixture class template.  It should be parameterized
124 // by a type.  Remember to derive it from testing::Test.
125 template <typename T>
126 class FooTest : public testing::Test {
127   ...
128 };
129 
130 // Next, declare that you will define a type-parameterized test suite
131 // (the _P suffix is for "parameterized" or "pattern", whichever you
132 // prefer):
133 TYPED_TEST_SUITE_P(FooTest);
134 
135 // Then, use TYPED_TEST_P() to define as many type-parameterized tests
136 // for this type-parameterized test suite as you want.
137 TYPED_TEST_P(FooTest, DoesBlah) {
138   // Inside a test, refer to TypeParam to get the type parameter.
139   TypeParam n = 0;
140   ...
141 }
142 
143 TYPED_TEST_P(FooTest, HasPropertyA) { ... }
144 
145 // Now the tricky part: you need to register all test patterns before
146 // you can instantiate them.  The first argument of the macro is the
147 // test suite name; the rest are the names of the tests in this test
148 // case.
149 REGISTER_TYPED_TEST_SUITE_P(FooTest,
150                             DoesBlah, HasPropertyA);
151 
152 // Finally, you are free to instantiate the pattern with the types you
153 // want.  If you put the above code in a header file, you can #include
154 // it in multiple C++ source files and instantiate it multiple times.
155 //
156 // To distinguish different instances of the pattern, the first
157 // argument to the INSTANTIATE_* macro is a prefix that will be added
158 // to the actual test suite name.  Remember to pick unique prefixes for
159 // different instances.
160 typedef testing::Types<char, int, unsigned int> MyTypes;
161 INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
162 
163 // If the type list contains only one type, you can write that type
164 // directly without Types<...>:
165 //   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
166 //
167 // Similar to the optional argument of TYPED_TEST_SUITE above,
168 // INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
169 // generate custom names.
170 //   INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
171 
172 #endif  // 0
173 
174 #include "gtest/internal/gtest-internal.h"
175 #include "gtest/internal/gtest-port.h"
176 #include "gtest/internal/gtest-type-util.h"
177 
178 // Implements typed tests.
179 
180 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
181 //
182 // Expands to the name of the typedef for the type parameters of the
183 // given test suite.
184 #define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
185 
186 // Expands to the name of the typedef for the NameGenerator, responsible for
187 // creating the suffixes of the name.
188 #define GTEST_NAME_GENERATOR_(TestSuiteName) \
189   gtest_type_params_##TestSuiteName##_NameGenerator
190 
191 #define TYPED_TEST_SUITE(CaseName, Types, ...)                          \
192   typedef ::testing::internal::GenerateTypeList<Types>::type            \
193       GTEST_TYPE_PARAMS_(CaseName);                                     \
194   typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
195   GTEST_NAME_GENERATOR_(CaseName)
196 
197 #define TYPED_TEST(CaseName, TestName)                                       \
198   static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1,                      \
199                 "test-name must not be empty");                              \
200   template <typename gtest_TypeParam_>                                       \
201   class GTEST_TEST_CLASS_NAME_(CaseName, TestName)                           \
202       : public CaseName<gtest_TypeParam_> {                                  \
203    private:                                                                  \
204     typedef CaseName<gtest_TypeParam_> TestFixture;                          \
205     typedef gtest_TypeParam_ TypeParam;                                      \
206     void TestBody() override;                                                \
207   };                                                                         \
208   GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool                          \
209       gtest_##CaseName##_##TestName##_registered_ =                          \
210           ::testing::internal::TypeParameterizedTest<                        \
211               CaseName,                                                      \
212               ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(       \
213                   CaseName, TestName)>,                                      \
214               GTEST_TYPE_PARAMS_(                                            \
215                   CaseName)>::Register("",                                   \
216                                        ::testing::internal::CodeLocation(    \
217                                            __FILE__, __LINE__),              \
218                                        GTEST_STRINGIFY_(CaseName),           \
219                                        GTEST_STRINGIFY_(TestName), 0,        \
220                                        ::testing::internal::GenerateNames<   \
221                                            GTEST_NAME_GENERATOR_(CaseName),  \
222                                            GTEST_TYPE_PARAMS_(CaseName)>()); \
223   template <typename gtest_TypeParam_>                                       \
224   void GTEST_TEST_CLASS_NAME_(CaseName,                                      \
225                               TestName)<gtest_TypeParam_>::TestBody()
226 
227 // Legacy API is deprecated but still available
228 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
229 #define TYPED_TEST_CASE                                                \
230   static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
231   TYPED_TEST_SUITE
232 #endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
233 
234 // Implements type-parameterized tests.
235 
236 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
237 //
238 // Expands to the namespace name that the type-parameterized tests for
239 // the given type-parameterized test suite are defined in.  The exact
240 // name of the namespace is subject to change without notice.
241 #define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
242 
243 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
244 //
245 // Expands to the name of the variable used to remember the names of
246 // the defined tests in the given test suite.
247 #define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
248   gtest_typed_test_suite_p_state_##TestSuiteName##_
249 
250 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
251 //
252 // Expands to the name of the variable used to remember the names of
253 // the registered tests in the given test suite.
254 #define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
255   gtest_registered_test_names_##TestSuiteName##_
256 
257 // The variables defined in the type-parameterized test macros are
258 // static as typically these macros are used in a .h file that can be
259 // #included in multiple translation units linked together.
260 #define TYPED_TEST_SUITE_P(SuiteName)              \
261   static ::testing::internal::TypedTestSuitePState \
262   GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
263 
264 // Legacy API is deprecated but still available
265 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
266 #define TYPED_TEST_CASE_P                                                 \
267   static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
268   TYPED_TEST_SUITE_P
269 #endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
270 
271 #define TYPED_TEST_P(SuiteName, TestName)                         \
272   namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                   \
273   template <typename gtest_TypeParam_>                            \
274   class TestName : public SuiteName<gtest_TypeParam_> {           \
275    private:                                                       \
276     typedef SuiteName<gtest_TypeParam_> TestFixture;              \
277     typedef gtest_TypeParam_ TypeParam;                           \
278     void TestBody() override;                                     \
279   };                                                              \
280   GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool               \
281       gtest_##TestName##_defined_ =                               \
282           GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
283               __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName),    \
284               GTEST_STRINGIFY_(TestName));                        \
285   }                                                               \
286   template <typename gtest_TypeParam_>                            \
287   void GTEST_SUITE_NAMESPACE_(                                    \
288       SuiteName)::TestName<gtest_TypeParam_>::TestBody()
289 
290 // Note: this won't work correctly if the trailing arguments are macros.
291 #define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...)                         \
292   namespace GTEST_SUITE_NAMESPACE_(SuiteName) {                             \
293   typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_;      \
294   }                                                                         \
295   GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static const char* const            \
296   GTEST_REGISTERED_TEST_NAMES_(SuiteName) =                                 \
297       GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
298           GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__)
299 
300 // Legacy API is deprecated but still available
301 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
302 #define REGISTER_TYPED_TEST_CASE_P                                           \
303   static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
304                 "");                                                         \
305   REGISTER_TYPED_TEST_SUITE_P
306 #endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
307 
308 #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...)        \
309   static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1,                        \
310                 "test-suit-prefix must not be empty");                       \
311   GTEST_INTERNAL_ATTRIBUTE_MAYBE_UNUSED static bool                          \
312       gtest_##Prefix##_##SuiteName =                                         \
313           ::testing::internal::TypeParameterizedTestSuite<                   \
314               SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
315               ::testing::internal::GenerateTypeList<Types>::type>::          \
316               Register(                                                      \
317                   GTEST_STRINGIFY_(Prefix),                                  \
318                   ::testing::internal::CodeLocation(__FILE__, __LINE__),     \
319                   &GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName),               \
320                   GTEST_STRINGIFY_(SuiteName),                               \
321                   GTEST_REGISTERED_TEST_NAMES_(SuiteName),                   \
322                   ::testing::internal::GenerateNames<                        \
323                       ::testing::internal::NameGeneratorSelector<            \
324                           __VA_ARGS__>::type,                                \
325                       ::testing::internal::GenerateTypeList<Types>::type>())
326 
327 // Legacy API is deprecated but still available
328 #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
329 #define INSTANTIATE_TYPED_TEST_CASE_P                                      \
330   static_assert(                                                           \
331       ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
332   INSTANTIATE_TYPED_TEST_SUITE_P
333 #endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
334 
335 #endif  // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
336