// Copyright (c) 2017 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/quartc/test/quartc_data_source.h"

#include <vector>

#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"

namespace quic {
namespace test {
namespace {

class FakeDelegate : public QuartcDataSource::Delegate {
 public:
  void OnDataProduced(const char* data, size_t length) override;

  const std::vector<ParsedQuartcDataFrame>& frames() { return frames_; }

 private:
  std::vector<ParsedQuartcDataFrame> frames_;
};

void FakeDelegate::OnDataProduced(const char* data, size_t length) {
  ParsedQuartcDataFrame frame;
  QuicStringPiece message(data, length);
  if (ParsedQuartcDataFrame::Parse(message, &frame)) {
    frames_.push_back(frame);
  } else {
    LOG(FATAL) << "Data source produced a frame it can't parse: " << message;
  }
}

class QuartcDataSourceTest : public QuicTest {
 protected:
  QuartcDataSourceTest() : simulator_() {}

  simulator::Simulator simulator_;
  FakeDelegate delegate_;

  std::unique_ptr<QuartcDataSource> source_;
};

TEST_F(QuartcDataSourceTest, ProducesFrameEveryInterval) {
  QuartcDataSource::Config config;
  config.frame_interval = QuicTime::Delta::FromMilliseconds(20);
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));
  source_->SetEnabled(true);

  simulator_.RunFor(config.frame_interval);
  EXPECT_EQ(delegate_.frames().size(), 1);

  simulator_.RunFor(config.frame_interval);
  EXPECT_EQ(delegate_.frames().size(), 2);

  simulator_.RunFor(config.frame_interval * 20);
  EXPECT_EQ(delegate_.frames().size(), 22);
}

TEST_F(QuartcDataSourceTest, DoesNotProduceFramesUntilEnabled) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));

  simulator_.RunFor(config.frame_interval * 20);
  EXPECT_EQ(delegate_.frames().size(), 0);

  // The first frame is produced immediately (but asynchronously) upon enabling
  // the source.
  source_->SetEnabled(true);
  simulator_.RunFor(QuicTime::Delta::FromMicroseconds(1));
  EXPECT_EQ(delegate_.frames().size(), 1);
}

TEST_F(QuartcDataSourceTest, DisableAndEnable) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));

  source_->SetEnabled(true);
  simulator_.RunFor(config.frame_interval * 20);
  EXPECT_EQ(delegate_.frames().size(), 20);

  // No new frames while the source is disabled.
  source_->SetEnabled(false);
  simulator_.RunFor(config.frame_interval * 20);
  EXPECT_EQ(delegate_.frames().size(), 20);

  // The first frame is produced immediately (but asynchronously) upon enabling
  // the source.
  source_->SetEnabled(true);
  simulator_.RunFor(QuicTime::Delta::FromMicroseconds(1));
  ASSERT_EQ(delegate_.frames().size(), 21);

  // The first frame after a pause should be no larger than previous frames.
  EXPECT_EQ(delegate_.frames()[0].payload.size(),
            delegate_.frames()[20].payload.size());

  // The first frame after the pause should have a much later timestamp.
  // Note that the previous frame (19) happens at the *start* of the 20th
  // interval.  Frame 20 would normally happen one interval later, but we've
  // delayed it by an extra 20 intervals (for a total of 21 intervals later).
  EXPECT_EQ(delegate_.frames()[20].send_time - delegate_.frames()[19].send_time,
            21 * config.frame_interval);
}

TEST_F(QuartcDataSourceTest, EnablingTwiceDoesNotChangeSchedule) {
  QuartcDataSource::Config config;
  config.frame_interval = QuicTime::Delta::FromMilliseconds(20);

  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));

  // The first frame is produced immediately (but asynchronously) upon enabling
  // the source.
  source_->SetEnabled(true);
  simulator_.RunFor(QuicTime::Delta::FromMicroseconds(1));
  EXPECT_EQ(delegate_.frames().size(), 1);

  // Enabling the source again does not re-schedule the alarm.
  source_->SetEnabled(true);
  simulator_.RunFor(QuicTime::Delta::FromMicroseconds(1));
  EXPECT_EQ(delegate_.frames().size(), 1);

  // The second frame is sent at the expected interval after the first.
  ASSERT_TRUE(
      simulator_.RunUntil([this] { return delegate_.frames().size() == 2; }));

  EXPECT_EQ(delegate_.frames()[1].send_time - delegate_.frames()[0].send_time,
            config.frame_interval);
}

