// Copyright (c) 2012 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/message_loop/message_loop_task_runner.h"

#include <memory>

#include "base/atomic_sequence_num.h"
#include "base/bind.h"
#include "base/debug/leak_annotations.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_task_runner.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"

namespace base {

class MessageLoopTaskRunnerTest : public testing::Test {
 public:
  MessageLoopTaskRunnerTest()
      : current_loop_(new MessageLoop()),
        task_thread_("task_thread"),
        thread_sync_(WaitableEvent::ResetPolicy::MANUAL,
                     WaitableEvent::InitialState::NOT_SIGNALED) {}

  void DeleteCurrentMessageLoop() { current_loop_.reset(); }

 protected:
  void SetUp() override {
    // Use SetUp() instead of the constructor to avoid posting a task to a
    // partially constructed object.
    task_thread_.Start();

    // Allow us to pause the |task_thread_|'s MessageLoop.
    task_thread_.task_runner()->PostTask(
        FROM_HERE, BindOnce(&MessageLoopTaskRunnerTest::BlockTaskThreadHelper,
                            Unretained(this)));
  }

  void TearDown() override {
    // Make sure the |task_thread_| is not blocked, and stop the thread
    // fully before destruction because its tasks may still depend on the
    // |thread_sync_| event.
    thread_sync_.Signal();
    task_thread_.Stop();
    DeleteCurrentMessageLoop();
  }

  // Make LoopRecorder threadsafe so that there is defined behavior even if a
  // threading mistake sneaks into the PostTaskAndReplyRelay implementation.
  class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> {
   public:
    LoopRecorder(MessageLoop** run_on,
                 MessageLoop** deleted_on,
                 int* destruct_order)
        : run_on_(run_on),
          deleted_on_(deleted_on),
          destruct_order_(destruct_order) {}

    void RecordRun() { *run_on_ = MessageLoop::current(); }

   private:
    friend class RefCountedThreadSafe<LoopRecorder>;
    ~LoopRecorder() {
      *deleted_on_ = MessageLoop::current();
      *destruct_order_ = g_order.GetNext();
    }

    MessageLoop** run_on_;
    MessageLoop** deleted_on_;
    int* destruct_order_;
  };

  static void RecordLoop(scoped_refptr<LoopRecorder> recorder) {
    recorder->RecordRun();
  }

  static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) {
    recorder->RecordRun();
    RunLoop::QuitCurrentWhenIdleDeprecated();
  }

  void UnblockTaskThread() { thread_sync_.Signal(); }

  void BlockTaskThreadHelper() { thread_sync_.Wait(); }

  static AtomicSequenceNumber g_order;

  std::unique_ptr<MessageLoop> current_loop_;
  Thread task_thread_;

 private:
  base::WaitableEvent thread_sync_;
};

AtomicSequenceNumber MessageLoopTaskRunnerTest::g_order;

TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) {
  MessageLoop* task_run_on = nullptr;
  MessageLoop* task_deleted_on = nullptr;
  int task_delete_order = -1;
  MessageLoop* reply_run_on = nullptr;
  MessageLoop* reply_deleted_on = nullptr;
  int reply_delete_order = -1;

  scoped_refptr<LoopRecorder> task_recorder =
      new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
  scoped_refptr<LoopRecorder> reply_recorder =
      new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);

  ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply(
      FROM_HERE, BindOnce(&RecordLoop, task_recorder),
      BindOnce(&RecordLoopAndQuit, reply_recorder)));

  // Die if base::Bind doesn't retain a reference to the recorders.
  task_recorder = nullptr;
  reply_recorder = nullptr;
  ASSERT_FALSE(task_deleted_on);
  ASSERT_FALSE(reply_deleted_on);

  UnblockTaskThread();
  RunLoop().Run();

  EXPECT_EQ(task_thread_.message_loop(), task_run_on);
  EXPECT_EQ(task_thread_.message_loop(), task_deleted_on);
  EXPECT_EQ(current_loop_.get(), reply_run_on);
  EXPECT_EQ(current_loop_.get(), reply_deleted_on);
  EXPECT_LT(task_delete_order, reply_delete_order);
}

TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) {
  MessageLoop* task_run_on = nullptr;
  MessageLoop* task_deleted_on = nullptr;
  int task_delete_order = -1;
  MessageLoop* reply_run_on = nullptr;
  MessageLoop* reply_deleted_on = nullptr;
  int reply_delete_order = -1;

  scoped_refptr<LoopRecorder> task_recorder =
      new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
  scoped_refptr<LoopRecorder> reply_recorder =
      new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);

  // Grab a task runner to a dead MessageLoop.
  scoped_refptr<SingleThreadTaskRunner> task_runner =
      task_thread_.task_runner();
  UnblockTaskThread();
  task_thread_.Stop();

  ASSERT_FALSE(task_runner->PostTaskAndReply(
      FROM_HERE, BindOnce(&RecordLoop, task_recorder),
      BindOnce(&RecordLoopAndQuit, reply_recorder)));

  // The relay should have properly deleted its resources leaving us as the only
  // reference.
  EXPECT_EQ(task_delete_order, reply_delete_order);
  ASSERT_TRUE(task_recorder->HasOneRef());
  ASSERT_TRUE(reply_recorder->HasOneRef());

  // Nothing should have run though.
  EXPECT_FALSE(task_run_on);
  EXPECT_FALSE(reply_run_on);
}

TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) {
  MessageLoop* task_run_on = nullptr;
  MessageLoop* task_deleted_on = nullptr;
  int task_delete_order = -1;
  MessageLoop* reply_run_on = nullptr;
  MessageLoop* reply_deleted_on = nullptr;
  int reply_delete_order = -1;

  scoped_refptr<LoopRecorder> task_recorder =
      new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
  scoped_refptr<LoopRecorder> reply_recorder =
      new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);

  // Enqueue the relay.
  ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply(
      FROM_HERE, BindOnce(&RecordLoop, task_recorder),
      BindOnce(&RecordLoopAndQuit, reply_recorder)));

  // Die if base::Bind doesn't retain a reference to the recorders.
  task_recorder = nullptr;
  reply_recorder = nullptr;
  ASSERT_FALSE(task_deleted_on);
  ASSERT_FALSE(reply_deleted_on);

  RunLoop().Run();

  EXPECT_EQ(current_loop_.get(), task_run_on);
  EXPECT_EQ(current_loop_.get(), task_deleted_on);
  EXPECT_EQ(current_loop_.get(), reply_run_on);
  EXPECT_EQ(current_loop_.get(), reply_deleted_on);
  EXPECT_LT(task_delete_order, reply_delete_order);
}

TEST_F(MessageLoopTaskRunnerTest,
       PostTaskAndReply_DeadReplyTaskRunnerBehavior) {
  // Annotate the scope as having memory leaks to suppress heapchecker reports.
  ANNOTATE_SCOPED_MEMORY_LEAK;
  MessageLoop* task_run_on = nullptr;
  MessageLoop* task_deleted_on = nullptr;
  int task_delete_order = -1;
  MessageLoop* reply_run_on = nullptr;
  MessageLoop* reply_deleted_on = nullptr;
  int reply_delete_order = -1;

  scoped_refptr<LoopRecorder> task_recorder =
      new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
  scoped_refptr<LoopRecorder> reply_recorder =
      new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);

  // Enqueue the relay.
  task_thread_.task_runner()->PostTaskAndReply(
      FROM_HERE, BindOnce(&RecordLoop, task_recorder),
      BindOnce(&RecordLoopAndQuit, reply_recorder));

  // Die if base::Bind doesn't retain a reference to the recorders.
  task_recorder = nullptr;
  reply_recorder = nullptr;
  ASSERT_FALSE(task_deleted_on);
  ASSERT_FALSE(reply_deleted_on);

  UnblockTaskThread();

  // Mercilessly whack the current loop before |reply| gets to run.
  current_loop_.reset();

  // This should ensure the relay has been run.  We need to record the
  // MessageLoop pointer before stopping the thread because Thread::Stop() will
  // NULL out its own pointer.
  MessageLoop* task_loop = task_thread_.message_loop();
  task_thread_.Stop();

  // Even if the reply task runner is already gone, the original task should
  // already be deleted. However, the reply which hasn't executed yet should
  // leak to avoid thread-safety issues.
  EXPECT_EQ(task_loop, task_run_on);
  EXPECT_EQ(task_loop, task_deleted_on);
  EXPECT_FALSE(reply_run_on);
  ASSERT_FALSE(reply_deleted_on);

  // The PostTaskAndReplyRelay is leaked here.  Even if we had a reference to
  // it, we cannot just delete it because PostTaskAndReplyRelay's destructor
  // checks that MessageLoop::current() is the the same as when the
  // PostTaskAndReplyRelay object was constructed.  However, this loop must have
  // already been deleted in order to perform this test.  See
  // http://crbug.com/86301.
}

