| // Copyright (c) 2019 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/core/quic_bandwidth.h" |
| #include "net/third_party/quiche/src/quic/core/quic_time.h" |
| #include "net/third_party/quiche/src/quic/core/quic_types.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" |
| #include "net/third_party/quiche/src/quic/quartc/simulated_packet_transport.h" |
| #include "net/third_party/quiche/src/quic/quartc/test/bidi_test_runner.h" |
| #include "net/third_party/quiche/src/quic/quartc/test/quartc_competing_endpoint.h" |
| #include "net/third_party/quiche/src/quic/quartc/test/quic_trace_interceptor.h" |
| #include "net/third_party/quiche/src/quic/quartc/test/random_packet_filter.h" |
| #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" |
| #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h" |
| #include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.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 test { |
| namespace { |
| |
| class QuartcBidiTest : public QuicTest { |
| protected: |
| QuartcBidiTest() { |
| uint64_t seed = QuicRandom::GetInstance()->RandUint64(); |
| QUIC_LOG(INFO) << "Setting random seed to " << seed; |
| random_.set_seed(seed); |
| simulator_.set_random_generator(&random_); |
| |
| client_trace_interceptor_ = QuicMakeUnique<QuicTraceInterceptor>("client"); |
| server_trace_interceptor_ = QuicMakeUnique<QuicTraceInterceptor>("server"); |
| } |
| |
| void CreateTransports(QuicBandwidth bandwidth, |
| QuicTime::Delta propagation_delay, |
| QuicByteCount queue_length, |
| int loss_percent) { |
| // Endpoints which serve as the transports for client and server. |
| client_transport_ = |
| QuicMakeUnique<simulator::SimulatedQuartcPacketTransport>( |
| &simulator_, "client_transport", "server_transport", queue_length); |
| server_transport_ = |
| QuicMakeUnique<simulator::SimulatedQuartcPacketTransport>( |
| &simulator_, "server_transport", "client_transport", queue_length); |
| |
| // Filters on each of the endpoints facilitate random packet loss. |
| client_filter_ = QuicMakeUnique<simulator::RandomPacketFilter>( |
| &simulator_, "client_filter", client_transport_.get()); |
| server_filter_ = QuicMakeUnique<simulator::RandomPacketFilter>( |
| &simulator_, "server_filter", server_transport_.get()); |
| client_filter_->set_loss_percent(loss_percent); |
| server_filter_->set_loss_percent(loss_percent); |
| |
| // Each endpoint connects directly to a switch. |
| client_switch_ = QuicMakeUnique<simulator::Switch>( |
| &simulator_, "client_switch", /*port_count=*/8, 2 * queue_length); |
| server_switch_ = QuicMakeUnique<simulator::Switch>( |
| &simulator_, "server_switch", /*port_count=*/8, 2 * queue_length); |
| |
| // Links to the switch have significantly higher bandwidth than the |
| // bottleneck and insignificant propagation delay. |
| client_link_ = QuicMakeUnique<simulator::SymmetricLink>( |
| client_filter_.get(), client_switch_->port(1), 10 * bandwidth, |
| QuicTime::Delta::FromMicroseconds(1)); |
| server_link_ = QuicMakeUnique<simulator::SymmetricLink>( |
| server_filter_.get(), server_switch_->port(1), 10 * bandwidth, |
| QuicTime::Delta::FromMicroseconds(1)); |
| |
| // The bottleneck link connects the two switches with the bandwidth and |
| // propagation delay specified by the test case. |
| bottleneck_link_ = QuicMakeUnique<simulator::SymmetricLink>( |
| client_switch_->port(2), server_switch_->port(2), bandwidth, |
| propagation_delay); |
| } |
| |
| void SetupCompetingEndpoints(QuicBandwidth bandwidth, |
| QuicTime::Delta send_interval, |
| QuicByteCount bytes_per_interval) { |
| competing_client_ = QuicMakeUnique<QuartcCompetingEndpoint>( |
| &simulator_, send_interval, bytes_per_interval, "competing_client", |
| "competing_server", quic::Perspective::IS_CLIENT, |
| quic::test::TestConnectionId(3)); |
| competing_server_ = QuicMakeUnique<QuartcCompetingEndpoint>( |
| &simulator_, send_interval, bytes_per_interval, "competing_server", |
| "competing_client", quic::Perspective::IS_SERVER, |
| quic::test::TestConnectionId(3)); |
| |
| competing_client_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>( |
| competing_client_->endpoint(), client_switch_->port(3), 10 * bandwidth, |
| QuicTime::Delta::FromMicroseconds(1)); |
| competing_server_link_ = QuicMakeUnique<quic::simulator::SymmetricLink>( |
| competing_server_->endpoint(), server_switch_->port(3), 10 * bandwidth, |
| QuicTime::Delta::FromMicroseconds(1)); |
| } |
| |
| simulator::Simulator simulator_; |
| SimpleRandom random_; |
| |
| std::unique_ptr<simulator::SimulatedQuartcPacketTransport> client_transport_; |
| std::unique_ptr<simulator::SimulatedQuartcPacketTransport> server_transport_; |
| std::unique_ptr<simulator::RandomPacketFilter> client_filter_; |
| std::unique_ptr<simulator::RandomPacketFilter> server_filter_; |
| std::unique_ptr<simulator::Switch> client_switch_; |
| std::unique_ptr<simulator::Switch> server_switch_; |
| std::unique_ptr<simulator::SymmetricLink> client_link_; |
| std::unique_ptr<simulator::SymmetricLink> server_link_; |
| std::unique_ptr<simulator::SymmetricLink> bottleneck_link_; |
| |
| std::unique_ptr<QuartcCompetingEndpoint> competing_client_; |
| std::unique_ptr<QuartcCompetingEndpoint> competing_server_; |
| std::unique_ptr<simulator::SymmetricLink> competing_client_link_; |
| std::unique_ptr<simulator::SymmetricLink> competing_server_link_; |
| |
| std::unique_ptr<QuicTraceInterceptor> client_trace_interceptor_; |
| std::unique_ptr<QuicTraceInterceptor> server_trace_interceptor_; |
| }; |
| |
| TEST_F(QuartcBidiTest, Basic300kbps200ms) { |
| CreateTransports(QuicBandwidth::FromKBitsPerSecond(300), |
| QuicTime::Delta::FromMilliseconds(200), |
| 10 * kDefaultMaxPacketSize, /*loss_percent=*/0); |
| BidiTestRunner runner(&simulator_, client_transport_.get(), |
| server_transport_.get()); |
| runner.set_client_interceptor(client_trace_interceptor_.get()); |
| runner.set_server_interceptor(server_trace_interceptor_.get()); |
| EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30))); |
| } |
| |
| TEST_F(QuartcBidiTest, 300kbps200ms2PercentLoss) { |
| CreateTransports(QuicBandwidth::FromKBitsPerSecond(300), |
| QuicTime::Delta::FromMilliseconds(200), |
| 10 * kDefaultMaxPacketSize, /*loss_percent=*/2); |
| BidiTestRunner runner(&simulator_, client_transport_.get(), |
| server_transport_.get()); |
| runner.set_client_interceptor(client_trace_interceptor_.get()); |
| runner.set_server_interceptor(server_trace_interceptor_.get()); |
| EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30))); |
| } |
| |
| TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossCompetingBurst) { |
| QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300); |
| CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200), |
| 10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2); |
| SetupCompetingEndpoints(bandwidth, QuicTime::Delta::FromSeconds(15), |
| /*bytes_per_interval=*/50 * 1024); |
| |
| quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(), |
| server_transport_.get()); |
| runner.set_client_interceptor(client_trace_interceptor_.get()); |
| runner.set_server_interceptor(server_trace_interceptor_.get()); |
| EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30))); |
| } |
| |
| TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossSmallCompetingSpikes) { |
| QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300); |
| CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200), |
| 10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2); |
| |
| // Competition sends a small amount of data (10 kb) every 2 seconds. |
| SetupCompetingEndpoints(bandwidth, QuicTime::Delta::FromSeconds(2), |
| /*bytes_per_interval=*/10 * 1024); |
| |
| quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(), |
| server_transport_.get()); |
| runner.set_client_interceptor(client_trace_interceptor_.get()); |
| runner.set_server_interceptor(server_trace_interceptor_.get()); |
| EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30))); |
| } |
| |
| TEST_F(QuartcBidiTest, 300kbps200ms2PercentLossAggregation) { |
| QuicBandwidth bandwidth = QuicBandwidth::FromKBitsPerSecond(300); |
| CreateTransports(bandwidth, QuicTime::Delta::FromMilliseconds(200), |
| 10 * quic::kDefaultMaxPacketSize, /*loss_percent=*/2); |
| |
| // Set aggregation on the queues at either end of the bottleneck. |
| client_switch_->port_queue(2)->EnableAggregation( |
| 10 * 1024, QuicTime::Delta::FromMilliseconds(100)); |
| server_switch_->port_queue(2)->EnableAggregation( |
| 10 * 1024, QuicTime::Delta::FromMilliseconds(100)); |
| |
| quic::test::BidiTestRunner runner(&simulator_, client_transport_.get(), |
| server_transport_.get()); |
| runner.set_client_interceptor(client_trace_interceptor_.get()); |
| runner.set_server_interceptor(server_trace_interceptor_.get()); |
| EXPECT_TRUE(runner.RunTest(QuicTime::Delta::FromSeconds(30))); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace quic |