// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/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 {

class CancelableTaskTrackerTest : public testing::Test {
 protected:
  virtual ~CancelableTaskTrackerTest() {
    RunCurrentLoopUntilIdle();
  }

  void RunCurrentLoopUntilIdle() {
    base::RunLoop run_loop;
    run_loop.RunUntilIdle();
  }

  CancelableTaskTracker task_tracker_;

 private:
  // Needed by CancelableTaskTracker methods.
  base::MessageLoop message_loop_;
};

void AddFailureAt(const tracked_objects::Location& location) {
  ADD_FAILURE_AT(location.file_name(), location.line_number());
}

// Returns a closure that fails if run.
base::Closure MakeExpectedNotRunClosure(
    const tracked_objects::Location& location) {
  return base::Bind(&AddFailureAt, location);
}

// A helper class for MakeExpectedRunClosure() that fails if it is
// destroyed without Run() having been called.  This class may be used
// from multiple threads as long as Run() is called at most once
// before destruction.
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_;
};

// Returns a closure that fails on destruction if it hasn't been run.
base::Closure MakeExpectedRunClosure(
    const tracked_objects::Location& location) {
  return base::Bind(&RunChecker::Run, base::Owned(new RunChecker(location)));
}

// With the task tracker, post a task, a task with a reply, and get a
// new task id without canceling any of them.  The tasks and the reply
// should run and the "is canceled" callback should return false.
TEST_F(CancelableTaskTrackerTest, NoCancel) {
  base::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());
}

// Post a task with the task tracker but cancel it before running the
// task runner.  The task should not run.
TEST_F(CancelableTaskTrackerTest, CancelPostedTask) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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();
}

// Post a task with reply with the task tracker and cancel it before
// running the task runner.  Neither the task nor the reply should
// run.
TEST_F(CancelableTaskTrackerTest, CancelPostedTaskAndReply) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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();
}

// Post a task with reply with the task tracker and cancel it after
// running the task runner but before running the current message
// loop.  The task should run but the reply should not.
TEST_F(CancelableTaskTrackerTest, CancelReply) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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);
}

// Post a task with reply with the task tracker on a worker thread and
// cancel it before running the current message loop.  The task should
// run but the reply should not.
TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) {
  base::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,
                                     base::Bind(&base::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());
}

// Create a new task ID and check its status on a separate thread
// before and after canceling.  The is-canceled callback should be
// thread-safe (i.e., nothing should blow up).
TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) {
  CancelableTaskTracker::IsCanceledCallback is_canceled;
  CancelableTaskTracker::TaskId task_id =
      task_tracker_.NewTrackedTaskId(&is_canceled);

  EXPECT_FALSE(is_canceled.Run());

  base::Thread other_thread("other thread");
  ASSERT_TRUE(other_thread.Start());
  other_thread.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::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,
      base::Bind(&ExpectIsCanceled, is_canceled, true));
  other_thread.Stop();
}

// With the task tracker, post a task, a task with a reply, get a new
// task id, and then cancel all of them.  None of the tasks nor the
// reply should run and the "is canceled" callback should return
// true.
TEST_F(CancelableTaskTrackerTest, CancelAll) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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());
}

// With the task tracker, post a task, a task with a reply, get a new
// task id, and then cancel all of them.  None of the tasks nor the
// reply should run and the "is canceled" callback should return
// true.
TEST_F(CancelableTaskTrackerTest, DestructionCancelsAll) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::TestSimpleTaskRunner());

  CancelableTaskTracker::IsCanceledCallback is_canceled;

  {
    // Create another task tracker with a smaller scope.
    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());
}

// Post a task and cancel it.  HasTrackedTasks() should return true
// from when the task is posted until the (do-nothing) reply task is
// flushed.
TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPost) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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());
}

// Post a task with a reply and cancel it.  HasTrackedTasks() should
// return true from when the task is posted until it is canceled.
TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPostWithReply) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::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());
}

// Create a new tracked task ID.  HasTrackedTasks() should return true
// until the IsCanceledCallback is destroyed.
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());
}

// The death tests below make sure that calling task tracker member
// functions from a thread different from its owner thread DCHECKs in
// debug mode.

class CancelableTaskTrackerDeathTest : public CancelableTaskTrackerTest {
 protected:
  CancelableTaskTrackerDeathTest() {
    // The default style "fast" does not support multi-threaded tests.
    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  }

  virtual ~CancelableTaskTrackerDeathTest() {}
};

// Duplicated from base/threading/thread_checker.h so that we can be
// good citizens there and undef the macro.
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#define ENABLE_THREAD_CHECKER 1
#else
#define ENABLE_THREAD_CHECKER 0
#endif

// Runs |fn| with |task_tracker|, expecting it to crash in debug mode.
void MaybeRunDeadlyTaskTrackerMemberFunction(
    CancelableTaskTracker* task_tracker,
    const base::Callback<void(CancelableTaskTracker*)>& fn) {
  // CancelableTask uses DCHECKs with its ThreadChecker (itself only
  // enabled in debug mode).
#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<base::TestSimpleTaskRunner>(
                                 new base::TestSimpleTaskRunner())
                                 .get(),
                             FROM_HERE,
                             base::Bind(&base::DoNothing)));
}

TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) {
  base::Thread bad_thread("bad thread");
  ASSERT_TRUE(bad_thread.Start());

  bad_thread.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
                 base::Unretained(&task_tracker_),
                 base::Bind(&PostDoNothingTask)));
}

void TryCancel(CancelableTaskTracker::TaskId task_id,
               CancelableTaskTracker* task_tracker) {
  task_tracker->TryCancel(task_id);
}

TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::TestSimpleTaskRunner());

  base::Thread bad_thread("bad thread");
  ASSERT_TRUE(bad_thread.Start());

  CancelableTaskTracker::TaskId task_id =
      task_tracker_.PostTask(
          test_task_runner.get(),
          FROM_HERE,
          base::Bind(&base::DoNothing));
  EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);

  bad_thread.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
                 base::Unretained(&task_tracker_),
                 base::Bind(&TryCancel, task_id)));

  test_task_runner->RunUntilIdle();
}

TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) {
  scoped_refptr<base::TestSimpleTaskRunner> test_task_runner(
      new base::TestSimpleTaskRunner());

  base::Thread bad_thread("bad thread");
  ASSERT_TRUE(bad_thread.Start());

  CancelableTaskTracker::TaskId task_id =
      task_tracker_.PostTask(
          test_task_runner.get(),
          FROM_HERE,
          base::Bind(&base::DoNothing));
  EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);

  bad_thread.message_loop_proxy()->PostTask(
      FROM_HERE,
      base::Bind(&MaybeRunDeadlyTaskTrackerMemberFunction,
                 base::Unretained(&task_tracker_),
                 base::Bind(&CancelableTaskTracker::TryCancelAll)));

  test_task_runner->RunUntilIdle();
}

}  // namespace
