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