Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/quartc/simulated_packet_transport_test.cc b/quic/quartc/simulated_packet_transport_test.cc
new file mode 100644
index 0000000..3fbd18b
--- /dev/null
+++ b/quic/quartc/simulated_packet_transport_test.cc
@@ -0,0 +1,165 @@
+// 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