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

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"

namespace quic {
namespace simulator {
namespace {

using ::testing::ElementsAre;

const QuicBandwidth kDefaultBandwidth =
    QuicBandwidth::FromKBitsPerSecond(10 * 1000);
const QuicTime::Delta kDefaultPropagationDelay =
    QuicTime::Delta::FromMilliseconds(20);
const QuicByteCount kDefaultBdp = kDefaultBandwidth * kDefaultPropagationDelay;
const QuicByteCount kDefaultPacketSize = 1200;
const QuicPacketCount kDefaultQueueLength = 10;

class FakeDelegate : public QuartcPacketTransport::Delegate {
 public:
  explicit FakeDelegate(QuartcPacketTransport* transport)
      : transport_(transport) {
    transport_->SetDelegate(this);
  }

  ~FakeDelegate() { transport_->SetDelegate(nullptr); }

  void OnTransportCanWrite() override {
    while (!packets_to_send_.empty()) {
      const std::string& packet = packets_to_send_.front();
      if (transport_->Write(packet.data(), packet.size(),
                            QuartcPacketTransport::PacketInfo()) <
          static_cast<int>(packet.size())) {
        ++write_blocked_count_;
        return;
      }
      packets_to_send_.pop();
    }
  }

  void OnTransportReceived(const char* data, size_t data_len) override {
    packets_received_.emplace_back(data, data_len);
  }

  void AddPacketToSend(const std::string& packet) {
    packets_to_send_.push(packet);
  }

  size_t packets_to_send() { return packets_to_send_.size(); }
  const std::vector<std::string>& packets_received() {
    return packets_received_;
  }
  int write_blocked_count() { return write_blocked_count_; }

 private:
  QuartcPacketTransport* const transport_ = nullptr;
  std::queue<std::string> packets_to_send_;
  std::vector<std::string> packets_received_;
  int write_blocked_count_ = 0;
};

class SimulatedPacketTransportTest : public QuicTest {
 protected:
  SimulatedPacketTransportTest()
      : switch_(&simulator_, "Switch", /*port_count=*/8, 2 * kDefaultBdp),
        client_(&simulator_,
                "sender",
                "receiver",
                kDefaultQueueLength * kDefaultPacketSize),
        server_(&simulator_,
                "receiver",
                "sender",
                kDefaultQueueLength * kDefaultPacketSize),
        client_link_(&client_,
                     switch_.port(1),
                     kDefaultBandwidth,
                     kDefaultPropagationDelay),
        server_link_(&server_,
                     switch_.port(2),
                     kDefaultBandwidth,
                     kDefaultPropagationDelay),
        client_delegate_(&client_),
        server_delegate_(&server_) {}

  Simulator simulator_;
  Switch switch_;

  SimulatedQuartcPacketTransport client_;
  SimulatedQuartcPacketTransport server_;

  SymmetricLink client_link_;
  SymmetricLink server_link_;

  FakeDelegate client_delegate_;
  FakeDelegate server_delegate_;
};

TEST_F(SimulatedPacketTransportTest, OneWayTransmission) {
  std::string packet_1(kDefaultPacketSize, 'a');
  std::string packet_2(kDefaultPacketSize, 'b');
  client_delegate_.AddPacketToSend(packet_1);
  client_delegate_.AddPacketToSend(packet_2);

  simulator_.RunUntil(
      [this] { return client_delegate_.packets_to_send() == 0; });
  simulator_.RunFor(3 * kDefaultPropagationDelay);

  EXPECT_THAT(server_delegate_.packets_received(),
              ElementsAre(packet_1, packet_2));
  EXPECT_THAT(client_delegate_.packets_received(), ElementsAre());
}

TEST_F(SimulatedPacketTransportTest, TwoWayTransmission) {
  std::string packet_1(kDefaultPacketSize, 'a');
  std::string packet_2(kDefaultPacketSize, 'b');
  std::string packet_3(kDefaultPacketSize, 'c');
  std::string packet_4(kDefaultPacketSize, 'd');

  client_delegate_.AddPacketToSend(packet_1);
  client_delegate_.AddPacketToSend(packet_2);
  server_delegate_.AddPacketToSend(packet_3);
  server_delegate_.AddPacketToSend(packet_4);

  simulator_.RunUntil(
      [this] { return client_delegate_.packets_to_send() == 0; });
  simulator_.RunUntil(
      [this] { return server_delegate_.packets_to_send() == 0; });
  simulator_.RunFor(3 * kDefaultPropagationDelay);

  EXPECT_THAT(server_delegate_.packets_received(),
              ElementsAre(packet_1, packet_2));
  EXPECT_THAT(client_delegate_.packets_received(),
              ElementsAre(packet_3, packet_4));
}

TEST_F(SimulatedPacketTransportTest, TestWriteBlocked) {
  // Add 10 packets beyond what fits in the egress queue.
  std::vector<std::string> packets;
  for (unsigned int i = 0; i < kDefaultQueueLength + 10; ++i) {
    packets.push_back(std::string(kDefaultPacketSize, 'a' + i));
    client_delegate_.AddPacketToSend(packets.back());
  }

  simulator_.RunUntil(
      [this] { return client_delegate_.packets_to_send() == 0; });
  simulator_.RunFor(3 * kDefaultPropagationDelay);

  // Each of the 10 packets in excess of the sender's egress queue length will
  // block the first time |client_delegate_| tries to write them.
  EXPECT_EQ(client_delegate_.write_blocked_count(), 10);
  EXPECT_EQ(server_delegate_.packets_received(), packets);
}

}  // namespace
}  // namespace simulator
}  // namespace quic
