Path: blob/main/contrib/googletest/googlemock/test/gmock_stress_test.cc
48255 views
// Copyright 2007, Google Inc.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above10// copyright notice, this list of conditions and the following disclaimer11// in the documentation and/or other materials provided with the12// distribution.13// * Neither the name of Google Inc. nor the names of its14// contributors may be used to endorse or promote products derived from15// this software without specific prior written permission.16//17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2829// Tests that Google Mock constructs can be used in a large number of30// threads concurrently.3132#include "gmock/gmock.h"33#include "gtest/gtest.h"3435namespace testing {36namespace {3738// From gtest-port.h.39using ::testing::internal::ThreadWithParam;4041// The maximum number of test threads (not including helper threads)42// to create.43const int kMaxTestThreads = 50;4445// How many times to repeat a task in a test thread.46const int kRepeat = 50;4748class MockFoo {49public:50MOCK_METHOD1(Bar, int(int n)); // NOLINT51MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT52};5354// Helper for waiting for the given thread to finish and then deleting it.55template <typename T>56void JoinAndDelete(ThreadWithParam<T>* t) {57t->Join();58delete t;59}6061struct Dummy {};6263// Tests that different mock objects can be used in their respective64// threads. This should generate no Google Test failure.65void TestConcurrentMockObjects(Dummy /* dummy */) {66// Creates a mock and does some typical operations on it.67MockFoo foo;68ON_CALL(foo, Bar(_)).WillByDefault(Return(1));69ON_CALL(foo, Baz(_, _)).WillByDefault(Return('b'));70ON_CALL(foo, Baz(_, "you")).WillByDefault(Return('a'));7172EXPECT_CALL(foo, Bar(0)).Times(AtMost(3));73EXPECT_CALL(foo, Baz(_, _));74EXPECT_CALL(foo, Baz("hi", "you"))75.WillOnce(Return('z'))76.WillRepeatedly(DoDefault());7778EXPECT_EQ(1, foo.Bar(0));79EXPECT_EQ(1, foo.Bar(0));80EXPECT_EQ('z', foo.Baz("hi", "you"));81EXPECT_EQ('a', foo.Baz("hi", "you"));82EXPECT_EQ('b', foo.Baz("hi", "me"));83}8485// Tests invoking methods of the same mock object in multiple threads.8687struct Helper1Param {88MockFoo* mock_foo;89int* count;90};9192void Helper1(Helper1Param param) {93for (int i = 0; i < kRepeat; i++) {94const char ch = param.mock_foo->Baz("a", "b");95if (ch == 'a') {96// It was an expected call.97(*param.count)++;98} else {99// It was an excessive call.100EXPECT_EQ('\0', ch);101}102103// An unexpected call.104EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";105106// An uninteresting call.107EXPECT_EQ(1, param.mock_foo->Bar(5));108}109}110111// This should generate 3*kRepeat + 1 failures in total.112void TestConcurrentCallsOnSameObject(Dummy /* dummy */) {113MockFoo foo;114115ON_CALL(foo, Bar(_)).WillByDefault(Return(1));116EXPECT_CALL(foo, Baz(_, "b")).Times(kRepeat).WillRepeatedly(Return('a'));117EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied.118119// This chunk of code should generate kRepeat failures about120// excessive calls, and 2*kRepeat failures about unexpected calls.121int count1 = 0;122const Helper1Param param = {&foo, &count1};123ThreadWithParam<Helper1Param>* const t =124new ThreadWithParam<Helper1Param>(Helper1, param, nullptr);125126int count2 = 0;127const Helper1Param param2 = {&foo, &count2};128Helper1(param2);129JoinAndDelete(t);130131EXPECT_EQ(kRepeat, count1 + count2);132133// foo's destructor should generate one failure about unsatisfied134// expectation.135}136137// Tests using the same mock object in multiple threads when the138// expectations are partially ordered.139140void Helper2(MockFoo* foo) {141for (int i = 0; i < kRepeat; i++) {142foo->Bar(2);143foo->Bar(3);144}145}146147// This should generate no Google Test failures.148void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {149MockFoo foo;150Sequence s1, s2;151152{153InSequence dummy;154EXPECT_CALL(foo, Bar(0));155EXPECT_CALL(foo, Bar(1)).InSequence(s1, s2);156}157158EXPECT_CALL(foo, Bar(2))159.Times(2 * kRepeat)160.InSequence(s1)161.RetiresOnSaturation();162EXPECT_CALL(foo, Bar(3)).Times(2 * kRepeat).InSequence(s2);163164{165InSequence dummy;166EXPECT_CALL(foo, Bar(2)).InSequence(s1, s2);167EXPECT_CALL(foo, Bar(4));168}169170foo.Bar(0);171foo.Bar(1);172173ThreadWithParam<MockFoo*>* const t =174new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr);175Helper2(&foo);176JoinAndDelete(t);177178foo.Bar(2);179foo.Bar(4);180}181182// Tests using Google Mock constructs in many threads concurrently.183TEST(StressTest, CanUseGMockWithThreads) {184void (*test_routines[])(Dummy dummy) = {185&TestConcurrentMockObjects,186&TestConcurrentCallsOnSameObject,187&TestPartiallyOrderedExpectationsWithThreads,188};189190const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]);191const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;192const int kTestThreads = kCopiesOfEachRoutine * kRoutines;193ThreadWithParam<Dummy>* threads[kTestThreads] = {};194for (int i = 0; i < kTestThreads; i++) {195// Creates a thread to run the test function.196threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines],197Dummy(), nullptr);198GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";199}200201// At this point, we have many threads running.202for (int i = 0; i < kTestThreads; i++) {203JoinAndDelete(threads[i]);204}205206// Ensures that the correct number of failures have been reported.207const TestInfo* const info = UnitTest::GetInstance()->current_test_info();208const TestResult& result = *info->result();209const int kExpectedFailures = (3 * kRepeat + 1) * kCopiesOfEachRoutine;210GTEST_CHECK_(kExpectedFailures == result.total_part_count())211<< "Expected " << kExpectedFailures << " failures, but got "212<< result.total_part_count();213}214215} // namespace216} // namespace testing217218int main(int argc, char** argv) {219testing::InitGoogleMock(&argc, argv);220221const int exit_code = RUN_ALL_TESTS(); // Expected to fail.222GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";223224printf("\nPASS\n");225return 0;226}227228229