// Copyright (c) 2019 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_peer.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"
#include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"

namespace quic {
namespace test {
namespace {

class QuartcPeerTest : public QuicTest {
 protected:
  QuartcPeerTest()
      : client_transport_(&simulator_,
                          "client_transport",
                          "server_transport",
                          10 * kDefaultMaxPacketSize),
        server_transport_(&simulator_,
                          "server_transport",
                          "client_transport",
                          10 * kDefaultMaxPacketSize),
        client_server_link_(&client_transport_,
                            &server_transport_,
                            QuicBandwidth::FromKBitsPerSecond(512),
                            QuicTime::Delta::FromMilliseconds(100)) {}

  void CreatePeers(const std::vector<QuartcDataSource::Config>& configs) {
    client_peer_ = QuicMakeUnique<QuartcPeer>(
        simulator_.GetClock(), simulator_.GetAlarmFactory(),
        simulator_.GetRandomGenerator(), configs);
    server_peer_ = QuicMakeUnique<QuartcPeer>(
        simulator_.GetClock(), simulator_.GetAlarmFactory(),
        simulator_.GetRandomGenerator(), configs);
  }

  void Connect() {
    DCHECK(client_peer_);
    DCHECK(server_peer_);

    server_endpoint_ = QuicMakeUnique<QuartcServerEndpoint>(
        simulator_.GetAlarmFactory(), simulator_.GetClock(),
        simulator_.GetRandomGenerator(), server_peer_.get(),
        QuartcSessionConfig());
    client_endpoint_ = QuicMakeUnique<QuartcClientEndpoint>(
        simulator_.GetAlarmFactory(), simulator_.GetClock(),
        simulator_.GetRandomGenerator(), client_peer_.get(),
        QuartcSessionConfig(), server_endpoint_->server_crypto_config());

    server_endpoint_->Connect(&server_transport_);
    client_endpoint_->Connect(&client_transport_);
  }

  simulator::Simulator simulator_;
  simulator::SimulatedQuartcPacketTransport client_transport_;
  simulator::SimulatedQuartcPacketTransport server_transport_;
  simulator::SymmetricLink client_server_link_;

  std::unique_ptr<QuartcClientEndpoint> client_endpoint_;
  std::unique_ptr<QuartcPeer> client_peer_;

