// Copyright (c) 2015 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 "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h"

#include "gfe/gfe2/test_tools/fake_epoll_server.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/quic/platform/impl/quic_epoll_clock.h"

namespace quic {
namespace test {
namespace {

class TestDelegate : public QuicAlarm::Delegate {
 public:
  TestDelegate() : fired_(false) {}

  void OnAlarm() override { fired_ = true; }

  bool fired() const { return fired_; }

 private:
  bool fired_;
};

// The boolean parameter denotes whether or not to use an arena.
class QuicEpollAlarmFactoryTest : public QuicTestWithParam<bool> {
 protected:
  QuicEpollAlarmFactoryTest()
      : clock_(&epoll_server_), alarm_factory_(&epoll_server_) {}

  QuicConnectionArena* GetArenaParam() {
    return GetParam() ? &arena_ : nullptr;
  }

  const QuicEpollClock clock_;
  QuicEpollAlarmFactory alarm_factory_;
  gfe2::test::FakeEpollServer epoll_server_;
  QuicConnectionArena arena_;
};

INSTANTIATE_TEST_CASE_P(UseArena,
                        QuicEpollAlarmFactoryTest,
                        ::testing::ValuesIn({true, false}));

TEST_P(QuicEpollAlarmFactoryTest, CreateAlarm) {
  QuicArenaScopedPtr<TestDelegate> delegate =
      QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
  QuicArenaScopedPtr<QuicAlarm> alarm(
      alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam()));

  QuicTime start = clock_.Now();
  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
  alarm->Set(start + delta);

  epoll_server_.AdvanceByAndWaitForEventsAndExecuteCallbacks(
      delta.ToMicroseconds());
  EXPECT_EQ(start + delta, clock_.Now());
}

TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndCancel) {
  QuicArenaScopedPtr<TestDelegate> delegate =
      QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
  TestDelegate* unowned_delegate = delegate.get();
  QuicArenaScopedPtr<QuicAlarm> alarm(
      alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam()));

  QuicTime start = clock_.Now();
  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
  alarm->Set(start + delta);
  alarm->Cancel();

  epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
  EXPECT_EQ(start + delta, clock_.Now());
  EXPECT_FALSE(unowned_delegate->fired());
}

TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndReset) {
  QuicArenaScopedPtr<TestDelegate> delegate =
      QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
  TestDelegate* unowned_delegate = delegate.get();
  QuicArenaScopedPtr<QuicAlarm> alarm(
      alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam()));

  QuicTime start = clock_.Now();
  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
  alarm->Set(clock_.Now() + delta);
  alarm->Cancel();
  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
  alarm->Set(clock_.Now() + new_delta);

  epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
  EXPECT_EQ(start + delta, clock_.Now());
  EXPECT_FALSE(unowned_delegate->fired());

  epoll_server_.AdvanceByExactlyAndCallCallbacks(
      (new_delta - delta).ToMicroseconds());
  EXPECT_EQ(start + new_delta, clock_.Now());
  EXPECT_TRUE(unowned_delegate->fired());
}

TEST_P(QuicEpollAlarmFactoryTest, CreateAlarmAndUpdate) {
  QuicArenaScopedPtr<TestDelegate> delegate =
      QuicArenaScopedPtr<TestDelegate>(new TestDelegate());
  TestDelegate* unowned_delegate = delegate.get();
  QuicArenaScopedPtr<QuicAlarm> alarm(
      alarm_factory_.CreateAlarm(std::move(delegate), GetArenaParam()));

  QuicTime start = clock_.Now();
  QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
  alarm->Set(clock_.Now() + delta);
  QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
  alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1));

  epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
  EXPECT_EQ(start + delta, clock_.Now());
  EXPECT_FALSE(unowned_delegate->fired());

  // Move the alarm forward 1us and ensure it doesn't move forward.
  alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(2));

  epoll_server_.AdvanceByExactlyAndCallCallbacks(
      (new_delta - delta).ToMicroseconds());
  EXPECT_EQ(start + new_delta, clock_.Now());
  EXPECT_TRUE(unowned_delegate->fired());

  // Set the alarm via an update call.
  new_delta = QuicTime::Delta::FromMicroseconds(5);
  alarm->Update(clock_.Now() + new_delta, QuicTime::Delta::FromMicroseconds(1));
  EXPECT_TRUE(alarm->IsSet());

  // Update it with an uninitialized time and ensure it's cancelled.
  alarm->Update(QuicTime::Zero(), QuicTime::Delta::FromMicroseconds(1));
  EXPECT_FALSE(alarm->IsSet());
}

}  // namespace
}  // namespace test
}  // namespace quic
