This source file includes following definitions.
- DoStuff
- DetachFromSequence
- SetUp
- TearDown
- other_thread
- pool
- PostDoStuffToWorkerPool
- PostDoStuffToOtherThread
- PostDeleteToOtherThread
- ResetPool
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- MethodOnDifferentThreadDeathTest
- TEST_F
- TEST_F
- DetachThenCallFromDifferentThreadDeathTest
- TEST_F
- TEST_F
- DifferentSequenceTokensDeathTest
- TEST_F
- TEST_F
- WorkerPoolAndSimpleThreadDeathTest
- TEST_F
- TEST_F
- TwoDifferentWorkerPoolsDeathTest
- TEST_F
- TEST_F
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/sequence_checker.h"
#include "base/test/sequenced_worker_pool_owner.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define ENABLE_SEQUENCE_CHECKER 1
#else
#define ENABLE_SEQUENCE_CHECKER 0
#endif
namespace base {
namespace {
const size_t kNumWorkerThreads = 3;
class SequenceCheckedObject {
public:
SequenceCheckedObject() {}
~SequenceCheckedObject() {}
void DoStuff() {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
}
void DetachFromSequence() {
sequence_checker_.DetachFromSequence();
}
private:
SequenceChecker sequence_checker_;
DISALLOW_COPY_AND_ASSIGN(SequenceCheckedObject);
};
class SequenceCheckerTest : public testing::Test {
public:
SequenceCheckerTest() : other_thread_("sequence_checker_test_other_thread") {}
virtual ~SequenceCheckerTest() {}
virtual void SetUp() OVERRIDE {
other_thread_.Start();
ResetPool();
}
virtual void TearDown() OVERRIDE {
other_thread_.Stop();
pool()->Shutdown();
}
protected:
base::Thread* other_thread() { return &other_thread_; }
const scoped_refptr<SequencedWorkerPool>& pool() {
return pool_owner_->pool();
}
void PostDoStuffToWorkerPool(SequenceCheckedObject* sequence_checked_object,
const std::string& token_name) {
pool()->PostNamedSequencedWorkerTask(
token_name,
FROM_HERE,
base::Bind(&SequenceCheckedObject::DoStuff,
base::Unretained(sequence_checked_object)));
}
void PostDoStuffToOtherThread(
SequenceCheckedObject* sequence_checked_object) {
other_thread()->message_loop()->PostTask(
FROM_HERE,
base::Bind(&SequenceCheckedObject::DoStuff,
base::Unretained(sequence_checked_object)));
}
void PostDeleteToOtherThread(
scoped_ptr<SequenceCheckedObject> sequence_checked_object) {
other_thread()->message_loop()->DeleteSoon(
FROM_HERE,
sequence_checked_object.release());
}
void ResetPool() {
pool_owner_.reset(new SequencedWorkerPoolOwner(kNumWorkerThreads, "test"));
}
void MethodOnDifferentThreadDeathTest();
void DetachThenCallFromDifferentThreadDeathTest();
void DifferentSequenceTokensDeathTest();
void WorkerPoolAndSimpleThreadDeathTest();
void TwoDifferentWorkerPoolsDeathTest();
private:
MessageLoop message_loop_;
base::Thread other_thread_;
scoped_ptr<SequencedWorkerPoolOwner> pool_owner_;
};
TEST_F(SequenceCheckerTest, CallsAllowedOnSameThread) {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DoStuff();
sequence_checked_object.reset();
}
TEST_F(SequenceCheckerTest, DestructorAllowedOnDifferentThread) {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
PostDeleteToOtherThread(sequence_checked_object.Pass());
other_thread()->Stop();
}
TEST_F(SequenceCheckerTest, DetachFromSequence) {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToOtherThread(sequence_checked_object.get());
other_thread()->Stop();
}
TEST_F(SequenceCheckerTest, SameSequenceTokenValid) {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
pool()->FlushForTesting();
PostDeleteToOtherThread(sequence_checked_object.Pass());
other_thread()->Stop();
}
TEST_F(SequenceCheckerTest, DetachSequenceTokenValid) {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
pool()->FlushForTesting();
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
pool()->FlushForTesting();
PostDeleteToOtherThread(sequence_checked_object.Pass());
other_thread()->Stop();
}
#if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCE_CHECKER
void SequenceCheckerTest::MethodOnDifferentThreadDeathTest() {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
PostDoStuffToOtherThread(sequence_checked_object.get());
other_thread()->Stop();
}
#if ENABLE_SEQUENCE_CHECKER
TEST_F(SequenceCheckerTest, MethodNotAllowedOnDifferentThreadDeathTestInDebug) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_DEATH({
MethodOnDifferentThreadDeathTest();
}, "");
}
#else
TEST_F(SequenceCheckerTest, MethodAllowedOnDifferentThreadDeathTestInRelease) {
MethodOnDifferentThreadDeathTest();
}
#endif
void SequenceCheckerTest::DetachThenCallFromDifferentThreadDeathTest() {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToOtherThread(sequence_checked_object.get());
other_thread()->Stop();
sequence_checked_object->DoStuff();
}
#if ENABLE_SEQUENCE_CHECKER
TEST_F(SequenceCheckerTest, DetachFromSequenceDeathTestInDebug) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_DEATH({
DetachThenCallFromDifferentThreadDeathTest();
}, "");
}
#else
TEST_F(SequenceCheckerTest, DetachFromThreadDeathTestInRelease) {
DetachThenCallFromDifferentThreadDeathTest();
}
#endif
void SequenceCheckerTest::DifferentSequenceTokensDeathTest() {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "B");
pool()->FlushForTesting();
PostDeleteToOtherThread(sequence_checked_object.Pass());
other_thread()->Stop();
}
#if ENABLE_SEQUENCE_CHECKER
TEST_F(SequenceCheckerTest, DifferentSequenceTokensDeathTestInDebug) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_DEATH({
DifferentSequenceTokensDeathTest();
}, "");
}
#else
TEST_F(SequenceCheckerTest,
DifferentSequenceTokensDeathTestInRelease) {
DifferentSequenceTokensDeathTest();
}
#endif
void SequenceCheckerTest::WorkerPoolAndSimpleThreadDeathTest() {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
pool()->FlushForTesting();
PostDoStuffToOtherThread(sequence_checked_object.get());
other_thread()->Stop();
}
#if ENABLE_SEQUENCE_CHECKER
TEST_F(SequenceCheckerTest, WorkerPoolAndSimpleThreadDeathTestInDebug) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_DEATH({
WorkerPoolAndSimpleThreadDeathTest();
}, "");
}
#else
TEST_F(SequenceCheckerTest,
WorkerPoolAndSimpleThreadDeathTestInRelease) {
WorkerPoolAndSimpleThreadDeathTest();
}
#endif
void SequenceCheckerTest::TwoDifferentWorkerPoolsDeathTest() {
scoped_ptr<SequenceCheckedObject> sequence_checked_object(
new SequenceCheckedObject);
sequence_checked_object->DetachFromSequence();
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
PostDoStuffToWorkerPool(sequence_checked_object.get(), "A");
pool()->FlushForTesting();
SequencedWorkerPoolOwner second_pool_owner(kNumWorkerThreads, "test2");
second_pool_owner.pool()->PostNamedSequencedWorkerTask(
"A",
FROM_HERE,
base::Bind(&SequenceCheckedObject::DoStuff,
base::Unretained(sequence_checked_object.get())));
second_pool_owner.pool()->FlushForTesting();
second_pool_owner.pool()->Shutdown();
}
#if ENABLE_SEQUENCE_CHECKER
TEST_F(SequenceCheckerTest, TwoDifferentWorkerPoolsDeathTestInDebug) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
ASSERT_DEATH({
TwoDifferentWorkerPoolsDeathTest();
}, "");
}
#else
TEST_F(SequenceCheckerTest,
TwoDifferentWorkerPoolsDeathTestInRelease) {
TwoDifferentWorkerPoolsDeathTest();
}
#endif
#endif
}
}
#undef ENABLE_SEQUENCE_CHECKER