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