// Copyright (c) 2013 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 "base/deferred_sequenced_task_runner.h"

#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace {

class DeferredSequencedTaskRunnerTest : public testing::Test {
 public:
  class ExecuteTaskOnDestructor : public RefCounted<ExecuteTaskOnDestructor> {
   public:
    ExecuteTaskOnDestructor(
        DeferredSequencedTaskRunnerTest* executor,
        int task_id)
        : executor_(executor),
          task_id_(task_id) {
    }
  private:
   friend class RefCounted<ExecuteTaskOnDestructor>;
   virtual ~ExecuteTaskOnDestructor() { executor_->ExecuteTask(task_id_); }
   DeferredSequencedTaskRunnerTest* executor_;
   int task_id_;
  };

  void ExecuteTask(int task_id) {
    AutoLock lock(lock_);
    executed_task_ids_.push_back(task_id);
  }

  void PostExecuteTask(int task_id) {
    runner_->PostTask(FROM_HERE,
                      BindOnce(&DeferredSequencedTaskRunnerTest::ExecuteTask,
                               Unretained(this), task_id));
  }

  void StartRunner() {
    runner_->Start();
  }

  void DoNothing(ExecuteTaskOnDestructor* object) {
  }

 protected:
  DeferredSequencedTaskRunnerTest()
      : runner_(
            new DeferredSequencedTaskRunner(ThreadTaskRunnerHandle::Get())) {}

  test::TaskEnvironment task_environment_;
  scoped_refptr<DeferredSequencedTaskRunner> runner_;
  mutable Lock lock_;
  std::vector<int> executed_task_ids_;
};

TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
  PostExecuteTask(1);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
}

TEST_F(DeferredSequencedTaskRunnerTest, Start) {
  StartRunner();
  PostExecuteTask(1);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
}

TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) {
  StartRunner();
  for (int i = 1; i < 5; ++i)
    PostExecuteTask(i);

  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
}

TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
  PostExecuteTask(1);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());

  StartRunner();
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));

  PostExecuteTask(2);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
}

TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
  for (int i = 1; i < 5; ++i)
    PostExecuteTask(i);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre());

  StartRunner();
  for (int i = 5; i < 9; ++i)
    PostExecuteTask(i);
  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
}

TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) {
  {
    Thread thread1("DeferredSequencedTaskRunnerTestThread1");
    Thread thread2("DeferredSequencedTaskRunnerTestThread2");
    thread1.Start();
    thread2.Start();
    for (int i = 0; i < 5; ++i) {
      thread1.task_runner()->PostTask(
          FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
                              Unretained(this), 2 * i));
      thread2.task_runner()->PostTask(
          FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
                              Unretained(this), 2 * i + 1));
      if (i == 2) {
        thread1.task_runner()->PostTask(
            FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::StartRunner,
                                Unretained(this)));
      }
    }
  }

  RunLoop().RunUntilIdle();
  EXPECT_THAT(executed_task_ids_,
      testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
}

TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) {
  {
    Thread thread("DeferredSequencedTaskRunnerTestThread");
    thread.Start();
    runner_ = new DeferredSequencedTaskRunner(thread.task_runner());
    for (int i = 0; i < 5; ++i) {
      {
        // Use a block to ensure that no reference to |short_lived_object|
        // is kept on the main thread after it is posted to |runner_|.
        scoped_refptr<ExecuteTaskOnDestructor> short_lived_object =
            new ExecuteTaskOnDestructor(this, 2 * i);
        runner_->PostTask(
            FROM_HERE,
            BindOnce(&DeferredSequencedTaskRunnerTest::DoNothing,
                     Unretained(this), RetainedRef(short_lived_object)));
      }
      // |short_lived_object| with id |2 * i| should be destroyed before the
      // task |2 * i + 1| is executed.
      PostExecuteTask(2 * i + 1);
    }
    StartRunner();
  }

  // All |short_lived_object| with id |2 * i| are destroyed before the task
  // |2 * i + 1| is executed.
  EXPECT_THAT(executed_task_ids_,
              testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
}

void GetRunsTasksInCurrentSequence(bool* result,
                                   scoped_refptr<SequencedTaskRunner> runner,
                                   OnceClosure quit) {
  *result = runner->RunsTasksInCurrentSequence();
  std::move(quit).Run();
}

TEST_F(DeferredSequencedTaskRunnerTest, RunsTasksInCurrentSequence) {
  scoped_refptr<DeferredSequencedTaskRunner> runner =
      MakeRefCounted<DeferredSequencedTaskRunner>();
  EXPECT_TRUE(runner->RunsTasksInCurrentSequence());

  Thread thread1("DeferredSequencedTaskRunnerTestThread1");
  thread1.Start();
  bool runs_task_in_current_thread = true;
  base::RunLoop run_loop;
  thread1.task_runner()->PostTask(
      FROM_HERE,
      BindOnce(&GetRunsTasksInCurrentSequence, &runs_task_in_current_thread,
               runner, run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_FALSE(runs_task_in_current_thread);
}

TEST_F(DeferredSequencedTaskRunnerTest, StartWithTaskRunner) {
  scoped_refptr<DeferredSequencedTaskRunner> runner =
      MakeRefCounted<DeferredSequencedTaskRunner>();
  bool run_called = false;
  base::RunLoop run_loop;
  runner->PostTask(FROM_HERE,
                   BindOnce(
                       [](bool* run_called, base::OnceClosure quit_closure) {
                         *run_called = true;
                         std::move(quit_closure).Run();
                       },
                       &run_called, run_loop.QuitClosure()));
  runner->StartWithTaskRunner(ThreadTaskRunnerHandle::Get());
  run_loop.Run();
  EXPECT_TRUE(run_called);
}

}  // namespace
}  // namespace base
