1*b89a7cc2SEnji Cooper // Copyright 2007, Google Inc. 2*b89a7cc2SEnji Cooper // All rights reserved. 3*b89a7cc2SEnji Cooper // 4*b89a7cc2SEnji Cooper // Redistribution and use in source and binary forms, with or without 5*b89a7cc2SEnji Cooper // modification, are permitted provided that the following conditions are 6*b89a7cc2SEnji Cooper // met: 7*b89a7cc2SEnji Cooper // 8*b89a7cc2SEnji Cooper // * Redistributions of source code must retain the above copyright 9*b89a7cc2SEnji Cooper // notice, this list of conditions and the following disclaimer. 10*b89a7cc2SEnji Cooper // * Redistributions in binary form must reproduce the above 11*b89a7cc2SEnji Cooper // copyright notice, this list of conditions and the following disclaimer 12*b89a7cc2SEnji Cooper // in the documentation and/or other materials provided with the 13*b89a7cc2SEnji Cooper // distribution. 14*b89a7cc2SEnji Cooper // * Neither the name of Google Inc. nor the names of its 15*b89a7cc2SEnji Cooper // contributors may be used to endorse or promote products derived from 16*b89a7cc2SEnji Cooper // this software without specific prior written permission. 17*b89a7cc2SEnji Cooper // 18*b89a7cc2SEnji Cooper // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19*b89a7cc2SEnji Cooper // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20*b89a7cc2SEnji Cooper // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21*b89a7cc2SEnji Cooper // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22*b89a7cc2SEnji Cooper // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23*b89a7cc2SEnji Cooper // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24*b89a7cc2SEnji Cooper // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25*b89a7cc2SEnji Cooper // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26*b89a7cc2SEnji Cooper // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27*b89a7cc2SEnji Cooper // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28*b89a7cc2SEnji Cooper // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*b89a7cc2SEnji Cooper 30*b89a7cc2SEnji Cooper 31*b89a7cc2SEnji Cooper // Tests that Google Mock constructs can be used in a large number of 32*b89a7cc2SEnji Cooper // threads concurrently. 33*b89a7cc2SEnji Cooper 34*b89a7cc2SEnji Cooper #include "gmock/gmock.h" 35*b89a7cc2SEnji Cooper #include "gtest/gtest.h" 36*b89a7cc2SEnji Cooper 37*b89a7cc2SEnji Cooper namespace testing { 38*b89a7cc2SEnji Cooper namespace { 39*b89a7cc2SEnji Cooper 40*b89a7cc2SEnji Cooper // From gtest-port.h. 41*b89a7cc2SEnji Cooper using ::testing::internal::ThreadWithParam; 42*b89a7cc2SEnji Cooper 43*b89a7cc2SEnji Cooper // The maximum number of test threads (not including helper threads) 44*b89a7cc2SEnji Cooper // to create. 45*b89a7cc2SEnji Cooper const int kMaxTestThreads = 50; 46*b89a7cc2SEnji Cooper 47*b89a7cc2SEnji Cooper // How many times to repeat a task in a test thread. 48*b89a7cc2SEnji Cooper const int kRepeat = 50; 49*b89a7cc2SEnji Cooper 50*b89a7cc2SEnji Cooper class MockFoo { 51*b89a7cc2SEnji Cooper public: 52*b89a7cc2SEnji Cooper MOCK_METHOD1(Bar, int(int n)); // NOLINT 53*b89a7cc2SEnji Cooper MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT 54*b89a7cc2SEnji Cooper }; 55*b89a7cc2SEnji Cooper 56*b89a7cc2SEnji Cooper // Helper for waiting for the given thread to finish and then deleting it. 57*b89a7cc2SEnji Cooper template <typename T> 58*b89a7cc2SEnji Cooper void JoinAndDelete(ThreadWithParam<T>* t) { 59*b89a7cc2SEnji Cooper t->Join(); 60*b89a7cc2SEnji Cooper delete t; 61*b89a7cc2SEnji Cooper } 62*b89a7cc2SEnji Cooper 63*b89a7cc2SEnji Cooper using internal::linked_ptr; 64*b89a7cc2SEnji Cooper 65*b89a7cc2SEnji Cooper // Helper classes for testing using linked_ptr concurrently. 66*b89a7cc2SEnji Cooper 67*b89a7cc2SEnji Cooper class Base { 68*b89a7cc2SEnji Cooper public: 69*b89a7cc2SEnji Cooper explicit Base(int a_x) : x_(a_x) {} 70*b89a7cc2SEnji Cooper virtual ~Base() {} 71*b89a7cc2SEnji Cooper int x() const { return x_; } 72*b89a7cc2SEnji Cooper private: 73*b89a7cc2SEnji Cooper int x_; 74*b89a7cc2SEnji Cooper }; 75*b89a7cc2SEnji Cooper 76*b89a7cc2SEnji Cooper class Derived1 : public Base { 77*b89a7cc2SEnji Cooper public: 78*b89a7cc2SEnji Cooper Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {} 79*b89a7cc2SEnji Cooper int y() const { return y_; } 80*b89a7cc2SEnji Cooper private: 81*b89a7cc2SEnji Cooper int y_; 82*b89a7cc2SEnji Cooper }; 83*b89a7cc2SEnji Cooper 84*b89a7cc2SEnji Cooper class Derived2 : public Base { 85*b89a7cc2SEnji Cooper public: 86*b89a7cc2SEnji Cooper Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {} 87*b89a7cc2SEnji Cooper int z() const { return z_; } 88*b89a7cc2SEnji Cooper private: 89*b89a7cc2SEnji Cooper int z_; 90*b89a7cc2SEnji Cooper }; 91*b89a7cc2SEnji Cooper 92*b89a7cc2SEnji Cooper linked_ptr<Derived1> pointer1(new Derived1(1, 2)); 93*b89a7cc2SEnji Cooper linked_ptr<Derived2> pointer2(new Derived2(3, 4)); 94*b89a7cc2SEnji Cooper 95*b89a7cc2SEnji Cooper struct Dummy {}; 96*b89a7cc2SEnji Cooper 97*b89a7cc2SEnji Cooper // Tests that we can copy from a linked_ptr and read it concurrently. 98*b89a7cc2SEnji Cooper void TestConcurrentCopyAndReadLinkedPtr(Dummy /* dummy */) { 99*b89a7cc2SEnji Cooper // Reads pointer1 and pointer2 while they are being copied from in 100*b89a7cc2SEnji Cooper // another thread. 101*b89a7cc2SEnji Cooper EXPECT_EQ(1, pointer1->x()); 102*b89a7cc2SEnji Cooper EXPECT_EQ(2, pointer1->y()); 103*b89a7cc2SEnji Cooper EXPECT_EQ(3, pointer2->x()); 104*b89a7cc2SEnji Cooper EXPECT_EQ(4, pointer2->z()); 105*b89a7cc2SEnji Cooper 106*b89a7cc2SEnji Cooper // Copies from pointer1. 107*b89a7cc2SEnji Cooper linked_ptr<Derived1> p1(pointer1); 108*b89a7cc2SEnji Cooper EXPECT_EQ(1, p1->x()); 109*b89a7cc2SEnji Cooper EXPECT_EQ(2, p1->y()); 110*b89a7cc2SEnji Cooper 111*b89a7cc2SEnji Cooper // Assigns from pointer2 where the LHS was empty. 112*b89a7cc2SEnji Cooper linked_ptr<Base> p2; 113*b89a7cc2SEnji Cooper p2 = pointer1; 114*b89a7cc2SEnji Cooper EXPECT_EQ(1, p2->x()); 115*b89a7cc2SEnji Cooper 116*b89a7cc2SEnji Cooper // Assigns from pointer2 where the LHS was not empty. 117*b89a7cc2SEnji Cooper p2 = pointer2; 118*b89a7cc2SEnji Cooper EXPECT_EQ(3, p2->x()); 119*b89a7cc2SEnji Cooper } 120*b89a7cc2SEnji Cooper 121*b89a7cc2SEnji Cooper const linked_ptr<Derived1> p0(new Derived1(1, 2)); 122*b89a7cc2SEnji Cooper 123*b89a7cc2SEnji Cooper // Tests that we can concurrently modify two linked_ptrs that point to 124*b89a7cc2SEnji Cooper // the same object. 125*b89a7cc2SEnji Cooper void TestConcurrentWriteToEqualLinkedPtr(Dummy /* dummy */) { 126*b89a7cc2SEnji Cooper // p1 and p2 point to the same, shared thing. One thread resets p1. 127*b89a7cc2SEnji Cooper // Another thread assigns to p2. This will cause the same 128*b89a7cc2SEnji Cooper // underlying "ring" to be updated concurrently. 129*b89a7cc2SEnji Cooper linked_ptr<Derived1> p1(p0); 130*b89a7cc2SEnji Cooper linked_ptr<Derived1> p2(p0); 131*b89a7cc2SEnji Cooper 132*b89a7cc2SEnji Cooper EXPECT_EQ(1, p1->x()); 133*b89a7cc2SEnji Cooper EXPECT_EQ(2, p1->y()); 134*b89a7cc2SEnji Cooper 135*b89a7cc2SEnji Cooper EXPECT_EQ(1, p2->x()); 136*b89a7cc2SEnji Cooper EXPECT_EQ(2, p2->y()); 137*b89a7cc2SEnji Cooper 138*b89a7cc2SEnji Cooper p1.reset(); 139*b89a7cc2SEnji Cooper p2 = p0; 140*b89a7cc2SEnji Cooper 141*b89a7cc2SEnji Cooper EXPECT_EQ(1, p2->x()); 142*b89a7cc2SEnji Cooper EXPECT_EQ(2, p2->y()); 143*b89a7cc2SEnji Cooper } 144*b89a7cc2SEnji Cooper 145*b89a7cc2SEnji Cooper // Tests that different mock objects can be used in their respective 146*b89a7cc2SEnji Cooper // threads. This should generate no Google Test failure. 147*b89a7cc2SEnji Cooper void TestConcurrentMockObjects(Dummy /* dummy */) { 148*b89a7cc2SEnji Cooper // Creates a mock and does some typical operations on it. 149*b89a7cc2SEnji Cooper MockFoo foo; 150*b89a7cc2SEnji Cooper ON_CALL(foo, Bar(_)) 151*b89a7cc2SEnji Cooper .WillByDefault(Return(1)); 152*b89a7cc2SEnji Cooper ON_CALL(foo, Baz(_, _)) 153*b89a7cc2SEnji Cooper .WillByDefault(Return('b')); 154*b89a7cc2SEnji Cooper ON_CALL(foo, Baz(_, "you")) 155*b89a7cc2SEnji Cooper .WillByDefault(Return('a')); 156*b89a7cc2SEnji Cooper 157*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(0)) 158*b89a7cc2SEnji Cooper .Times(AtMost(3)); 159*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Baz(_, _)); 160*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Baz("hi", "you")) 161*b89a7cc2SEnji Cooper .WillOnce(Return('z')) 162*b89a7cc2SEnji Cooper .WillRepeatedly(DoDefault()); 163*b89a7cc2SEnji Cooper 164*b89a7cc2SEnji Cooper EXPECT_EQ(1, foo.Bar(0)); 165*b89a7cc2SEnji Cooper EXPECT_EQ(1, foo.Bar(0)); 166*b89a7cc2SEnji Cooper EXPECT_EQ('z', foo.Baz("hi", "you")); 167*b89a7cc2SEnji Cooper EXPECT_EQ('a', foo.Baz("hi", "you")); 168*b89a7cc2SEnji Cooper EXPECT_EQ('b', foo.Baz("hi", "me")); 169*b89a7cc2SEnji Cooper } 170*b89a7cc2SEnji Cooper 171*b89a7cc2SEnji Cooper // Tests invoking methods of the same mock object in multiple threads. 172*b89a7cc2SEnji Cooper 173*b89a7cc2SEnji Cooper struct Helper1Param { 174*b89a7cc2SEnji Cooper MockFoo* mock_foo; 175*b89a7cc2SEnji Cooper int* count; 176*b89a7cc2SEnji Cooper }; 177*b89a7cc2SEnji Cooper 178*b89a7cc2SEnji Cooper void Helper1(Helper1Param param) { 179*b89a7cc2SEnji Cooper for (int i = 0; i < kRepeat; i++) { 180*b89a7cc2SEnji Cooper const char ch = param.mock_foo->Baz("a", "b"); 181*b89a7cc2SEnji Cooper if (ch == 'a') { 182*b89a7cc2SEnji Cooper // It was an expected call. 183*b89a7cc2SEnji Cooper (*param.count)++; 184*b89a7cc2SEnji Cooper } else { 185*b89a7cc2SEnji Cooper // It was an excessive call. 186*b89a7cc2SEnji Cooper EXPECT_EQ('\0', ch); 187*b89a7cc2SEnji Cooper } 188*b89a7cc2SEnji Cooper 189*b89a7cc2SEnji Cooper // An unexpected call. 190*b89a7cc2SEnji Cooper EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure."; 191*b89a7cc2SEnji Cooper 192*b89a7cc2SEnji Cooper // An uninteresting call. 193*b89a7cc2SEnji Cooper EXPECT_EQ(1, param.mock_foo->Bar(5)); 194*b89a7cc2SEnji Cooper } 195*b89a7cc2SEnji Cooper } 196*b89a7cc2SEnji Cooper 197*b89a7cc2SEnji Cooper // This should generate 3*kRepeat + 1 failures in total. 198*b89a7cc2SEnji Cooper void TestConcurrentCallsOnSameObject(Dummy /* dummy */) { 199*b89a7cc2SEnji Cooper MockFoo foo; 200*b89a7cc2SEnji Cooper 201*b89a7cc2SEnji Cooper ON_CALL(foo, Bar(_)) 202*b89a7cc2SEnji Cooper .WillByDefault(Return(1)); 203*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Baz(_, "b")) 204*b89a7cc2SEnji Cooper .Times(kRepeat) 205*b89a7cc2SEnji Cooper .WillRepeatedly(Return('a')); 206*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied. 207*b89a7cc2SEnji Cooper 208*b89a7cc2SEnji Cooper // This chunk of code should generate kRepeat failures about 209*b89a7cc2SEnji Cooper // excessive calls, and 2*kRepeat failures about unexpected calls. 210*b89a7cc2SEnji Cooper int count1 = 0; 211*b89a7cc2SEnji Cooper const Helper1Param param = { &foo, &count1 }; 212*b89a7cc2SEnji Cooper ThreadWithParam<Helper1Param>* const t = 213*b89a7cc2SEnji Cooper new ThreadWithParam<Helper1Param>(Helper1, param, NULL); 214*b89a7cc2SEnji Cooper 215*b89a7cc2SEnji Cooper int count2 = 0; 216*b89a7cc2SEnji Cooper const Helper1Param param2 = { &foo, &count2 }; 217*b89a7cc2SEnji Cooper Helper1(param2); 218*b89a7cc2SEnji Cooper JoinAndDelete(t); 219*b89a7cc2SEnji Cooper 220*b89a7cc2SEnji Cooper EXPECT_EQ(kRepeat, count1 + count2); 221*b89a7cc2SEnji Cooper 222*b89a7cc2SEnji Cooper // foo's destructor should generate one failure about unsatisfied 223*b89a7cc2SEnji Cooper // expectation. 224*b89a7cc2SEnji Cooper } 225*b89a7cc2SEnji Cooper 226*b89a7cc2SEnji Cooper // Tests using the same mock object in multiple threads when the 227*b89a7cc2SEnji Cooper // expectations are partially ordered. 228*b89a7cc2SEnji Cooper 229*b89a7cc2SEnji Cooper void Helper2(MockFoo* foo) { 230*b89a7cc2SEnji Cooper for (int i = 0; i < kRepeat; i++) { 231*b89a7cc2SEnji Cooper foo->Bar(2); 232*b89a7cc2SEnji Cooper foo->Bar(3); 233*b89a7cc2SEnji Cooper } 234*b89a7cc2SEnji Cooper } 235*b89a7cc2SEnji Cooper 236*b89a7cc2SEnji Cooper // This should generate no Google Test failures. 237*b89a7cc2SEnji Cooper void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) { 238*b89a7cc2SEnji Cooper MockFoo foo; 239*b89a7cc2SEnji Cooper Sequence s1, s2; 240*b89a7cc2SEnji Cooper 241*b89a7cc2SEnji Cooper { 242*b89a7cc2SEnji Cooper InSequence dummy; 243*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(0)); 244*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(1)) 245*b89a7cc2SEnji Cooper .InSequence(s1, s2); 246*b89a7cc2SEnji Cooper } 247*b89a7cc2SEnji Cooper 248*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(2)) 249*b89a7cc2SEnji Cooper .Times(2*kRepeat) 250*b89a7cc2SEnji Cooper .InSequence(s1) 251*b89a7cc2SEnji Cooper .RetiresOnSaturation(); 252*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(3)) 253*b89a7cc2SEnji Cooper .Times(2*kRepeat) 254*b89a7cc2SEnji Cooper .InSequence(s2); 255*b89a7cc2SEnji Cooper 256*b89a7cc2SEnji Cooper { 257*b89a7cc2SEnji Cooper InSequence dummy; 258*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(2)) 259*b89a7cc2SEnji Cooper .InSequence(s1, s2); 260*b89a7cc2SEnji Cooper EXPECT_CALL(foo, Bar(4)); 261*b89a7cc2SEnji Cooper } 262*b89a7cc2SEnji Cooper 263*b89a7cc2SEnji Cooper foo.Bar(0); 264*b89a7cc2SEnji Cooper foo.Bar(1); 265*b89a7cc2SEnji Cooper 266*b89a7cc2SEnji Cooper ThreadWithParam<MockFoo*>* const t = 267*b89a7cc2SEnji Cooper new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL); 268*b89a7cc2SEnji Cooper Helper2(&foo); 269*b89a7cc2SEnji Cooper JoinAndDelete(t); 270*b89a7cc2SEnji Cooper 271*b89a7cc2SEnji Cooper foo.Bar(2); 272*b89a7cc2SEnji Cooper foo.Bar(4); 273*b89a7cc2SEnji Cooper } 274*b89a7cc2SEnji Cooper 275*b89a7cc2SEnji Cooper // Tests using Google Mock constructs in many threads concurrently. 276*b89a7cc2SEnji Cooper TEST(StressTest, CanUseGMockWithThreads) { 277*b89a7cc2SEnji Cooper void (*test_routines[])(Dummy dummy) = { 278*b89a7cc2SEnji Cooper &TestConcurrentCopyAndReadLinkedPtr, 279*b89a7cc2SEnji Cooper &TestConcurrentWriteToEqualLinkedPtr, 280*b89a7cc2SEnji Cooper &TestConcurrentMockObjects, 281*b89a7cc2SEnji Cooper &TestConcurrentCallsOnSameObject, 282*b89a7cc2SEnji Cooper &TestPartiallyOrderedExpectationsWithThreads, 283*b89a7cc2SEnji Cooper }; 284*b89a7cc2SEnji Cooper 285*b89a7cc2SEnji Cooper const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]); 286*b89a7cc2SEnji Cooper const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines; 287*b89a7cc2SEnji Cooper const int kTestThreads = kCopiesOfEachRoutine * kRoutines; 288*b89a7cc2SEnji Cooper ThreadWithParam<Dummy>* threads[kTestThreads] = {}; 289*b89a7cc2SEnji Cooper for (int i = 0; i < kTestThreads; i++) { 290*b89a7cc2SEnji Cooper // Creates a thread to run the test function. 291*b89a7cc2SEnji Cooper threads[i] = 292*b89a7cc2SEnji Cooper new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL); 293*b89a7cc2SEnji Cooper GTEST_LOG_(INFO) << "Thread #" << i << " running . . ."; 294*b89a7cc2SEnji Cooper } 295*b89a7cc2SEnji Cooper 296*b89a7cc2SEnji Cooper // At this point, we have many threads running. 297*b89a7cc2SEnji Cooper for (int i = 0; i < kTestThreads; i++) { 298*b89a7cc2SEnji Cooper JoinAndDelete(threads[i]); 299*b89a7cc2SEnji Cooper } 300*b89a7cc2SEnji Cooper 301*b89a7cc2SEnji Cooper // Ensures that the correct number of failures have been reported. 302*b89a7cc2SEnji Cooper const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); 303*b89a7cc2SEnji Cooper const TestResult& result = *info->result(); 304*b89a7cc2SEnji Cooper const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine; 305*b89a7cc2SEnji Cooper GTEST_CHECK_(kExpectedFailures == result.total_part_count()) 306*b89a7cc2SEnji Cooper << "Expected " << kExpectedFailures << " failures, but got " 307*b89a7cc2SEnji Cooper << result.total_part_count(); 308*b89a7cc2SEnji Cooper } 309*b89a7cc2SEnji Cooper 310*b89a7cc2SEnji Cooper } // namespace 311*b89a7cc2SEnji Cooper } // namespace testing 312*b89a7cc2SEnji Cooper 313*b89a7cc2SEnji Cooper int main(int argc, char **argv) { 314*b89a7cc2SEnji Cooper testing::InitGoogleMock(&argc, argv); 315*b89a7cc2SEnji Cooper 316*b89a7cc2SEnji Cooper const int exit_code = RUN_ALL_TESTS(); // Expected to fail. 317*b89a7cc2SEnji Cooper GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected"; 318*b89a7cc2SEnji Cooper 319*b89a7cc2SEnji Cooper printf("\nPASS\n"); 320*b89a7cc2SEnji Cooper return 0; 321*b89a7cc2SEnji Cooper } 322