/*
 *  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 "test/time_controller/simulated_time_controller.h"

#include <atomic>
#include <memory>

#include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "rtc_base/event.h"
#include "rtc_base/task_queue_for_test.h"
#include "rtc_base/task_utils/repeating_task.h"
#include "test/gmock.h"
#include "test/gtest.h"

// NOTE: Since these tests rely on real time behavior, they will be flaky
// if run on heavily loaded systems.
namespace webrtc {
namespace {
using ::testing::AtLeast;
using ::testing::Invoke;
using ::testing::MockFunction;
using ::testing::NiceMock;
using ::testing::Return;
constexpr Timestamp kStartTime = Timestamp::Seconds(1000);
}  // namespace

TEST(SimulatedTimeControllerTest, TaskIsStoppedOnStop) {
  const TimeDelta kShortInterval = TimeDelta::Millis(5);
  const TimeDelta kLongInterval = TimeDelta::Millis(20);
  const int kShortIntervalCount = 4;
  const int kMargin = 1;
  GlobalSimulatedTimeController time_simulation(kStartTime);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
      time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
          "TestQueue", TaskQueueFactory::Priority::NORMAL);
  std::atomic_int counter(0);
  auto handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
    if (++counter >= kShortIntervalCount)
      return kLongInterval;
    return kShortInterval;
  });
  // Sleep long enough to go through the initial phase.
  time_simulation.AdvanceTime(kShortInterval * (kShortIntervalCount + kMargin));
  EXPECT_EQ(counter.load(), kShortIntervalCount);

  task_queue->PostTask(
      [handle = std::move(handle)]() mutable { handle.Stop(); });

  // Sleep long enough that the task would run at least once more if not
  // stopped.
  time_simulation.AdvanceTime(kLongInterval * 2);
  EXPECT_EQ(counter.load(), kShortIntervalCount);
}

TEST(SimulatedTimeControllerTest, TaskCanStopItself) {
  std::atomic_int counter(0);
  GlobalSimulatedTimeController time_simulation(kStartTime);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
      time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
          "TestQueue", TaskQueueFactory::Priority::NORMAL);

  RepeatingTaskHandle handle;
  task_queue->PostTask([&] {
    handle = RepeatingTaskHandle::Start(task_queue.get(), [&] {
      ++counter;
      handle.Stop();
      return TimeDelta::Millis(2);
    });
  });
  time_simulation.AdvanceTime(TimeDelta::Millis(10));
  EXPECT_EQ(counter.load(), 1);
}

TEST(SimulatedTimeControllerTest, Example) {
  class ObjectOnTaskQueue {
   public:
    void DoPeriodicTask() {}
    TimeDelta TimeUntilNextRun() { return TimeDelta::Millis(100); }
    void StartPeriodicTask(RepeatingTaskHandle* handle,
                           TaskQueueBase* task_queue) {
      *handle = RepeatingTaskHandle::Start(task_queue, [this] {
        DoPeriodicTask();
        return TimeUntilNextRun();
      });
    }
  };
  GlobalSimulatedTimeController time_simulation(kStartTime);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
      time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
          "TestQueue", TaskQueueFactory::Priority::NORMAL);
  auto object = std::make_unique<ObjectOnTaskQueue>();
  // Create and start the periodic task.
  RepeatingTaskHandle handle;
  object->StartPeriodicTask(&handle, task_queue.get());
  // Restart the task
  task_queue->PostTask(
      [handle = std::move(handle)]() mutable { handle.Stop(); });
  object->StartPeriodicTask(&handle, task_queue.get());
  task_queue->PostTask(
      [handle = std::move(handle)]() mutable { handle.Stop(); });

  task_queue->PostTask([object = std::move(object)] {});
}

TEST(SimulatedTimeControllerTest, DelayTaskRunOnTime) {
  GlobalSimulatedTimeController time_simulation(kStartTime);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue =
      time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
          "TestQueue", TaskQueueFactory::Priority::NORMAL);

  bool delay_task_executed = false;
  task_queue->PostDelayedTask([&] { delay_task_executed = true; },
                              TimeDelta::Millis(10));

  time_simulation.AdvanceTime(TimeDelta::Millis(10));
  EXPECT_TRUE(delay_task_executed);
}

TEST(SimulatedTimeControllerTest, ThreadYeildsOnSynchronousCall) {
  GlobalSimulatedTimeController sim(kStartTime);
  auto main_thread = sim.GetMainThread();
  auto t2 = sim.CreateThread("thread", nullptr);
  bool task_has_run = false;
  // Posting a task to the main thread, this should not run until AdvanceTime is
  // called.
  main_thread->PostTask([&] { task_has_run = true; });
  SendTask(t2.get(), [] {
    rtc::Event yield_event;
    // Wait() triggers YieldExecution() which will runs message processing on
    // all threads that are not in the yielded set.

    yield_event.Wait(TimeDelta::Zero());
  });
  // Since we are doing an invoke from the main thread, we don't expect the main
  // thread message loop to be processed.
  EXPECT_FALSE(task_has_run);
  sim.AdvanceTime(TimeDelta::Seconds(1));
  ASSERT_TRUE(task_has_run);
}

TEST(SimulatedTimeControllerTest, SkipsDelayedTaskForward) {
  GlobalSimulatedTimeController sim(kStartTime);
  auto main_thread = sim.GetMainThread();
  constexpr auto duration_during_which_nothing_runs = TimeDelta::Seconds(2);
  constexpr auto shorter_duration = TimeDelta::Seconds(1);
  MockFunction<void()> fun;
  EXPECT_CALL(fun, Call).WillOnce(Invoke([&] {
    ASSERT_EQ(sim.GetClock()->CurrentTime(),
              kStartTime + duration_during_which_nothing_runs);
  }));
  main_thread->PostDelayedTask(fun.AsStdFunction(), shorter_duration);
  sim.SkipForwardBy(duration_during_which_nothing_runs);
  // Run tasks that were pending during the skip.
  sim.AdvanceTime(TimeDelta::Zero());
}

}  // namespace webrtc
