// 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/quic/quartc/simulated_packet_transport.h"

#include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/quartc/quartc_packet_writer.h"
#include "net/third_party/quic/test_tools/simulator/simulator.h"
#include "net/third_party/quic/test_tools/simulator/switch.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.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
