github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/src/third_party/googlemock/test/gmock_stress_test.cc (about)

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