/*
 *  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/operations_chain.h"

#include <atomic>
#include <cstddef>
#include <functional>
#include <memory>
#include <utility>
#include <vector>

#include "api/scoped_refptr.h"
#include "api/test/rtc_error_matchers.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/event.h"
#include "rtc_base/thread.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/wait_until.h"

namespace rtc {

using ::testing::ElementsAre;

namespace {

constexpr webrtc::TimeDelta kDefaultTimeout = webrtc::TimeDelta::Millis(3000);

}  // namespace

class OperationTracker {
 public:
  OperationTracker() : background_thread_(webrtc::Thread::Create()) {
    background_thread_->Start();
  }
  // The caller is responsible for ensuring that no operations are pending.
  ~OperationTracker() {}

  // Creates a binding for the synchronous operation (see
  // StartSynchronousOperation() below).
  std::function<void(std::function<void()>)> BindSynchronousOperation(
      webrtc::Event* operation_complete_event) {
    return [this, operation_complete_event](std::function<void()> callback) {
      StartSynchronousOperation(operation_complete_event, std::move(callback));
    };
  }

  // Creates a binding for the asynchronous operation (see
  // StartAsynchronousOperation() below).
  std::function<void(std::function<void()>)> BindAsynchronousOperation(
      webrtc::Event* unblock_operation_event,
      webrtc::Event* operation_complete_event) {
    return [this, unblock_operation_event,
            operation_complete_event](std::function<void()> callback) {
      StartAsynchronousOperation(unblock_operation_event,
                                 operation_complete_event, std::move(callback));
    };
  }

  // When an operation is completed, its associated Event* is added to this
  // list, in chronological order. This allows you to verify the order that
  // operations are executed.
  const std::vector<webrtc::Event*>& completed_operation_events() const {
    return completed_operation_events_;
  }

 private:
  // This operation is completed synchronously; the callback is invoked before
  // the function returns.
  void StartSynchronousOperation(webrtc::Event* operation_complete_event,
                                 std::function<void()> callback) {
    completed_operation_events_.push_back(operation_complete_event);
    operation_complete_event->Set();
    callback();
  }

  // This operation is completed asynchronously; it pings `background_thread_`,
  // blocking that thread until `unblock_operation_event` is signaled and then
  // completes upon posting back to the thread that the operation started on.
  // Note that this requires the starting thread to be executing tasks (handle
  // messages), i.e. must not be blocked.
  void StartAsynchronousOperation(webrtc::Event* unblock_operation_event,
                                  webrtc::Event* operation_complete_event,
                                  std::function<void()> callback) {
    webrtc::Thread* current_thread = webrtc::Thread::Current();
    background_thread_->PostTask([this, current_thread, unblock_operation_event,
                                  operation_complete_event, callback]() {
      unblock_operation_event->Wait(webrtc::Event::kForever);
      current_thread->PostTask([this, operation_complete_event, callback]() {
        completed_operation_events_.push_back(operation_complete_event);
        operation_complete_event->Set();
        callback();
      });
    });
  }

  std::unique_ptr<webrtc::Thread> background_thread_;
  std::vector<webrtc::Event*> completed_operation_events_;
};

// The OperationTrackerProxy ensures all operations are chained on a separate
// thread. This allows tests to block while chained operations are posting
// between threads.
class OperationTrackerProxy {
 public:
  OperationTrackerProxy()
      : operations_chain_thread_(webrtc::Thread::Create()),
        operation_tracker_(nullptr),
        operations_chain_(nullptr) {
    operations_chain_thread_->Start();
  }

  std::unique_ptr<webrtc::Event> Initialize() {
    std::unique_ptr<webrtc::Event> event = std::make_unique<webrtc::Event>();
    operations_chain_thread_->PostTask([this, event_ptr = event.get()]() {
      operation_tracker_ = std::make_unique<OperationTracker>();
      operations_chain_ = OperationsChain::Create();
      event_ptr->Set();
    });
    return event;
  }

  void SetOnChainEmptyCallback(std::function<void()> on_chain_empty_callback) {
    webrtc::Event event;
    operations_chain_thread_->PostTask(
        [this, &event,
         on_chain_empty_callback = std::move(on_chain_empty_callback)]() {
          operations_chain_->SetOnChainEmptyCallback(
              std::move(on_chain_empty_callback));
          event.Set();
        });
    event.Wait(webrtc::Event::kForever);
  }

  bool IsEmpty() {
    webrtc::Event event;
    bool is_empty = false;
    operations_chain_thread_->PostTask([this, &event, &is_empty]() {
      is_empty = operations_chain_->IsEmpty();
      event.Set();
    });
    event.Wait(webrtc::Event::kForever);
    return is_empty;
  }

  std::unique_ptr<webrtc::Event> ReleaseOperationChain() {
    std::unique_ptr<webrtc::Event> event = std::make_unique<webrtc::Event>();
    operations_chain_thread_->PostTask([this, event_ptr = event.get()]() {
      operations_chain_ = nullptr;
      event_ptr->Set();
    });
    return event;
  }

  // Chains a synchronous operation on the operation chain's thread.
  std::unique_ptr<webrtc::Event> PostSynchronousOperation() {
    std::unique_ptr<webrtc::Event> operation_complete_event =
        std::make_unique<webrtc::Event>();
    operations_chain_thread_->PostTask(
        [this,
         operation_complete_event_ptr = operation_complete_event.get()]() {
          operations_chain_->ChainOperation(
              operation_tracker_->BindSynchronousOperation(
                  operation_complete_event_ptr));
        });
    return operation_complete_event;
  }

  // Chains an asynchronous operation on the operation chain's thread. This
  // involves the operation chain thread and an additional background thread.
  std::unique_ptr<webrtc::Event> PostAsynchronousOperation(
      webrtc::Event* unblock_operation_event) {
    std::unique_ptr<webrtc::Event> operation_complete_event =
        std::make_unique<webrtc::Event>();
    operations_chain_thread_->PostTask(
        [this, unblock_operation_event,
         operation_complete_event_ptr = operation_complete_event.get()]() {
          operations_chain_->ChainOperation(
              operation_tracker_->BindAsynchronousOperation(
                  unblock_operation_event, operation_complete_event_ptr));
        });
    return operation_complete_event;
  }

  // The order of completed events. Touches the `operation_tracker_` on the
  // calling thread, this is only thread safe if all chained operations have
  // completed.
  const std::vector<webrtc::Event*>& completed_operation_events() const {
    return operation_tracker_->completed_operation_events();
  }

 private:
  std::unique_ptr<webrtc::Thread> operations_chain_thread_;
  std::unique_ptr<OperationTracker> operation_tracker_;
  scoped_refptr<OperationsChain> operations_chain_;
};

// On destruction, sets a boolean flag to true.
class SignalOnDestruction final {
 public:
  SignalOnDestruction(bool* destructor_called)
      : destructor_called_(destructor_called) {
    RTC_DCHECK(destructor_called_);
  }
  ~SignalOnDestruction() {
    // Moved objects will have `destructor_called_` set to null. Destroying a
    // moved SignalOnDestruction should not signal.
    if (destructor_called_) {
      *destructor_called_ = true;
    }
  }

  SignalOnDestruction(const SignalOnDestruction&) = delete;
  SignalOnDestruction& operator=(const SignalOnDestruction&) = delete;

  // Move operators.
  SignalOnDestruction(SignalOnDestruction&& other)
      : SignalOnDestruction(other.destructor_called_) {
    other.destructor_called_ = nullptr;
  }
  SignalOnDestruction& operator=(SignalOnDestruction&& other) {
    destructor_called_ = other.destructor_called_;
    other.destructor_called_ = nullptr;
    return *this;
  }

 private:
  bool* destructor_called_;
};

TEST(OperationsChainTest, SynchronousOperation) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  operation_tracker_proxy.PostSynchronousOperation()->Wait(
      webrtc::Event::kForever);
}

TEST(OperationsChainTest, AsynchronousOperation) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  webrtc::Event unblock_async_operation_event;
  auto async_operation_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event);
  // This should not be signaled until we unblock the operation.
  EXPECT_FALSE(
      async_operation_completed_event->Wait(webrtc::TimeDelta::Zero()));
  // Unblock the operation and wait for it to complete.
  unblock_async_operation_event.Set();
  async_operation_completed_event->Wait(webrtc::Event::kForever);
}

TEST(OperationsChainTest,
     SynchronousOperationsAreExecutedImmediatelyWhenChainIsEmpty) {
  // Testing synchonicity must be done without the OperationTrackerProxy to
  // ensure messages are not processed in parallel. This test has no background
  // threads.
  scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();
  OperationTracker operation_tracker;
  webrtc::Event event0;
  operations_chain->ChainOperation(
      operation_tracker.BindSynchronousOperation(&event0));
  // This should already be signaled. (If it wasn't, waiting wouldn't help,
  // because we'd be blocking the only thread that exists.)
  EXPECT_TRUE(event0.Wait(webrtc::TimeDelta::Zero()));
  // Chaining another operation should also execute immediately because the
  // chain should already be empty.
  webrtc::Event event1;
  operations_chain->ChainOperation(
      operation_tracker.BindSynchronousOperation(&event1));
  EXPECT_TRUE(event1.Wait(webrtc::TimeDelta::Zero()));
}

TEST(OperationsChainTest, AsynchronousOperationBlocksSynchronousOperation) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  webrtc::Event unblock_async_operation_event;
  auto async_operation_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event);

  auto sync_operation_completed_event =
      operation_tracker_proxy.PostSynchronousOperation();

  unblock_async_operation_event.Set();

  sync_operation_completed_event->Wait(webrtc::Event::kForever);
  // The asynchronous avent should have blocked the synchronous event, meaning
  // this should already be signaled.
  EXPECT_TRUE(async_operation_completed_event->Wait(webrtc::TimeDelta::Zero()));
}

TEST(OperationsChainTest, OperationsAreExecutedInOrder) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  // Chain a mix of asynchronous and synchronous operations.
  webrtc::Event operation0_unblock_event;
  auto operation0_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &operation0_unblock_event);

  webrtc::Event operation1_unblock_event;
  auto operation1_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &operation1_unblock_event);

  auto operation2_completed_event =
      operation_tracker_proxy.PostSynchronousOperation();

  auto operation3_completed_event =
      operation_tracker_proxy.PostSynchronousOperation();

  webrtc::Event operation4_unblock_event;
  auto operation4_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &operation4_unblock_event);

  auto operation5_completed_event =
      operation_tracker_proxy.PostSynchronousOperation();

  webrtc::Event operation6_unblock_event;
  auto operation6_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &operation6_unblock_event);

  // Unblock events in reverse order. Operations 5, 3 and 2 are synchronous and
  // don't need to be unblocked.
  operation6_unblock_event.Set();
  operation4_unblock_event.Set();
  operation1_unblock_event.Set();
  operation0_unblock_event.Set();
  // Await all operations. The await-order shouldn't matter since they all get
  // executed eventually.
  operation0_completed_event->Wait(webrtc::Event::kForever);
  operation1_completed_event->Wait(webrtc::Event::kForever);
  operation2_completed_event->Wait(webrtc::Event::kForever);
  operation3_completed_event->Wait(webrtc::Event::kForever);
  operation4_completed_event->Wait(webrtc::Event::kForever);
  operation5_completed_event->Wait(webrtc::Event::kForever);
  operation6_completed_event->Wait(webrtc::Event::kForever);

  EXPECT_THAT(
      operation_tracker_proxy.completed_operation_events(),
      ElementsAre(
          operation0_completed_event.get(), operation1_completed_event.get(),
          operation2_completed_event.get(), operation3_completed_event.get(),
          operation4_completed_event.get(), operation5_completed_event.get(),
          operation6_completed_event.get()));
}

TEST(OperationsChainTest, IsEmpty) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  // The chain is initially empty.
  EXPECT_TRUE(operation_tracker_proxy.IsEmpty());
  // Chain a single event.
  webrtc::Event unblock_async_operation_event0;
  auto async_operation_completed_event0 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event0);
  // The chain is not empty while an event is pending.
  EXPECT_FALSE(operation_tracker_proxy.IsEmpty());
  // Completing the operation empties the chain.
  unblock_async_operation_event0.Set();
  async_operation_completed_event0->Wait(webrtc::Event::kForever);
  EXPECT_TRUE(operation_tracker_proxy.IsEmpty());

  // Chain multiple events.
  webrtc::Event unblock_async_operation_event1;
  auto async_operation_completed_event1 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event1);
  webrtc::Event unblock_async_operation_event2;
  auto async_operation_completed_event2 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event2);
  // Again, the chain is not empty while an event is pending.
  EXPECT_FALSE(operation_tracker_proxy.IsEmpty());
  // Upon completing the first event, the chain is still not empty.
  unblock_async_operation_event1.Set();
  async_operation_completed_event1->Wait(webrtc::Event::kForever);
  EXPECT_FALSE(operation_tracker_proxy.IsEmpty());
  // Completing the last event empties the chain.
  unblock_async_operation_event2.Set();
  async_operation_completed_event2->Wait(webrtc::Event::kForever);
  EXPECT_TRUE(operation_tracker_proxy.IsEmpty());
}

TEST(OperationsChainTest, OnChainEmptyCallback) {
  webrtc::AutoThread main_thread;
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  std::atomic<size_t> on_empty_callback_counter(0u);
  operation_tracker_proxy.SetOnChainEmptyCallback(
      [&on_empty_callback_counter] { ++on_empty_callback_counter; });

  // Chain a single event.
  webrtc::Event unblock_async_operation_event0;
  auto async_operation_completed_event0 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event0);
  // The callback is not invoked until the operation has completed.
  EXPECT_EQ(0u, on_empty_callback_counter);
  // Completing the operation empties the chain, invoking the callback.
  unblock_async_operation_event0.Set();
  async_operation_completed_event0->Wait(webrtc::Event::kForever);
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return on_empty_callback_counter == 1u; },
                        ::testing::IsTrue(), {.timeout = kDefaultTimeout}),
      webrtc::IsRtcOk());

  // Chain multiple events.
  webrtc::Event unblock_async_operation_event1;
  auto async_operation_completed_event1 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event1);
  webrtc::Event unblock_async_operation_event2;
  auto async_operation_completed_event2 =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event2);
  // Again, the callback is not invoked until the operation has completed.
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return on_empty_callback_counter == 1u; },
                        ::testing::IsTrue(), {.timeout = kDefaultTimeout}),
      webrtc::IsRtcOk());
  // Upon completing the first event, the chain is still not empty, so the
  // callback must not be invoked yet.
  unblock_async_operation_event1.Set();
  async_operation_completed_event1->Wait(webrtc::Event::kForever);
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return on_empty_callback_counter == 1u; },
                        ::testing::IsTrue(), {.timeout = kDefaultTimeout}),
      webrtc::IsRtcOk());
  // Completing the last event empties the chain, invoking the callback.
  unblock_async_operation_event2.Set();
  async_operation_completed_event2->Wait(webrtc::Event::kForever);
  EXPECT_THAT(
      webrtc::WaitUntil([&] { return on_empty_callback_counter == 2u; },
                        ::testing::IsTrue(), {.timeout = kDefaultTimeout}),
      webrtc::IsRtcOk());
}

TEST(OperationsChainTest,
     SafeToReleaseReferenceToOperationChainWhileOperationIsPending) {
  OperationTrackerProxy operation_tracker_proxy;
  operation_tracker_proxy.Initialize()->Wait(webrtc::Event::kForever);

  webrtc::Event unblock_async_operation_event;
  auto async_operation_completed_event =
      operation_tracker_proxy.PostAsynchronousOperation(
          &unblock_async_operation_event);

  // Pending operations keep the OperationChain alive, making it safe for the
  // test to release any references before unblocking the async operation.
  operation_tracker_proxy.ReleaseOperationChain()->Wait(
      webrtc::Event::kForever);

  unblock_async_operation_event.Set();
  async_operation_completed_event->Wait(webrtc::Event::kForever);
}

TEST(OperationsChainTest, FunctorIsNotDestroyedWhileExecuting) {
  scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();

  bool destructor_called = false;
  SignalOnDestruction signal_on_destruction(&destructor_called);

  operations_chain->ChainOperation(
      [signal_on_destruction = std::move(signal_on_destruction),
       &destructor_called](std::function<void()> callback) {
        EXPECT_FALSE(destructor_called);
        // Invoking the callback marks the operation as complete, popping the
        // Operation object from the OperationsChain internal queue.
        callback();
        // Even though the internal Operation object has been destroyed,
        // variables captured by this lambda expression must still be valid (the
        // associated functor must not be deleted while executing).
        EXPECT_FALSE(destructor_called);
      });
  // The lambda having executed synchronously and completed, its captured
  // variables should now have been deleted.
  EXPECT_TRUE(destructor_called);
}

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)

TEST(OperationsChainDeathTest, OperationNotInvokingCallbackShouldCrash) {
  scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();
  EXPECT_DEATH(
      operations_chain->ChainOperation([](std::function<void()> callback) {}),
      "");
}

TEST(OperationsChainDeathTest,
     OperationInvokingCallbackMultipleTimesShouldCrash) {
  scoped_refptr<OperationsChain> operations_chain = OperationsChain::Create();
  EXPECT_DEATH(
      operations_chain->ChainOperation([](std::function<void()> callback) {
        // Signal that the operation has completed multiple times.
        callback();
        callback();
      }),
      "");
}

#endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)

}  // namespace rtc
