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