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 31// Tests that Google Mock constructs can be used in a large number of 32// threads concurrently. 33 34#include "gmock/gmock.h" 35#include "gtest/gtest.h" 36 37namespace testing { 38namespace { 39 40// From gtest-port.h. 41using ::testing::internal::ThreadWithParam; 42 43// The maximum number of test threads (not including helper threads) 44// to create. 45const int kMaxTestThreads = 50; 46 47// How many times to repeat a task in a test thread. 48const int kRepeat = 50; 49 50class MockFoo { 51 public: 52 MOCK_METHOD1(Bar, int(int n)); // NOLINT 53 MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT 54}; 55 56// Helper for waiting for the given thread to finish and then deleting it. 57template <typename T> 58void JoinAndDelete(ThreadWithParam<T>* t) { 59 t->Join(); 60 delete t; 61} 62 63using internal::linked_ptr; 64 65// Helper classes for testing using linked_ptr concurrently. 66 67class Base { 68 public: 69 explicit Base(int a_x) : x_(a_x) {} 70 virtual ~Base() {} 71 int x() const { return x_; } 72 private: 73 int x_; 74}; 75 76class Derived1 : public Base { 77 public: 78 Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {} 79 int y() const { return y_; } 80 private: 81 int y_; 82}; 83 84class Derived2 : public Base { 85 public: 86 Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {} 87 int z() const { return z_; } 88 private: 89 int z_; 90}; 91 92linked_ptr<Derived1> pointer1(new Derived1(1, 2)); 93linked_ptr<Derived2> pointer2(new Derived2(3, 4)); 94 95struct Dummy {}; 96 97// Tests that we can copy from a linked_ptr and read it concurrently. 98void TestConcurrentCopyAndReadLinkedPtr(Dummy /* dummy */) { 99 // Reads pointer1 and pointer2 while they are being copied from in 100 // another thread. 101 EXPECT_EQ(1, pointer1->x()); 102 EXPECT_EQ(2, pointer1->y()); 103 EXPECT_EQ(3, pointer2->x()); 104 EXPECT_EQ(4, pointer2->z()); 105 106 // Copies from pointer1. 107 linked_ptr<Derived1> p1(pointer1); 108 EXPECT_EQ(1, p1->x()); 109 EXPECT_EQ(2, p1->y()); 110 111 // Assigns from pointer2 where the LHS was empty. 112 linked_ptr<Base> p2; 113 p2 = pointer1; 114 EXPECT_EQ(1, p2->x()); 115 116 // Assigns from pointer2 where the LHS was not empty. 117 p2 = pointer2; 118 EXPECT_EQ(3, p2->x()); 119} 120 121const linked_ptr<Derived1> p0(new Derived1(1, 2)); 122 123// Tests that we can concurrently modify two linked_ptrs that point to 124// the same object. 125void TestConcurrentWriteToEqualLinkedPtr(Dummy /* dummy */) { 126 // p1 and p2 point to the same, shared thing. One thread resets p1. 127 // Another thread assigns to p2. This will cause the same 128 // underlying "ring" to be updated concurrently. 129 linked_ptr<Derived1> p1(p0); 130 linked_ptr<Derived1> p2(p0); 131 132 EXPECT_EQ(1, p1->x()); 133 EXPECT_EQ(2, p1->y()); 134 135 EXPECT_EQ(1, p2->x()); 136 EXPECT_EQ(2, p2->y()); 137 138 p1.reset(); 139 p2 = p0; 140 141 EXPECT_EQ(1, p2->x()); 142 EXPECT_EQ(2, p2->y()); 143} 144 145// Tests that different mock objects can be used in their respective 146// threads. This should generate no Google Test failure. 147void TestConcurrentMockObjects(Dummy /* dummy */) { 148 // Creates a mock and does some typical operations on it. 149 MockFoo foo; 150 ON_CALL(foo, Bar(_)) 151 .WillByDefault(Return(1)); 152 ON_CALL(foo, Baz(_, _)) 153 .WillByDefault(Return('b')); 154 ON_CALL(foo, Baz(_, "you")) 155 .WillByDefault(Return('a')); 156 157 EXPECT_CALL(foo, Bar(0)) 158 .Times(AtMost(3)); 159 EXPECT_CALL(foo, Baz(_, _)); 160 EXPECT_CALL(foo, Baz("hi", "you")) 161 .WillOnce(Return('z')) 162 .WillRepeatedly(DoDefault()); 163 164 EXPECT_EQ(1, foo.Bar(0)); 165 EXPECT_EQ(1, foo.Bar(0)); 166 EXPECT_EQ('z', foo.Baz("hi", "you")); 167 EXPECT_EQ('a', foo.Baz("hi", "you")); 168 EXPECT_EQ('b', foo.Baz("hi", "me")); 169} 170 171// Tests invoking methods of the same mock object in multiple threads. 172 173struct Helper1Param { 174 MockFoo* mock_foo; 175 int* count; 176}; 177 178void Helper1(Helper1Param param) { 179 for (int i = 0; i < kRepeat; i++) { 180 const char ch = param.mock_foo->Baz("a", "b"); 181 if (ch == 'a') { 182 // It was an expected call. 183 (*param.count)++; 184 } else { 185 // It was an excessive call. 186 EXPECT_EQ('\0', ch); 187 } 188 189 // An unexpected call. 190 EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure."; 191 192 // An uninteresting call. 193 EXPECT_EQ(1, param.mock_foo->Bar(5)); 194 } 195} 196 197// This should generate 3*kRepeat + 1 failures in total. 198void TestConcurrentCallsOnSameObject(Dummy /* dummy */) { 199 MockFoo foo; 200 201 ON_CALL(foo, Bar(_)) 202 .WillByDefault(Return(1)); 203 EXPECT_CALL(foo, Baz(_, "b")) 204 .Times(kRepeat) 205 .WillRepeatedly(Return('a')); 206 EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied. 207 208 // This chunk of code should generate kRepeat failures about 209 // excessive calls, and 2*kRepeat failures about unexpected calls. 210 int count1 = 0; 211 const Helper1Param param = { &foo, &count1 }; 212 ThreadWithParam<Helper1Param>* const t = 213 new ThreadWithParam<Helper1Param>(Helper1, param, NULL); 214 215 int count2 = 0; 216 const Helper1Param param2 = { &foo, &count2 }; 217 Helper1(param2); 218 JoinAndDelete(t); 219 220 EXPECT_EQ(kRepeat, count1 + count2); 221 222 // foo's destructor should generate one failure about unsatisfied 223 // expectation. 224} 225 226// Tests using the same mock object in multiple threads when the 227// expectations are partially ordered. 228 229void Helper2(MockFoo* foo) { 230 for (int i = 0; i < kRepeat; i++) { 231 foo->Bar(2); 232 foo->Bar(3); 233 } 234} 235 236// This should generate no Google Test failures. 237void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) { 238 MockFoo foo; 239 Sequence s1, s2; 240 241 { 242 InSequence dummy; 243 EXPECT_CALL(foo, Bar(0)); 244 EXPECT_CALL(foo, Bar(1)) 245 .InSequence(s1, s2); 246 } 247 248 EXPECT_CALL(foo, Bar(2)) 249 .Times(2*kRepeat) 250 .InSequence(s1) 251 .RetiresOnSaturation(); 252 EXPECT_CALL(foo, Bar(3)) 253 .Times(2*kRepeat) 254 .InSequence(s2); 255 256 { 257 InSequence dummy; 258 EXPECT_CALL(foo, Bar(2)) 259 .InSequence(s1, s2); 260 EXPECT_CALL(foo, Bar(4)); 261 } 262 263 foo.Bar(0); 264 foo.Bar(1); 265 266 ThreadWithParam<MockFoo*>* const t = 267 new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL); 268 Helper2(&foo); 269 JoinAndDelete(t); 270 271 foo.Bar(2); 272 foo.Bar(4); 273} 274 275// Tests using Google Mock constructs in many threads concurrently. 276TEST(StressTest, CanUseGMockWithThreads) { 277 void (*test_routines[])(Dummy dummy) = { 278 &TestConcurrentCopyAndReadLinkedPtr, 279 &TestConcurrentWriteToEqualLinkedPtr, 280 &TestConcurrentMockObjects, 281 &TestConcurrentCallsOnSameObject, 282 &TestPartiallyOrderedExpectationsWithThreads, 283 }; 284 285 const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]); 286 const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines; 287 const int kTestThreads = kCopiesOfEachRoutine * kRoutines; 288 ThreadWithParam<Dummy>* threads[kTestThreads] = {}; 289 for (int i = 0; i < kTestThreads; i++) { 290 // Creates a thread to run the test function. 291 threads[i] = 292 new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL); 293 GTEST_LOG_(INFO) << "Thread #" << i << " running . . ."; 294 } 295 296 // At this point, we have many threads running. 297 for (int i = 0; i < kTestThreads; i++) { 298 JoinAndDelete(threads[i]); 299 } 300 301 // Ensures that the correct number of failures have been reported. 302 const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); 303 const TestResult& result = *info->result(); 304 const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine; 305 GTEST_CHECK_(kExpectedFailures == result.total_part_count()) 306 << "Expected " << kExpectedFailures << " failures, but got " 307 << result.total_part_count(); 308} 309 310} // namespace 311} // namespace testing 312 313int main(int argc, char **argv) { 314 testing::InitGoogleMock(&argc, argv); 315 316 const int exit_code = RUN_ALL_TESTS(); // Expected to fail. 317 GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected"; 318 319 printf("\nPASS\n"); 320 return 0; 321} 322