  std::unique_ptr<QuartcServerEndpoint> server_endpoint_;
  std::unique_ptr<QuartcPeer> server_peer_;
};

const ReceivedMessage& FindLastMessageFromSource(
    const std::vector<ReceivedMessage>& messages,
    int32_t source_id) {
  const auto& it = std::find_if(messages.rbegin(), messages.rend(),
                                [source_id](const ReceivedMessage& r) {
                                  return r.frame.source_id == source_id;
                                });
  return *it;
}

TEST_F(QuartcPeerTest, SendReceiveMessages) {
  QuicTime start_time = simulator_.GetClock()->Now();

  QuartcDataSource::Config config;
  config.id = 1;

  CreatePeers({config});
  Connect();

  ASSERT_TRUE(simulator_.RunUntil([this] {
    return !client_peer_->received_messages().empty() &&
           !server_peer_->received_messages().empty();
  }));

  QuicTime end_time = simulator_.GetClock()->Now();

  // Sanity checks on messages.
  const ReceivedMessage& client_message = client_peer_->received_messages()[0];
  EXPECT_EQ(client_message.frame.source_id, 1);
  EXPECT_EQ(client_message.frame.sequence_number, 0);
  EXPECT_GE(client_message.frame.send_time, start_time);
  EXPECT_LE(client_message.receive_time, end_time);

  const ReceivedMessage& server_message = server_peer_->received_messages()[0];
  EXPECT_EQ(server_message.frame.source_id, 1);
  EXPECT_EQ(server_message.frame.sequence_number, 0);
  EXPECT_GE(server_message.frame.send_time, start_time);
  EXPECT_LE(server_message.receive_time, end_time);
}

TEST_F(QuartcPeerTest, MaxFrameSizeUnset) {
  // Configure the source with no max frame size, and a framerate and max
  // bandwidth that allows very large frames (larger than will fit in a packet).
  QuartcDataSource::Config config;
  config.id = 1;
  config.frame_interval = QuicTime::Delta::FromMilliseconds(20);
  config.max_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(
      2 * kDefaultMaxPacketSize, config.frame_interval);

  CreatePeers({config});
  Connect();

  // Run long enough for the bandwidth estimate to ramp up.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  // The peers generate frames that fit in one packet.
  EXPECT_LT(client_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
  EXPECT_LT(server_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
}

TEST_F(QuartcPeerTest, MaxFrameSizeLargerThanPacketSize) {
  // Configure the source with a max frame size larger than the packet size.
  QuartcDataSource::Config config;
  config.id = 1;
  config.max_frame_size = 2 * kDefaultMaxPacketSize;

  CreatePeers({config});
  Connect();

  // Run long enough for the bandwidth estimate to ramp up.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  // The peers generate frames that fit in one packet.
  EXPECT_LT(client_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
  EXPECT_LT(server_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
}

TEST_F(QuartcPeerTest, MaxFrameSizeSmallerThanPacketSize) {
  QuartcDataSource::Config config;
  config.id = 1;
  config.max_frame_size = 100;
  // Note that a long frame interval helps to ensure that the test produces
  // enough bytes per frame to reach max_frame_size.
  config.frame_interval = QuicTime::Delta::FromMilliseconds(100);

  CreatePeers({config});
  Connect();

  // Run long enough for the bandwidth estimate to ramp up.
  // Note that the ramp-up time is longer for this test because of the long
  // frame_interval.  This seems especially true when QUIC enables all flags for
  // testing.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(30));

  EXPECT_EQ(client_peer_->received_messages().back().frame.size, 100);
  EXPECT_EQ(server_peer_->received_messages().back().frame.size, 100);
}

TEST_F(QuartcPeerTest, MaxFrameSizeSmallerThanFrameHeader) {
  QuartcDataSource::Config config;
  config.id = 1;
  config.max_frame_size = kDataFrameHeaderSize - 1;

  CreatePeers({config});
  Connect();

  // Run long enough for the bandwidth estimate to ramp up.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  // Max frame sizes smaller than the header are ignored, and the frame size is
  // limited by packet size.
  EXPECT_LT(client_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
  EXPECT_LT(server_peer_->received_messages().back().frame.size,
            kDefaultMaxPacketSize);
}

TEST_F(QuartcPeerTest, SendReceiveMultipleSources) {
  QuicTime start_time = simulator_.GetClock()->Now();

  // Note: use of really long frame intervals means that each source should send
  // one frame during this test.  This simplifies expectations for received
  // data.
  QuartcDataSource::Config config_1;
  config_1.id = 1;
  config_1.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(32);
  config_1.frame_interval = QuicTime::Delta::FromSeconds(10);

  QuartcDataSource::Config config_2;
  config_2.id = 2;
  config_2.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(64);
  config_2.frame_interval = QuicTime::Delta::FromSeconds(10);

  QuartcDataSource::Config config_3;
  config_3.id = 3;
  config_3.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(128);
  config_3.frame_interval = QuicTime::Delta::FromSeconds(10);

  CreatePeers({config_1, config_2, config_3});
  Connect();

  ASSERT_TRUE(simulator_.RunUntil([this] {
    return client_peer_->received_messages().size() == 3 &&
           server_peer_->received_messages().size() == 3;
  }));

  QuicTime end_time = simulator_.GetClock()->Now();

  // Sanity checks on messages.
  const auto& order = [](const ReceivedMessage& lhs,
                         const ReceivedMessage& rhs) {
    return lhs.frame.source_id < rhs.frame.source_id;
  };

  std::vector<ReceivedMessage> client_messages =
      client_peer_->received_messages();
  std::sort(client_messages.begin(), client_messages.end(), order);
  for (int i = 0; i < client_messages.size(); ++i) {
    EXPECT_EQ(client_messages[i].frame.source_id, i + 1);
    EXPECT_EQ(client_messages[i].frame.sequence_number, 0);
    EXPECT_GE(client_messages[i].frame.send_time, start_time);
    EXPECT_LE(client_messages[i].receive_time, end_time);
  }

  std::vector<ReceivedMessage> server_messages =
      server_peer_->received_messages();
  std::sort(server_messages.begin(), server_messages.end(), order);
  for (int i = 0; i < server_messages.size(); ++i) {
    EXPECT_EQ(server_messages[i].frame.source_id, i + 1);
    EXPECT_EQ(server_messages[i].frame.sequence_number, 0);
    EXPECT_GE(server_messages[i].frame.send_time, start_time);
    EXPECT_LE(server_messages[i].receive_time, end_time);
  }
}

TEST_F(QuartcPeerTest, BandwidthAllocationWithEnoughAvailable) {
  QuartcDataSource::Config config_1;
  config_1.id = 1;
  config_1.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(32);
  config_1.frame_interval = QuicTime::Delta::FromMilliseconds(100);

  QuartcDataSource::Config config_2;
  config_2.id = 2;
  config_2.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(64);
  config_2.frame_interval = QuicTime::Delta::FromMilliseconds(25);

  QuartcDataSource::Config config_3;
  config_3.id = 3;
  config_3.max_bandwidth = QuicBandwidth::FromKBitsPerSecond(128);
  config_3.frame_interval = QuicTime::Delta::FromMilliseconds(10);

  CreatePeers({config_1, config_2, config_3});
  Connect();

  // Run for long enough that bandwidth ramps up and meets the requirements of
  // all three sources.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  // The last message from each source should be the size allowed by that
  // source's maximum bandwidth and frame interval.
  QuicByteCount source_1_size =
      config_1.max_bandwidth.ToBytesPerPeriod(config_1.frame_interval);
  QuicByteCount source_2_size =
      config_2.max_bandwidth.ToBytesPerPeriod(config_2.frame_interval);
  QuicByteCount source_3_size =
      config_3.max_bandwidth.ToBytesPerPeriod(config_3.frame_interval);

  const std::vector<ReceivedMessage>& client_messages =
      client_peer_->received_messages();
  EXPECT_EQ(FindLastMessageFromSource(client_messages, 1).frame.size,
            source_1_size);
  EXPECT_EQ(FindLastMessageFromSource(client_messages, 2).frame.size,
            source_2_size);
  EXPECT_EQ(FindLastMessageFromSource(client_messages, 3).frame.size,
            source_3_size);

  const std::vector<ReceivedMessage>& server_messages =
      server_peer_->received_messages();
  EXPECT_EQ(FindLastMessageFromSource(server_messages, 1).frame.size,
            source_1_size);
  EXPECT_EQ(FindLastMessageFromSource(server_messages, 2).frame.size,
            source_2_size);
  EXPECT_EQ(FindLastMessageFromSource(server_messages, 3).frame.size,
            source_3_size);
}

TEST_F(QuartcPeerTest, BandwidthAllocationWithoutEnoughAvailable) {
  QuartcDataSource::Config config_1;
  config_1.id = 1;
  config_1.max_bandwidth = client_server_link_.bandwidth() * 0.5;
  config_1.frame_interval = QuicTime::Delta::FromMilliseconds(10);

  QuartcDataSource::Config config_2;
  config_2.id = 2;
  config_2.min_bandwidth = QuicBandwidth::FromKBitsPerSecond(32);
  config_2.max_bandwidth = client_server_link_.bandwidth();
  config_2.frame_interval = QuicTime::Delta::FromMilliseconds(5);

  QuartcDataSource::Config config_3;
  config_3.id = 3;
  config_3.min_bandwidth = QuicBandwidth::FromKBitsPerSecond(32);
  config_3.max_bandwidth = client_server_link_.bandwidth() * 2;
  config_3.frame_interval = QuicTime::Delta::FromMilliseconds(20);

  CreatePeers({config_1, config_2, config_3});
  Connect();

  // Run for long enough that bandwidth ramps up to link capacity.
  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  const std::vector<ReceivedMessage>& client_messages =
      client_peer_->received_messages();
  const std::vector<ReceivedMessage>& server_messages =
      server_peer_->received_messages();

  // Source 1 eventually ramps up to full bandwidth.
  const QuicByteCount source_1_size =
      config_1.max_bandwidth.ToBytesPerPeriod(config_1.frame_interval);
  EXPECT_EQ(FindLastMessageFromSource(client_messages, 1).frame.size,
            source_1_size);
  EXPECT_EQ(FindLastMessageFromSource(server_messages, 1).frame.size,
            source_1_size);

  // Source 2 takes the remainder of available bandwidth.  However, the exact
  // value depends on the bandwidth estimate.
  const QuicByteCount source_2_min =
      config_2.min_bandwidth.ToBytesPerPeriod(config_2.frame_interval);
  const QuicByteCount source_2_max =
      config_2.max_bandwidth.ToBytesPerPeriod(config_2.frame_interval);
  EXPECT_GT(FindLastMessageFromSource(client_messages, 2).frame.size,
            source_2_min);
  EXPECT_LT(FindLastMessageFromSource(client_messages, 2).frame.size,
            source_2_max);
  EXPECT_GT(FindLastMessageFromSource(server_messages, 2).frame.size,
            source_2_min);
  EXPECT_LT(FindLastMessageFromSource(server_messages, 2).frame.size,
            source_2_max);

  // Source 3 gets only its minimum bandwidth.
  const QuicByteCount source_3_size =
      config_3.min_bandwidth.ToBytesPerPeriod(config_3.frame_interval);
  EXPECT_EQ(FindLastMessageFromSource(client_messages, 3).frame.size,
            source_3_size);
  EXPECT_EQ(FindLastMessageFromSource(server_messages, 3).frame.size,
            source_3_size);
}

TEST_F(QuartcPeerTest, DisableAndDrainMessages) {
  QuartcDataSource::Config config;
  config.id = 1;
  config.max_bandwidth = client_server_link_.bandwidth() * 0.5;
  config.frame_interval = QuicTime::Delta::FromMilliseconds(10);

  CreatePeers({config});
  Connect();

  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  // After these calls, we should observe no new messages.
  server_peer_->SetEnabled(false);
  client_peer_->SetEnabled(false);

  std::map<int32_t, int64_t> last_sent_by_client =
      client_peer_->GetLastSequenceNumbers();
  std::map<int32_t, int64_t> last_sent_by_server =
      server_peer_->GetLastSequenceNumbers();

  simulator_.RunFor(QuicTime::Delta::FromSeconds(15));

  ASSERT_FALSE(client_peer_->received_messages().empty());
  EXPECT_EQ(client_peer_->received_messages().back().frame.sequence_number,
            last_sent_by_server[1]);

  ASSERT_FALSE(server_peer_->received_messages().empty());
  EXPECT_EQ(server_peer_->received_messages().back().frame.sequence_number,
            last_sent_by_client[1]);
}

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