// 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 QuicString& 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 QuicString& packet) {
    packets_to_send_.push(packet);
  }

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

 private:
  QuartcPacketTransport* const transport_ = nullptr;
  std::queue<QuicString> packets_to_send_;
  std::vector<QuicString> 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) {
  QuicString packet_1(kDefaultPacketSize, 'a');
  QuicString 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) {
  QuicString packet_1(kDefaultPacketSize, 'a');
  QuicString packet_2(kDefaultPacketSize, 'b');
  QuicString packet_3(kDefaultPacketSize, 'c');
  QuicString 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<QuicString> packets;
  for (unsigned int i = 0; i < kDefaultQueueLength + 10; ++i) {
    packets.push_back(QuicString(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
