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#include "test/gtest-typed-test_test.h"
31
32#include <set>
33#include <string>
34#include <type_traits>
35#include <vector>
36
37#include "gtest/gtest.h"
38
39GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127 /* conditional expression is constant */)
40
41using testing::Test;
42
43// Used for testing that SetUpTestSuite()/TearDownTestSuite(), fixture
44// ctor/dtor, and SetUp()/TearDown() work correctly in typed tests and
45// type-parameterized test.
46template <typename T>
47class CommonTest : public Test {
48  // For some technical reason, SetUpTestSuite() and TearDownTestSuite()
49  // must be public.
50 public:
51  static void SetUpTestSuite() { shared_ = new T(5); }
52
53  static void TearDownTestSuite() {
54    delete shared_;
55    shared_ = nullptr;
56  }
57
58  // This 'protected:' is optional.  There's no harm in making all
59  // members of this fixture class template public.
60 protected:
61  // We used to use std::list here, but switched to std::vector since
62  // MSVC's <list> doesn't compile cleanly with /W4.
63  typedef std::vector<T> Vector;
64  typedef std::set<int> IntSet;
65
66  CommonTest() : value_(1) {}
67
68  ~CommonTest() override { EXPECT_EQ(3, value_); }
69
70  void SetUp() override {
71    EXPECT_EQ(1, value_);
72    value_++;
73  }
74
75  void TearDown() override {
76    EXPECT_EQ(2, value_);
77    value_++;
78  }
79
80  T value_;
81  static T* shared_;
82};
83
84template <typename T>
85T* CommonTest<T>::shared_ = nullptr;
86
87using testing::Types;
88
89// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
90// and SetUp()/TearDown() work correctly in typed tests
91
92typedef Types<char, int> TwoTypes;
93TYPED_TEST_SUITE(CommonTest, TwoTypes);
94
95TYPED_TEST(CommonTest, ValuesAreCorrect) {
96  // Static members of the fixture class template can be visited via
97  // the TestFixture:: prefix.
98  EXPECT_EQ(5, *TestFixture::shared_);
99
100  // Typedefs in the fixture class template can be visited via the
101  // "typename TestFixture::" prefix.
102  typename TestFixture::Vector empty;
103  EXPECT_EQ(0U, empty.size());
104
105  typename TestFixture::IntSet empty2;
106  EXPECT_EQ(0U, empty2.size());
107
108  // Non-static members of the fixture class must be visited via
109  // 'this', as required by C++ for class templates.
110  EXPECT_EQ(2, this->value_);
111}
112
113// The second test makes sure shared_ is not deleted after the first
114// test.
115TYPED_TEST(CommonTest, ValuesAreStillCorrect) {
116  // Static members of the fixture class template can also be visited
117  // via 'this'.
118  ASSERT_TRUE(this->shared_ != nullptr);
119  EXPECT_EQ(5, *this->shared_);
120
121  // TypeParam can be used to refer to the type parameter.
122  EXPECT_EQ(static_cast<TypeParam>(2), this->value_);
123}
124
125// Tests that multiple TYPED_TEST_SUITE's can be defined in the same
126// translation unit.
127
128template <typename T>
129class TypedTest1 : public Test {};
130
131// Verifies that the second argument of TYPED_TEST_SUITE can be a
132// single type.
133TYPED_TEST_SUITE(TypedTest1, int);
134TYPED_TEST(TypedTest1, A) {}
135
136template <typename T>
137class TypedTest2 : public Test {};
138
139// Verifies that the second argument of TYPED_TEST_SUITE can be a
140// Types<...> type list.
141TYPED_TEST_SUITE(TypedTest2, Types<int>);
142
143// This also verifies that tests from different typed test cases can
144// share the same name.
145TYPED_TEST(TypedTest2, A) {}
146
147// Tests that a typed test case can be defined in a namespace.
148
149namespace library1 {
150
151template <typename T>
152class NumericTest : public Test {};
153
154typedef Types<int, long> NumericTypes;
155TYPED_TEST_SUITE(NumericTest, NumericTypes);
156
157TYPED_TEST(NumericTest, DefaultIsZero) { EXPECT_EQ(0, TypeParam()); }
158
159}  // namespace library1
160
161// Tests that custom names work.
162template <typename T>
163class TypedTestWithNames : public Test {};
164
165class TypedTestNames {
166 public:
167  template <typename T>
168  static std::string GetName(int i) {
169    if (std::is_same<T, char>::value) {
170      return std::string("char") + ::testing::PrintToString(i);
171    }
172    if (std::is_same<T, int>::value) {
173      return std::string("int") + ::testing::PrintToString(i);
174    }
175  }
176};
177
178TYPED_TEST_SUITE(TypedTestWithNames, TwoTypes, TypedTestNames);
179
180TYPED_TEST(TypedTestWithNames, TestSuiteName) {
181  if (std::is_same<TypeParam, char>::value) {
182    EXPECT_STREQ(::testing::UnitTest::GetInstance()
183                     ->current_test_info()
184                     ->test_suite_name(),
185                 "TypedTestWithNames/char0");
186  }
187  if (std::is_same<TypeParam, int>::value) {
188    EXPECT_STREQ(::testing::UnitTest::GetInstance()
189                     ->current_test_info()
190                     ->test_suite_name(),
191                 "TypedTestWithNames/int1");
192  }
193}
194
195using testing::Types;
196using testing::internal::TypedTestSuitePState;
197
198// Tests TypedTestSuitePState.
199
200class TypedTestSuitePStateTest : public Test {
201 protected:
202  void SetUp() override {
203    state_.AddTestName("foo.cc", 0, "FooTest", "A");
204    state_.AddTestName("foo.cc", 0, "FooTest", "B");
205    state_.AddTestName("foo.cc", 0, "FooTest", "C");
206  }
207
208  TypedTestSuitePState state_;
209};
210
211TEST_F(TypedTestSuitePStateTest, SucceedsForMatchingList) {
212  const char* tests = "A, B, C";
213  EXPECT_EQ(tests,
214            state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests));
215}
216
217// Makes sure that the order of the tests and spaces around the names
218// don't matter.
219TEST_F(TypedTestSuitePStateTest, IgnoresOrderAndSpaces) {
220  const char* tests = "A,C,   B";
221  EXPECT_EQ(tests,
222            state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, tests));
223}
224
225using TypedTestSuitePStateDeathTest = TypedTestSuitePStateTest;
226
227TEST_F(TypedTestSuitePStateDeathTest, DetectsDuplicates) {
228  EXPECT_DEATH_IF_SUPPORTED(
229      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, A, C"),
230      "foo\\.cc.1.?: Test A is listed more than once\\.");
231}
232
233TEST_F(TypedTestSuitePStateDeathTest, DetectsExtraTest) {
234  EXPECT_DEATH_IF_SUPPORTED(
235      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C, D"),
236      "foo\\.cc.1.?: No test named D can be found in this test suite\\.");
237}
238
239TEST_F(TypedTestSuitePStateDeathTest, DetectsMissedTest) {
240  EXPECT_DEATH_IF_SUPPORTED(
241      state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, C"),
242      "foo\\.cc.1.?: You forgot to list test B\\.");
243}
244
245// Tests that defining a test for a parameterized test case generates
246// a run-time error if the test case has been registered.
247TEST_F(TypedTestSuitePStateDeathTest, DetectsTestAfterRegistration) {
248  state_.VerifyRegisteredTestNames("Suite", "foo.cc", 1, "A, B, C");
249  EXPECT_DEATH_IF_SUPPORTED(
250      state_.AddTestName("foo.cc", 2, "FooTest", "D"),
251      "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_SUITE_P"
252      "\\(FooTest, \\.\\.\\.\\)\\.");
253}
254
255// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
256// and SetUp()/TearDown() work correctly in type-parameterized tests.
257
258template <typename T>
259class DerivedTest : public CommonTest<T> {};
260
261TYPED_TEST_SUITE_P(DerivedTest);
262
263TYPED_TEST_P(DerivedTest, ValuesAreCorrect) {
264  // Static members of the fixture class template can be visited via
265  // the TestFixture:: prefix.
266  EXPECT_EQ(5, *TestFixture::shared_);
267
268  // Non-static members of the fixture class must be visited via
269  // 'this', as required by C++ for class templates.
270  EXPECT_EQ(2, this->value_);
271}
272
273// The second test makes sure shared_ is not deleted after the first
274// test.
275TYPED_TEST_P(DerivedTest, ValuesAreStillCorrect) {
276  // Static members of the fixture class template can also be visited
277  // via 'this'.
278  ASSERT_TRUE(this->shared_ != nullptr);
279  EXPECT_EQ(5, *this->shared_);
280  EXPECT_EQ(2, this->value_);
281}
282
283REGISTER_TYPED_TEST_SUITE_P(DerivedTest, ValuesAreCorrect,
284                            ValuesAreStillCorrect);
285
286typedef Types<short, long> MyTwoTypes;
287INSTANTIATE_TYPED_TEST_SUITE_P(My, DerivedTest, MyTwoTypes);
288
289// Tests that custom names work with type parametrized tests. We reuse the
290// TwoTypes from above here.
291template <typename T>
292class TypeParametrizedTestWithNames : public Test {};
293
294TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames);
295
296TYPED_TEST_P(TypeParametrizedTestWithNames, TestSuiteName) {
297  if (std::is_same<TypeParam, char>::value) {
298    EXPECT_STREQ(::testing::UnitTest::GetInstance()
299                     ->current_test_info()
300                     ->test_suite_name(),
301                 "CustomName/TypeParametrizedTestWithNames/parChar0");
302  }
303  if (std::is_same<TypeParam, int>::value) {
304    EXPECT_STREQ(::testing::UnitTest::GetInstance()
305                     ->current_test_info()
306                     ->test_suite_name(),
307                 "CustomName/TypeParametrizedTestWithNames/parInt1");
308  }
309}
310
311REGISTER_TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames, TestSuiteName);
312
313class TypeParametrizedTestNames {
314 public:
315  template <typename T>
316  static std::string GetName(int i) {
317    if (std::is_same<T, char>::value) {
318      return std::string("parChar") + ::testing::PrintToString(i);
319    }
320    if (std::is_same<T, int>::value) {
321      return std::string("parInt") + ::testing::PrintToString(i);
322    }
323  }
324};
325
326INSTANTIATE_TYPED_TEST_SUITE_P(CustomName, TypeParametrizedTestWithNames,
327                               TwoTypes, TypeParametrizedTestNames);
328
329// Tests that multiple TYPED_TEST_SUITE_P's can be defined in the same
330// translation unit.
331
332template <typename T>
333class TypedTestP1 : public Test {};
334
335TYPED_TEST_SUITE_P(TypedTestP1);
336
337// For testing that the code between TYPED_TEST_SUITE_P() and
338// TYPED_TEST_P() is not enclosed in a namespace.
339using IntAfterTypedTestSuiteP = int;
340
341TYPED_TEST_P(TypedTestP1, A) {}
342TYPED_TEST_P(TypedTestP1, B) {}
343
344// For testing that the code between TYPED_TEST_P() and
345// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
346using IntBeforeRegisterTypedTestSuiteP = int;
347
348REGISTER_TYPED_TEST_SUITE_P(TypedTestP1, A, B);
349
350template <typename T>
351class TypedTestP2 : public Test {};
352
353TYPED_TEST_SUITE_P(TypedTestP2);
354
355// This also verifies that tests from different type-parameterized
356// test cases can share the same name.
357TYPED_TEST_P(TypedTestP2, A) {}
358
359REGISTER_TYPED_TEST_SUITE_P(TypedTestP2, A);
360
361// Verifies that the code between TYPED_TEST_SUITE_P() and
362// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
363IntAfterTypedTestSuiteP after = 0;
364IntBeforeRegisterTypedTestSuiteP before = 0;
365
366// Verifies that the last argument of INSTANTIATE_TYPED_TEST_SUITE_P()
367// can be either a single type or a Types<...> type list.
368INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP1, int);
369INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP2, Types<int>);
370
371// Tests that the same type-parameterized test case can be
372// instantiated more than once in the same translation unit.
373INSTANTIATE_TYPED_TEST_SUITE_P(Double, TypedTestP2, Types<double>);
374
375// Tests that the same type-parameterized test case can be
376// instantiated in different translation units linked together.
377// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
378typedef Types<std::vector<double>, std::set<char> > MyContainers;
379INSTANTIATE_TYPED_TEST_SUITE_P(My, ContainerTest, MyContainers);
380
381// Tests that a type-parameterized test case can be defined and
382// instantiated in a namespace.
383
384namespace library2 {
385
386template <typename T>
387class NumericTest : public Test {};
388
389TYPED_TEST_SUITE_P(NumericTest);
390
391TYPED_TEST_P(NumericTest, DefaultIsZero) { EXPECT_EQ(0, TypeParam()); }
392
393TYPED_TEST_P(NumericTest, ZeroIsLessThanOne) {
394  EXPECT_LT(TypeParam(0), TypeParam(1));
395}
396
397REGISTER_TYPED_TEST_SUITE_P(NumericTest, DefaultIsZero, ZeroIsLessThanOne);
398typedef Types<int, double> NumericTypes;
399INSTANTIATE_TYPED_TEST_SUITE_P(My, NumericTest, NumericTypes);
400
401static const char* GetTestName() {
402  return testing::UnitTest::GetInstance()->current_test_info()->name();
403}
404// Test the stripping of space from test names
405template <typename T>
406class TrimmedTest : public Test {};
407TYPED_TEST_SUITE_P(TrimmedTest);
408TYPED_TEST_P(TrimmedTest, Test1) { EXPECT_STREQ("Test1", GetTestName()); }
409TYPED_TEST_P(TrimmedTest, Test2) { EXPECT_STREQ("Test2", GetTestName()); }
410TYPED_TEST_P(TrimmedTest, Test3) { EXPECT_STREQ("Test3", GetTestName()); }
411TYPED_TEST_P(TrimmedTest, Test4) { EXPECT_STREQ("Test4", GetTestName()); }
412TYPED_TEST_P(TrimmedTest, Test5) { EXPECT_STREQ("Test5", GetTestName()); }
413REGISTER_TYPED_TEST_SUITE_P(TrimmedTest, Test1, Test2, Test3, Test4,
414                            Test5);  // NOLINT
415template <typename T1, typename T2>
416struct MyPair {};
417// Be sure to try a type with a comma in its name just in case it matters.
418typedef Types<int, double, MyPair<int, int> > TrimTypes;
419INSTANTIATE_TYPED_TEST_SUITE_P(My, TrimmedTest, TrimTypes);
420
421}  // namespace library2
422
423GTEST_DISABLE_MSC_WARNINGS_POP_()  // 4127
424