blob: f5721777feda8703dd98261240d65343f8a96d0a [file] [log] [blame]
wubf975eac2019-08-19 19:41:01 -07001// Copyright (c) 2019 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/qbone/qbone_packet_exchanger.h"
6
bnc463f2352019-10-10 04:49:34 -07007#include <utility>
8
wubf975eac2019-08-19 19:41:01 -07009#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
10#include "net/third_party/quiche/src/quic/qbone/mock_qbone_client.h"
11
12namespace quic {
13namespace {
14
15using ::testing::StrEq;
16using ::testing::StrictMock;
17
18const size_t kMaxPendingPackets = 2;
19
20class MockVisitor : public QbonePacketExchanger::Visitor {
21 public:
22 MOCK_METHOD1(OnReadError, void(const string&));
23 MOCK_METHOD1(OnWriteError, void(const string&));
24};
25
26class FakeQbonePacketExchanger : public QbonePacketExchanger {
27 public:
28 using QbonePacketExchanger::QbonePacketExchanger;
29
30 // Adds a packet to the end of list of packets to be returned by ReadPacket.
31 // When the list is empty, ReadPacket returns nullptr to signify error as
32 // defined by QbonePacketExchanger. If SetReadError is not called or called
33 // with empty error string, ReadPacket sets blocked to true.
34 void AddPacketToBeRead(std::unique_ptr<QuicData> packet) {
35 packets_to_be_read_.push_back(std::move(packet));
36 }
37
38 // Sets the error to be returned by ReadPacket when the list of packets is
39 // empty. If error is empty string, blocked is set by ReadPacket.
40 void SetReadError(const string& error) { read_error_ = error; }
41
42 // Force WritePacket to fail with the given status. WritePacket returns true
43 // when blocked == true and error is empty.
44 void ForceWriteFailure(bool blocked, const string& error) {
45 write_blocked_ = blocked;
46 write_error_ = error;
47 }
48
49 // Packets that have been successfully written by WritePacket.
50 const std::vector<string>& packets_written() const {
51 return packets_written_;
52 }
53
54 private:
55 // Implements QbonePacketExchanger::ReadPacket.
56 std::unique_ptr<QuicData> ReadPacket(bool* blocked, string* error) override {
57 *blocked = false;
58
59 if (packets_to_be_read_.empty()) {
60 *blocked = read_error_.empty();
61 *error = read_error_;
62 return nullptr;
63 }
64
65 std::unique_ptr<QuicData> packet = std::move(packets_to_be_read_.front());
66 packets_to_be_read_.pop_front();
67 return packet;
68 }
69
70 // Implements QbonePacketExchanger::WritePacket.
71 bool WritePacket(const char* packet,
72 size_t size,
73 bool* blocked,
74 string* error) override {
75 *blocked = false;
76
77 if (write_blocked_ || !write_error_.empty()) {
78 *blocked = write_blocked_;
79 *error = write_error_;
80 return false;
81 }
82
83 packets_written_.push_back(string(packet, size));
84 return true;
85 }
86
87 string read_error_;
88 std::list<std::unique_ptr<QuicData>> packets_to_be_read_;
89
90 string write_error_;
91 bool write_blocked_ = false;
92 std::vector<string> packets_written_;
93};
94
95TEST(QbonePacketExchangerTest,
96 ReadAndDeliverPacketDeliversPacketToQboneClient) {
97 StrictMock<MockVisitor> visitor;
98 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
99 StrictMock<MockQboneClient> client;
100
101 string packet = "data";
102 exchanger.AddPacketToBeRead(
vasilvv0fc587f2019-09-06 13:33:08 -0700103 std::make_unique<QuicData>(packet.data(), packet.length()));
wubf975eac2019-08-19 19:41:01 -0700104 EXPECT_CALL(client, ProcessPacketFromNetwork(StrEq("data")));
105
106 EXPECT_TRUE(exchanger.ReadAndDeliverPacket(&client));
107}
108
109TEST(QbonePacketExchangerTest,
110 ReadAndDeliverPacketNotifiesVisitorOnReadFailure) {
111 MockVisitor visitor;
112 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
113 MockQboneClient client;
114
115 // Force read error.
116 string io_error = "I/O error";
117 exchanger.SetReadError(io_error);
118 EXPECT_CALL(visitor, OnReadError(StrEq(io_error))).Times(1);
119
120 EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client));
121}
122
123TEST(QbonePacketExchangerTest,
124 ReadAndDeliverPacketDoesNotNotifyVisitorOnBlockedIO) {
125 MockVisitor visitor;
126 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
127 MockQboneClient client;
128
129 // No more packets to read.
130 EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client));
131}
132
133TEST(QbonePacketExchangerTest,
134 WritePacketToNetworkWritesDirectlyToNetworkWhenNotBlocked) {
135 MockVisitor visitor;
136 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
137 MockQboneClient client;
138
139 string packet = "data";
140 exchanger.WritePacketToNetwork(packet.data(), packet.length());
141
142 ASSERT_EQ(exchanger.packets_written().size(), 1);
143 EXPECT_THAT(exchanger.packets_written()[0], StrEq(packet));
144}
145
146TEST(QbonePacketExchangerTest,
147 WritePacketToNetworkQueuesPacketsAndProcessThemLater) {
148 MockVisitor visitor;
149 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
150 MockQboneClient client;
151
152 // Force write to be blocked so that packets are queued.
153 exchanger.ForceWriteFailure(true, "");
154 std::vector<string> packets = {"packet0", "packet1"};
155 for (int i = 0; i < packets.size(); i++) {
156 exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
157 }
158
159 // Nothing should have been written because of blockage.
160 ASSERT_TRUE(exchanger.packets_written().empty());
161
162 // Remove blockage and start proccessing queued packets.
163 exchanger.ForceWriteFailure(false, "");
164 exchanger.SetWritable();
165
166 // Queued packets are processed.
167 ASSERT_EQ(exchanger.packets_written().size(), 2);
168 for (int i = 0; i < packets.size(); i++) {
169 EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
170 }
171}
172
173TEST(QbonePacketExchangerTest,
174 SetWritableContinuesProcessingPacketIfPreviousCallBlocked) {
175 MockVisitor visitor;
176 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
177 MockQboneClient client;
178
179 // Force write to be blocked so that packets are queued.
180 exchanger.ForceWriteFailure(true, "");
181 std::vector<string> packets = {"packet0", "packet1"};
182 for (int i = 0; i < packets.size(); i++) {
183 exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
184 }
185
186 // Nothing should have been written because of blockage.
187 ASSERT_TRUE(exchanger.packets_written().empty());
188
189 // Start processing packets, but since writes are still blocked, nothing
190 // should have been written.
191 exchanger.SetWritable();
192 ASSERT_TRUE(exchanger.packets_written().empty());
193
194 // Remove blockage and start processing packets again.
195 exchanger.ForceWriteFailure(false, "");
196 exchanger.SetWritable();
197
198 ASSERT_EQ(exchanger.packets_written().size(), 2);
199 for (int i = 0; i < packets.size(); i++) {
200 EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
201 }
202}
203
204TEST(QbonePacketExchangerTest, WritePacketToNetworkDropsPacketIfQueueIfFull) {
205 std::vector<string> packets = {"packet0", "packet1", "packet2"};
206 size_t queue_size = packets.size() - 1;
207 MockVisitor visitor;
208 // exchanger has smaller queue than number of packets.
209 FakeQbonePacketExchanger exchanger(&visitor, queue_size);
210 MockQboneClient client;
211
212 exchanger.ForceWriteFailure(true, "");
213 for (int i = 0; i < packets.size(); i++) {
214 exchanger.WritePacketToNetwork(packets[i].data(), packets[i].length());
215 }
216
217 // Blocked writes cause packets to be queued or dropped.
218 ASSERT_TRUE(exchanger.packets_written().empty());
219
220 exchanger.ForceWriteFailure(false, "");
221 exchanger.SetWritable();
222
223 ASSERT_EQ(exchanger.packets_written().size(), queue_size);
224 for (int i = 0; i < queue_size; i++) {
225 EXPECT_THAT(exchanger.packets_written()[i], StrEq(packets[i]));
226 }
227}
228
229TEST(QbonePacketExchangerTest, WriteErrorsGetNotified) {
230 MockVisitor visitor;
231 FakeQbonePacketExchanger exchanger(&visitor, kMaxPendingPackets);
232 MockQboneClient client;
233 string packet = "data";
234
235 // Write error is delivered to visitor during WritePacketToNetwork.
236 string io_error = "I/O error";
237 exchanger.ForceWriteFailure(false, io_error);
238 EXPECT_CALL(visitor, OnWriteError(StrEq(io_error))).Times(1);
239 exchanger.WritePacketToNetwork(packet.data(), packet.length());
240 ASSERT_TRUE(exchanger.packets_written().empty());
241
242 // Write error is delivered to visitor during SetWritable.
243 exchanger.ForceWriteFailure(true, "");
244 exchanger.WritePacketToNetwork(packet.data(), packet.length());
245
246 string sys_error = "sys error";
247 exchanger.ForceWriteFailure(false, sys_error);
248 EXPECT_CALL(visitor, OnWriteError(StrEq(sys_error))).Times(1);
249 exchanger.SetWritable();
250 ASSERT_TRUE(exchanger.packets_written().empty());
251}
252
253} // namespace
254} // namespace quic