You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
7.1 KiB

  1. // Copyright 2007, 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. // Tests that Google Mock constructs can be used in a large number of
  30. // threads concurrently.
  31. #include "gmock/gmock.h"
  32. #include "gtest/gtest.h"
  33. namespace testing {
  34. namespace {
  35. // From gtest-port.h.
  36. using ::testing::internal::ThreadWithParam;
  37. // The maximum number of test threads (not including helper threads)
  38. // to create.
  39. const int kMaxTestThreads = 50;
  40. // How many times to repeat a task in a test thread.
  41. const int kRepeat = 50;
  42. class MockFoo {
  43. public:
  44. MOCK_METHOD1(Bar, int(int n)); // NOLINT
  45. MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT
  46. };
  47. // Helper for waiting for the given thread to finish and then deleting it.
  48. template <typename T>
  49. void JoinAndDelete(ThreadWithParam<T>* t) {
  50. t->Join();
  51. delete t;
  52. }
  53. struct Dummy {};
  54. // Tests that different mock objects can be used in their respective
  55. // threads. This should generate no Google Test failure.
  56. void TestConcurrentMockObjects(Dummy /* dummy */) {
  57. // Creates a mock and does some typical operations on it.
  58. MockFoo foo;
  59. ON_CALL(foo, Bar(_))
  60. .WillByDefault(Return(1));
  61. ON_CALL(foo, Baz(_, _))
  62. .WillByDefault(Return('b'));
  63. ON_CALL(foo, Baz(_, "you"))
  64. .WillByDefault(Return('a'));
  65. EXPECT_CALL(foo, Bar(0))
  66. .Times(AtMost(3));
  67. EXPECT_CALL(foo, Baz(_, _));
  68. EXPECT_CALL(foo, Baz("hi", "you"))
  69. .WillOnce(Return('z'))
  70. .WillRepeatedly(DoDefault());
  71. EXPECT_EQ(1, foo.Bar(0));
  72. EXPECT_EQ(1, foo.Bar(0));
  73. EXPECT_EQ('z', foo.Baz("hi", "you"));
  74. EXPECT_EQ('a', foo.Baz("hi", "you"));
  75. EXPECT_EQ('b', foo.Baz("hi", "me"));
  76. }
  77. // Tests invoking methods of the same mock object in multiple threads.
  78. struct Helper1Param {
  79. MockFoo* mock_foo;
  80. int* count;
  81. };
  82. void Helper1(Helper1Param param) {
  83. for (int i = 0; i < kRepeat; i++) {
  84. const char ch = param.mock_foo->Baz("a", "b");
  85. if (ch == 'a') {
  86. // It was an expected call.
  87. (*param.count)++;
  88. } else {
  89. // It was an excessive call.
  90. EXPECT_EQ('\0', ch);
  91. }
  92. // An unexpected call.
  93. EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
  94. // An uninteresting call.
  95. EXPECT_EQ(1, param.mock_foo->Bar(5));
  96. }
  97. }
  98. // This should generate 3*kRepeat + 1 failures in total.
  99. void TestConcurrentCallsOnSameObject(Dummy /* dummy */) {
  100. MockFoo foo;
  101. ON_CALL(foo, Bar(_))
  102. .WillByDefault(Return(1));
  103. EXPECT_CALL(foo, Baz(_, "b"))
  104. .Times(kRepeat)
  105. .WillRepeatedly(Return('a'));
  106. EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied.
  107. // This chunk of code should generate kRepeat failures about
  108. // excessive calls, and 2*kRepeat failures about unexpected calls.
  109. int count1 = 0;
  110. const Helper1Param param = { &foo, &count1 };
  111. ThreadWithParam<Helper1Param>* const t =
  112. new ThreadWithParam<Helper1Param>(Helper1, param, nullptr);
  113. int count2 = 0;
  114. const Helper1Param param2 = { &foo, &count2 };
  115. Helper1(param2);
  116. JoinAndDelete(t);
  117. EXPECT_EQ(kRepeat, count1 + count2);
  118. // foo's destructor should generate one failure about unsatisfied
  119. // expectation.
  120. }
  121. // Tests using the same mock object in multiple threads when the
  122. // expectations are partially ordered.
  123. void Helper2(MockFoo* foo) {
  124. for (int i = 0; i < kRepeat; i++) {
  125. foo->Bar(2);
  126. foo->Bar(3);
  127. }
  128. }
  129. // This should generate no Google Test failures.
  130. void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {
  131. MockFoo foo;
  132. Sequence s1, s2;
  133. {
  134. InSequence dummy;
  135. EXPECT_CALL(foo, Bar(0));
  136. EXPECT_CALL(foo, Bar(1))
  137. .InSequence(s1, s2);
  138. }
  139. EXPECT_CALL(foo, Bar(2))
  140. .Times(2*kRepeat)
  141. .InSequence(s1)
  142. .RetiresOnSaturation();
  143. EXPECT_CALL(foo, Bar(3))
  144. .Times(2*kRepeat)
  145. .InSequence(s2);
  146. {
  147. InSequence dummy;
  148. EXPECT_CALL(foo, Bar(2))
  149. .InSequence(s1, s2);
  150. EXPECT_CALL(foo, Bar(4));
  151. }
  152. foo.Bar(0);
  153. foo.Bar(1);
  154. ThreadWithParam<MockFoo*>* const t =
  155. new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr);
  156. Helper2(&foo);
  157. JoinAndDelete(t);
  158. foo.Bar(2);
  159. foo.Bar(4);
  160. }
  161. // Tests using Google Mock constructs in many threads concurrently.
  162. TEST(StressTest, CanUseGMockWithThreads) {
  163. void (*test_routines[])(Dummy dummy) = {
  164. &TestConcurrentMockObjects,
  165. &TestConcurrentCallsOnSameObject,
  166. &TestPartiallyOrderedExpectationsWithThreads,
  167. };
  168. const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]);
  169. const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
  170. const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
  171. ThreadWithParam<Dummy>* threads[kTestThreads] = {};
  172. for (int i = 0; i < kTestThreads; i++) {
  173. // Creates a thread to run the test function.
  174. threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines],
  175. Dummy(), nullptr);
  176. GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
  177. }
  178. // At this point, we have many threads running.
  179. for (int i = 0; i < kTestThreads; i++) {
  180. JoinAndDelete(threads[i]);
  181. }
  182. // Ensures that the correct number of failures have been reported.
  183. const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
  184. const TestResult& result = *info->result();
  185. const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine;
  186. GTEST_CHECK_(kExpectedFailures == result.total_part_count())
  187. << "Expected " << kExpectedFailures << " failures, but got "
  188. << result.total_part_count();
  189. }
  190. } // namespace
  191. } // namespace testing
  192. int main(int argc, char **argv) {
  193. testing::InitGoogleMock(&argc, argv);
  194. const int exit_code = RUN_ALL_TESTS(); // Expected to fail.
  195. GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
  196. printf("\nPASS\n");
  197. return 0;
  198. }