blob: 3fbd18b83f33861dc73add84555d044eeadf059a [file] [log] [blame]
// 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