// Copyright 2019 The Chromium OS 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 <functional>
#include <memory>
#include <string>
#include <vector>

#include <base/barrier_closure.h>
#include <base/bind.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/run_loop.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "diagnostics/dpsl/internal/dpsl_global_context_impl.h"
#include "diagnostics/dpsl/internal/dpsl_thread_context_impl.h"
#include "diagnostics/dpsl/internal/test_dpsl_background_thread.h"
#include "diagnostics/dpsl/public/dpsl_global_context.h"
#include "diagnostics/dpsl/public/dpsl_thread_context.h"

namespace diagnostics {

class DpslThreadContextImplBaseTest : public testing::Test {
 public:
  DpslThreadContextImplBaseTest() = default;
  DpslThreadContextImplBaseTest(const DpslThreadContextImplBaseTest&) = delete;
  DpslThreadContextImplBaseTest& operator=(
      const DpslThreadContextImplBaseTest&) = delete;

  ~DpslThreadContextImplBaseTest() override {
    DpslThreadContextImpl::CleanThreadCounterForTesting();
    DpslGlobalContextImpl::CleanGlobalCounterForTesting();
  }

  void SetUp() override {
    global_context_ = DpslGlobalContext::Create();
    ASSERT_TRUE(global_context_);
  }

 protected:
  std::unique_ptr<DpslGlobalContext> global_context_;
};

using DpslThreadContextImplBaseDeathTest = DpslThreadContextImplBaseTest;

TEST_F(DpslThreadContextImplBaseDeathTest, CreateWithNullptrGlobalContext) {
  ASSERT_DEATH(DpslThreadContext::Create(nullptr), "GlobalContext is nullptr");
}

TEST_F(DpslThreadContextImplBaseDeathTest, CreateAndForget) {
  ASSERT_TRUE(DpslThreadContext::Create(global_context_.get()));

  ASSERT_DEATH(DpslThreadContext::Create(global_context_.get()),
               "Duplicate DpslThreadContext instances");
}

TEST_F(DpslThreadContextImplBaseDeathTest, CreateAndSave) {
  auto thread_context = DpslThreadContext::Create(global_context_.get());
  ASSERT_TRUE(thread_context);

  ASSERT_DEATH(DpslThreadContext::Create(global_context_.get()),
               "Duplicate DpslThreadContext instances");
}

TEST_F(DpslThreadContextImplBaseDeathTest, RunLoopTwice) {
  ASSERT_DEATH(
      [global_context = global_context_.get()]() {
        auto thread_context = DpslThreadContext::Create(global_context);
        thread_context->PostTask(
            std::function<void()>([thread_context = thread_context.get()]() {
              thread_context->RunEventLoop();
            }));
        thread_context->RunEventLoop();
      }(),
      "Called from already running message loop");
}

class DpslThreadContextImplMainThreadTest
    : public DpslThreadContextImplBaseTest {
 public:
  DpslThreadContextImplMainThreadTest() = default;
  DpslThreadContextImplMainThreadTest(
      const DpslThreadContextImplMainThreadTest&) = delete;
  DpslThreadContextImplMainThreadTest& operator=(
      const DpslThreadContextImplMainThreadTest&) = delete;

  void SetUp() override {
    DpslThreadContextImplBaseTest::SetUp();

    main_thread_context_ = DpslThreadContext::Create(global_context_.get());
    ASSERT_TRUE(main_thread_context_);
  }

  void QuitEventLoop() {
    EXPECT_TRUE(main_thread_context_->IsEventLoopRunning());
    main_thread_context_->QuitEventLoop();
  }

  void AddToQueueTask(int task_id) { task_id_queue_.push_back(task_id); }

  void GenerateFailure() {
    ADD_FAILURE() << "This function shouldn't be called";
  }

 protected:
  std::unique_ptr<DpslThreadContext> main_thread_context_;

  std::vector<int> task_id_queue_;
};

TEST_F(DpslThreadContextImplMainThreadTest, BelongsToCurrentThread) {
  EXPECT_TRUE(main_thread_context_->BelongsToCurrentThread());
}

TEST_F(DpslThreadContextImplMainThreadTest, PostTask) {
  main_thread_context_->PostTask(
      std::bind(&DpslThreadContextImplMainThreadTest::QuitEventLoop, this));

  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
  main_thread_context_->RunEventLoop();
  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
}

TEST_F(DpslThreadContextImplMainThreadTest, PostDelayedTask) {
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::QuitEventLoop, this),
      100);

  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
  main_thread_context_->RunEventLoop();
  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
}

TEST_F(DpslThreadContextImplMainThreadTest, PostDelayedTaskDifferentDelays) {
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 3),
      200);
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 2),
      100);
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 1),
      0);

  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::QuitEventLoop, this),
      200);

  // Should not be processsed after quit from event loop.
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::GenerateFailure, this),
      200);

  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
  main_thread_context_->RunEventLoop();
  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());

  EXPECT_THAT(task_id_queue_, testing::ElementsAreArray({1, 2, 3}));
}

TEST_F(DpslThreadContextImplMainThreadTest, PostDelayedTaskSameDelays) {
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 1),
      100);
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 2),
      100);
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::AddToQueueTask, this, 3),
      100);

  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::QuitEventLoop, this),
      100);

  // Should not be processsed after quit from event loop.
  main_thread_context_->PostDelayedTask(
      std::bind(&DpslThreadContextImplMainThreadTest::GenerateFailure, this),
      200);

  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());
  main_thread_context_->RunEventLoop();
  EXPECT_FALSE(main_thread_context_->IsEventLoopRunning());

  EXPECT_THAT(task_id_queue_, testing::ElementsAreArray({1, 2, 3}));
}

