| Index: net/quic/core/congestion_control/simulation/quic_endpoint_test.cc
|
| diff --git a/net/quic/core/congestion_control/simulation/quic_endpoint_test.cc b/net/quic/core/congestion_control/simulation/quic_endpoint_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3e287ab936aedce23b634e2b365cbec1f2e1667b
|
| --- /dev/null
|
| +++ b/net/quic/core/congestion_control/simulation/quic_endpoint_test.cc
|
| @@ -0,0 +1,138 @@
|
| +#include "net/quic/core/congestion_control/simulation/quic_endpoint.h"
|
| +#include "net/quic/core/congestion_control/simulation/simulator.h"
|
| +#include "net/quic/core/congestion_control/simulation/switch.h"
|
| +#include "util/gtl/ptr_util.h"
|
| +
|
| +#include "testing/base/public/gmock.h"
|
| +#include "testing/base/public/gunit.h"
|
| +
|
| +namespace net {
|
| +namespace simulation {
|
| +
|
| +const QuicBandwidth kDefaultBandwidth =
|
| + QuicBandwidth::FromKBitsPerSecond(10 * 1000);
|
| +const QuicTime::Delta kDefaultPropagationDelay =
|
| + QuicTime::Delta::FromMilliseconds(20);
|
| +const QuicByteCount kDefaultBdp = kDefaultBandwidth * kDefaultPropagationDelay;
|
| +
|
| +// A simple test harness where all hosts are connected to a switch with
|
| +// identical links.
|
| +class QuicEndpointTest : public ::testing::Test {
|
| + public:
|
| + QuicEndpointTest()
|
| + : simulator_(), switch_(&simulator_, "Switch", 8, kDefaultBdp * 2) {}
|
| +
|
| + protected:
|
| + Simulator simulator_;
|
| + Switch switch_;
|
| +
|
| + std::unique_ptr<SymmetricLink> Link(Endpoint* a, Endpoint* b) {
|
| + return gtl::MakeUnique<SymmetricLink>(a, b, kDefaultBandwidth,
|
| + kDefaultPropagationDelay);
|
| + }
|
| +};
|
| +
|
| +// Test transmission from one host to another.
|
| +TEST_F(QuicEndpointTest, OneWayTransmission) {
|
| + QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
|
| + Perspective::IS_CLIENT, 42);
|
| + QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
|
| + Perspective::IS_SERVER, 42);
|
| + auto link_a = Link(&endpoint_a, switch_.port(1));
|
| + auto link_b = Link(&endpoint_b, switch_.port(2));
|
| +
|
| + // First transmit a small, packet-size chunk of data.
|
| + endpoint_a.AddBytesToTransfer(600);
|
| + QuicTime end_time =
|
| + simulator_.GetClock()->Now() + QuicTime::Delta::FromMilliseconds(1000);
|
| + simulator_.RunUntil(
|
| + [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
|
| +
|
| + EXPECT_EQ(600u, endpoint_a.bytes_transferred());
|
| + ASSERT_EQ(600u, endpoint_b.bytes_received());
|
| + EXPECT_FALSE(endpoint_a.wrong_data_received());
|
| + EXPECT_FALSE(endpoint_b.wrong_data_received());
|
| +
|
| + // After a small chunk succeeds, try to transfer 2 MiB.
|
| + endpoint_a.AddBytesToTransfer(2 * 1024 * 1024);
|
| + end_time = simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(5);
|
| + simulator_.RunUntil(
|
| + [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
|
| +
|
| + const QuicByteCount total_bytes_transferred = 600 + 2 * 1024 * 1024;
|
| + EXPECT_EQ(total_bytes_transferred, endpoint_a.bytes_transferred());
|
| + EXPECT_EQ(total_bytes_transferred, endpoint_b.bytes_received());
|
| + EXPECT_FALSE(endpoint_a.wrong_data_received());
|
| + EXPECT_FALSE(endpoint_b.wrong_data_received());
|
| +}
|
| +
|
| +// Test transmission of 1 MiB of data between two hosts simultaneously in both
|
| +// directions.
|
| +TEST_F(QuicEndpointTest, TwoWayTransmission) {
|
| + QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
|
| + Perspective::IS_CLIENT, 42);
|
| + QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
|
| + Perspective::IS_SERVER, 42);
|
| + auto link_a = Link(&endpoint_a, switch_.port(1));
|
| + auto link_b = Link(&endpoint_b, switch_.port(2));
|
| +
|
| + endpoint_a.AddBytesToTransfer(1024 * 1024);
|
| + endpoint_b.AddBytesToTransfer(1024 * 1024);
|
| + QuicTime end_time =
|
| + simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(5);
|
| + simulator_.RunUntil(
|
| + [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
|
| +
|
| + EXPECT_EQ(1024u * 1024u, endpoint_a.bytes_transferred());
|
| + EXPECT_EQ(1024u * 1024u, endpoint_b.bytes_transferred());
|
| + EXPECT_EQ(1024u * 1024u, endpoint_a.bytes_received());
|
| + EXPECT_EQ(1024u * 1024u, endpoint_b.bytes_received());
|
| + EXPECT_FALSE(endpoint_a.wrong_data_received());
|
| + EXPECT_FALSE(endpoint_b.wrong_data_received());
|
| +}
|
| +
|
| +// Simulate three hosts trying to send data to a fourth one simultaneously.
|
| +TEST_F(QuicEndpointTest, Competition) {
|
| + auto endpoint_a = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint A", "Endpoint D (A)", Perspective::IS_CLIENT, 42);
|
| + auto endpoint_b = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint B", "Endpoint D (B)", Perspective::IS_CLIENT, 43);
|
| + auto endpoint_c = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint C", "Endpoint D (C)", Perspective::IS_CLIENT, 44);
|
| + auto endpoint_d_a = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint D (A)", "Endpoint A", Perspective::IS_SERVER, 42);
|
| + auto endpoint_d_b = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint D (B)", "Endpoint B", Perspective::IS_SERVER, 43);
|
| + auto endpoint_d_c = gtl::MakeUnique<QuicEndpoint>(
|
| + &simulator_, "Endpoint D (C)", "Endpoint C", Perspective::IS_SERVER, 44);
|
| + QuicEndpointMultiplexer endpoint_d(
|
| + "Endpoint D",
|
| + {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()});
|
| +
|
| + auto link_a = Link(endpoint_a.get(), switch_.port(1));
|
| + auto link_b = Link(endpoint_b.get(), switch_.port(2));
|
| + auto link_c = Link(endpoint_c.get(), switch_.port(3));
|
| + auto link_d = Link(&endpoint_d, switch_.port(4));
|
| +
|
| + endpoint_a->AddBytesToTransfer(2 * 1024 * 1024);
|
| + endpoint_b->AddBytesToTransfer(2 * 1024 * 1024);
|
| + endpoint_c->AddBytesToTransfer(2 * 1024 * 1024);
|
| + QuicTime end_time =
|
| + simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(8);
|
| + simulator_.RunUntil(
|
| + [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
|
| +
|
| + for (QuicEndpoint* endpoint :
|
| + {endpoint_a.get(), endpoint_b.get(), endpoint_c.get()}) {
|
| + EXPECT_EQ(2u * 1024u * 1024u, endpoint->bytes_transferred());
|
| + EXPECT_GE(endpoint->connection()->GetStats().packets_lost, 0);
|
| + }
|
| + for (QuicEndpoint* endpoint :
|
| + {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()}) {
|
| + EXPECT_EQ(2u * 1024u * 1024u, endpoint->bytes_received());
|
| + EXPECT_FALSE(endpoint->wrong_data_received());
|
| + }
|
| +}
|
| +
|
| +} // namespace simulation
|
| +} // namespace net
|
|
|