class MessageLoopTaskRunnerThreadingTest : public testing::Test {
 public:
  void Release() const {
    AssertOnIOThread();
    Quit();
  }

  void Quit() const {
    loop_.task_runner()->PostTask(
        FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
  }

  void AssertOnIOThread() const {
    ASSERT_TRUE(io_thread_->task_runner()->BelongsToCurrentThread());
    ASSERT_EQ(io_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
  }

  void AssertOnFileThread() const {
    ASSERT_TRUE(file_thread_->task_runner()->BelongsToCurrentThread());
    ASSERT_EQ(file_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
  }

 protected:
  void SetUp() override {
    io_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_IO"));
    file_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_File"));
    io_thread_->Start();
    file_thread_->Start();
  }

  void TearDown() override {
    io_thread_->Stop();
    file_thread_->Stop();
  }

  static void BasicFunction(MessageLoopTaskRunnerThreadingTest* test) {
    test->AssertOnFileThread();
    test->Quit();
  }

  static void AssertNotRun() { FAIL() << "Callback Should not get executed."; }

  class DeletedOnFile {
   public:
    explicit DeletedOnFile(MessageLoopTaskRunnerThreadingTest* test)
        : test_(test) {}

    ~DeletedOnFile() {
      test_->AssertOnFileThread();
      test_->Quit();
    }

   private:
    MessageLoopTaskRunnerThreadingTest* test_;
  };

  std::unique_ptr<Thread> io_thread_;
  std::unique_ptr<Thread> file_thread_;

 private:
  mutable MessageLoop loop_;
};

TEST_F(MessageLoopTaskRunnerThreadingTest, Release) {
  EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this));
  RunLoop().Run();
}

TEST_F(MessageLoopTaskRunnerThreadingTest, Delete) {
  DeletedOnFile* deleted_on_file = new DeletedOnFile(this);
  EXPECT_TRUE(
      file_thread_->task_runner()->DeleteSoon(FROM_HERE, deleted_on_file));
  RunLoop().Run();
}

TEST_F(MessageLoopTaskRunnerThreadingTest, PostTask) {
  EXPECT_TRUE(file_thread_->task_runner()->PostTask(
      FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::BasicFunction,
                          Unretained(this))));
  RunLoop().Run();
}

TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadExits) {
  std::unique_ptr<Thread> test_thread(
      new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
  test_thread->Start();
  scoped_refptr<SingleThreadTaskRunner> task_runner =
      test_thread->task_runner();
  test_thread->Stop();

  bool ret = task_runner->PostTask(
      FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
  EXPECT_FALSE(ret);
}

TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadIsDeleted) {
  scoped_refptr<SingleThreadTaskRunner> task_runner;
  {
    std::unique_ptr<Thread> test_thread(
        new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
    test_thread->Start();
    task_runner = test_thread->task_runner();
  }
  bool ret = task_runner->PostTask(
      FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
  EXPECT_FALSE(ret);
}

}  // namespace base
