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 37 namespace testing { 38 namespace { 39 40 // From gtest-port.h. 41 using ::testing::internal::ThreadWithParam; 42 43 // The maximum number of test threads (not including helper threads) 44 // to create. 45 const int kMaxTestThreads = 50; 46 47 // How many times to repeat a task in a test thread. 48 const int kRepeat = 50; 49 50 class 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. 57 template <typename T> 58 void JoinAndDelete(ThreadWithParam<T>* t) { 59 t->Join(); 60 delete t; 61 } 62 63 using internal::linked_ptr; 64 65 // Helper classes for testing using linked_ptr concurrently. 66 67 class 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 76 class 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 84 class 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 92 linked_ptr<Derived1> pointer1(new Derived1(1, 2)); 93 linked_ptr<Derived2> pointer2(new Derived2(3, 4)); 94 95 struct Dummy {}; 96 97 // Tests that we can copy from a linked_ptr and read it concurrently. 98 void 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 121 const 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. 125 void 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. 147 void 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 173 struct Helper1Param { 174 MockFoo* mock_foo; 175 int* count; 176 }; 177 178 void 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. 198 void 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 229 void 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. 237 void 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. 276 TEST(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 313 int 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