OLD | NEW |
| (Empty) |
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/quic/reliable_quic_stream.h" | |
6 | |
7 #include "net/quic/quic_ack_notifier.h" | |
8 #include "net/quic/quic_connection.h" | |
9 #include "net/quic/quic_utils.h" | |
10 #include "net/quic/quic_write_blocked_list.h" | |
11 #include "net/quic/spdy_utils.h" | |
12 #include "net/quic/test_tools/quic_config_peer.h" | |
13 #include "net/quic/test_tools/quic_connection_peer.h" | |
14 #include "net/quic/test_tools/quic_flow_controller_peer.h" | |
15 #include "net/quic/test_tools/quic_session_peer.h" | |
16 #include "net/quic/test_tools/quic_test_utils.h" | |
17 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | |
18 #include "net/test/gtest_util.h" | |
19 #include "testing/gmock/include/gmock/gmock.h" | |
20 #include "testing/gmock_mutant.h" | |
21 | |
22 using base::StringPiece; | |
23 using std::min; | |
24 using std::string; | |
25 using testing::CreateFunctor; | |
26 using testing::InSequence; | |
27 using testing::Invoke; | |
28 using testing::Return; | |
29 using testing::SaveArg; | |
30 using testing::StrictMock; | |
31 using testing::WithArgs; | |
32 using testing::_; | |
33 | |
34 namespace net { | |
35 namespace test { | |
36 namespace { | |
37 | |
38 const char kData1[] = "FooAndBar"; | |
39 const char kData2[] = "EepAndBaz"; | |
40 const size_t kDataLen = 9; | |
41 const bool kIsServer = true; | |
42 const bool kShouldProcessData = true; | |
43 | |
44 class TestStream : public ReliableQuicStream { | |
45 public: | |
46 TestStream(QuicStreamId id, | |
47 QuicSession* session, | |
48 bool should_process_data) | |
49 : ReliableQuicStream(id, session), | |
50 should_process_data_(should_process_data) {} | |
51 | |
52 uint32 ProcessRawData(const char* data, uint32 data_len) override { | |
53 EXPECT_NE(0u, data_len); | |
54 DVLOG(1) << "ProcessData data_len: " << data_len; | |
55 data_ += string(data, data_len); | |
56 return should_process_data_ ? data_len : 0; | |
57 } | |
58 | |
59 QuicPriority EffectivePriority() const override { | |
60 return QuicUtils::HighestPriority(); | |
61 } | |
62 | |
63 using ReliableQuicStream::WriteOrBufferData; | |
64 using ReliableQuicStream::CloseReadSide; | |
65 using ReliableQuicStream::CloseWriteSide; | |
66 using ReliableQuicStream::OnClose; | |
67 | |
68 private: | |
69 bool should_process_data_; | |
70 string data_; | |
71 }; | |
72 | |
73 class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> { | |
74 public: | |
75 ReliableQuicStreamTest() | |
76 : initial_flow_control_window_bytes_(kMaxPacketSize), | |
77 zero_(QuicTime::Delta::Zero()), | |
78 supported_versions_(QuicSupportedVersions()) { | |
79 headers_[":host"] = "www.google.com"; | |
80 headers_[":path"] = "/index.hml"; | |
81 headers_[":scheme"] = "https"; | |
82 headers_["cookie"] = | |
83 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " | |
84 "__utmc=160408618; " | |
85 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX" | |
86 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX" | |
87 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT" | |
88 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0" | |
89 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh" | |
90 "1zFMi5vzcns38-8_Sns; " | |
91 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-" | |
92 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339" | |
93 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c" | |
94 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%" | |
95 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4" | |
96 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1" | |
97 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP" | |
98 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6" | |
99 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b" | |
100 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6" | |
101 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG" | |
102 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk" | |
103 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn" | |
104 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" | |
105 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; | |
106 } | |
107 | |
108 void set_supported_versions(const QuicVersionVector& versions) { | |
109 supported_versions_ = versions; | |
110 } | |
111 | |
112 void Initialize(bool stream_should_process_data) { | |
113 connection_ = | |
114 new StrictMock<MockConnection>(kIsServer, supported_versions_); | |
115 session_.reset(new StrictMock<MockSession>(connection_)); | |
116 | |
117 // New streams rely on having the peer's flow control receive window | |
118 // negotiated in the config. | |
119 QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow( | |
120 session_->config(), initial_flow_control_window_bytes_); | |
121 | |
122 stream_.reset(new TestStream(kHeadersStreamId, session_.get(), | |
123 stream_should_process_data)); | |
124 write_blocked_list_ = | |
125 QuicSessionPeer::GetWriteBlockedStreams(session_.get()); | |
126 } | |
127 | |
128 bool fin_sent() { return ReliableQuicStreamPeer::FinSent(stream_.get()); } | |
129 bool rst_sent() { return ReliableQuicStreamPeer::RstSent(stream_.get()); } | |
130 | |
131 void set_initial_flow_control_window_bytes(uint32 val) { | |
132 initial_flow_control_window_bytes_ = val; | |
133 } | |
134 | |
135 bool HasWriteBlockedStreams() { | |
136 return write_blocked_list_->HasWriteBlockedCryptoOrHeadersStream() || | |
137 write_blocked_list_->HasWriteBlockedDataStreams(); | |
138 } | |
139 | |
140 protected: | |
141 MockConnection* connection_; | |
142 scoped_ptr<MockSession> session_; | |
143 scoped_ptr<TestStream> stream_; | |
144 SpdyHeaderBlock headers_; | |
145 QuicWriteBlockedList* write_blocked_list_; | |
146 uint32 initial_flow_control_window_bytes_; | |
147 QuicTime::Delta zero_; | |
148 QuicVersionVector supported_versions_; | |
149 }; | |
150 | |
151 TEST_F(ReliableQuicStreamTest, WriteAllData) { | |
152 Initialize(kShouldProcessData); | |
153 | |
154 size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( | |
155 PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, | |
156 PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP); | |
157 QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length( | |
158 length); | |
159 | |
160 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)).WillOnce( | |
161 Return(QuicConsumedData(kDataLen, true))); | |
162 stream_->WriteOrBufferData(kData1, false, nullptr); | |
163 EXPECT_FALSE(HasWriteBlockedStreams()); | |
164 } | |
165 | |
166 TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) { | |
167 Initialize(kShouldProcessData); | |
168 | |
169 // Write no data and no fin. If we consume nothing we should not be write | |
170 // blocked. | |
171 EXPECT_DFATAL(stream_->WriteOrBufferData(StringPiece(), false, nullptr), ""); | |
172 EXPECT_FALSE(HasWriteBlockedStreams()); | |
173 } | |
174 | |
175 TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { | |
176 Initialize(kShouldProcessData); | |
177 | |
178 // Write some data and no fin. If we consume some but not all of the data, | |
179 // we should be write blocked a not all the data was consumed. | |
180 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
181 .WillOnce(Return(QuicConsumedData(1, false))); | |
182 stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr); | |
183 ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); | |
184 } | |
185 | |
186 TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { | |
187 Initialize(kShouldProcessData); | |
188 | |
189 // Write some data and no fin. If we consume all the data but not the fin, | |
190 // we should be write blocked because the fin was not consumed. | |
191 // (This should never actually happen as the fin should be sent out with the | |
192 // last data) | |
193 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
194 .WillOnce(Return(QuicConsumedData(2, false))); | |
195 stream_->WriteOrBufferData(StringPiece(kData1, 2), true, nullptr); | |
196 ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); | |
197 } | |
198 | |
199 TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) { | |
200 Initialize(kShouldProcessData); | |
201 | |
202 // Write no data and a fin. If we consume nothing we should be write blocked, | |
203 // as the fin was not consumed. | |
204 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
205 .WillOnce(Return(QuicConsumedData(0, false))); | |
206 stream_->WriteOrBufferData(StringPiece(), true, nullptr); | |
207 ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); | |
208 } | |
209 | |
210 TEST_F(ReliableQuicStreamTest, WriteOrBufferData) { | |
211 Initialize(kShouldProcessData); | |
212 | |
213 EXPECT_FALSE(HasWriteBlockedStreams()); | |
214 size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( | |
215 PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, | |
216 PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP); | |
217 QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length( | |
218 length); | |
219 | |
220 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).WillOnce( | |
221 Return(QuicConsumedData(kDataLen - 1, false))); | |
222 stream_->WriteOrBufferData(kData1, false, nullptr); | |
223 EXPECT_TRUE(HasWriteBlockedStreams()); | |
224 | |
225 // Queue a bytes_consumed write. | |
226 stream_->WriteOrBufferData(kData2, false, nullptr); | |
227 | |
228 // Make sure we get the tail of the first write followed by the bytes_consumed | |
229 InSequence s; | |
230 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)). | |
231 WillOnce(Return(QuicConsumedData(1, false))); | |
232 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)). | |
233 WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); | |
234 stream_->OnCanWrite(); | |
235 | |
236 // And finally the end of the bytes_consumed. | |
237 EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)). | |
238 WillOnce(Return(QuicConsumedData(2, true))); | |
239 stream_->OnCanWrite(); | |
240 } | |
241 | |
242 TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectAlways) { | |
243 Initialize(kShouldProcessData); | |
244 | |
245 // Set FEC policy on stream. | |
246 ReliableQuicStreamPeer::SetFecPolicy(stream_.get(), FEC_PROTECT_ALWAYS); | |
247 | |
248 EXPECT_FALSE(HasWriteBlockedStreams()); | |
249 size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( | |
250 PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, | |
251 PACKET_6BYTE_SEQUENCE_NUMBER, 0u, IN_FEC_GROUP); | |
252 QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length( | |
253 length); | |
254 | |
255 // Write first data onto stream, which will cause one session write. | |
256 EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)).WillOnce( | |
257 Return(QuicConsumedData(kDataLen - 1, false))); | |
258 stream_->WriteOrBufferData(kData1, false, nullptr); | |
259 EXPECT_TRUE(HasWriteBlockedStreams()); | |
260 | |
261 // Queue a bytes_consumed write. | |
262 stream_->WriteOrBufferData(kData2, false, nullptr); | |
263 | |
264 // Make sure we get the tail of the first write followed by the bytes_consumed | |
265 InSequence s; | |
266 EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)). | |
267 WillOnce(Return(QuicConsumedData(1, false))); | |
268 EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)). | |
269 WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); | |
270 stream_->OnCanWrite(); | |
271 | |
272 // And finally the end of the bytes_consumed. | |
273 EXPECT_CALL(*session_, WritevData(_, _, _, _, MUST_FEC_PROTECT, _)). | |
274 WillOnce(Return(QuicConsumedData(2, true))); | |
275 stream_->OnCanWrite(); | |
276 } | |
277 | |
278 TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithFecProtectOptional) { | |
279 Initialize(kShouldProcessData); | |
280 | |
281 // Set FEC policy on stream. | |
282 ReliableQuicStreamPeer::SetFecPolicy(stream_.get(), FEC_PROTECT_OPTIONAL); | |
283 | |
284 EXPECT_FALSE(HasWriteBlockedStreams()); | |
285 size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( | |
286 PACKET_8BYTE_CONNECTION_ID, !kIncludeVersion, | |
287 PACKET_6BYTE_SEQUENCE_NUMBER, 0u, NOT_IN_FEC_GROUP); | |
288 QuicConnectionPeer::GetPacketCreator(connection_)->set_max_packet_length( | |
289 length); | |
290 | |
291 // Write first data onto stream, which will cause one session write. | |
292 EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)).WillOnce( | |
293 Return(QuicConsumedData(kDataLen - 1, false))); | |
294 stream_->WriteOrBufferData(kData1, false, nullptr); | |
295 EXPECT_TRUE(HasWriteBlockedStreams()); | |
296 | |
297 // Queue a bytes_consumed write. | |
298 stream_->WriteOrBufferData(kData2, false, nullptr); | |
299 | |
300 // Make sure we get the tail of the first write followed by the bytes_consumed | |
301 InSequence s; | |
302 EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)). | |
303 WillOnce(Return(QuicConsumedData(1, false))); | |
304 EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)). | |
305 WillOnce(Return(QuicConsumedData(kDataLen - 2, false))); | |
306 stream_->OnCanWrite(); | |
307 | |
308 // And finally the end of the bytes_consumed. | |
309 EXPECT_CALL(*session_, WritevData(_, _, _, _, MAY_FEC_PROTECT, _)). | |
310 WillOnce(Return(QuicConsumedData(2, true))); | |
311 stream_->OnCanWrite(); | |
312 } | |
313 | |
314 TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) { | |
315 Initialize(kShouldProcessData); | |
316 | |
317 stream_->CloseReadSide(); | |
318 stream_->CloseWriteSide(); | |
319 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | |
320 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); | |
321 stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false); | |
322 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | |
323 EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error()); | |
324 } | |
325 | |
326 TEST_F(ReliableQuicStreamTest, RstAlwaysSentIfNoFinSent) { | |
327 // For flow control accounting, a stream must send either a FIN or a RST frame | |
328 // before termination. | |
329 // Test that if no FIN has been sent, we send a RST. | |
330 | |
331 Initialize(kShouldProcessData); | |
332 EXPECT_FALSE(fin_sent()); | |
333 EXPECT_FALSE(rst_sent()); | |
334 | |
335 // Write some data, with no FIN. | |
336 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
337 .WillOnce(Return(QuicConsumedData(1, false))); | |
338 stream_->WriteOrBufferData(StringPiece(kData1, 1), false, nullptr); | |
339 EXPECT_FALSE(fin_sent()); | |
340 EXPECT_FALSE(rst_sent()); | |
341 | |
342 // Now close the stream, and expect that we send a RST. | |
343 EXPECT_CALL(*session_, SendRstStream(_, _, _)); | |
344 stream_->OnClose(); | |
345 EXPECT_FALSE(fin_sent()); | |
346 EXPECT_TRUE(rst_sent()); | |
347 } | |
348 | |
349 TEST_F(ReliableQuicStreamTest, RstNotSentIfFinSent) { | |
350 // For flow control accounting, a stream must send either a FIN or a RST frame | |
351 // before termination. | |
352 // Test that if a FIN has been sent, we don't also send a RST. | |
353 | |
354 Initialize(kShouldProcessData); | |
355 EXPECT_FALSE(fin_sent()); | |
356 EXPECT_FALSE(rst_sent()); | |
357 | |
358 // Write some data, with FIN. | |
359 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
360 .WillOnce(Return(QuicConsumedData(1, true))); | |
361 stream_->WriteOrBufferData(StringPiece(kData1, 1), true, nullptr); | |
362 EXPECT_TRUE(fin_sent()); | |
363 EXPECT_FALSE(rst_sent()); | |
364 | |
365 // Now close the stream, and expect that we do not send a RST. | |
366 stream_->OnClose(); | |
367 EXPECT_TRUE(fin_sent()); | |
368 EXPECT_FALSE(rst_sent()); | |
369 } | |
370 | |
371 TEST_F(ReliableQuicStreamTest, OnlySendOneRst) { | |
372 // For flow control accounting, a stream must send either a FIN or a RST frame | |
373 // before termination. | |
374 // Test that if a stream sends a RST, it doesn't send an additional RST during | |
375 // OnClose() (this shouldn't be harmful, but we shouldn't do it anyway...) | |
376 | |
377 Initialize(kShouldProcessData); | |
378 EXPECT_FALSE(fin_sent()); | |
379 EXPECT_FALSE(rst_sent()); | |
380 | |
381 // Reset the stream. | |
382 const int expected_resets = 1; | |
383 EXPECT_CALL(*session_, SendRstStream(_, _, _)).Times(expected_resets); | |
384 stream_->Reset(QUIC_STREAM_CANCELLED); | |
385 EXPECT_FALSE(fin_sent()); | |
386 EXPECT_TRUE(rst_sent()); | |
387 | |
388 // Now close the stream (any further resets being sent would break the | |
389 // expectation above). | |
390 stream_->OnClose(); | |
391 EXPECT_FALSE(fin_sent()); | |
392 EXPECT_TRUE(rst_sent()); | |
393 } | |
394 | |
395 TEST_F(ReliableQuicStreamTest, StreamFlowControlMultipleWindowUpdates) { | |
396 set_initial_flow_control_window_bytes(1000); | |
397 | |
398 Initialize(kShouldProcessData); | |
399 | |
400 // If we receive multiple WINDOW_UPDATES (potentially out of order), then we | |
401 // want to make sure we latch the largest offset we see. | |
402 | |
403 // Initially should be default. | |
404 EXPECT_EQ( | |
405 initial_flow_control_window_bytes_, | |
406 QuicFlowControllerPeer::SendWindowOffset(stream_->flow_controller())); | |
407 | |
408 // Check a single WINDOW_UPDATE results in correct offset. | |
409 QuicWindowUpdateFrame window_update_1(stream_->id(), 1234); | |
410 stream_->OnWindowUpdateFrame(window_update_1); | |
411 EXPECT_EQ( | |
412 window_update_1.byte_offset, | |
413 QuicFlowControllerPeer::SendWindowOffset(stream_->flow_controller())); | |
414 | |
415 // Now send a few more WINDOW_UPDATES and make sure that only the largest is | |
416 // remembered. | |
417 QuicWindowUpdateFrame window_update_2(stream_->id(), 1); | |
418 QuicWindowUpdateFrame window_update_3(stream_->id(), 9999); | |
419 QuicWindowUpdateFrame window_update_4(stream_->id(), 5678); | |
420 stream_->OnWindowUpdateFrame(window_update_2); | |
421 stream_->OnWindowUpdateFrame(window_update_3); | |
422 stream_->OnWindowUpdateFrame(window_update_4); | |
423 EXPECT_EQ( | |
424 window_update_3.byte_offset, | |
425 QuicFlowControllerPeer::SendWindowOffset(stream_->flow_controller())); | |
426 } | |
427 | |
428 void SaveProxyAckNotifierDelegate( | |
429 scoped_refptr<QuicAckNotifier::DelegateInterface>* delegate_out, | |
430 QuicAckNotifier::DelegateInterface* delegate) { | |
431 *delegate_out = delegate; | |
432 } | |
433 | |
434 TEST_F(ReliableQuicStreamTest, WriteOrBufferDataWithQuicAckNotifier) { | |
435 Initialize(kShouldProcessData); | |
436 | |
437 scoped_refptr<MockAckNotifierDelegate> delegate( | |
438 new StrictMock<MockAckNotifierDelegate>); | |
439 | |
440 const int kDataSize = 16 * 1024; | |
441 const string kData(kDataSize, 'a'); | |
442 | |
443 const int kFirstWriteSize = 100; | |
444 const int kSecondWriteSize = 50; | |
445 const int kLastWriteSize = kDataSize - kFirstWriteSize - kSecondWriteSize; | |
446 | |
447 // Set a large flow control send window so this doesn't interfere with test. | |
448 stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); | |
449 session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); | |
450 | |
451 scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; | |
452 | |
453 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
454 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
455 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
456 Return(QuicConsumedData(kFirstWriteSize, false)))); | |
457 stream_->WriteOrBufferData(kData, false, delegate.get()); | |
458 EXPECT_TRUE(HasWriteBlockedStreams()); | |
459 | |
460 EXPECT_CALL(*session_, | |
461 WritevData(kHeadersStreamId, _, _, _, _, proxy_delegate.get())) | |
462 .WillOnce(Return(QuicConsumedData(kSecondWriteSize, false))); | |
463 stream_->OnCanWrite(); | |
464 | |
465 // No ack expected for an empty write. | |
466 EXPECT_CALL(*session_, | |
467 WritevData(kHeadersStreamId, _, _, _, _, proxy_delegate.get())) | |
468 .WillOnce(Return(QuicConsumedData(0, false))); | |
469 stream_->OnCanWrite(); | |
470 | |
471 EXPECT_CALL(*session_, | |
472 WritevData(kHeadersStreamId, _, _, _, _, proxy_delegate.get())) | |
473 .WillOnce(Return(QuicConsumedData(kLastWriteSize, false))); | |
474 stream_->OnCanWrite(); | |
475 | |
476 // There were two writes, so OnAckNotification is not propagated | |
477 // until the third Ack arrives. | |
478 proxy_delegate->OnAckNotification(3, 4, zero_); | |
479 proxy_delegate->OnAckNotification(30, 40, zero_); | |
480 | |
481 // The arguments to delegate->OnAckNotification are the sum of the | |
482 // arguments to proxy_delegate OnAckNotification calls. | |
483 EXPECT_CALL(*delegate.get(), OnAckNotification(333, 444, zero_)); | |
484 proxy_delegate->OnAckNotification(300, 400, zero_); | |
485 } | |
486 | |
487 // Verify delegate behavior when packets are acked before the | |
488 // WritevData call that sends out the last byte. | |
489 TEST_F(ReliableQuicStreamTest, WriteOrBufferDataAckNotificationBeforeFlush) { | |
490 Initialize(kShouldProcessData); | |
491 | |
492 scoped_refptr<MockAckNotifierDelegate> delegate( | |
493 new StrictMock<MockAckNotifierDelegate>); | |
494 | |
495 const int kDataSize = 16 * 1024; | |
496 const string kData(kDataSize, 'a'); | |
497 | |
498 const int kInitialWriteSize = 100; | |
499 | |
500 // Set a large flow control send window so this doesn't interfere with test. | |
501 stream_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); | |
502 session_->flow_controller()->UpdateSendWindowOffset(kDataSize + 1); | |
503 | |
504 scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; | |
505 | |
506 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
507 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
508 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
509 Return(QuicConsumedData(kInitialWriteSize, false)))); | |
510 stream_->WriteOrBufferData(kData, false, delegate.get()); | |
511 EXPECT_TRUE(HasWriteBlockedStreams()); | |
512 | |
513 // Handle the ack of the first write. | |
514 proxy_delegate->OnAckNotification(3, 4, zero_); | |
515 proxy_delegate = nullptr; | |
516 | |
517 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)).WillOnce( | |
518 DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
519 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
520 Return(QuicConsumedData(kDataSize - kInitialWriteSize, false)))); | |
521 stream_->OnCanWrite(); | |
522 | |
523 // Handle the ack for the second write. | |
524 EXPECT_CALL(*delegate.get(), OnAckNotification(303, 404, zero_)); | |
525 proxy_delegate->OnAckNotification(300, 400, zero_); | |
526 } | |
527 | |
528 // Verify delegate behavior when WriteOrBufferData does not buffer. | |
529 TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferNoBuffer) { | |
530 Initialize(kShouldProcessData); | |
531 | |
532 scoped_refptr<MockAckNotifierDelegate> delegate( | |
533 new StrictMock<MockAckNotifierDelegate>); | |
534 | |
535 scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; | |
536 | |
537 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
538 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
539 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
540 Return(QuicConsumedData(kDataLen, true)))); | |
541 stream_->WriteOrBufferData(kData1, true, delegate.get()); | |
542 EXPECT_FALSE(HasWriteBlockedStreams()); | |
543 | |
544 // Handle the ack. | |
545 EXPECT_CALL(*delegate.get(), OnAckNotification(3, 4, zero_)); | |
546 proxy_delegate->OnAckNotification(3, 4, zero_); | |
547 } | |
548 | |
549 // Verify delegate behavior when WriteOrBufferData buffers all the data. | |
550 TEST_F(ReliableQuicStreamTest, BufferOnWriteAndBufferDataWithAckNotifer) { | |
551 Initialize(kShouldProcessData); | |
552 | |
553 scoped_refptr<MockAckNotifierDelegate> delegate( | |
554 new StrictMock<MockAckNotifierDelegate>); | |
555 | |
556 scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; | |
557 | |
558 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
559 .WillOnce(Return(QuicConsumedData(0, false))); | |
560 stream_->WriteOrBufferData(kData1, true, delegate.get()); | |
561 EXPECT_TRUE(HasWriteBlockedStreams()); | |
562 | |
563 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
564 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
565 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
566 Return(QuicConsumedData(kDataLen, true)))); | |
567 stream_->OnCanWrite(); | |
568 | |
569 // Handle the ack. | |
570 EXPECT_CALL(*delegate.get(), OnAckNotification(3, 4, zero_)); | |
571 proxy_delegate->OnAckNotification(3, 4, zero_); | |
572 } | |
573 | |
574 // Verify delegate behavior when WriteOrBufferData when the FIN is | |
575 // sent out in a different packet. | |
576 TEST_F(ReliableQuicStreamTest, WriteAndBufferDataWithAckNotiferOnlyFinRemains) { | |
577 Initialize(kShouldProcessData); | |
578 | |
579 scoped_refptr<MockAckNotifierDelegate> delegate( | |
580 new StrictMock<MockAckNotifierDelegate>); | |
581 | |
582 scoped_refptr<QuicAckNotifier::DelegateInterface> proxy_delegate; | |
583 | |
584 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
585 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
586 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
587 Return(QuicConsumedData(kDataLen, false)))); | |
588 stream_->WriteOrBufferData(kData1, true, delegate.get()); | |
589 EXPECT_TRUE(HasWriteBlockedStreams()); | |
590 | |
591 EXPECT_CALL(*session_, WritevData(kHeadersStreamId, _, _, _, _, _)) | |
592 .WillOnce(DoAll(WithArgs<5>(Invoke(CreateFunctor( | |
593 &SaveProxyAckNotifierDelegate, &proxy_delegate))), | |
594 Return(QuicConsumedData(0, true)))); | |
595 stream_->OnCanWrite(); | |
596 | |
597 // Handle the acks. | |
598 proxy_delegate->OnAckNotification(3, 4, zero_); | |
599 EXPECT_CALL(*delegate.get(), OnAckNotification(33, 44, zero_)); | |
600 proxy_delegate->OnAckNotification(30, 40, zero_); | |
601 } | |
602 | |
603 // Verify that when we receive a packet which violates flow control (i.e. sends | |
604 // too much data on the stream) that the stream sequencer never sees this frame, | |
605 // as we check for violation and close the connection early. | |
606 TEST_F(ReliableQuicStreamTest, | |
607 StreamSequencerNeverSeesPacketsViolatingFlowControl) { | |
608 Initialize(kShouldProcessData); | |
609 | |
610 // Receive a stream frame that violates flow control: the byte offset is | |
611 // higher than the receive window offset. | |
612 QuicStreamFrame frame(stream_->id(), false, | |
613 kInitialSessionFlowControlWindowForTest + 1, | |
614 MakeIOVector(".")); | |
615 EXPECT_GT(frame.offset, QuicFlowControllerPeer::ReceiveWindowOffset( | |
616 stream_->flow_controller())); | |
617 | |
618 // Stream should not accept the frame, and the connection should be closed. | |
619 EXPECT_CALL(*connection_, | |
620 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)); | |
621 stream_->OnStreamFrame(frame); | |
622 } | |
623 | |
624 TEST_F(ReliableQuicStreamTest, FinalByteOffsetFromFin) { | |
625 Initialize(kShouldProcessData); | |
626 | |
627 EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); | |
628 | |
629 QuicStreamFrame stream_frame_no_fin(stream_->id(), false, 1234, | |
630 MakeIOVector(".")); | |
631 stream_->OnStreamFrame(stream_frame_no_fin); | |
632 EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); | |
633 | |
634 QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, | |
635 MakeIOVector(".")); | |
636 stream_->OnStreamFrame(stream_frame_with_fin); | |
637 EXPECT_TRUE(stream_->HasFinalReceivedByteOffset()); | |
638 } | |
639 | |
640 TEST_F(ReliableQuicStreamTest, FinalByteOffsetFromRst) { | |
641 Initialize(kShouldProcessData); | |
642 | |
643 EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); | |
644 QuicRstStreamFrame rst_frame(stream_->id(), QUIC_STREAM_CANCELLED, 1234); | |
645 stream_->OnStreamReset(rst_frame); | |
646 EXPECT_TRUE(stream_->HasFinalReceivedByteOffset()); | |
647 } | |
648 | |
649 } // namespace | |
650 } // namespace test | |
651 } // namespace net | |
OLD | NEW |