using DpslThreadContextImplDeathTest = DpslThreadContextImplMainThreadTest;

TEST_F(DpslThreadContextImplDeathTest, PostDelayedTaskInvalidDelay) {
  ASSERT_DEATH(
      main_thread_context_->PostDelayedTask(
          std::bind(&DpslThreadContextImplMainThreadTest::QuitEventLoop, this),
          -5),
      "Delay must be non-negative");
}

class DpslThreadContextImplMultiThreadTest
    : public DpslThreadContextImplMainThreadTest {
 public:
  DpslThreadContextImplMultiThreadTest() {
    // The default style "fast" does not support multi-threaded tests.
    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  }
  DpslThreadContextImplMultiThreadTest(
      const DpslThreadContextImplMultiThreadTest&) = delete;
  DpslThreadContextImplMultiThreadTest& operator=(
      const DpslThreadContextImplMultiThreadTest&) = delete;

  ~DpslThreadContextImplMultiThreadTest() override = default;

  void SetUp() override {
    DpslThreadContextImplMainThreadTest::SetUp();

    background_thread_ = std::make_unique<TestDpslBackgroundThread>(
        "background" /* name */, global_context_.get(),
        main_thread_context_.get());
  }

  DpslThreadContext* background_thread_context() const {
    DCHECK(background_thread_);
    DpslThreadContext* thread_context = background_thread_->thread_context();
    DCHECK(thread_context);
    return thread_context;
  }

  std::function<void()> CreateAddToQueueTaskForBackground(
      int task_id, const base::Closure& main_thread_callback) {
    base::Closure main_thread_add_to_queue_task = base::Bind(
        [](const base::Closure& task,
           const base::Closure& main_thread_callback) {
          task.Run();
          main_thread_callback.Run();
        },
        base::Bind(&DpslThreadContextImplMultiThreadTest::AddToQueueTask,
                   base::Unretained(this), task_id),
        main_thread_callback);

    return background_thread_->WrapTaskToReplyOnMainThread(
        base::Closure(), main_thread_context_.get(),
        main_thread_add_to_queue_task);
  }

 protected:
  std::unique_ptr<TestDpslBackgroundThread> background_thread_;
};

TEST_F(DpslThreadContextImplMultiThreadTest, PostTask) {
  base::Closure quit_closure =
      base::BarrierClosure(3, base::Bind(
                                  [](DpslThreadContext* main_thread_context) {
                                    main_thread_context->QuitEventLoop();
                                  },
                                  main_thread_context_.get()));

  background_thread_context()->PostTask(
      CreateAddToQueueTaskForBackground(1, quit_closure));
  background_thread_context()->PostTask(
      CreateAddToQueueTaskForBackground(2, quit_closure));
  background_thread_context()->PostTask(
      CreateAddToQueueTaskForBackground(3, quit_closure));

  background_thread_->StartEventLoop();
  main_thread_context_->RunEventLoop();

  EXPECT_THAT(task_id_queue_, testing::ElementsAreArray({1, 2, 3}));
}

TEST_F(DpslThreadContextImplMultiThreadTest, PostDelayedTask) {
  base::Closure quit_closure =
      base::BarrierClosure(3, base::Bind(
                                  [](DpslThreadContext* main_thread_context) {
                                    main_thread_context->QuitEventLoop();
                                  },
                                  main_thread_context_.get()));

  background_thread_context()->PostDelayedTask(
      CreateAddToQueueTaskForBackground(3, quit_closure), 200);
  background_thread_context()->PostDelayedTask(
      CreateAddToQueueTaskForBackground(2, quit_closure), 100);
  background_thread_context()->PostDelayedTask(
      CreateAddToQueueTaskForBackground(1, quit_closure), 0);

  background_thread_->StartEventLoop();
  main_thread_context_->RunEventLoop();

  EXPECT_THAT(task_id_queue_, testing::ElementsAreArray({1, 2, 3}));
}

TEST_F(DpslThreadContextImplMultiThreadTest, BelongsToCurrentThread) {
  EXPECT_FALSE(background_thread_context()->BelongsToCurrentThread());
}

using DpslThreadContextImplMultiThreadDeathTest =
    DpslThreadContextImplMultiThreadTest;

TEST_F(DpslThreadContextImplMultiThreadDeathTest, RunEventLoopCrash) {
  ASSERT_DEATH(background_thread_context()->RunEventLoop(),
               "Called from wrong thread");
}

TEST_F(DpslThreadContextImplMultiThreadDeathTest, IsEventLoopRunningCrash) {
  ASSERT_DEATH(background_thread_context()->IsEventLoopRunning(),
               "Called from wrong thread");
}

TEST_F(DpslThreadContextImplMultiThreadDeathTest, QuitEventLoopCrash) {
  ASSERT_DEATH(background_thread_context()->QuitEventLoop(),
               "Called from wrong thread");
}

TEST_F(DpslThreadContextImplMultiThreadDeathTest, DestructorCrash) {
  ASSERT_DEATH(delete background_thread_context(), "Called from wrong thread");
}

}  // namespace diagnostics
