// 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() override {
    DpslThreadContextImpl::CleanThreadCounterForTesting();
    DpslGlobalContextImpl::CleanGlobalCounterForTesting();
  }

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

 protected:
  std::unique_ptr<DpslGlobalContext> global_context_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DpslThreadContextImplBaseTest);
};

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;

  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_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DpslThreadContextImplMainThreadTest);
};

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() 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_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DpslThreadContextImplMultiThreadTest);
};

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
