| // 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 "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 |