/*
 *  Copyright 2019 The WebRTC 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 in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/task_utils/pending_task_safety_flag.h"

#include <memory>

#include "rtc_base/event.h"
#include "rtc_base/logging.h"
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/task_utils/to_queued_task.h"
#include "test/gmock.h"
#include "test/gtest.h"

namespace webrtc {
namespace {
using ::testing::AtLeast;
using ::testing::Invoke;
using ::testing::MockFunction;
using ::testing::NiceMock;
using ::testing::Return;
}  // namespace

TEST(PendingTaskSafetyFlagTest, Basic) {
  rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag;
  {
    // Scope for the |owner| instance.
    class Owner {
     public:
      Owner() = default;
      ~Owner() { flag_->SetNotAlive(); }

      rtc::scoped_refptr<PendingTaskSafetyFlag> flag_ =
          PendingTaskSafetyFlag::Create();
    } owner;
    EXPECT_TRUE(owner.flag_->alive());
    safety_flag = owner.flag_;
    EXPECT_TRUE(safety_flag->alive());
  }
  // |owner| now out of scope.
  EXPECT_FALSE(safety_flag->alive());
}

TEST(PendingTaskSafetyFlagTest, BasicScoped) {
  rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag;
  {
    struct Owner {
      ScopedTaskSafety safety;
    } owner;
    safety_flag = owner.safety.flag();
    EXPECT_TRUE(safety_flag->alive());
  }
  // |owner| now out of scope.
  EXPECT_FALSE(safety_flag->alive());
}

TEST(PendingTaskSafetyFlagTest, PendingTaskSuccess) {
  TaskQueueForTest tq1("OwnerHere");
  TaskQueueForTest tq2("OwnerNotHere");

  class Owner {
   public:
    Owner() : tq_main_(TaskQueueBase::Current()) { RTC_DCHECK(tq_main_); }
    ~Owner() {
      RTC_DCHECK(tq_main_->IsCurrent());
      flag_->SetNotAlive();
    }

    void DoStuff() {
      RTC_DCHECK(!tq_main_->IsCurrent());
      tq_main_->PostTask(ToQueuedTask([safe = flag_, this]() {
        if (!safe->alive())
          return;
        stuff_done_ = true;
      }));
    }

    bool stuff_done() const { return stuff_done_; }

   private:
    TaskQueueBase* const tq_main_;
    bool stuff_done_ = false;
    rtc::scoped_refptr<PendingTaskSafetyFlag> flag_{
        PendingTaskSafetyFlag::Create()};
  };

  std::unique_ptr<Owner> owner;
  tq1.SendTask(
      [&owner]() {
        owner.reset(new Owner());
        EXPECT_FALSE(owner->stuff_done());
      },
      RTC_FROM_HERE);
  ASSERT_TRUE(owner);
  tq2.SendTask([&owner]() { owner->DoStuff(); }, RTC_FROM_HERE);
  tq1.SendTask(
      [&owner]() {
        EXPECT_TRUE(owner->stuff_done());
        owner.reset();
      },
      RTC_FROM_HERE);
  ASSERT_FALSE(owner);
}

TEST(PendingTaskSafetyFlagTest, PendingTaskDropped) {
  TaskQueueForTest tq1("OwnerHere");
  TaskQueueForTest tq2("OwnerNotHere");

  class Owner {
   public:
    explicit Owner(bool* stuff_done)
        : tq_main_(TaskQueueBase::Current()), stuff_done_(stuff_done) {
      RTC_DCHECK(tq_main_);
      *stuff_done_ = false;
    }
    ~Owner() {
      RTC_DCHECK(tq_main_->IsCurrent());
    }

    void DoStuff() {
      RTC_DCHECK(!tq_main_->IsCurrent());
      tq_main_->PostTask(
          ToQueuedTask(safety_, [this]() { *stuff_done_ = true; }));
    }

   private:
    TaskQueueBase* const tq_main_;
    bool* const stuff_done_;
    ScopedTaskSafety safety_;
  };

  std::unique_ptr<Owner> owner;
  bool stuff_done = false;
  tq1.SendTask([&owner, &stuff_done]() { owner.reset(new Owner(&stuff_done)); },
               RTC_FROM_HERE);
  ASSERT_TRUE(owner);
  // Queue up a task on tq1 that will execute before the 'DoStuff' task
  // can, and delete the |owner| before the 'stuff' task can execute.
  rtc::Event blocker;
  tq1.PostTask([&blocker, &owner]() {
    blocker.Wait(rtc::Event::kForever);
    owner.reset();
  });

  // Queue up a DoStuff...
  tq2.SendTask([&owner]() { owner->DoStuff(); }, RTC_FROM_HERE);

  ASSERT_TRUE(owner);
  blocker.Set();

  // Run an empty task on tq1 to flush all the queued tasks.
  tq1.WaitForPreviouslyPostedTasks();
  ASSERT_FALSE(owner);
  EXPECT_FALSE(stuff_done);
}

TEST(PendingTaskSafetyFlagTest, PendingTaskNotAliveInitialized) {
  TaskQueueForTest tq("PendingTaskNotAliveInitialized");

  // Create a new flag that initially not `alive`.
  auto flag = PendingTaskSafetyFlag::CreateDetachedInactive();
  tq.SendTask([&flag]() { EXPECT_FALSE(flag->alive()); }, RTC_FROM_HERE);

  bool task_1_ran = false;
  bool task_2_ran = false;
  tq.PostTask(ToQueuedTask(flag, [&task_1_ran]() { task_1_ran = true; }));
  tq.PostTask([&flag]() { flag->SetAlive(); });
  tq.PostTask(ToQueuedTask(flag, [&task_2_ran]() { task_2_ran = true; }));

  tq.WaitForPreviouslyPostedTasks();
  EXPECT_FALSE(task_1_ran);
  EXPECT_TRUE(task_2_ran);
}

}  // namespace webrtc
