xref: /freebsd/contrib/googletest/googlemock/test/gmock_stress_test.cc (revision 28f6c2f292806bf31230a959bc4b19d7081669a7)
1b89a7cc2SEnji Cooper // Copyright 2007, Google Inc.
2b89a7cc2SEnji Cooper // All rights reserved.
3b89a7cc2SEnji Cooper //
4b89a7cc2SEnji Cooper // Redistribution and use in source and binary forms, with or without
5b89a7cc2SEnji Cooper // modification, are permitted provided that the following conditions are
6b89a7cc2SEnji Cooper // met:
7b89a7cc2SEnji Cooper //
8b89a7cc2SEnji Cooper //     * Redistributions of source code must retain the above copyright
9b89a7cc2SEnji Cooper // notice, this list of conditions and the following disclaimer.
10b89a7cc2SEnji Cooper //     * Redistributions in binary form must reproduce the above
11b89a7cc2SEnji Cooper // copyright notice, this list of conditions and the following disclaimer
12b89a7cc2SEnji Cooper // in the documentation and/or other materials provided with the
13b89a7cc2SEnji Cooper // distribution.
14b89a7cc2SEnji Cooper //     * Neither the name of Google Inc. nor the names of its
15b89a7cc2SEnji Cooper // contributors may be used to endorse or promote products derived from
16b89a7cc2SEnji Cooper // this software without specific prior written permission.
17b89a7cc2SEnji Cooper //
18b89a7cc2SEnji Cooper // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19b89a7cc2SEnji Cooper // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20b89a7cc2SEnji Cooper // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21b89a7cc2SEnji Cooper // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22b89a7cc2SEnji Cooper // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23b89a7cc2SEnji Cooper // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24b89a7cc2SEnji Cooper // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25b89a7cc2SEnji Cooper // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26b89a7cc2SEnji Cooper // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27b89a7cc2SEnji Cooper // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28b89a7cc2SEnji Cooper // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29b89a7cc2SEnji Cooper 
30b89a7cc2SEnji Cooper // Tests that Google Mock constructs can be used in a large number of
31b89a7cc2SEnji Cooper // threads concurrently.
32b89a7cc2SEnji Cooper 
33b89a7cc2SEnji Cooper #include "gmock/gmock.h"
34b89a7cc2SEnji Cooper #include "gtest/gtest.h"
35b89a7cc2SEnji Cooper 
36b89a7cc2SEnji Cooper namespace testing {
37b89a7cc2SEnji Cooper namespace {
38b89a7cc2SEnji Cooper 
39b89a7cc2SEnji Cooper // From gtest-port.h.
40b89a7cc2SEnji Cooper using ::testing::internal::ThreadWithParam;
41b89a7cc2SEnji Cooper 
42b89a7cc2SEnji Cooper // The maximum number of test threads (not including helper threads)
43b89a7cc2SEnji Cooper // to create.
44b89a7cc2SEnji Cooper const int kMaxTestThreads = 50;
45b89a7cc2SEnji Cooper 
46b89a7cc2SEnji Cooper // How many times to repeat a task in a test thread.
47b89a7cc2SEnji Cooper const int kRepeat = 50;
48b89a7cc2SEnji Cooper 
49b89a7cc2SEnji Cooper class MockFoo {
50b89a7cc2SEnji Cooper  public:
51b89a7cc2SEnji Cooper   MOCK_METHOD1(Bar, int(int n));                                   // NOLINT
52b89a7cc2SEnji Cooper   MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2));  // NOLINT
53b89a7cc2SEnji Cooper };
54b89a7cc2SEnji Cooper 
55b89a7cc2SEnji Cooper // Helper for waiting for the given thread to finish and then deleting it.
56b89a7cc2SEnji Cooper template <typename T>
JoinAndDelete(ThreadWithParam<T> * t)57b89a7cc2SEnji Cooper void JoinAndDelete(ThreadWithParam<T>* t) {
58b89a7cc2SEnji Cooper   t->Join();
59b89a7cc2SEnji Cooper   delete t;
60b89a7cc2SEnji Cooper }
61b89a7cc2SEnji Cooper 
62b89a7cc2SEnji Cooper struct Dummy {};
63b89a7cc2SEnji Cooper 
64b89a7cc2SEnji Cooper // Tests that different mock objects can be used in their respective
65b89a7cc2SEnji Cooper // threads.  This should generate no Google Test failure.
TestConcurrentMockObjects(Dummy)66b89a7cc2SEnji Cooper void TestConcurrentMockObjects(Dummy /* dummy */) {
67b89a7cc2SEnji Cooper   // Creates a mock and does some typical operations on it.
68b89a7cc2SEnji Cooper   MockFoo foo;
69*28f6c2f2SEnji Cooper   ON_CALL(foo, Bar(_)).WillByDefault(Return(1));
70*28f6c2f2SEnji Cooper   ON_CALL(foo, Baz(_, _)).WillByDefault(Return('b'));
71*28f6c2f2SEnji Cooper   ON_CALL(foo, Baz(_, "you")).WillByDefault(Return('a'));
72b89a7cc2SEnji Cooper 
73*28f6c2f2SEnji Cooper   EXPECT_CALL(foo, Bar(0)).Times(AtMost(3));
74b89a7cc2SEnji Cooper   EXPECT_CALL(foo, Baz(_, _));
75b89a7cc2SEnji Cooper   EXPECT_CALL(foo, Baz("hi", "you"))
76b89a7cc2SEnji Cooper       .WillOnce(Return('z'))
77b89a7cc2SEnji Cooper       .WillRepeatedly(DoDefault());
78b89a7cc2SEnji Cooper 
79b89a7cc2SEnji Cooper   EXPECT_EQ(1, foo.Bar(0));
80b89a7cc2SEnji Cooper   EXPECT_EQ(1, foo.Bar(0));
81b89a7cc2SEnji Cooper   EXPECT_EQ('z', foo.Baz("hi", "you"));
82b89a7cc2SEnji Cooper   EXPECT_EQ('a', foo.Baz("hi", "you"));
83b89a7cc2SEnji Cooper   EXPECT_EQ('b', foo.Baz("hi", "me"));
84b89a7cc2SEnji Cooper }
85b89a7cc2SEnji Cooper 
86b89a7cc2SEnji Cooper // Tests invoking methods of the same mock object in multiple threads.
87b89a7cc2SEnji Cooper 
88b89a7cc2SEnji Cooper struct Helper1Param {
89b89a7cc2SEnji Cooper   MockFoo* mock_foo;
90b89a7cc2SEnji Cooper   int* count;
91b89a7cc2SEnji Cooper };
92b89a7cc2SEnji Cooper 
Helper1(Helper1Param param)93b89a7cc2SEnji Cooper void Helper1(Helper1Param param) {
94b89a7cc2SEnji Cooper   for (int i = 0; i < kRepeat; i++) {
95b89a7cc2SEnji Cooper     const char ch = param.mock_foo->Baz("a", "b");
96b89a7cc2SEnji Cooper     if (ch == 'a') {
97b89a7cc2SEnji Cooper       // It was an expected call.
98b89a7cc2SEnji Cooper       (*param.count)++;
99b89a7cc2SEnji Cooper     } else {
100b89a7cc2SEnji Cooper       // It was an excessive call.
101b89a7cc2SEnji Cooper       EXPECT_EQ('\0', ch);
102b89a7cc2SEnji Cooper     }
103b89a7cc2SEnji Cooper 
104b89a7cc2SEnji Cooper     // An unexpected call.
105b89a7cc2SEnji Cooper     EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
106b89a7cc2SEnji Cooper 
107b89a7cc2SEnji Cooper     // An uninteresting call.
108b89a7cc2SEnji Cooper     EXPECT_EQ(1, param.mock_foo->Bar(5));
109b89a7cc2SEnji Cooper   }
110b89a7cc2SEnji Cooper }
111b89a7cc2SEnji Cooper 
112b89a7cc2SEnji Cooper // This should generate 3*kRepeat + 1 failures in total.
TestConcurrentCallsOnSameObject(Dummy)113b89a7cc2SEnji Cooper void TestConcurrentCallsOnSameObject(Dummy /* dummy */) {
114b89a7cc2SEnji Cooper   MockFoo foo;
115b89a7cc2SEnji Cooper 
116*28f6c2f2SEnji Cooper   ON_CALL(foo, Bar(_)).WillByDefault(Return(1));
117*28f6c2f2SEnji Cooper   EXPECT_CALL(foo, Baz(_, "b")).Times(kRepeat).WillRepeatedly(Return('a'));
118b89a7cc2SEnji Cooper   EXPECT_CALL(foo, Baz(_, "c"));  // Expected to be unsatisfied.
119b89a7cc2SEnji Cooper 
120b89a7cc2SEnji Cooper   // This chunk of code should generate kRepeat failures about
121b89a7cc2SEnji Cooper   // excessive calls, and 2*kRepeat failures about unexpected calls.
122b89a7cc2SEnji Cooper   int count1 = 0;
123b89a7cc2SEnji Cooper   const Helper1Param param = {&foo, &count1};
124b89a7cc2SEnji Cooper   ThreadWithParam<Helper1Param>* const t =
125*28f6c2f2SEnji Cooper       new ThreadWithParam<Helper1Param>(Helper1, param, nullptr);
126b89a7cc2SEnji Cooper 
127b89a7cc2SEnji Cooper   int count2 = 0;
128b89a7cc2SEnji Cooper   const Helper1Param param2 = {&foo, &count2};
129b89a7cc2SEnji Cooper   Helper1(param2);
130b89a7cc2SEnji Cooper   JoinAndDelete(t);
131b89a7cc2SEnji Cooper 
132b89a7cc2SEnji Cooper   EXPECT_EQ(kRepeat, count1 + count2);
133b89a7cc2SEnji Cooper 
134b89a7cc2SEnji Cooper   // foo's destructor should generate one failure about unsatisfied
135b89a7cc2SEnji Cooper   // expectation.
136b89a7cc2SEnji Cooper }
137b89a7cc2SEnji Cooper 
138b89a7cc2SEnji Cooper // Tests using the same mock object in multiple threads when the
139b89a7cc2SEnji Cooper // expectations are partially ordered.
140b89a7cc2SEnji Cooper 
Helper2(MockFoo * foo)141b89a7cc2SEnji Cooper void Helper2(MockFoo* foo) {
142b89a7cc2SEnji Cooper   for (int i = 0; i < kRepeat; i++) {
143b89a7cc2SEnji Cooper     foo->Bar(2);
144b89a7cc2SEnji Cooper     foo->Bar(3);
145b89a7cc2SEnji Cooper   }
146b89a7cc2SEnji Cooper }
147b89a7cc2SEnji Cooper 
148b89a7cc2SEnji Cooper // This should generate no Google Test failures.
TestPartiallyOrderedExpectationsWithThreads(Dummy)149b89a7cc2SEnji Cooper void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {
150b89a7cc2SEnji Cooper   MockFoo foo;
151b89a7cc2SEnji Cooper   Sequence s1, s2;
152b89a7cc2SEnji Cooper 
153b89a7cc2SEnji Cooper   {
154b89a7cc2SEnji Cooper     InSequence dummy;
155b89a7cc2SEnji Cooper     EXPECT_CALL(foo, Bar(0));
156*28f6c2f2SEnji Cooper     EXPECT_CALL(foo, Bar(1)).InSequence(s1, s2);
157b89a7cc2SEnji Cooper   }
158b89a7cc2SEnji Cooper 
159b89a7cc2SEnji Cooper   EXPECT_CALL(foo, Bar(2))
160b89a7cc2SEnji Cooper       .Times(2 * kRepeat)
161b89a7cc2SEnji Cooper       .InSequence(s1)
162b89a7cc2SEnji Cooper       .RetiresOnSaturation();
163*28f6c2f2SEnji Cooper   EXPECT_CALL(foo, Bar(3)).Times(2 * kRepeat).InSequence(s2);
164b89a7cc2SEnji Cooper 
165b89a7cc2SEnji Cooper   {
166b89a7cc2SEnji Cooper     InSequence dummy;
167*28f6c2f2SEnji Cooper     EXPECT_CALL(foo, Bar(2)).InSequence(s1, s2);
168b89a7cc2SEnji Cooper     EXPECT_CALL(foo, Bar(4));
169b89a7cc2SEnji Cooper   }
170b89a7cc2SEnji Cooper 
171b89a7cc2SEnji Cooper   foo.Bar(0);
172b89a7cc2SEnji Cooper   foo.Bar(1);
173b89a7cc2SEnji Cooper 
174b89a7cc2SEnji Cooper   ThreadWithParam<MockFoo*>* const t =
175*28f6c2f2SEnji Cooper       new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr);
176b89a7cc2SEnji Cooper   Helper2(&foo);
177b89a7cc2SEnji Cooper   JoinAndDelete(t);
178b89a7cc2SEnji Cooper 
179b89a7cc2SEnji Cooper   foo.Bar(2);
180b89a7cc2SEnji Cooper   foo.Bar(4);
181b89a7cc2SEnji Cooper }
182b89a7cc2SEnji Cooper 
183b89a7cc2SEnji Cooper // Tests using Google Mock constructs in many threads concurrently.
TEST(StressTest,CanUseGMockWithThreads)184b89a7cc2SEnji Cooper TEST(StressTest, CanUseGMockWithThreads) {
185b89a7cc2SEnji Cooper   void (*test_routines[])(Dummy dummy) = {
186b89a7cc2SEnji Cooper       &TestConcurrentMockObjects,
187b89a7cc2SEnji Cooper       &TestConcurrentCallsOnSameObject,
188b89a7cc2SEnji Cooper       &TestPartiallyOrderedExpectationsWithThreads,
189b89a7cc2SEnji Cooper   };
190b89a7cc2SEnji Cooper 
191b89a7cc2SEnji Cooper   const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]);
192b89a7cc2SEnji Cooper   const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
193b89a7cc2SEnji Cooper   const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
194b89a7cc2SEnji Cooper   ThreadWithParam<Dummy>* threads[kTestThreads] = {};
195b89a7cc2SEnji Cooper   for (int i = 0; i < kTestThreads; i++) {
196b89a7cc2SEnji Cooper     // Creates a thread to run the test function.
197*28f6c2f2SEnji Cooper     threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines],
198*28f6c2f2SEnji Cooper                                             Dummy(), nullptr);
199b89a7cc2SEnji Cooper     GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
200b89a7cc2SEnji Cooper   }
201b89a7cc2SEnji Cooper 
202b89a7cc2SEnji Cooper   // At this point, we have many threads running.
203b89a7cc2SEnji Cooper   for (int i = 0; i < kTestThreads; i++) {
204b89a7cc2SEnji Cooper     JoinAndDelete(threads[i]);
205b89a7cc2SEnji Cooper   }
206b89a7cc2SEnji Cooper 
207b89a7cc2SEnji Cooper   // Ensures that the correct number of failures have been reported.
208b89a7cc2SEnji Cooper   const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
209b89a7cc2SEnji Cooper   const TestResult& result = *info->result();
210b89a7cc2SEnji Cooper   const int kExpectedFailures = (3 * kRepeat + 1) * kCopiesOfEachRoutine;
211b89a7cc2SEnji Cooper   GTEST_CHECK_(kExpectedFailures == result.total_part_count())
212b89a7cc2SEnji Cooper       << "Expected " << kExpectedFailures << " failures, but got "
213b89a7cc2SEnji Cooper       << result.total_part_count();
214b89a7cc2SEnji Cooper }
215b89a7cc2SEnji Cooper 
216b89a7cc2SEnji Cooper }  // namespace
217b89a7cc2SEnji Cooper }  // namespace testing
218b89a7cc2SEnji Cooper 
main(int argc,char ** argv)219b89a7cc2SEnji Cooper int main(int argc, char** argv) {
220b89a7cc2SEnji Cooper   testing::InitGoogleMock(&argc, argv);
221b89a7cc2SEnji Cooper 
222b89a7cc2SEnji Cooper   const int exit_code = RUN_ALL_TESTS();  // Expected to fail.
223b89a7cc2SEnji Cooper   GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
224b89a7cc2SEnji Cooper 
225b89a7cc2SEnji Cooper   printf("\nPASS\n");
226b89a7cc2SEnji Cooper   return 0;
227b89a7cc2SEnji Cooper }
228