NetBurner 3.1
GTestConvertor.h
1 /*
2  * Copyright (c) 2011, Michael Feathers, James Grenning and Bas Vodde
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the <organization> nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef GTESTCONVERTOR_H_
29 #define GTESTCONVERTOR_H_
30 
31 #include "CppUTest/Utest.h"
32 
33 #ifdef GTEST__H_
34 #error "Please include this file before you include any other GTest files"
35 #endif
36 
37 /*
38  * Usage:
39  *
40  * This file must only be included in the main. The whole implementation is inline so that this can
41  * be compiled on usage and not on CppUTest compile-time. This avoids a hard dependency with CppUTest
42  * and with GTest
43  *
44  * Add the following lines to your main:
45  *
46  * GTestConvertor convertor;
47  * convertor.addAllGTestToTestRegistry();
48  *
49  *
50  */
51 
52 class GTestResultReporter;
53 class GTestFlagsThatAllocateMemory;
54 
55 namespace testing {
56  class TestInfo;
57  class TestCase;
58  class Test;
59 }
60 
61 class GTestShell : public UtestShell
62 {
63  ::testing::TestInfo* testinfo_;
64  GTestShell* next_;
65  GTestFlagsThatAllocateMemory* flags_;
66 public:
67  GTestShell(::testing::TestInfo* testinfo, GTestShell* next, GTestFlagsThatAllocateMemory* flags);
68 
69  virtual Utest* createTest() _override;
70 
71  GTestShell* nextGTest()
72  {
73  return next_;
74  }
75 };
76 
77 /* Enormous hack!
78  *
79  * This sucks enormously. We need to do two things in GTest that seem to not be possible without
80  * this hack. Hopefully there is *another way*.
81  *
82  * We need to access the factory in the TestInfo in order to be able to create tests. The factory
83  * is private and there seems to be no way to access it...
84  *
85  * We need to be able to call the Test SetUp and TearDown methods, but they are protected for
86  * some reason. We can't subclass either as the tests are created with the TEST macro.
87  *
88  * If anyone knows how to get the above things done *without* these ugly #defines, let me know!
89  *
90  */
91 
92 #define private public
93 #define protected public
94 
95 #include "CppUTestExt/GTest.h"
96 #include "CppUTestExt/GMock.h"
97 #include "gtest/gtest-spi.h"
98 #include "gtest/gtest-death-test.h"
99 /*
100  * We really need some of its internals as they don't have a public interface.
101  *
102  */
103 #define GTEST_IMPLEMENTATION_ 1
104 #include "src/gtest-internal-inl.h"
105 
106 #include "CppUTest/TestRegistry.h"
107 #include "CppUTest/TestFailure.h"
108 #include "CppUTest/TestResult.h"
109 
110 
111 #ifdef GTEST_VERSION_GTEST_1_7
112 #define GTEST_STRING std::string
113 #define GTEST_NO_STRING_VALUE ""
114 #else
115 #define GTEST_STRING ::testing::internal::String
116 #define GTEST_NO_STRING_VALUE NULL
117 #endif
118 
119 /* Store some of the flags as we'll need to reset them each test to avoid leaking memory */
120 
121 class GTestFlagsThatAllocateMemory
122 {
123 public:
124  void storeValuesOfGTestFLags()
125  {
126  GTestFlagcolor = ::testing::GTEST_FLAG(color);
127  GTestFlagfilter = ::testing::GTEST_FLAG(filter);
128  GTestFlagoutput = ::testing::GTEST_FLAG(output);
129  GTestFlagdeath_test_style = ::testing::GTEST_FLAG(death_test_style);
130  GTestFlaginternal_run_death_test = ::testing::internal::GTEST_FLAG(internal_run_death_test);
131  #ifndef GTEST_VERSION_GTEST_1_5
132  GTestFlagstream_result_to = ::testing::GTEST_FLAG(stream_result_to);
133  #endif
134  }
135 
136  void resetValuesOfGTestFlags()
137  {
138  ::testing::GTEST_FLAG(color) = GTestFlagcolor;
139  ::testing::GTEST_FLAG(filter) = GTestFlagfilter;
140  ::testing::GTEST_FLAG(output) = GTestFlagoutput;
141  ::testing::GTEST_FLAG(death_test_style) = GTestFlagdeath_test_style;
142  ::testing::internal::GTEST_FLAG(internal_run_death_test) = GTestFlaginternal_run_death_test;
143  #ifndef GTEST_VERSION_GTEST_1_5
144  ::testing::GTEST_FLAG(stream_result_to) = GTestFlagstream_result_to;
145  #endif
146  }
147 
148  void setGTestFLagValuesToNULLToAvoidMemoryLeaks()
149  {
150  #ifndef GTEST_VERSION_GTEST_1_7
151  ::testing::GTEST_FLAG(color) = GTEST_NO_STRING_VALUE;
152  ::testing::GTEST_FLAG(filter) = GTEST_NO_STRING_VALUE;
153  ::testing::GTEST_FLAG(output) = GTEST_NO_STRING_VALUE;
154  ::testing::GTEST_FLAG(death_test_style) = GTEST_NO_STRING_VALUE;
155  ::testing::internal::GTEST_FLAG(internal_run_death_test) = GTEST_NO_STRING_VALUE;
156  #ifndef GTEST_VERSION_GTEST_1_5
157  ::testing::GTEST_FLAG(stream_result_to) = GTEST_NO_STRING_VALUE;
158  #endif
159  #endif
160  }
161 
162 private:
163  GTEST_STRING GTestFlagcolor;
164  GTEST_STRING GTestFlagfilter;
165  GTEST_STRING GTestFlagoutput;
166  GTEST_STRING GTestFlagdeath_test_style;
167  GTEST_STRING GTestFlaginternal_run_death_test;
168  #ifndef GTEST_VERSION_GTEST_1_5
169  GTEST_STRING GTestFlagstream_result_to;
170  #endif
171 };
172 
173 class GTestConvertor
174 {
175 public:
176  GTestConvertor(bool shouldSimulateFailureAtCreationToAllocateThreadLocalData = true);
177  virtual ~GTestConvertor();
178 
179  virtual void addAllGTestToTestRegistry();
180 protected:
181  virtual void simulateGTestFailureToPreAllocateAllTheThreadLocalData();
182 
183  virtual void addNewTestCaseForTestInfo(::testing::TestInfo* testinfo);
184  virtual void addAllTestsFromTestCaseToTestRegistry(::testing::TestCase* testcase);
185 
186  virtual void createDummyInSequenceToAndFailureReporterAvoidMemoryLeakInGMock();
187 private:
188  GTestResultReporter* reporter_;
189  GTestShell* first_;
190  GTestFlagsThatAllocateMemory flags_;
191 };
192 
193 class GTestDummyResultReporter : public ::testing::ScopedFakeTestPartResultReporter
194 {
195 public:
196  GTestDummyResultReporter () : ::testing::ScopedFakeTestPartResultReporter(INTERCEPT_ALL_THREADS, NULL) {}
197  virtual void ReportTestPartResult(const ::testing::TestPartResult& /*result*/) {}
198 };
199 
200 class GMockTestTerminator : public TestTerminator
201 {
202 public:
203  GMockTestTerminator(const ::testing::TestPartResult& result) : result_(result)
204  {
205  }
206 
207  virtual void exitCurrentTest() const
208  {
209  /*
210  * When using GMock, it throws an exception fromt he destructor leaving
211  * the system in an unstable state.
212  * Therefore, when the test fails because of failed gmock expectation
213  * then don't throw the exception, but let it return. Usually this should
214  * already be at the end of the test, so it doesn't matter much
215  */
216 
217 
218  /*
219  * TODO: We probably want this check here, however the tests fail when putting it there. Also, we'll need to
220  * check how to get all the gTest tests to run within CppUTest. At the moment, the 'death tests' seem to fail
221  * still.
222  *
223  * if (result_.type() == ::testing::TestPartResult::kFatalFailure) {
224  */
225  if (!SimpleString(result_.message()).contains("Actual: never called") &&
226  !SimpleString(result_.message()).contains("Actual function call count doesn't match"))
227  throw CppUTestFailedException();
228 
229  }
230  virtual ~GMockTestTerminator()
231  {
232  }
233 private:
234  const ::testing::TestPartResult& result_;
235 };
236 
237 
238 class GTestResultReporter : public ::testing::ScopedFakeTestPartResultReporter
239 {
240 public:
241  GTestResultReporter () : ::testing::ScopedFakeTestPartResultReporter(INTERCEPT_ALL_THREADS, NULL) {}
242 
243  virtual void ReportTestPartResult(const ::testing::TestPartResult& result)
244  {
245  FailFailure failure(UtestShell::getCurrent(), result.file_name(), result.line_number(), result.message());
246  UtestShell::getCurrent()->failWith(failure, GMockTestTerminator(result));
247  }
248 };
249 
250 inline GTestShell::GTestShell(::testing::TestInfo* testinfo, GTestShell* next, GTestFlagsThatAllocateMemory* flags) : testinfo_(testinfo), next_(next), flags_(flags)
251 {
252  setGroupName(testinfo->test_case_name());
253  setTestName(testinfo->name());
254 }
255 
256 class GTestUTest: public Utest {
257 public:
258  GTestUTest(::testing::TestInfo* testinfo, GTestFlagsThatAllocateMemory* flags) : testinfo_(testinfo), test_(NULL), flags_(flags)
259  {
260 
261  }
262 
263  void testBody()
264  {
265  try {
266  test_->TestBody();
267  }
268  catch (CppUTestFailedException& ex)
269  {
270  }
271  }
272 
273  void setup()
274  {
275  flags_->resetValuesOfGTestFlags();
276 
277  #ifdef GTEST_VERSION_GTEST_1_5
278  test_ = testinfo_->impl()->factory_->CreateTest();
279  #else
280  test_ = testinfo_->factory_->CreateTest();
281  #endif
282 
283  ::testing::UnitTest::GetInstance()->impl()->set_current_test_info(testinfo_);
284  try {
285  test_->SetUp();
286  }
287  catch (CppUTestFailedException& ex)
288  {
289  }
290  }
291 
292  void teardown()
293  {
294  try {
295  test_->TearDown();
296  }
297  catch (CppUTestFailedException& ex)
298  {
299  }
300  ::testing::UnitTest::GetInstance()->impl()->set_current_test_info(NULL);
301  delete test_;
302 
303  flags_->setGTestFLagValuesToNULLToAvoidMemoryLeaks();
304  ::testing::internal::DeathTest::set_last_death_test_message(GTEST_NO_STRING_VALUE);
305  }
306 
307 private:
308  ::testing::Test* test_;
309  ::testing::TestInfo* testinfo_;
310  GTestFlagsThatAllocateMemory* flags_;
311 };
312 
313 inline Utest* GTestShell::createTest()
314 {
315  return new GTestUTest(testinfo_, flags_);
316 };
317 
318 inline void GTestConvertor::simulateGTestFailureToPreAllocateAllTheThreadLocalData()
319 {
320  GTestDummyResultReporter *dummyReporter = new GTestDummyResultReporter();
321  ASSERT_TRUE(false);
322  delete dummyReporter;
323 }
324 
325 inline GTestConvertor::GTestConvertor(bool shouldSimulateFailureAtCreationToAllocateThreadLocalData) : first_(NULL)
326 {
327  if (shouldSimulateFailureAtCreationToAllocateThreadLocalData)
328  simulateGTestFailureToPreAllocateAllTheThreadLocalData();
329  reporter_ = new GTestResultReporter();
330 }
331 
332 inline GTestConvertor::~GTestConvertor()
333 {
334  delete reporter_;
335 
336  while (first_) {
337  GTestShell* next = first_->nextGTest();
338  delete first_;
339  first_ = next;
340  }
341 }
342 
343 inline void GTestConvertor::addNewTestCaseForTestInfo(::testing::TestInfo* testinfo)
344 {
345  first_ = new GTestShell(testinfo, first_, &flags_);
346  TestRegistry::getCurrentRegistry()->addTest(first_);
347 }
348 
349 inline void GTestConvertor::addAllTestsFromTestCaseToTestRegistry(::testing::TestCase* testcase)
350 {
351  int currentTestCount = 0;
352  ::testing::TestInfo* currentTest = (::testing::TestInfo*) testcase->GetTestInfo(currentTestCount);
353  while (currentTest) {
354  addNewTestCaseForTestInfo(currentTest);
355  currentTestCount++;
356  currentTest = (::testing::TestInfo*) testcase->GetTestInfo(currentTestCount);
357  }
358 }
359 
360 inline void GTestConvertor::createDummyInSequenceToAndFailureReporterAvoidMemoryLeakInGMock()
361 {
362  ::testing::InSequence seq;
363  ::testing::internal::GetFailureReporter();
364 }
365 
366 inline void GTestConvertor::addAllGTestToTestRegistry()
367 {
368  createDummyInSequenceToAndFailureReporterAvoidMemoryLeakInGMock();
369  flags_.storeValuesOfGTestFLags();
370 
371  int argc = 2;
372  const char * argv[] = {"NameOfTheProgram", "--gmock_catch_leaked_mocks=0"};
373  ::testing::InitGoogleMock(&argc, (char**) argv);
374 
375  ::testing::UnitTest* unitTests = ::testing::UnitTest::GetInstance();
376 
377  int currentUnitTestCount = 0;
378  ::testing::TestCase* currentTestCase = (::testing::TestCase*) unitTests->GetTestCase(currentUnitTestCount);
379  while (currentTestCase) {
380  addAllTestsFromTestCaseToTestRegistry(currentTestCase);
381  currentUnitTestCount++;
382  currentTestCase = (::testing::TestCase*) unitTests->GetTestCase(currentUnitTestCount);
383  }
384 }
385 
386 
387 #endif
Definition: GTestConvertor.h:55
#define NULL
Definition: nm_bsp.h:76