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