blob: 5382eb56b1e6ba0d68fd5229dbd91dcfeb5587db [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/test_tools/simulator/quic_endpoint.h"
6
7#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
10#include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h"
11#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
12#include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h"
13#include "net/third_party/quiche/src/quic/test_tools/simulator/switch.h"
14
15using ::testing::_;
16using ::testing::NiceMock;
17using ::testing::Return;
18
19namespace quic {
20namespace simulator {
21
22const QuicBandwidth kDefaultBandwidth =
23 QuicBandwidth::FromKBitsPerSecond(10 * 1000);
24const QuicTime::Delta kDefaultPropagationDelay =
25 QuicTime::Delta::FromMilliseconds(20);
26const QuicByteCount kDefaultBdp = kDefaultBandwidth * kDefaultPropagationDelay;
27
28// A simple test harness where all hosts are connected to a switch with
29// identical links.
30class QuicEndpointTest : public QuicTest {
31 public:
32 QuicEndpointTest()
33 : simulator_(), switch_(&simulator_, "Switch", 8, kDefaultBdp * 2) {}
34
35 protected:
36 Simulator simulator_;
37 Switch switch_;
38
39 std::unique_ptr<SymmetricLink> Link(Endpoint* a, Endpoint* b) {
40 return QuicMakeUnique<SymmetricLink>(a, b, kDefaultBandwidth,
41 kDefaultPropagationDelay);
42 }
43
44 std::unique_ptr<SymmetricLink> CustomLink(Endpoint* a,
45 Endpoint* b,
46 uint64_t extra_rtt_ms) {
47 return QuicMakeUnique<SymmetricLink>(
48 a, b, kDefaultBandwidth,
49 kDefaultPropagationDelay +
50 QuicTime::Delta::FromMilliseconds(extra_rtt_ms));
51 }
52};
53
54// Test transmission from one host to another.
55TEST_F(QuicEndpointTest, OneWayTransmission) {
56 QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
57 Perspective::IS_CLIENT, test::TestConnectionId(42));
58 QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
59 Perspective::IS_SERVER, test::TestConnectionId(42));
60 auto link_a = Link(&endpoint_a, switch_.port(1));
61 auto link_b = Link(&endpoint_b, switch_.port(2));
62
63 // First transmit a small, packet-size chunk of data.
64 endpoint_a.AddBytesToTransfer(600);
65 QuicTime end_time =
66 simulator_.GetClock()->Now() + QuicTime::Delta::FromMilliseconds(1000);
67 simulator_.RunUntil(
68 [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
69
70 EXPECT_EQ(600u, endpoint_a.bytes_transferred());
71 ASSERT_EQ(600u, endpoint_b.bytes_received());
72 EXPECT_FALSE(endpoint_a.wrong_data_received());
73 EXPECT_FALSE(endpoint_b.wrong_data_received());
74
75 // After a small chunk succeeds, try to transfer 2 MiB.
76 endpoint_a.AddBytesToTransfer(2 * 1024 * 1024);
77 end_time = simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(5);
78 simulator_.RunUntil(
79 [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
80
81 const QuicByteCount total_bytes_transferred = 600 + 2 * 1024 * 1024;
82 EXPECT_EQ(total_bytes_transferred, endpoint_a.bytes_transferred());
83 EXPECT_EQ(total_bytes_transferred, endpoint_b.bytes_received());
84 EXPECT_EQ(0u, endpoint_a.write_blocked_count());
85 EXPECT_FALSE(endpoint_a.wrong_data_received());
86 EXPECT_FALSE(endpoint_b.wrong_data_received());
87}
88
89// Test the situation in which the writer becomes write-blocked.
90TEST_F(QuicEndpointTest, WriteBlocked) {
91 QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
92 Perspective::IS_CLIENT, test::TestConnectionId(42));
93 QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
94 Perspective::IS_SERVER, test::TestConnectionId(42));
95 auto link_a = Link(&endpoint_a, switch_.port(1));
96 auto link_b = Link(&endpoint_b, switch_.port(2));
97
98 // Will be owned by the sent packet manager.
99 auto* sender = new NiceMock<test::MockSendAlgorithm>();
100 EXPECT_CALL(*sender, CanSend(_)).WillRepeatedly(Return(true));
101 EXPECT_CALL(*sender, PacingRate(_))
102 .WillRepeatedly(Return(10 * kDefaultBandwidth));
103 EXPECT_CALL(*sender, BandwidthEstimate())
104 .WillRepeatedly(Return(10 * kDefaultBandwidth));
105 EXPECT_CALL(*sender, GetCongestionWindow())
106 .WillRepeatedly(
dschinazi66dea072019-04-09 11:41:06 -0700107 Return(kMaxOutgoingPacketSize * kDefaultMaxCongestionWindowPackets));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500108 test::QuicConnectionPeer::SetSendAlgorithm(endpoint_a.connection(), sender);
109
110 // First transmit a small, packet-size chunk of data.
111 QuicByteCount bytes_to_transfer = 3 * 1024 * 1024;
112 endpoint_a.AddBytesToTransfer(bytes_to_transfer);
113 QuicTime end_time =
114 simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(30);
115 simulator_.RunUntil([this, &endpoint_b, bytes_to_transfer, end_time]() {
116 return endpoint_b.bytes_received() == bytes_to_transfer ||
117 simulator_.GetClock()->Now() >= end_time;
118 });
119
120 EXPECT_EQ(bytes_to_transfer, endpoint_a.bytes_transferred());
121 EXPECT_EQ(bytes_to_transfer, endpoint_b.bytes_received());
122 EXPECT_GT(endpoint_a.write_blocked_count(), 0u);
123 EXPECT_FALSE(endpoint_a.wrong_data_received());
124 EXPECT_FALSE(endpoint_b.wrong_data_received());
125}
126
127// Test transmission of 1 MiB of data between two hosts simultaneously in both
128// directions.
129TEST_F(QuicEndpointTest, TwoWayTransmission) {
130 QuicEndpoint endpoint_a(&simulator_, "Endpoint A", "Endpoint B",
131 Perspective::IS_CLIENT, test::TestConnectionId(42));
132 QuicEndpoint endpoint_b(&simulator_, "Endpoint B", "Endpoint A",
133 Perspective::IS_SERVER, test::TestConnectionId(42));
134 auto link_a = Link(&endpoint_a, switch_.port(1));
135 auto link_b = Link(&endpoint_b, switch_.port(2));
136
137 endpoint_a.RecordTrace();
138 endpoint_b.RecordTrace();
139
140 endpoint_a.AddBytesToTransfer(1024 * 1024);
141 endpoint_b.AddBytesToTransfer(1024 * 1024);
142 QuicTime end_time =
143 simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(5);
144 simulator_.RunUntil(
145 [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
146
147 EXPECT_EQ(1024u * 1024u, endpoint_a.bytes_transferred());
148 EXPECT_EQ(1024u * 1024u, endpoint_b.bytes_transferred());
149 EXPECT_EQ(1024u * 1024u, endpoint_a.bytes_received());
150 EXPECT_EQ(1024u * 1024u, endpoint_b.bytes_received());
151 EXPECT_FALSE(endpoint_a.wrong_data_received());
152 EXPECT_FALSE(endpoint_b.wrong_data_received());
153}
154
155// Simulate three hosts trying to send data to a fourth one simultaneously.
156TEST_F(QuicEndpointTest, Competition) {
157 // TODO(63765788): Turn back on this flag when the issue if fixed.
158 SetQuicReloadableFlag(quic_bbr_one_mss_conservation, false);
159 auto endpoint_a = QuicMakeUnique<QuicEndpoint>(
160 &simulator_, "Endpoint A", "Endpoint D (A)", Perspective::IS_CLIENT,
161 test::TestConnectionId(42));
162 auto endpoint_b = QuicMakeUnique<QuicEndpoint>(
163 &simulator_, "Endpoint B", "Endpoint D (B)", Perspective::IS_CLIENT,
164 test::TestConnectionId(43));
165 auto endpoint_c = QuicMakeUnique<QuicEndpoint>(
166 &simulator_, "Endpoint C", "Endpoint D (C)", Perspective::IS_CLIENT,
167 test::TestConnectionId(44));
168 auto endpoint_d_a = QuicMakeUnique<QuicEndpoint>(
169 &simulator_, "Endpoint D (A)", "Endpoint A", Perspective::IS_SERVER,
170 test::TestConnectionId(42));
171 auto endpoint_d_b = QuicMakeUnique<QuicEndpoint>(
172 &simulator_, "Endpoint D (B)", "Endpoint B", Perspective::IS_SERVER,
173 test::TestConnectionId(43));
174 auto endpoint_d_c = QuicMakeUnique<QuicEndpoint>(
175 &simulator_, "Endpoint D (C)", "Endpoint C", Perspective::IS_SERVER,
176 test::TestConnectionId(44));
177 QuicEndpointMultiplexer endpoint_d(
178 "Endpoint D",
179 {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()});
180
181 // Create links with slightly different RTTs in order to avoid pathological
182 // side-effects of packets entering the queue at the exactly same time.
183 auto link_a = CustomLink(endpoint_a.get(), switch_.port(1), 0);
184 auto link_b = CustomLink(endpoint_b.get(), switch_.port(2), 1);
185 auto link_c = CustomLink(endpoint_c.get(), switch_.port(3), 2);
186 auto link_d = Link(&endpoint_d, switch_.port(4));
187
188 endpoint_a->AddBytesToTransfer(2 * 1024 * 1024);
189 endpoint_b->AddBytesToTransfer(2 * 1024 * 1024);
190 endpoint_c->AddBytesToTransfer(2 * 1024 * 1024);
191 QuicTime end_time =
192 simulator_.GetClock()->Now() + QuicTime::Delta::FromSeconds(10);
193 simulator_.RunUntil(
194 [this, end_time]() { return simulator_.GetClock()->Now() >= end_time; });
195
196 for (QuicEndpoint* endpoint :
197 {endpoint_a.get(), endpoint_b.get(), endpoint_c.get()}) {
198 EXPECT_EQ(2u * 1024u * 1024u, endpoint->bytes_transferred());
199 EXPECT_GE(endpoint->connection()->GetStats().packets_lost, 0u);
200 }
201 for (QuicEndpoint* endpoint :
202 {endpoint_d_a.get(), endpoint_d_b.get(), endpoint_d_c.get()}) {
203 EXPECT_EQ(2u * 1024u * 1024u, endpoint->bytes_received());
204 EXPECT_FALSE(endpoint->wrong_data_received());
205 }
206}
207
208} // namespace simulator
209} // namespace quic