This source file includes following definitions.
- RunCurrentLoopUntilIdle
- AddFailureAt
- MakeExpectedNotRunClosure
- called_
- Run
- MakeExpectedRunClosure
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- ExpectIsCanceled
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- MaybeRunDeadlyTaskTrackerMemberFunction
- PostDoNothingTask
- TEST_F
- TryCancel
- TEST_F
- TEST_F
#include "base/task/cancelable_task_tracker.h"
#include <cstddef>
#include <deque>
#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/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
namespace {
class CancelableTaskTrackerTest : public testing::Test {
protected:
virtual ~CancelableTaskTrackerTest() { RunCurrentLoopUntilIdle(); }
void RunCurrentLoopUntilIdle() {
RunLoop run_loop;
run_loop.RunUntilIdle();
}
CancelableTaskTracker task_tracker_;
private:
MessageLoop message_loop_;
};
void AddFailureAt(const tracked_objects::Location& location) {
ADD_FAILURE_AT(location.file_name(), location.line_number());
}
Closure MakeExpectedNotRunClosure(const tracked_objects::Location& location) {
return Bind(&AddFailureAt, location);
}
class RunChecker {
public:
explicit RunChecker(const tracked_objects::Location& location)
: location_(location), called_(false) {}
~RunChecker() {
if (!called_) {
ADD_FAILURE_AT(location_.file_name(), location_.line_number());
}
}
void Run() { called_ = true; }
private:
tracked_objects::Location location_;
bool called_;
};
Closure MakeExpectedRunClosure(const tracked_objects::Location& location) {
return Bind(&RunChecker::Run, Owned(new RunChecker(location)));
}
}
TEST_F(CancelableTaskTrackerTest, NoCancel) {
Thread worker_thread("worker thread");
ASSERT_TRUE(worker_thread.Start());
ignore_result(task_tracker_.PostTask(worker_thread.message_loop_proxy().get(),
FROM_HERE,
MakeExpectedRunClosure(FROM_HERE)));
ignore_result(
task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(),
FROM_HERE,
MakeExpectedRunClosure(FROM_HERE),
MakeExpectedRunClosure(FROM_HERE)));
CancelableTaskTracker::IsCanceledCallback is_canceled;
ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
worker_thread.Stop();
RunCurrentLoopUntilIdle();
EXPECT_FALSE(is_canceled.Run());
}
TEST_F(CancelableTaskTrackerTest, CancelPostedTask) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask(
test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
EXPECT_EQ(1U, test_task_runner->GetPendingTasks().size());
task_tracker_.TryCancel(task_id);
test_task_runner->RunUntilIdle();
}
TEST_F(CancelableTaskTrackerTest, CancelPostedTaskAndReply) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
CancelableTaskTracker::TaskId task_id =
task_tracker_.PostTaskAndReply(test_task_runner.get(),
FROM_HERE,
MakeExpectedNotRunClosure(FROM_HERE),
MakeExpectedNotRunClosure(FROM_HERE));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
task_tracker_.TryCancel(task_id);
test_task_runner->RunUntilIdle();
}
TEST_F(CancelableTaskTrackerTest, CancelReply) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
CancelableTaskTracker::TaskId task_id =
task_tracker_.PostTaskAndReply(test_task_runner.get(),
FROM_HERE,
MakeExpectedRunClosure(FROM_HERE),
MakeExpectedNotRunClosure(FROM_HERE));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
test_task_runner->RunUntilIdle();
task_tracker_.TryCancel(task_id);
}
TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) {
Thread worker_thread("worker thread");
ASSERT_TRUE(worker_thread.Start());
CancelableTaskTracker::TaskId task_id =
task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(),
FROM_HERE,
Bind(&DoNothing),
MakeExpectedNotRunClosure(FROM_HERE));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
task_tracker_.TryCancel(task_id);
worker_thread.Stop();
}
void ExpectIsCanceled(
const CancelableTaskTracker::IsCanceledCallback& is_canceled,
bool expected_is_canceled) {
EXPECT_EQ(expected_is_canceled, is_canceled.Run());
}
TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) {
CancelableTaskTracker::IsCanceledCallback is_canceled;
CancelableTaskTracker::TaskId task_id =
task_tracker_.NewTrackedTaskId(&is_canceled);
EXPECT_FALSE(is_canceled.Run());
Thread other_thread("other thread");
ASSERT_TRUE(other_thread.Start());
other_thread.message_loop_proxy()->PostTask(
FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, false));
other_thread.Stop();
task_tracker_.TryCancel(task_id);
ASSERT_TRUE(other_thread.Start());
other_thread.message_loop_proxy()->PostTask(
FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, true));
other_thread.Stop();
}
TEST_F(CancelableTaskTrackerTest, CancelAll) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
ignore_result(task_tracker_.PostTask(
test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
ignore_result(
task_tracker_.PostTaskAndReply(test_task_runner.get(),
FROM_HERE,
MakeExpectedNotRunClosure(FROM_HERE),
MakeExpectedNotRunClosure(FROM_HERE)));
CancelableTaskTracker::IsCanceledCallback is_canceled;
ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
task_tracker_.TryCancelAll();
test_task_runner->RunUntilIdle();
RunCurrentLoopUntilIdle();
EXPECT_TRUE(is_canceled.Run());
}
TEST_F(CancelableTaskTrackerTest, DestructionCancelsAll) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
CancelableTaskTracker::IsCanceledCallback is_canceled;
{
CancelableTaskTracker task_tracker;
ignore_result(task_tracker.PostTask(test_task_runner.get(),
FROM_HERE,
MakeExpectedNotRunClosure(FROM_HERE)));
ignore_result(
task_tracker.PostTaskAndReply(test_task_runner.get(),
FROM_HERE,
MakeExpectedNotRunClosure(FROM_HERE),
MakeExpectedNotRunClosure(FROM_HERE)));
ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
}
test_task_runner->RunUntilIdle();
RunCurrentLoopUntilIdle();
EXPECT_FALSE(is_canceled.Run());
}
TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPost) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
ignore_result(task_tracker_.PostTask(
test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
task_tracker_.TryCancelAll();
test_task_runner->RunUntilIdle();
EXPECT_TRUE(task_tracker_.HasTrackedTasks());
RunCurrentLoopUntilIdle();
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
}
TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPostWithReply) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
ignore_result(
task_tracker_.PostTaskAndReply(test_task_runner.get(),
FROM_HERE,
MakeExpectedNotRunClosure(FROM_HERE),
MakeExpectedNotRunClosure(FROM_HERE)));
task_tracker_.TryCancelAll();
test_task_runner->RunUntilIdle();
EXPECT_TRUE(task_tracker_.HasTrackedTasks());
RunCurrentLoopUntilIdle();
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
}
TEST_F(CancelableTaskTrackerTest, HasTrackedTasksIsCancelled) {
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
CancelableTaskTracker::IsCanceledCallback is_canceled;
ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
task_tracker_.TryCancelAll();
EXPECT_TRUE(task_tracker_.HasTrackedTasks());
is_canceled.Reset();
EXPECT_FALSE(task_tracker_.HasTrackedTasks());
}
class CancelableTaskTrackerDeathTest : public CancelableTaskTrackerTest {
protected:
CancelableTaskTrackerDeathTest() {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
}
virtual ~CancelableTaskTrackerDeathTest() {}
};
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#define ENABLE_THREAD_CHECKER 1
#else
#define ENABLE_THREAD_CHECKER 0
#endif
void MaybeRunDeadlyTaskTrackerMemberFunction(
CancelableTaskTracker* task_tracker,
const Callback<void(CancelableTaskTracker*)>& fn) {
#if ENABLE_THREAD_CHECKER
EXPECT_DEATH_IF_SUPPORTED(fn.Run(task_tracker), "");
#endif
}
void PostDoNothingTask(CancelableTaskTracker* task_tracker) {
ignore_result(task_tracker->PostTask(
scoped_refptr<TestSimpleTaskRunner>(new TestSimpleTaskRunner()).get(),
FROM_HERE,
Bind(&DoNothing)));
}
TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) {
Thread bad_thread("bad thread");
ASSERT_TRUE(bad_thread.Start());
bad_thread.message_loop_proxy()->PostTask(
FROM_HERE,
Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
Unretained(&task_tracker_),
Bind(&PostDoNothingTask)));
}
void TryCancel(CancelableTaskTracker::TaskId task_id,
CancelableTaskTracker* task_tracker) {
task_tracker->TryCancel(task_id);
}
TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
Thread bad_thread("bad thread");
ASSERT_TRUE(bad_thread.Start());
CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask(
test_task_runner.get(), FROM_HERE, Bind(&DoNothing));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
bad_thread.message_loop_proxy()->PostTask(
FROM_HERE,
Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
Unretained(&task_tracker_),
Bind(&TryCancel, task_id)));
test_task_runner->RunUntilIdle();
}
TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) {
scoped_refptr<TestSimpleTaskRunner> test_task_runner(
new TestSimpleTaskRunner());
Thread bad_thread("bad thread");
ASSERT_TRUE(bad_thread.Start());
CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask(
test_task_runner.get(), FROM_HERE, Bind(&DoNothing));
EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
bad_thread.message_loop_proxy()->PostTask(
FROM_HERE,
Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
Unretained(&task_tracker_),
Bind(&CancelableTaskTracker::TryCancelAll)));
test_task_runner->RunUntilIdle();
}
}