113481Sgiacomo.travaglini@arm.com// Copyright 2007, Google Inc.
213481Sgiacomo.travaglini@arm.com// All rights reserved.
313481Sgiacomo.travaglini@arm.com//
413481Sgiacomo.travaglini@arm.com// Redistribution and use in source and binary forms, with or without
513481Sgiacomo.travaglini@arm.com// modification, are permitted provided that the following conditions are
613481Sgiacomo.travaglini@arm.com// met:
713481Sgiacomo.travaglini@arm.com//
813481Sgiacomo.travaglini@arm.com//     * Redistributions of source code must retain the above copyright
913481Sgiacomo.travaglini@arm.com// notice, this list of conditions and the following disclaimer.
1013481Sgiacomo.travaglini@arm.com//     * Redistributions in binary form must reproduce the above
1113481Sgiacomo.travaglini@arm.com// copyright notice, this list of conditions and the following disclaimer
1213481Sgiacomo.travaglini@arm.com// in the documentation and/or other materials provided with the
1313481Sgiacomo.travaglini@arm.com// distribution.
1413481Sgiacomo.travaglini@arm.com//     * Neither the name of Google Inc. nor the names of its
1513481Sgiacomo.travaglini@arm.com// contributors may be used to endorse or promote products derived from
1613481Sgiacomo.travaglini@arm.com// this software without specific prior written permission.
1713481Sgiacomo.travaglini@arm.com//
1813481Sgiacomo.travaglini@arm.com// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1913481Sgiacomo.travaglini@arm.com// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2013481Sgiacomo.travaglini@arm.com// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2113481Sgiacomo.travaglini@arm.com// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2213481Sgiacomo.travaglini@arm.com// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2313481Sgiacomo.travaglini@arm.com// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2413481Sgiacomo.travaglini@arm.com// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2513481Sgiacomo.travaglini@arm.com// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2613481Sgiacomo.travaglini@arm.com// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2713481Sgiacomo.travaglini@arm.com// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2813481Sgiacomo.travaglini@arm.com// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2913481Sgiacomo.travaglini@arm.com//
3013481Sgiacomo.travaglini@arm.com// Author: wan@google.com (Zhanyong Wan)
3113481Sgiacomo.travaglini@arm.com
3213481Sgiacomo.travaglini@arm.com// Tests that Google Mock constructs can be used in a large number of
3313481Sgiacomo.travaglini@arm.com// threads concurrently.
3413481Sgiacomo.travaglini@arm.com
3513481Sgiacomo.travaglini@arm.com#include "gmock/gmock.h"
3613481Sgiacomo.travaglini@arm.com#include "gtest/gtest.h"
3713481Sgiacomo.travaglini@arm.com
3813481Sgiacomo.travaglini@arm.comnamespace testing {
3913481Sgiacomo.travaglini@arm.comnamespace {
4013481Sgiacomo.travaglini@arm.com
4113481Sgiacomo.travaglini@arm.com// From <gtest/internal/gtest-port.h>.
4213481Sgiacomo.travaglini@arm.comusing ::testing::internal::ThreadWithParam;
4313481Sgiacomo.travaglini@arm.com
4413481Sgiacomo.travaglini@arm.com// The maximum number of test threads (not including helper threads)
4513481Sgiacomo.travaglini@arm.com// to create.
4613481Sgiacomo.travaglini@arm.comconst int kMaxTestThreads = 50;
4713481Sgiacomo.travaglini@arm.com
4813481Sgiacomo.travaglini@arm.com// How many times to repeat a task in a test thread.
4913481Sgiacomo.travaglini@arm.comconst int kRepeat = 50;
5013481Sgiacomo.travaglini@arm.com
5113481Sgiacomo.travaglini@arm.comclass MockFoo {
5213481Sgiacomo.travaglini@arm.com public:
5313481Sgiacomo.travaglini@arm.com  MOCK_METHOD1(Bar, int(int n));  // NOLINT
5413481Sgiacomo.travaglini@arm.com  MOCK_METHOD2(Baz, char(const char* s1, const internal::string& s2));  // NOLINT
5513481Sgiacomo.travaglini@arm.com};
5613481Sgiacomo.travaglini@arm.com
5713481Sgiacomo.travaglini@arm.com// Helper for waiting for the given thread to finish and then deleting it.
5813481Sgiacomo.travaglini@arm.comtemplate <typename T>
5913481Sgiacomo.travaglini@arm.comvoid JoinAndDelete(ThreadWithParam<T>* t) {
6013481Sgiacomo.travaglini@arm.com  t->Join();
6113481Sgiacomo.travaglini@arm.com  delete t;
6213481Sgiacomo.travaglini@arm.com}
6313481Sgiacomo.travaglini@arm.com
6413481Sgiacomo.travaglini@arm.comusing internal::linked_ptr;
6513481Sgiacomo.travaglini@arm.com
6613481Sgiacomo.travaglini@arm.com// Helper classes for testing using linked_ptr concurrently.
6713481Sgiacomo.travaglini@arm.com
6813481Sgiacomo.travaglini@arm.comclass Base {
6913481Sgiacomo.travaglini@arm.com public:
7013481Sgiacomo.travaglini@arm.com  explicit Base(int a_x) : x_(a_x) {}
7113481Sgiacomo.travaglini@arm.com  virtual ~Base() {}
7213481Sgiacomo.travaglini@arm.com  int x() const { return x_; }
7313481Sgiacomo.travaglini@arm.com private:
7413481Sgiacomo.travaglini@arm.com  int x_;
7513481Sgiacomo.travaglini@arm.com};
7613481Sgiacomo.travaglini@arm.com
7713481Sgiacomo.travaglini@arm.comclass Derived1 : public Base {
7813481Sgiacomo.travaglini@arm.com public:
7913481Sgiacomo.travaglini@arm.com  Derived1(int a_x, int a_y) : Base(a_x), y_(a_y) {}
8013481Sgiacomo.travaglini@arm.com  int y() const { return y_; }
8113481Sgiacomo.travaglini@arm.com private:
8213481Sgiacomo.travaglini@arm.com  int y_;
8313481Sgiacomo.travaglini@arm.com};
8413481Sgiacomo.travaglini@arm.com
8513481Sgiacomo.travaglini@arm.comclass Derived2 : public Base {
8613481Sgiacomo.travaglini@arm.com public:
8713481Sgiacomo.travaglini@arm.com  Derived2(int a_x, int a_z) : Base(a_x), z_(a_z) {}
8813481Sgiacomo.travaglini@arm.com  int z() const { return z_; }
8913481Sgiacomo.travaglini@arm.com private:
9013481Sgiacomo.travaglini@arm.com  int z_;
9113481Sgiacomo.travaglini@arm.com};
9213481Sgiacomo.travaglini@arm.com
9313481Sgiacomo.travaglini@arm.comlinked_ptr<Derived1> pointer1(new Derived1(1, 2));
9413481Sgiacomo.travaglini@arm.comlinked_ptr<Derived2> pointer2(new Derived2(3, 4));
9513481Sgiacomo.travaglini@arm.com
9613481Sgiacomo.travaglini@arm.comstruct Dummy {};
9713481Sgiacomo.travaglini@arm.com
9813481Sgiacomo.travaglini@arm.com// Tests that we can copy from a linked_ptr and read it concurrently.
9913481Sgiacomo.travaglini@arm.comvoid TestConcurrentCopyAndReadLinkedPtr(Dummy /* dummy */) {
10013481Sgiacomo.travaglini@arm.com  // Reads pointer1 and pointer2 while they are being copied from in
10113481Sgiacomo.travaglini@arm.com  // another thread.
10213481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, pointer1->x());
10313481Sgiacomo.travaglini@arm.com  EXPECT_EQ(2, pointer1->y());
10413481Sgiacomo.travaglini@arm.com  EXPECT_EQ(3, pointer2->x());
10513481Sgiacomo.travaglini@arm.com  EXPECT_EQ(4, pointer2->z());
10613481Sgiacomo.travaglini@arm.com
10713481Sgiacomo.travaglini@arm.com  // Copies from pointer1.
10813481Sgiacomo.travaglini@arm.com  linked_ptr<Derived1> p1(pointer1);
10913481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, p1->x());
11013481Sgiacomo.travaglini@arm.com  EXPECT_EQ(2, p1->y());
11113481Sgiacomo.travaglini@arm.com
11213481Sgiacomo.travaglini@arm.com  // Assigns from pointer2 where the LHS was empty.
11313481Sgiacomo.travaglini@arm.com  linked_ptr<Base> p2;
11413481Sgiacomo.travaglini@arm.com  p2 = pointer1;
11513481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, p2->x());
11613481Sgiacomo.travaglini@arm.com
11713481Sgiacomo.travaglini@arm.com  // Assigns from pointer2 where the LHS was not empty.
11813481Sgiacomo.travaglini@arm.com  p2 = pointer2;
11913481Sgiacomo.travaglini@arm.com  EXPECT_EQ(3, p2->x());
12013481Sgiacomo.travaglini@arm.com}
12113481Sgiacomo.travaglini@arm.com
12213481Sgiacomo.travaglini@arm.comconst linked_ptr<Derived1> p0(new Derived1(1, 2));
12313481Sgiacomo.travaglini@arm.com
12413481Sgiacomo.travaglini@arm.com// Tests that we can concurrently modify two linked_ptrs that point to
12513481Sgiacomo.travaglini@arm.com// the same object.
12613481Sgiacomo.travaglini@arm.comvoid TestConcurrentWriteToEqualLinkedPtr(Dummy /* dummy */) {
12713481Sgiacomo.travaglini@arm.com  // p1 and p2 point to the same, shared thing.  One thread resets p1.
12813481Sgiacomo.travaglini@arm.com  // Another thread assigns to p2.  This will cause the same
12913481Sgiacomo.travaglini@arm.com  // underlying "ring" to be updated concurrently.
13013481Sgiacomo.travaglini@arm.com  linked_ptr<Derived1> p1(p0);
13113481Sgiacomo.travaglini@arm.com  linked_ptr<Derived1> p2(p0);
13213481Sgiacomo.travaglini@arm.com
13313481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, p1->x());
13413481Sgiacomo.travaglini@arm.com  EXPECT_EQ(2, p1->y());
13513481Sgiacomo.travaglini@arm.com
13613481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, p2->x());
13713481Sgiacomo.travaglini@arm.com  EXPECT_EQ(2, p2->y());
13813481Sgiacomo.travaglini@arm.com
13913481Sgiacomo.travaglini@arm.com  p1.reset();
14013481Sgiacomo.travaglini@arm.com  p2 = p0;
14113481Sgiacomo.travaglini@arm.com
14213481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, p2->x());
14313481Sgiacomo.travaglini@arm.com  EXPECT_EQ(2, p2->y());
14413481Sgiacomo.travaglini@arm.com}
14513481Sgiacomo.travaglini@arm.com
14613481Sgiacomo.travaglini@arm.com// Tests that different mock objects can be used in their respective
14713481Sgiacomo.travaglini@arm.com// threads.  This should generate no Google Test failure.
14813481Sgiacomo.travaglini@arm.comvoid TestConcurrentMockObjects(Dummy /* dummy */) {
14913481Sgiacomo.travaglini@arm.com  // Creates a mock and does some typical operations on it.
15013481Sgiacomo.travaglini@arm.com  MockFoo foo;
15113481Sgiacomo.travaglini@arm.com  ON_CALL(foo, Bar(_))
15213481Sgiacomo.travaglini@arm.com      .WillByDefault(Return(1));
15313481Sgiacomo.travaglini@arm.com  ON_CALL(foo, Baz(_, _))
15413481Sgiacomo.travaglini@arm.com      .WillByDefault(Return('b'));
15513481Sgiacomo.travaglini@arm.com  ON_CALL(foo, Baz(_, "you"))
15613481Sgiacomo.travaglini@arm.com      .WillByDefault(Return('a'));
15713481Sgiacomo.travaglini@arm.com
15813481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Bar(0))
15913481Sgiacomo.travaglini@arm.com      .Times(AtMost(3));
16013481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Baz(_, _));
16113481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Baz("hi", "you"))
16213481Sgiacomo.travaglini@arm.com      .WillOnce(Return('z'))
16313481Sgiacomo.travaglini@arm.com      .WillRepeatedly(DoDefault());
16413481Sgiacomo.travaglini@arm.com
16513481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, foo.Bar(0));
16613481Sgiacomo.travaglini@arm.com  EXPECT_EQ(1, foo.Bar(0));
16713481Sgiacomo.travaglini@arm.com  EXPECT_EQ('z', foo.Baz("hi", "you"));
16813481Sgiacomo.travaglini@arm.com  EXPECT_EQ('a', foo.Baz("hi", "you"));
16913481Sgiacomo.travaglini@arm.com  EXPECT_EQ('b', foo.Baz("hi", "me"));
17013481Sgiacomo.travaglini@arm.com}
17113481Sgiacomo.travaglini@arm.com
17213481Sgiacomo.travaglini@arm.com// Tests invoking methods of the same mock object in multiple threads.
17313481Sgiacomo.travaglini@arm.com
17413481Sgiacomo.travaglini@arm.comstruct Helper1Param {
17513481Sgiacomo.travaglini@arm.com  MockFoo* mock_foo;
17613481Sgiacomo.travaglini@arm.com  int* count;
17713481Sgiacomo.travaglini@arm.com};
17813481Sgiacomo.travaglini@arm.com
17913481Sgiacomo.travaglini@arm.comvoid Helper1(Helper1Param param) {
18013481Sgiacomo.travaglini@arm.com  for (int i = 0; i < kRepeat; i++) {
18113481Sgiacomo.travaglini@arm.com    const char ch = param.mock_foo->Baz("a", "b");
18213481Sgiacomo.travaglini@arm.com    if (ch == 'a') {
18313481Sgiacomo.travaglini@arm.com      // It was an expected call.
18413481Sgiacomo.travaglini@arm.com      (*param.count)++;
18513481Sgiacomo.travaglini@arm.com    } else {
18613481Sgiacomo.travaglini@arm.com      // It was an excessive call.
18713481Sgiacomo.travaglini@arm.com      EXPECT_EQ('\0', ch);
18813481Sgiacomo.travaglini@arm.com    }
18913481Sgiacomo.travaglini@arm.com
19013481Sgiacomo.travaglini@arm.com    // An unexpected call.
19113481Sgiacomo.travaglini@arm.com    EXPECT_EQ('\0', param.mock_foo->Baz("x", "y")) << "Expected failure.";
19213481Sgiacomo.travaglini@arm.com
19313481Sgiacomo.travaglini@arm.com    // An uninteresting call.
19413481Sgiacomo.travaglini@arm.com    EXPECT_EQ(1, param.mock_foo->Bar(5));
19513481Sgiacomo.travaglini@arm.com  }
19613481Sgiacomo.travaglini@arm.com}
19713481Sgiacomo.travaglini@arm.com
19813481Sgiacomo.travaglini@arm.com// This should generate 3*kRepeat + 1 failures in total.
19913481Sgiacomo.travaglini@arm.comvoid TestConcurrentCallsOnSameObject(Dummy /* dummy */) {
20013481Sgiacomo.travaglini@arm.com  MockFoo foo;
20113481Sgiacomo.travaglini@arm.com
20213481Sgiacomo.travaglini@arm.com  ON_CALL(foo, Bar(_))
20313481Sgiacomo.travaglini@arm.com      .WillByDefault(Return(1));
20413481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Baz(_, "b"))
20513481Sgiacomo.travaglini@arm.com      .Times(kRepeat)
20613481Sgiacomo.travaglini@arm.com      .WillRepeatedly(Return('a'));
20713481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Baz(_, "c"));  // Expected to be unsatisfied.
20813481Sgiacomo.travaglini@arm.com
20913481Sgiacomo.travaglini@arm.com  // This chunk of code should generate kRepeat failures about
21013481Sgiacomo.travaglini@arm.com  // excessive calls, and 2*kRepeat failures about unexpected calls.
21113481Sgiacomo.travaglini@arm.com  int count1 = 0;
21213481Sgiacomo.travaglini@arm.com  const Helper1Param param = { &foo, &count1 };
21313481Sgiacomo.travaglini@arm.com  ThreadWithParam<Helper1Param>* const t =
21413481Sgiacomo.travaglini@arm.com      new ThreadWithParam<Helper1Param>(Helper1, param, NULL);
21513481Sgiacomo.travaglini@arm.com
21613481Sgiacomo.travaglini@arm.com  int count2 = 0;
21713481Sgiacomo.travaglini@arm.com  const Helper1Param param2 = { &foo, &count2 };
21813481Sgiacomo.travaglini@arm.com  Helper1(param2);
21913481Sgiacomo.travaglini@arm.com  JoinAndDelete(t);
22013481Sgiacomo.travaglini@arm.com
22113481Sgiacomo.travaglini@arm.com  EXPECT_EQ(kRepeat, count1 + count2);
22213481Sgiacomo.travaglini@arm.com
22313481Sgiacomo.travaglini@arm.com  // foo's destructor should generate one failure about unsatisfied
22413481Sgiacomo.travaglini@arm.com  // expectation.
22513481Sgiacomo.travaglini@arm.com}
22613481Sgiacomo.travaglini@arm.com
22713481Sgiacomo.travaglini@arm.com// Tests using the same mock object in multiple threads when the
22813481Sgiacomo.travaglini@arm.com// expectations are partially ordered.
22913481Sgiacomo.travaglini@arm.com
23013481Sgiacomo.travaglini@arm.comvoid Helper2(MockFoo* foo) {
23113481Sgiacomo.travaglini@arm.com  for (int i = 0; i < kRepeat; i++) {
23213481Sgiacomo.travaglini@arm.com    foo->Bar(2);
23313481Sgiacomo.travaglini@arm.com    foo->Bar(3);
23413481Sgiacomo.travaglini@arm.com  }
23513481Sgiacomo.travaglini@arm.com}
23613481Sgiacomo.travaglini@arm.com
23713481Sgiacomo.travaglini@arm.com// This should generate no Google Test failures.
23813481Sgiacomo.travaglini@arm.comvoid TestPartiallyOrderedExpectationsWithThreads(Dummy /* dummy */) {
23913481Sgiacomo.travaglini@arm.com  MockFoo foo;
24013481Sgiacomo.travaglini@arm.com  Sequence s1, s2;
24113481Sgiacomo.travaglini@arm.com
24213481Sgiacomo.travaglini@arm.com  {
24313481Sgiacomo.travaglini@arm.com    InSequence dummy;
24413481Sgiacomo.travaglini@arm.com    EXPECT_CALL(foo, Bar(0));
24513481Sgiacomo.travaglini@arm.com    EXPECT_CALL(foo, Bar(1))
24613481Sgiacomo.travaglini@arm.com        .InSequence(s1, s2);
24713481Sgiacomo.travaglini@arm.com  }
24813481Sgiacomo.travaglini@arm.com
24913481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Bar(2))
25013481Sgiacomo.travaglini@arm.com      .Times(2*kRepeat)
25113481Sgiacomo.travaglini@arm.com      .InSequence(s1)
25213481Sgiacomo.travaglini@arm.com      .RetiresOnSaturation();
25313481Sgiacomo.travaglini@arm.com  EXPECT_CALL(foo, Bar(3))
25413481Sgiacomo.travaglini@arm.com      .Times(2*kRepeat)
25513481Sgiacomo.travaglini@arm.com      .InSequence(s2);
25613481Sgiacomo.travaglini@arm.com
25713481Sgiacomo.travaglini@arm.com  {
25813481Sgiacomo.travaglini@arm.com    InSequence dummy;
25913481Sgiacomo.travaglini@arm.com    EXPECT_CALL(foo, Bar(2))
26013481Sgiacomo.travaglini@arm.com        .InSequence(s1, s2);
26113481Sgiacomo.travaglini@arm.com    EXPECT_CALL(foo, Bar(4));
26213481Sgiacomo.travaglini@arm.com  }
26313481Sgiacomo.travaglini@arm.com
26413481Sgiacomo.travaglini@arm.com  foo.Bar(0);
26513481Sgiacomo.travaglini@arm.com  foo.Bar(1);
26613481Sgiacomo.travaglini@arm.com
26713481Sgiacomo.travaglini@arm.com  ThreadWithParam<MockFoo*>* const t =
26813481Sgiacomo.travaglini@arm.com      new ThreadWithParam<MockFoo*>(Helper2, &foo, NULL);
26913481Sgiacomo.travaglini@arm.com  Helper2(&foo);
27013481Sgiacomo.travaglini@arm.com  JoinAndDelete(t);
27113481Sgiacomo.travaglini@arm.com
27213481Sgiacomo.travaglini@arm.com  foo.Bar(2);
27313481Sgiacomo.travaglini@arm.com  foo.Bar(4);
27413481Sgiacomo.travaglini@arm.com}
27513481Sgiacomo.travaglini@arm.com
27613481Sgiacomo.travaglini@arm.com// Tests using Google Mock constructs in many threads concurrently.
27713481Sgiacomo.travaglini@arm.comTEST(StressTest, CanUseGMockWithThreads) {
27813481Sgiacomo.travaglini@arm.com  void (*test_routines[])(Dummy dummy) = {
27913481Sgiacomo.travaglini@arm.com    &TestConcurrentCopyAndReadLinkedPtr,
28013481Sgiacomo.travaglini@arm.com    &TestConcurrentWriteToEqualLinkedPtr,
28113481Sgiacomo.travaglini@arm.com    &TestConcurrentMockObjects,
28213481Sgiacomo.travaglini@arm.com    &TestConcurrentCallsOnSameObject,
28313481Sgiacomo.travaglini@arm.com    &TestPartiallyOrderedExpectationsWithThreads,
28413481Sgiacomo.travaglini@arm.com  };
28513481Sgiacomo.travaglini@arm.com
28613481Sgiacomo.travaglini@arm.com  const int kRoutines = sizeof(test_routines)/sizeof(test_routines[0]);
28713481Sgiacomo.travaglini@arm.com  const int kCopiesOfEachRoutine = kMaxTestThreads / kRoutines;
28813481Sgiacomo.travaglini@arm.com  const int kTestThreads = kCopiesOfEachRoutine * kRoutines;
28913481Sgiacomo.travaglini@arm.com  ThreadWithParam<Dummy>* threads[kTestThreads] = {};
29013481Sgiacomo.travaglini@arm.com  for (int i = 0; i < kTestThreads; i++) {
29113481Sgiacomo.travaglini@arm.com    // Creates a thread to run the test function.
29213481Sgiacomo.travaglini@arm.com    threads[i] =
29313481Sgiacomo.travaglini@arm.com        new ThreadWithParam<Dummy>(test_routines[i % kRoutines], Dummy(), NULL);
29413481Sgiacomo.travaglini@arm.com    GTEST_LOG_(INFO) << "Thread #" << i << " running . . .";
29513481Sgiacomo.travaglini@arm.com  }
29613481Sgiacomo.travaglini@arm.com
29713481Sgiacomo.travaglini@arm.com  // At this point, we have many threads running.
29813481Sgiacomo.travaglini@arm.com  for (int i = 0; i < kTestThreads; i++) {
29913481Sgiacomo.travaglini@arm.com    JoinAndDelete(threads[i]);
30013481Sgiacomo.travaglini@arm.com  }
30113481Sgiacomo.travaglini@arm.com
30213481Sgiacomo.travaglini@arm.com  // Ensures that the correct number of failures have been reported.
30313481Sgiacomo.travaglini@arm.com  const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
30413481Sgiacomo.travaglini@arm.com  const TestResult& result = *info->result();
30513481Sgiacomo.travaglini@arm.com  const int kExpectedFailures = (3*kRepeat + 1)*kCopiesOfEachRoutine;
30613481Sgiacomo.travaglini@arm.com  GTEST_CHECK_(kExpectedFailures == result.total_part_count())
30713481Sgiacomo.travaglini@arm.com      << "Expected " << kExpectedFailures << " failures, but got "
30813481Sgiacomo.travaglini@arm.com      << result.total_part_count();
30913481Sgiacomo.travaglini@arm.com}
31013481Sgiacomo.travaglini@arm.com
31113481Sgiacomo.travaglini@arm.com}  // namespace
31213481Sgiacomo.travaglini@arm.com}  // namespace testing
31313481Sgiacomo.travaglini@arm.com
31413481Sgiacomo.travaglini@arm.comint main(int argc, char **argv) {
31513481Sgiacomo.travaglini@arm.com  testing::InitGoogleMock(&argc, argv);
31613481Sgiacomo.travaglini@arm.com
31713481Sgiacomo.travaglini@arm.com  const int exit_code = RUN_ALL_TESTS();  // Expected to fail.
31813481Sgiacomo.travaglini@arm.com  GTEST_CHECK_(exit_code != 0) << "RUN_ALL_TESTS() did not fail as expected";
31913481Sgiacomo.travaglini@arm.com
32013481Sgiacomo.travaglini@arm.com  printf("\nPASS\n");
32113481Sgiacomo.travaglini@arm.com  return 0;
32213481Sgiacomo.travaglini@arm.com}
323