00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "gmock/gmock.h"
00036 #include "gtest/gtest.h"
00037
00038 namespace testing {
00039 namespace {
00040
00041
00042 using ::testing::internal::ThreadWithParam;
00043
00044
00045
00046 const int kMaxTestThreads = 50;
00047
00048
00049 const int kRepeat = 50;
00050
00051 class MockFoo {
00052 public:
00053 MOCK_METHOD1(Bar, int(int n));
00054 MOCK_METHOD2(Baz, char(const char* s1, const internal::string& s2));
00055 };
00056
00057
00058 template <typename T>
00059 void JoinAndDelete(ThreadWithParam<T>* t) {
00060 t->Join();
00061 delete t;
00062 }
00063
00064 using internal::linked_ptr;
00065
00066
00067
00068 class Base {
00069 public:
00070 explicit Base(int a_x) : x_(a_x) {}
00071 virtual ~Base() {}
00072 int x() const { return x_; }
00073 private:
00074 int x_;
00075 };
00076
00077 class Derived1 : public Base {
00078 public:
00079 Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {}
00080 int y() const { return y_; }
00081 private:
00082 int y_;
00083 };
00084
00085 class Derived2 : public Base {
00086 public:
00087 Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {}
00088 int z() const { return z_; }
00089 private:
00090 int z_;
00091 };
00092
00093 linked_ptr<Derived1> pointer1(new Derived1(1, 2));
00094 linked_ptr<Derived2> pointer2(new Derived2(3, 4));
00095
00096 struct Dummy {};
00097
00098
00099 void TestConcurrentCopyAndReadLinkedPtr(Dummy ) {
00100
00101
00102 EXPECT_EQ(1, pointer1->x());
00103 EXPECT_EQ(2, pointer1->y());
00104 EXPECT_EQ(3, pointer2->x());
00105 EXPECT_EQ(4, pointer2->z());
00106
00107
00108 linked_ptr<Derived1> p1(pointer1);
00109 EXPECT_EQ(1, p1->x());
00110 EXPECT_EQ(2, p1->y());
00111
00112
00113 linked_ptr<Base> p2;
00114 p2 = pointer1;
00115 EXPECT_EQ(1, p2->x());
00116
00117
00118 p2 = pointer2;
00119 EXPECT_EQ(3, p2->x());
00120 }
00121
00122 const linked_ptr<Derived1> p0(new Derived1(1, 2));
00123
00124
00125
00126 void TestConcurrentWriteToEqualLinkedPtr(Dummy ) {
00127
00128
00129
00130 linked_ptr<Derived1> p1(p0);
00131 linked_ptr<Derived1> p2(p0);
00132
00133 EXPECT_EQ(1, p1->x());
00134 EXPECT_EQ(2, p1->y());
00135
00136 EXPECT_EQ(1, p2->x());
00137 EXPECT_EQ(2, p2->y());
00138
00139 p1.reset();
00140 p2 = p0;
00141
00142 EXPECT_EQ(1, p2->x());
00143 EXPECT_EQ(2, p2->y());
00144 }
00145
00146
00147
00148 void TestConcurrentMockObjects(Dummy ) {
00149
00150 MockFoo foo;
00151 ON_CALL(foo, Bar(_))
00152 .WillByDefault(Return(1));
00153 ON_CALL(foo, Baz(_, _))
00154 .WillByDefault(Return('b'));
00155 ON_CALL(foo, Baz(_, "you"))
00156 .WillByDefault(Return('a'));
00157
00158 EXPECT_CALL(foo, Bar(0))
00159 .Times(AtMost(3));
00160 EXPECT_CALL(foo, Baz(_, _));
00161 EXPECT_CALL(foo, Baz("hi", "you"))
00162 .WillOnce(Return('z'))
00163 .WillRepeatedly(DoDefault());
00164
00165 EXPECT_EQ(1, foo.Bar(0));
00166 EXPECT_EQ(1, foo.Bar(0));
00167 EXPECT_EQ('z', foo.Baz("hi", "you"));
00168 EXPECT_EQ('a', foo.Baz("hi", "you"));
00169 EXPECT_EQ('b', foo.Baz("hi", "me"));
00170 }
00171
00172
00173
00174 struct Helper1Param {
00175 MockFoo* mock_foo;
00176 int* count;
00177 };
00178
00179 void Helper1(Helper1Param param) {
00180 for (int i = 0; i < kRepeat; i++) {
00181 const char ch = param.mock_foo->Baz("a", "b");
00182 if (ch == 'a') {
00183
00184 (*param.count)++;
00185 } else {
00186
00187 EXPECT_EQ('\0', ch);
00188 }
00189
00190
00191 EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
00192
00193
00194 EXPECT_EQ(1, param.mock_foo->Bar(5));
00195 }
00196 }
00197
00198
00199 void TestConcurrentCallsOnSameObject(Dummy ) {
00200 MockFoo foo;
00201
00202 ON_CALL(foo, Bar(_))
00203 .WillByDefault(Return(1));
00204 EXPECT_CALL(foo, Baz(_, "b"))
00205 .Times(kRepeat)
00206 .WillRepeatedly(Return('a'));
00207 EXPECT_CALL(foo, Baz(_, "c"));
00208
00209
00210
00211 int count1 = 0;
00212 const Helper1Param param = { &foo, &count1 };
00213 ThreadWithParam<Helper1Param>* const t =
00214 new ThreadWithParam<Helper1Param>(Helper1, param, NULL);
00215
00216 int count2 = 0;
00217 const Helper1Param param2 = { &foo, &count2 };
00218 Helper1(param2);
00219 JoinAndDelete(t);
00220
00221 EXPECT_EQ(kRepeat, count1 + count2);
00222
00223
00224
00225 }
00226
00227
00228
00229
00230 void Helper2(MockFoo* foo) {
00231 for (int i = 0; i < kRepeat; i++) {
00232 foo->Bar(2);
00233 foo->Bar(3);
00234 }
00235 }
00236
00237
00238 void TestPartiallyOrderedExpectationsWithThreads(Dummy ) {
00239 MockFoo foo;
00240 Sequence s1, s2;
00241
00242 {
00243 InSequence dummy;
00244 EXPECT_CALL(foo, Bar(0));
00245 EXPECT_CALL(foo, Bar(1))
00246 .InSequence(s1, s2);
00247 }
00248
00249 EXPECT_CALL(foo, Bar(2))
00250 .Times(2*kRepeat)
00251 .InSequence(s1)
00252 .RetiresOnSaturation();
00253 EXPECT_CALL(foo, Bar(3))
00254 .Times(2*kRepeat)
00255 .InSequence(s2);
00256
00257 {
00258 InSequence dummy;
00259 EXPECT_CALL(foo, Bar(2))
00260 .InSequence(s1, s2);
00261 EXPECT_CALL(foo, Bar(4));
00262 }
00263
00264 foo.Bar(0);
00265 foo.Bar(1);
00266
00267 ThreadWithParam<MockFoo*>* const t =
00268 new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL);
00269 Helper2(&foo);
00270 JoinAndDelete(t);
00271
00272 foo.Bar(2);
00273 foo.Bar(4);
00274 }
00275
00276
00277 TEST(StressTest, CanUseGMockWithThreads) {
00278 void (*test_routines[])(Dummy dummy) = {
00279 &TestConcurrentCopyAndReadLinkedPtr,
00280 &TestConcurrentWriteToEqualLinkedPtr,
00281 &TestConcurrentMockObjects,
00282 &TestConcurrentCallsOnSameObject,
00283 &TestPartiallyOrderedExpectationsWithThreads,
00284 };
00285
00286 const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]);
00287 const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
00288 const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
00289 ThreadWithParam<Dummy>* threads[kTestThreads] = {};
00290 for (int i = 0; i < kTestThreads; i++) {
00291
00292 threads[i] =
00293 new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL);
00294 GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
00295 }
00296
00297
00298 for (int i = 0; i < kTestThreads; i++) {
00299 JoinAndDelete(threads[i]);
00300 }
00301
00302
00303 const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
00304 const TestResult& result = *info->result();
00305 const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine;
00306 GTEST_CHECK_(kExpectedFailures == result.total_part_count())
00307 << "Expected " << kExpectedFailures << " failures, but got "
00308 << result.total_part_count();
00309 }
00310
00311 }
00312 }
00313
00314 int main(int argc, char **argv) {
00315 testing::InitGoogleMock(&argc, argv);
00316
00317 const int exit_code = RUN_ALL_TESTS();
00318 GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
00319
00320 printf("\nPASS\n");
00321 return 0;
00322 }