TEST_F(QuartcDataSourceTest, ProducesFramesWithConfiguredSourceId) {
  QuartcDataSource::Config config;
  config.id = 7;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));
  source_->SetEnabled(true);
  simulator_.RunFor(config.frame_interval);

  ASSERT_EQ(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].source_id, config.id);
}

TEST_F(QuartcDataSourceTest, ProducesFramesAtAllocatedBandwidth) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  constexpr QuicByteCount bytes_per_frame = 1000;
  source_->AllocateBandwidth(QuicBandwidth::FromBytesAndTimeDelta(
      bytes_per_frame, config.frame_interval));
  source_->SetEnabled(true);
  simulator_.RunFor(config.frame_interval);

  ASSERT_EQ(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].payload.size(),
            bytes_per_frame - kDataFrameHeaderSize);
  EXPECT_EQ(delegate_.frames()[0].size, bytes_per_frame);
}

TEST_F(QuartcDataSourceTest, ProducesParseableHeaderWhenNotEnoughBandwidth) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  // Allocate less bandwidth than the source requires for its header.
  source_->AllocateBandwidth(QuicBandwidth::FromBytesAndTimeDelta(
      kDataFrameHeaderSize - 10, config.frame_interval));
  source_->SetEnabled(true);

  QuicTime start_time = simulator_.GetClock()->Now();
  simulator_.RunFor(config.frame_interval);

  ASSERT_EQ(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].payload.size(), 0);
  EXPECT_EQ(delegate_.frames()[0].size, kDataFrameHeaderSize);

  // Header fields are still present and parseable.
  EXPECT_EQ(delegate_.frames()[0].source_id, 0);
  EXPECT_EQ(delegate_.frames()[0].sequence_number, 0);
  EXPECT_EQ(delegate_.frames()[0].send_time, start_time);
}

TEST_F(QuartcDataSourceTest, ProducesSequenceNumbers) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));
  source_->SetEnabled(true);

  simulator_.RunFor(config.frame_interval * 20);

  ASSERT_EQ(delegate_.frames().size(), 20);
  for (int i = 0; i < 20; ++i) {
    EXPECT_EQ(delegate_.frames()[i].sequence_number, i);
  }
}

TEST_F(QuartcDataSourceTest, ProducesSendTimes) {
  QuartcDataSource::Config config;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(1000, config.frame_interval));
  source_->SetEnabled(true);

  simulator_.RunFor(config.frame_interval * 20);

  ASSERT_EQ(delegate_.frames().size(), 20);
  QuicTime first_send_time = delegate_.frames()[0].send_time;
  for (int i = 1; i < 20; ++i) {
    EXPECT_EQ(delegate_.frames()[i].send_time,
              first_send_time + i * config.frame_interval);
  }
}

TEST_F(QuartcDataSourceTest, AllocateClampsToMin) {
  QuartcDataSource::Config config;
  config.min_bandwidth = QuicBandwidth::FromBitsPerSecond(8000);
  config.frame_interval = QuicTime::Delta::FromMilliseconds(100);
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  // When allocating less than the minimum, there is nothing left over.
  EXPECT_EQ(source_->AllocateBandwidth(QuicBandwidth::FromBitsPerSecond(6000)),
            QuicBandwidth::Zero());

  source_->SetEnabled(true);
  simulator_.RunFor(config.frame_interval);

  // The frames produced use min_bandwidth instead of the lower allocation.
  QuicByteCount bytes_per_frame =
      config.min_bandwidth.ToBytesPerPeriod(config.frame_interval);
  ASSERT_EQ(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].payload.size(),
            bytes_per_frame - kDataFrameHeaderSize);
  EXPECT_EQ(delegate_.frames()[0].size, bytes_per_frame);
}

