File indexing completed on 2025-08-06 08:19:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include "gmock/gmock.h"
0036 #include "gtest/gtest.h"
0037
0038 namespace testing {
0039 namespace {
0040
0041
0042 using ::testing::internal::ThreadWithParam;
0043
0044
0045
0046 const int kMaxTestThreads = 50;
0047
0048
0049 const int kRepeat = 50;
0050
0051 class MockFoo {
0052 public:
0053 MOCK_METHOD1(Bar, int(int n));
0054 MOCK_METHOD2(Baz, char(const char* s1, const internal::string& s2));
0055 };
0056
0057
0058 template <typename T>
0059 void JoinAndDelete(ThreadWithParam<T>* t) {
0060 t->Join();
0061 delete t;
0062 }
0063
0064 using internal::linked_ptr;
0065
0066
0067
0068 class Base {
0069 public:
0070 explicit Base(int a_x) : x_(a_x) {}
0071 virtual ~Base() {}
0072 int x() const { return x_; }
0073 private:
0074 int x_;
0075 };
0076
0077 class Derived1 : public Base {
0078 public:
0079 Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {}
0080 int y() const { return y_; }
0081 private:
0082 int y_;
0083 };
0084
0085 class Derived2 : public Base {
0086 public:
0087 Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {}
0088 int z() const { return z_; }
0089 private:
0090 int z_;
0091 };
0092
0093 linked_ptr<Derived1> pointer1(new Derived1(1, 2));
0094 linked_ptr<Derived2> pointer2(new Derived2(3, 4));
0095
0096 struct Dummy {};
0097
0098
0099 void TestConcurrentCopyAndReadLinkedPtr(Dummy ) {
0100
0101
0102 EXPECT_EQ(1, pointer1->x());
0103 EXPECT_EQ(2, pointer1->y());
0104 EXPECT_EQ(3, pointer2->x());
0105 EXPECT_EQ(4, pointer2->z());
0106
0107
0108 linked_ptr<Derived1> p1(pointer1);
0109 EXPECT_EQ(1, p1->x());
0110 EXPECT_EQ(2, p1->y());
0111
0112
0113 linked_ptr<Base> p2;
0114 p2 = pointer1;
0115 EXPECT_EQ(1, p2->x());
0116
0117
0118 p2 = pointer2;
0119 EXPECT_EQ(3, p2->x());
0120 }
0121
0122 const linked_ptr<Derived1> p0(new Derived1(1, 2));
0123
0124
0125
0126 void TestConcurrentWriteToEqualLinkedPtr(Dummy ) {
0127
0128
0129
0130 linked_ptr<Derived1> p1(p0);
0131 linked_ptr<Derived1> p2(p0);
0132
0133 EXPECT_EQ(1, p1->x());
0134 EXPECT_EQ(2, p1->y());
0135
0136 EXPECT_EQ(1, p2->x());
0137 EXPECT_EQ(2, p2->y());
0138
0139 p1.reset();
0140 p2 = p0;
0141
0142 EXPECT_EQ(1, p2->x());
0143 EXPECT_EQ(2, p2->y());
0144 }
0145
0146
0147
0148 void TestConcurrentMockObjects(Dummy ) {
0149
0150 MockFoo foo;
0151 ON_CALL(foo, Bar(_))
0152 .WillByDefault(Return(1));
0153 ON_CALL(foo, Baz(_, _))
0154 .WillByDefault(Return('b'));
0155 ON_CALL(foo, Baz(_, "you"))
0156 .WillByDefault(Return('a'));
0157
0158 EXPECT_CALL(foo, Bar(0))
0159 .Times(AtMost(3));
0160 EXPECT_CALL(foo, Baz(_, _));
0161 EXPECT_CALL(foo, Baz("hi", "you"))
0162 .WillOnce(Return('z'))
0163 .WillRepeatedly(DoDefault());
0164
0165 EXPECT_EQ(1, foo.Bar(0));
0166 EXPECT_EQ(1, foo.Bar(0));
0167 EXPECT_EQ('z', foo.Baz("hi", "you"));
0168 EXPECT_EQ('a', foo.Baz("hi", "you"));
0169 EXPECT_EQ('b', foo.Baz("hi", "me"));
0170 }
0171
0172
0173
0174 struct Helper1Param {
0175 MockFoo* mock_foo;
0176 int* count;
0177 };
0178
0179 void Helper1(Helper1Param param) {
0180 for (int i = 0; i < kRepeat; i++) {
0181 const char ch = param.mock_foo->Baz("a", "b");
0182 if (ch == 'a') {
0183
0184 (*param.count)++;
0185 } else {
0186
0187 EXPECT_EQ('\0', ch);
0188 }
0189
0190
0191 EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
0192
0193
0194 EXPECT_EQ(1, param.mock_foo->Bar(5));
0195 }
0196 }
0197
0198
0199 void TestConcurrentCallsOnSameObject(Dummy ) {
0200 MockFoo foo;
0201
0202 ON_CALL(foo, Bar(_))
0203 .WillByDefault(Return(1));
0204 EXPECT_CALL(foo, Baz(_, "b"))
0205 .Times(kRepeat)
0206 .WillRepeatedly(Return('a'));
0207 EXPECT_CALL(foo, Baz(_, "c"));
0208
0209
0210
0211 int count1 = 0;
0212 const Helper1Param param = { &foo, &count1 };
0213 ThreadWithParam<Helper1Param>* const t =
0214 new ThreadWithParam<Helper1Param>(Helper1, param, NULL);
0215
0216 int count2 = 0;
0217 const Helper1Param param2 = { &foo, &count2 };
0218 Helper1(param2);
0219 JoinAndDelete(t);
0220
0221 EXPECT_EQ(kRepeat, count1 + count2);
0222
0223
0224
0225 }
0226
0227
0228
0229
0230 void Helper2(MockFoo* foo) {
0231 for (int i = 0; i < kRepeat; i++) {
0232 foo->Bar(2);
0233 foo->Bar(3);
0234 }
0235 }
0236
0237
0238 void TestPartiallyOrderedExpectationsWithThreads(Dummy ) {
0239 MockFoo foo;
0240 Sequence s1, s2;
0241
0242 {
0243 InSequence dummy;
0244 EXPECT_CALL(foo, Bar(0));
0245 EXPECT_CALL(foo, Bar(1))
0246 .InSequence(s1, s2);
0247 }
0248
0249 EXPECT_CALL(foo, Bar(2))
0250 .Times(2*kRepeat)
0251 .InSequence(s1)
0252 .RetiresOnSaturation();
0253 EXPECT_CALL(foo, Bar(3))
0254 .Times(2*kRepeat)
0255 .InSequence(s2);
0256
0257 {
0258 InSequence dummy;
0259 EXPECT_CALL(foo, Bar(2))
0260 .InSequence(s1, s2);
0261 EXPECT_CALL(foo, Bar(4));
0262 }
0263
0264 foo.Bar(0);
0265 foo.Bar(1);
0266
0267 ThreadWithParam<MockFoo*>* const t =
0268 new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL);
0269 Helper2(&foo);
0270 JoinAndDelete(t);
0271
0272 foo.Bar(2);
0273 foo.Bar(4);
0274 }
0275
0276
0277 TEST(StressTest, CanUseGMockWithThreads) {
0278 void (*test_routines[])(Dummy dummy) = {
0279 &TestConcurrentCopyAndReadLinkedPtr,
0280 &TestConcurrentWriteToEqualLinkedPtr,
0281 &TestConcurrentMockObjects,
0282 &TestConcurrentCallsOnSameObject,
0283 &TestPartiallyOrderedExpectationsWithThreads,
0284 };
0285
0286 const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]);
0287 const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
0288 const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
0289 ThreadWithParam<Dummy>* threads[kTestThreads] = {};
0290 for (int i = 0; i < kTestThreads; i++) {
0291
0292 threads[i] =
0293 new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL);
0294 GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
0295 }
0296
0297
0298 for (int i = 0; i < kTestThreads; i++) {
0299 JoinAndDelete(threads[i]);
0300 }
0301
0302
0303 const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
0304 const TestResult& result = *info->result();
0305 const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine;
0306 GTEST_CHECK_(kExpectedFailures == result.total_part_count())
0307 << "Expected " << kExpectedFailures << " failures, but got "
0308 << result.total_part_count();
0309 }
0310
0311 }
0312 }
0313
0314 int main(int argc, char **argv) {
0315 testing::InitGoogleMock(&argc, argv);
0316
0317 const int exit_code = RUN_ALL_TESTS();
0318 GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
0319
0320 printf("\nPASS\n");
0321 return 0;
0322 }