// Copyright 2015 the V8 project 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 "src/base/atomicops.h"
#include "src/base/platform/platform.h"
#include "src/tasks/cancelable-task.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace v8 {
namespace internal {

namespace {

using ResultType = std::atomic<CancelableTaskManager::Id>;

class CancelableTaskManagerTest;

class TestTask : public Task, public Cancelable {
 public:
  enum Mode { kDoNothing, kWaitTillCancelTriggered, kCheckNotRun };

  TestTask(CancelableTaskManagerTest* test, ResultType* result, Mode mode);

  // Task override.
  void Run() final;

 private:
  ResultType* const result_;
  const Mode mode_;
  CancelableTaskManagerTest* const test_;
};

class SequentialRunner {
 public:
  explicit SequentialRunner(std::unique_ptr<TestTask> task)
      : task_(std::move(task)), task_id_(task_->id()) {}

  void Run() {
    task_->Run();
    task_.reset();
  }

  CancelableTaskManager::Id task_id() const { return task_id_; }

 private:
  std::unique_ptr<TestTask> task_;
  const CancelableTaskManager::Id task_id_;
};

class ThreadedRunner final : public base::Thread {
 public:
  explicit ThreadedRunner(std::unique_ptr<TestTask> task)
      : Thread(Options("runner thread")),
        task_(std::move(task)),
        task_id_(task_->id()) {}

  void Run() override {
    task_->Run();
    task_.reset();
  }

  CancelableTaskManager::Id task_id() const { return task_id_; }

 private:
  std::unique_ptr<TestTask> task_;
  const CancelableTaskManager::Id task_id_;
};

class CancelableTaskManagerTest : public ::testing::Test {
 public:
  CancelableTaskManager* manager() { return &manager_; }

  std::unique_ptr<TestTask> NewTask(
      ResultType* result, TestTask::Mode mode = TestTask::kDoNothing) {
    return std::make_unique<TestTask>(this, result, mode);
  }

  void CancelAndWait() {
    cancel_triggered_.store(true);
    manager_.CancelAndWait();
  }

  TryAbortResult TryAbortAll() {
    cancel_triggered_.store(true);
    return manager_.TryAbortAll();
  }

  bool cancel_triggered() const { return cancel_triggered_.load(); }

 private:
  CancelableTaskManager manager_;
  std::atomic<bool> cancel_triggered_{false};
};

TestTask::TestTask(CancelableTaskManagerTest* test, ResultType* result,
                   Mode mode)
    : Cancelable(test->manager()), result_(result), mode_(mode), test_(test) {}

void TestTask::Run() {
  if (!TryRun()) return;

  result_->store(id());

  switch (mode_) {
    case kWaitTillCancelTriggered:
      // Simple busy wait until the main thread tried to cancel.
      while (!test_->cancel_triggered()) {
      }
      break;
    case kCheckNotRun:
      // Check that we never execute {RunInternal}.
      EXPECT_TRUE(false);
      break;
    default:
      break;
  }
}

}  // namespace

TEST_F(CancelableTaskManagerTest, EmptyCancelableTaskManager) {
  CancelAndWait();
}

TEST_F(CancelableTaskManagerTest, SequentialCancelAndWait) {
  ResultType result1{0};
  SequentialRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
  EXPECT_EQ(0u, result1);
  CancelAndWait();
  EXPECT_EQ(0u, result1);
  runner1.Run();
  EXPECT_EQ(0u, result1);
}

TEST_F(CancelableTaskManagerTest, SequentialMultipleTasks) {
  ResultType result1{0};
  ResultType result2{0};
  SequentialRunner runner1(NewTask(&result1));
  SequentialRunner runner2(NewTask(&result2));
  EXPECT_EQ(1u, runner1.task_id());
  EXPECT_EQ(2u, runner2.task_id());

  EXPECT_EQ(0u, result1);
  runner1.Run();
  EXPECT_EQ(1u, result1);

  EXPECT_EQ(0u, result2);
  runner2.Run();
  EXPECT_EQ(2u, result2);

  CancelAndWait();
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
}

TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStarted) {
  ResultType result1{0};
  ResultType result2{0};
  ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCancelTriggered));
  ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCancelTriggered));
  CHECK(runner1.Start());
  CHECK(runner2.Start());
  // Busy wait on result to make sure both tasks are done.
  while (result1.load() == 0 || result2.load() == 0) {
  }
  CancelAndWait();
  runner1.Join();
  runner2.Join();
  EXPECT_EQ(1u, result1);
  EXPECT_EQ(2u, result2);
}

TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRun) {
  ResultType result1{0};
  ResultType result2{0};
  ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
  ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
  CancelAndWait();
  // Tasks are canceled, hence the runner will bail out and not update result.
  CHECK(runner1.Start());
  CHECK(runner2.Start());
  runner1.Join();
  runner2.Join();
  EXPECT_EQ(0u, result1);
  EXPECT_EQ(0u, result2);
}

TEST_F(CancelableTaskManagerTest, RemoveBeforeCancelAndWait) {
  ResultType result1{0};
  ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
  CancelableTaskManager::Id id = runner1.task_id();
  EXPECT_EQ(1u, id);
  EXPECT_EQ(TryAbortResult::kTaskAborted, manager()->TryAbort(id));
  CHECK(runner1.Start());
  runner1.Join();
  CancelAndWait();
  EXPECT_EQ(0u, result1);
}

TEST_F(CancelableTaskManagerTest, RemoveAfterCancelAndWait) {
  ResultType result1{0};
  ThreadedRunner runner1(NewTask(&result1));
  CancelableTaskManager::Id id = runner1.task_id();
  EXPECT_EQ(1u, id);
  CHECK(runner1.Start());
  runner1.Join();
  CancelAndWait();
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(id));
  EXPECT_EQ(1u, result1);
}

TEST_F(CancelableTaskManagerTest, RemoveUnmanagedId) {
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
  CancelAndWait();
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
  EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(3));
}

TEST_F(CancelableTaskManagerTest, EmptyTryAbortAll) {
  EXPECT_EQ(TryAbortResult::kTaskRemoved, TryAbortAll());
  CancelAndWait();
}

TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRunTryAbortAll) {
  ResultType result1{0};
  ResultType result2{0};
  ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
  ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
  EXPECT_EQ(TryAbortResult::kTaskAborted, TryAbortAll());
  // Tasks are canceled, hence the runner will bail out and not update result.
  CHECK(runner1.Start());
  CHECK(runner2.Start());
  runner1.Join();
  runner2.Join();
  EXPECT_EQ(0u, result1);
  EXPECT_EQ(0u, result2);
  CancelAndWait();
}

TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStartedTryAbortAll) {
  ResultType result1{0};
  ResultType result2{0};
  ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCancelTriggered));
  ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCancelTriggered));
  CHECK(runner1.Start());
  // Busy wait on result to make sure task1 is done.
  while (result1.load() == 0) {
  }
  // If the task saw that we triggered the cancel and finished *before* the
  // actual cancel happened, we get {kTaskAborted}. Otherwise, we get
  // {kTaskRunning}.
  EXPECT_THAT(TryAbortAll(),
              testing::AnyOf(testing::Eq(TryAbortResult::kTaskAborted),
                             testing::Eq(TryAbortResult::kTaskRunning)));
  CHECK(runner2.Start());
  runner1.Join();
  runner2.Join();
  EXPECT_EQ(1u, result1);
  EXPECT_EQ(0u, result2);
  CancelAndWait();
}

}  // namespace internal
}  // namespace v8