TEST_F(QuartcDataSourceTest, AllocateClampsToMax) {
  QuartcDataSource::Config config;
  config.max_bandwidth = QuicBandwidth::FromBitsPerSecond(8000);
  config.frame_interval = QuicTime::Delta::FromMilliseconds(100);
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  // When allocating more than the maximum, the excess is returned.
  EXPECT_EQ(source_->AllocateBandwidth(QuicBandwidth::FromBitsPerSecond(10000)),
            QuicBandwidth::FromBitsPerSecond(2000));

  source_->SetEnabled(true);
  simulator_.RunFor(config.frame_interval);

  // The frames produced use max_bandwidth instead of the higher allocation.
  QuicByteCount bytes_per_frame =
      config.max_bandwidth.ToBytesPerPeriod(config.frame_interval);
  ASSERT_EQ(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].payload.size(),
            bytes_per_frame - kDataFrameHeaderSize);
  EXPECT_EQ(delegate_.frames()[0].size, bytes_per_frame);
}

TEST_F(QuartcDataSourceTest, MaxFrameSize) {
  constexpr QuicByteCount bytes_per_frame = 1000;
  QuartcDataSource::Config config;
  config.max_frame_size = bytes_per_frame;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  // Allocate enough bandwidth for more than one frame per interval.
  source_->AllocateBandwidth(QuicBandwidth::FromBytesAndTimeDelta(
      3 * bytes_per_frame, config.frame_interval));
  source_->SetEnabled(true);

  QuicTime start_time = simulator_.GetClock()->Now();
  simulator_.RunFor(config.frame_interval);

  // Since there's enough bandwidth for three frames per interval, that's what
  // the source should generate.
  EXPECT_EQ(delegate_.frames().size(), 3);
  int i = 0;
  for (const auto& frame : delegate_.frames()) {
    // Each of the frames should start with a header that can be parsed.
    // Each gets the same timestamp, but a different sequence number.
    EXPECT_EQ(frame.source_id, config.id);
    EXPECT_EQ(frame.sequence_number, i++);
    EXPECT_EQ(frame.send_time, start_time);

    // Each of the frames should have the configured maximum size.
    EXPECT_EQ(frame.payload.size(), bytes_per_frame - kDataFrameHeaderSize);
    EXPECT_EQ(frame.size, bytes_per_frame);
  }
}

TEST_F(QuartcDataSourceTest, ProducesParseableHeaderWhenMaxFrameSizeTooSmall) {
  QuartcDataSource::Config config;
  config.max_frame_size = kDataFrameHeaderSize - 1;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(200, config.frame_interval));
  source_->SetEnabled(true);

  QuicTime start_time = simulator_.GetClock()->Now();
  simulator_.RunFor(config.frame_interval);

  ASSERT_GE(delegate_.frames().size(), 1);
  EXPECT_EQ(delegate_.frames()[0].payload.size(), 0);
  EXPECT_EQ(delegate_.frames()[0].size, kDataFrameHeaderSize);

  // Header fields are still present and parseable.
  EXPECT_EQ(delegate_.frames()[0].source_id, 0);
  EXPECT_EQ(delegate_.frames()[0].sequence_number, 0);
  EXPECT_EQ(delegate_.frames()[0].send_time, start_time);
}

TEST_F(QuartcDataSourceTest, ProducesParseableHeaderWhenLeftoverSizeTooSmall) {
  QuartcDataSource::Config config;
  config.max_frame_size = 200;
  source_ = QuicMakeUnique<QuartcDataSource>(
      simulator_.GetClock(), simulator_.GetAlarmFactory(),
      simulator_.GetRandomGenerator(), config, &delegate_);

  // Allocate enough bandwidth to send a 200-byte frame and a 1-byte frame.
  source_->AllocateBandwidth(
      QuicBandwidth::FromBytesAndTimeDelta(201, config.frame_interval));
  source_->SetEnabled(true);

  QuicTime start_time = simulator_.GetClock()->Now();
  simulator_.RunFor(config.frame_interval);

  ASSERT_EQ(delegate_.frames().size(), 2);
  EXPECT_EQ(delegate_.frames()[0].payload.size(), 200 - kDataFrameHeaderSize);
  EXPECT_EQ(delegate_.frames()[0].size, 200);

  // The second frame, using the 1 leftover byte from the first, rounds up to
  // the minimum frame size (just the header and no payload).
  EXPECT_EQ(delegate_.frames()[1].payload.size(), 0);
  EXPECT_EQ(delegate_.frames()[1].size, kDataFrameHeaderSize);

  // Header fields are still present and parseable.
  EXPECT_EQ(delegate_.frames()[1].source_id, 0);
  EXPECT_EQ(delegate_.frames()[1].sequence_number, 1);
  EXPECT_EQ(delegate_.frames()[1].send_time, start_time);
}

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