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