gmock_stress_test.cc (googletest-release-1.11.0) | : | gmock_stress_test.cc (googletest-release-1.12.0) | ||
---|---|---|---|---|
skipping to change at line 51 | skipping to change at line 51 | |||
// The maximum number of test threads (not including helper threads) | // The maximum number of test threads (not including helper threads) | |||
// to create. | // to create. | |||
const int kMaxTestThreads = 50; | const int kMaxTestThreads = 50; | |||
// How many times to repeat a task in a test thread. | // How many times to repeat a task in a test thread. | |||
const int kRepeat = 50; | const int kRepeat = 50; | |||
class MockFoo { | class MockFoo { | |||
public: | public: | |||
MOCK_METHOD1(Bar, int(int n)); // NOLINT | MOCK_METHOD1(Bar, int(int n)); // NOLINT | |||
MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT | MOCK_METHOD2(Baz, char(const char* s1, const std::string& s2)); // NOLINT | |||
}; | }; | |||
// Helper for waiting for the given thread to finish and then deleting it. | // Helper for waiting for the given thread to finish and then deleting it. | |||
template <typename T> | template <typename T> | |||
void JoinAndDelete(ThreadWithParam<T>* t) { | void JoinAndDelete(ThreadWithParam<T>* t) { | |||
t->Join(); | t->Join(); | |||
delete t; | delete t; | |||
} | } | |||
struct Dummy {}; | struct Dummy {}; | |||
// Tests that different mock objects can be used in their respective | // Tests that different mock objects can be used in their respective | |||
// threads. This should generate no Google Test failure. | // threads. This should generate no Google Test failure. | |||
void TestConcurrentMockObjects(Dummy /* dummy */) { | void TestConcurrentMockObjects(Dummy /* dummy */) { | |||
// Creates a mock and does some typical operations on it. | // Creates a mock and does some typical operations on it. | |||
MockFoo foo; | MockFoo foo; | |||
ON_CALL(foo, Bar(_)) | ON_CALL(foo, Bar(_)).WillByDefault(Return(1)); | |||
.WillByDefault(Return(1)); | ON_CALL(foo, Baz(_, _)).WillByDefault(Return('b')); | |||
ON_CALL(foo, Baz(_, _)) | ON_CALL(foo, Baz(_, "you")).WillByDefault(Return('a')); | |||
.WillByDefault(Return('b')); | ||||
ON_CALL(foo, Baz(_, "you")) | ||||
.WillByDefault(Return('a')); | ||||
EXPECT_CALL(foo, Bar(0)) | EXPECT_CALL(foo, Bar(0)).Times(AtMost(3)); | |||
.Times(AtMost(3)); | ||||
EXPECT_CALL(foo, Baz(_, _)); | EXPECT_CALL(foo, Baz(_, _)); | |||
EXPECT_CALL(foo, Baz("hi", "you")) | EXPECT_CALL(foo, Baz("hi", "you")) | |||
.WillOnce(Return('z')) | .WillOnce(Return('z')) | |||
.WillRepeatedly(DoDefault()); | .WillRepeatedly(DoDefault()); | |||
EXPECT_EQ(1, foo.Bar(0)); | EXPECT_EQ(1, foo.Bar(0)); | |||
EXPECT_EQ(1, foo.Bar(0)); | EXPECT_EQ(1, foo.Bar(0)); | |||
EXPECT_EQ('z', foo.Baz("hi", "you")); | EXPECT_EQ('z', foo.Baz("hi", "you")); | |||
EXPECT_EQ('a', foo.Baz("hi", "you")); | EXPECT_EQ('a', foo.Baz("hi", "you")); | |||
EXPECT_EQ('b', foo.Baz("hi", "me")); | EXPECT_EQ('b', foo.Baz("hi", "me")); | |||
skipping to change at line 120 | skipping to change at line 116 | |||
// An uninteresting call. | // An uninteresting call. | |||
EXPECT_EQ(1, param.mock_foo->Bar(5)); | EXPECT_EQ(1, param.mock_foo->Bar(5)); | |||
} | } | |||
} | } | |||
// This should generate 3*kRepeat + 1 failures in total. | // This should generate 3*kRepeat + 1 failures in total. | |||
void TestConcurrentCallsOnSameObject(Dummy /* dummy */) { | void TestConcurrentCallsOnSameObject(Dummy /* dummy */) { | |||
MockFoo foo; | MockFoo foo; | |||
ON_CALL(foo, Bar(_)) | ON_CALL(foo, Bar(_)).WillByDefault(Return(1)); | |||
.WillByDefault(Return(1)); | EXPECT_CALL(foo, Baz(_, "b")).Times(kRepeat).WillRepeatedly(Return('a')); | |||
EXPECT_CALL(foo, Baz(_, "b")) | ||||
.Times(kRepeat) | ||||
.WillRepeatedly(Return('a')); | ||||
EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied. | EXPECT_CALL(foo, Baz(_, "c")); // Expected to be unsatisfied. | |||
// This chunk of code should generate kRepeat failures about | // This chunk of code should generate kRepeat failures about | |||
// excessive calls, and 2*kRepeat failures about unexpected calls. | // excessive calls, and 2*kRepeat failures about unexpected calls. | |||
int count1 = 0; | int count1 = 0; | |||
const Helper1Param param = { &foo, &count1 }; | const Helper1Param param = {&foo, &count1}; | |||
ThreadWithParam<Helper1Param>* const t = | ThreadWithParam<Helper1Param>* const t = | |||
new ThreadWithParam<Helper1Param>(Helper1, param, nullptr); | new ThreadWithParam<Helper1Param>(Helper1, param, nullptr); | |||
int count2 = 0; | int count2 = 0; | |||
const Helper1Param param2 = { &foo, &count2 }; | const Helper1Param param2 = {&foo, &count2}; | |||
Helper1(param2); | Helper1(param2); | |||
JoinAndDelete(t); | JoinAndDelete(t); | |||
EXPECT_EQ(kRepeat, count1 + count2); | EXPECT_EQ(kRepeat, count1 + count2); | |||
// foo's destructor should generate one failure about unsatisfied | // foo's destructor should generate one failure about unsatisfied | |||
// expectation. | // expectation. | |||
} | } | |||
// Tests using the same mock object in multiple threads when the | // Tests using the same mock object in multiple threads when the | |||
skipping to change at line 163 | skipping to change at line 156 | |||
} | } | |||
// This should generate no Google Test failures. | // This should generate no Google Test failures. | |||
void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) { | void TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) { | |||
MockFoo foo; | MockFoo foo; | |||
Sequence s1, s2; | Sequence s1, s2; | |||
{ | { | |||
InSequence dummy; | InSequence dummy; | |||
EXPECT_CALL(foo, Bar(0)); | EXPECT_CALL(foo, Bar(0)); | |||
EXPECT_CALL(foo, Bar(1)) | EXPECT_CALL(foo, Bar(1)).InSequence(s1, s2); | |||
.InSequence(s1, s2); | ||||
} | } | |||
EXPECT_CALL(foo, Bar(2)) | EXPECT_CALL(foo, Bar(2)) | |||
.Times(2*kRepeat) | .Times(2 * kRepeat) | |||
.InSequence(s1) | .InSequence(s1) | |||
.RetiresOnSaturation(); | .RetiresOnSaturation(); | |||
EXPECT_CALL(foo, Bar(3)) | EXPECT_CALL(foo, Bar(3)).Times(2 * kRepeat).InSequence(s2); | |||
.Times(2*kRepeat) | ||||
.InSequence(s2); | ||||
{ | { | |||
InSequence dummy; | InSequence dummy; | |||
EXPECT_CALL(foo, Bar(2)) | EXPECT_CALL(foo, Bar(2)).InSequence(s1, s2); | |||
.InSequence(s1, s2); | ||||
EXPECT_CALL(foo, Bar(4)); | EXPECT_CALL(foo, Bar(4)); | |||
} | } | |||
foo.Bar(0); | foo.Bar(0); | |||
foo.Bar(1); | foo.Bar(1); | |||
ThreadWithParam<MockFoo*>* const t = | ThreadWithParam<MockFoo*>* const t = | |||
new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr); | new ThreadWithParam<MockFoo*>(Helper2, &foo, nullptr); | |||
Helper2(&foo); | Helper2(&foo); | |||
JoinAndDelete(t); | JoinAndDelete(t); | |||
foo.Bar(2); | foo.Bar(2); | |||
foo.Bar(4); | foo.Bar(4); | |||
} | } | |||
// Tests using Google Mock constructs in many threads concurrently. | // Tests using Google Mock constructs in many threads concurrently. | |||
TEST(StressTest, CanUseGMockWithThreads) { | TEST(StressTest, CanUseGMockWithThreads) { | |||
void (*test_routines[])(Dummy dummy) = { | void (*test_routines[])(Dummy dummy) = { | |||
&TestConcurrentMockObjects, | &TestConcurrentMockObjects, | |||
&TestConcurrentCallsOnSameObject, | &TestConcurrentCallsOnSameObject, | |||
&TestPartiallyOrderedExpectationsWithThreads, | &TestPartiallyOrderedExpectationsWithThreads, | |||
}; | }; | |||
const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]); | const int kRoutines = sizeof(test_routines) / sizeof(test_routines[0]); | |||
const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines; | const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines; | |||
const int kTestThreads = kCopiesOfEachRoutine * kRoutines; | const int kTestThreads = kCopiesOfEachRoutine * kRoutines; | |||
ThreadWithParam<Dummy>* threads[kTestThreads] = {}; | ThreadWithParam<Dummy>* threads[kTestThreads] = {}; | |||
for (int i = 0; i < kTestThreads; i++) { | for (int i = 0; i < kTestThreads; i++) { | |||
// Creates a thread to run the test function. | // Creates a thread to run the test function. | |||
threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines], | threads[i] = new ThreadWithParam<Dummy>(test_routines[i % kRoutines], | |||
Dummy(), nullptr); | Dummy(), nullptr); | |||
GTEST_LOG_(INFO) << "Thread #" << i << " running . . ."; | GTEST_LOG_(INFO) << "Thread #" << i << " running . . ."; | |||
} | } | |||
// At this point, we have many threads running. | // At this point, we have many threads running. | |||
for (int i = 0; i < kTestThreads; i++) { | for (int i = 0; i < kTestThreads; i++) { | |||
JoinAndDelete(threads[i]); | JoinAndDelete(threads[i]); | |||
} | } | |||
// Ensures that the correct number of failures have been reported. | // Ensures that the correct number of failures have been reported. | |||
const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); | const TestInfo* const info = UnitTest::GetInstance()->current_test_info(); | |||
const TestResult& result = *info->result(); | const TestResult& result = *info->result(); | |||
const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine; | const int kExpectedFailures = (3 * kRepeat + 1) * kCopiesOfEachRoutine; | |||
GTEST_CHECK_(kExpectedFailures == result.total_part_count()) | GTEST_CHECK_(kExpectedFailures == result.total_part_count()) | |||
<< "Expected " << kExpectedFailures << " failures, but got " | << "Expected " << kExpectedFailures << " failures, but got " | |||
<< result.total_part_count(); | << result.total_part_count(); | |||
} | } | |||
} // namespace | } // namespace | |||
} // namespace testing | } // namespace testing | |||
int main(int argc, char **argv) { | int main(int argc, char** argv) { | |||
testing::InitGoogleMock(&argc, argv); | testing::InitGoogleMock(&argc, argv); | |||
const int exit_code = RUN_ALL_TESTS(); // Expected to fail. | const int exit_code = RUN_ALL_TESTS(); // Expected to fail. | |||
GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected"; | GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected"; | |||
printf("\nPASS\n"); | printf("\nPASS\n"); | |||
return 0; | return 0; | |||
} | } | |||
End of changes. 14 change blocks. | ||||
30 lines changed or deleted | 19 lines changed or added |