Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / quic / quic_data_stream_test.cc
blobbf3925ea7b6e77d277de52c8cc727520eae36cc3
1 // Copyright 2013 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.
5 #include "net/quic/quic_data_stream.h"
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_flow_controller_peer.h"
13 #include "net/quic/test_tools/quic_session_peer.h"
14 #include "net/quic/test_tools/quic_test_utils.h"
15 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
16 #include "net/test/gtest_util.h"
17 #include "testing/gmock/include/gmock/gmock.h"
19 using base::StringPiece;
20 using std::min;
21 using std::string;
22 using testing::Return;
23 using testing::StrictMock;
24 using testing::_;
26 namespace net {
27 namespace test {
28 namespace {
30 const bool kShouldProcessData = true;
32 class TestStream : public QuicDataStream {
33 public:
34 TestStream(QuicStreamId id,
35 QuicSpdySession* session,
36 bool should_process_data)
37 : QuicDataStream(id, session),
38 should_process_data_(should_process_data) {}
40 uint32 ProcessData(const char* data, uint32 data_len) override {
41 EXPECT_NE(0u, data_len);
42 DVLOG(1) << "ProcessData data_len: " << data_len;
43 data_ += string(data, data_len);
44 return should_process_data_ ? data_len : 0;
47 using ReliableQuicStream::WriteOrBufferData;
48 using ReliableQuicStream::CloseReadSide;
49 using ReliableQuicStream::CloseWriteSide;
51 const string& data() const { return data_; }
53 private:
54 bool should_process_data_;
55 string data_;
58 class QuicDataStreamTest : public ::testing::TestWithParam<QuicVersion> {
59 public:
60 QuicDataStreamTest() {
61 headers_[":host"] = "www.google.com";
62 headers_[":path"] = "/index.hml";
63 headers_[":scheme"] = "https";
64 headers_["cookie"] =
65 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
66 "__utmc=160408618; "
67 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
68 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
69 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
70 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
71 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
72 "1zFMi5vzcns38-8_Sns; "
73 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
74 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
75 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
76 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
77 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
78 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
79 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
80 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
81 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
82 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
83 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
84 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
85 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
86 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
87 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
90 void Initialize(bool stream_should_process_data) {
91 connection_ = new testing::StrictMock<MockConnection>(
92 Perspective::IS_SERVER, SupportedVersions(GetParam()));
93 session_.reset(new testing::StrictMock<MockQuicSpdySession>(connection_));
94 stream_.reset(new TestStream(kClientDataStreamId1, session_.get(),
95 stream_should_process_data));
96 stream2_.reset(new TestStream(kClientDataStreamId2, session_.get(),
97 stream_should_process_data));
98 write_blocked_list_ =
99 QuicSessionPeer::GetWriteBlockedStreams(session_.get());
102 protected:
103 MockConnection* connection_;
104 scoped_ptr<MockQuicSpdySession> session_;
105 scoped_ptr<TestStream> stream_;
106 scoped_ptr<TestStream> stream2_;
107 SpdyHeaderBlock headers_;
108 QuicWriteBlockedList* write_blocked_list_;
111 INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest,
112 ::testing::ValuesIn(QuicSupportedVersions()));
114 TEST_P(QuicDataStreamTest, ProcessHeaders) {
115 Initialize(kShouldProcessData);
117 string headers =
118 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
119 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority());
120 stream_->OnStreamHeaders(headers);
121 EXPECT_EQ("", stream_->data());
122 EXPECT_EQ(headers, stream_->decompressed_headers());
123 stream_->OnStreamHeadersComplete(false, headers.size());
124 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority());
125 EXPECT_EQ("", stream_->data());
126 EXPECT_EQ(headers, stream_->decompressed_headers());
127 EXPECT_FALSE(stream_->IsDoneReading());
130 TEST_P(QuicDataStreamTest, ProcessHeadersWithFin) {
131 Initialize(kShouldProcessData);
133 string headers =
134 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
135 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority());
136 stream_->OnStreamHeaders(headers);
137 EXPECT_EQ("", stream_->data());
138 EXPECT_EQ(headers, stream_->decompressed_headers());
139 stream_->OnStreamHeadersComplete(true, headers.size());
140 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority());
141 EXPECT_EQ("", stream_->data());
142 EXPECT_EQ(headers, stream_->decompressed_headers());
143 EXPECT_FALSE(stream_->IsDoneReading());
144 EXPECT_TRUE(stream_->HasFinalReceivedByteOffset());
147 TEST_P(QuicDataStreamTest, MarkHeadersConsumed) {
148 Initialize(kShouldProcessData);
150 string headers =
151 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
152 string body = "this is the body";
154 stream_->OnStreamHeaders(headers);
155 stream_->OnStreamHeadersComplete(false, headers.size());
156 EXPECT_EQ(headers, stream_->decompressed_headers());
158 headers.erase(0, 10);
159 stream_->MarkHeadersConsumed(10);
160 EXPECT_EQ(headers, stream_->decompressed_headers());
162 stream_->MarkHeadersConsumed(headers.length());
163 EXPECT_EQ("", stream_->decompressed_headers());
166 TEST_P(QuicDataStreamTest, ProcessHeadersAndBody) {
167 Initialize(kShouldProcessData);
169 string headers =
170 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
171 string body = "this is the body";
173 stream_->OnStreamHeaders(headers);
174 EXPECT_EQ("", stream_->data());
175 EXPECT_EQ(headers, stream_->decompressed_headers());
176 stream_->OnStreamHeadersComplete(false, headers.size());
177 EXPECT_EQ(headers, stream_->decompressed_headers());
178 stream_->MarkHeadersConsumed(headers.length());
179 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
180 stream_->OnStreamFrame(frame);
181 EXPECT_EQ("", stream_->decompressed_headers());
182 EXPECT_EQ(body, stream_->data());
185 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragments) {
186 string headers =
187 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
188 string body = "this is the body";
190 for (size_t fragment_size = 1; fragment_size < body.size();
191 ++fragment_size) {
192 Initialize(kShouldProcessData);
193 for (size_t offset = 0; offset < headers.size();
194 offset += fragment_size) {
195 size_t remaining_data = headers.size() - offset;
196 StringPiece fragment(headers.data() + offset,
197 min(fragment_size, remaining_data));
198 stream_->OnStreamHeaders(fragment);
200 stream_->OnStreamHeadersComplete(false, headers.size());
201 ASSERT_EQ(headers, stream_->decompressed_headers())
202 << "fragment_size: " << fragment_size;
203 stream_->MarkHeadersConsumed(headers.length());
204 for (size_t offset = 0; offset < body.size(); offset += fragment_size) {
205 size_t remaining_data = body.size() - offset;
206 StringPiece fragment(body.data() + offset,
207 min(fragment_size, remaining_data));
208 QuicStreamFrame frame(kClientDataStreamId1, false, offset,
209 StringPiece(fragment));
210 stream_->OnStreamFrame(frame);
212 ASSERT_EQ(body, stream_->data()) << "fragment_size: " << fragment_size;
216 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragmentsSplit) {
217 string headers =
218 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
219 string body = "this is the body";
221 for (size_t split_point = 1; split_point < body.size() - 1; ++split_point) {
222 Initialize(kShouldProcessData);
223 StringPiece headers1(headers.data(), split_point);
224 stream_->OnStreamHeaders(headers1);
226 StringPiece headers2(headers.data() + split_point,
227 headers.size() - split_point);
228 stream_->OnStreamHeaders(headers2);
229 stream_->OnStreamHeadersComplete(false, headers.size());
230 ASSERT_EQ(headers, stream_->decompressed_headers())
231 << "split_point: " << split_point;
232 stream_->MarkHeadersConsumed(headers.length());
234 StringPiece fragment1(body.data(), split_point);
235 QuicStreamFrame frame1(kClientDataStreamId1, false, 0,
236 StringPiece(fragment1));
237 stream_->OnStreamFrame(frame1);
239 StringPiece fragment2(body.data() + split_point,
240 body.size() - split_point);
241 QuicStreamFrame frame2(kClientDataStreamId1, false, split_point,
242 StringPiece(fragment2));
243 stream_->OnStreamFrame(frame2);
245 ASSERT_EQ(body, stream_->data()) << "split_point: " << split_point;
249 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyReadv) {
250 Initialize(!kShouldProcessData);
252 string headers =
253 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
254 string body = "this is the body";
256 stream_->OnStreamHeaders(headers);
257 stream_->OnStreamHeadersComplete(false, headers.size());
258 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
259 stream_->OnStreamFrame(frame);
260 stream_->MarkHeadersConsumed(headers.length());
262 char buffer[2048];
263 ASSERT_LT(body.length(), arraysize(buffer));
264 struct iovec vec;
265 vec.iov_base = buffer;
266 vec.iov_len = arraysize(buffer);
268 size_t bytes_read = stream_->Readv(&vec, 1);
269 EXPECT_EQ(body.length(), bytes_read);
270 EXPECT_EQ(body, string(buffer, bytes_read));
273 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyMarkConsumed) {
274 Initialize(!kShouldProcessData);
276 string headers =
277 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
278 string body = "this is the body";
280 stream_->OnStreamHeaders(headers);
281 stream_->OnStreamHeadersComplete(false, headers.size());
282 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
283 stream_->OnStreamFrame(frame);
284 stream_->MarkHeadersConsumed(headers.length());
286 struct iovec vec;
288 EXPECT_EQ(1, stream_->GetReadableRegions(&vec, 1));
289 EXPECT_EQ(body.length(), vec.iov_len);
290 EXPECT_EQ(body, string(static_cast<char*>(vec.iov_base), vec.iov_len));
292 stream_->MarkConsumed(body.length());
293 EXPECT_EQ(body.length(), stream_->flow_controller()->bytes_consumed());
296 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
297 Initialize(!kShouldProcessData);
299 string headers =
300 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
301 string body = "this is the body";
302 stream_->OnStreamHeaders(headers);
303 stream_->OnStreamHeadersComplete(false, headers.size());
304 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
305 stream_->OnStreamFrame(frame);
306 stream_->MarkHeadersConsumed(headers.length());
308 char buffer[1];
309 struct iovec vec;
310 vec.iov_base = buffer;
311 vec.iov_len = arraysize(buffer);
313 for (size_t i = 0; i < body.length(); ++i) {
314 size_t bytes_read = stream_->Readv(&vec, 1);
315 ASSERT_EQ(1u, bytes_read);
316 EXPECT_EQ(body.data()[i], buffer[0]);
320 TEST_P(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
321 Initialize(!kShouldProcessData);
323 string headers =
324 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
325 string body = "this is the body";
326 stream_->OnStreamHeaders(headers);
327 stream_->OnStreamHeadersComplete(false, headers.size());
328 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
329 stream_->OnStreamFrame(frame);
330 stream_->MarkHeadersConsumed(headers.length());
332 char buffer1[1];
333 char buffer2[1];
334 struct iovec vec[2];
335 vec[0].iov_base = buffer1;
336 vec[0].iov_len = arraysize(buffer1);
337 vec[1].iov_base = buffer2;
338 vec[1].iov_len = arraysize(buffer2);
340 for (size_t i = 0; i < body.length(); i += 2) {
341 size_t bytes_read = stream_->Readv(vec, 2);
342 ASSERT_EQ(2u, bytes_read) << i;
343 ASSERT_EQ(body.data()[i], buffer1[0]) << i;
344 ASSERT_EQ(body.data()[i + 1], buffer2[0]) << i;
348 TEST_P(QuicDataStreamTest, StreamFlowControlBlocked) {
349 // Tests that we send a BLOCKED frame to the peer when we attempt to write,
350 // but are flow control blocked.
351 Initialize(kShouldProcessData);
353 // Set a small flow control limit.
354 const uint64 kWindow = 36;
355 QuicFlowControllerPeer::SetSendWindowOffset(stream_->flow_controller(),
356 kWindow);
357 EXPECT_EQ(kWindow, QuicFlowControllerPeer::SendWindowOffset(
358 stream_->flow_controller()));
360 // Try to send more data than the flow control limit allows.
361 string headers =
362 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
363 string body;
364 const uint64 kOverflow = 15;
365 GenerateBody(&body, kWindow + kOverflow);
367 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1));
368 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _))
369 .WillOnce(Return(QuicConsumedData(kWindow, true)));
370 stream_->WriteOrBufferData(body, false, nullptr);
372 // Should have sent as much as possible, resulting in no send window left.
373 EXPECT_EQ(0u,
374 QuicFlowControllerPeer::SendWindowSize(stream_->flow_controller()));
376 // And we should have queued the overflowed data.
377 EXPECT_EQ(kOverflow,
378 ReliableQuicStreamPeer::SizeOfQueuedData(stream_.get()));
381 TEST_P(QuicDataStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
382 // The flow control receive window decreases whenever we add new bytes to the
383 // sequencer, whether they are consumed immediately or buffered. However we
384 // only send WINDOW_UPDATE frames based on increasing number of bytes
385 // consumed.
387 // Don't process data - it will be buffered instead.
388 Initialize(!kShouldProcessData);
390 // Expect no WINDOW_UPDATE frames to be sent.
391 EXPECT_CALL(*connection_, SendWindowUpdate(_, _)).Times(0);
393 // Set a small flow control receive window.
394 const uint64 kWindow = 36;
395 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
396 kWindow);
397 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
398 kWindow);
399 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset(
400 stream_->flow_controller()));
402 // Stream receives enough data to fill a fraction of the receive window.
403 string headers =
404 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
405 string body;
406 GenerateBody(&body, kWindow / 3);
407 stream_->OnStreamHeaders(headers);
408 stream_->OnStreamHeadersComplete(false, headers.size());
410 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
411 stream_->OnStreamFrame(frame1);
412 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize(
413 stream_->flow_controller()));
415 // Now receive another frame which results in the receive window being over
416 // half full. This should all be buffered, decreasing the receive window but
417 // not sending WINDOW_UPDATE.
418 QuicStreamFrame frame2(kClientDataStreamId1, false, kWindow / 3,
419 StringPiece(body));
420 stream_->OnStreamFrame(frame2);
421 EXPECT_EQ(
422 kWindow - (2 * kWindow / 3),
423 QuicFlowControllerPeer::ReceiveWindowSize(stream_->flow_controller()));
426 TEST_P(QuicDataStreamTest, StreamFlowControlWindowUpdate) {
427 // Tests that on receipt of data, the stream updates its receive window offset
428 // appropriately, and sends WINDOW_UPDATE frames when its receive window drops
429 // too low.
430 Initialize(kShouldProcessData);
432 // Set a small flow control limit.
433 const uint64 kWindow = 36;
434 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
435 kWindow);
436 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
437 kWindow);
438 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset(
439 stream_->flow_controller()));
441 // Stream receives enough data to fill a fraction of the receive window.
442 string headers =
443 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
444 string body;
445 GenerateBody(&body, kWindow / 3);
446 stream_->OnStreamHeaders(headers);
447 stream_->OnStreamHeadersComplete(false, headers.size());
448 stream_->MarkHeadersConsumed(headers.length());
450 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
451 stream_->OnStreamFrame(frame1);
452 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize(
453 stream_->flow_controller()));
455 // Now receive another frame which results in the receive window being over
456 // half full. This will trigger the stream to increase its receive window
457 // offset and send a WINDOW_UPDATE. The result will be again an available
458 // window of kWindow bytes.
459 QuicStreamFrame frame2(kClientDataStreamId1, false, kWindow / 3,
460 StringPiece(body));
461 EXPECT_CALL(*connection_,
462 SendWindowUpdate(kClientDataStreamId1,
463 QuicFlowControllerPeer::ReceiveWindowOffset(
464 stream_->flow_controller()) +
465 2 * kWindow / 3));
466 stream_->OnStreamFrame(frame2);
467 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowSize(
468 stream_->flow_controller()));
471 TEST_P(QuicDataStreamTest, ConnectionFlowControlWindowUpdate) {
472 // Tests that on receipt of data, the connection updates its receive window
473 // offset appropriately, and sends WINDOW_UPDATE frames when its receive
474 // window drops too low.
475 Initialize(kShouldProcessData);
477 // Set a small flow control limit for streams and connection.
478 const uint64 kWindow = 36;
479 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
480 kWindow);
481 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(),
482 kWindow);
483 QuicFlowControllerPeer::SetReceiveWindowOffset(stream2_->flow_controller(),
484 kWindow);
485 QuicFlowControllerPeer::SetMaxReceiveWindow(stream2_->flow_controller(),
486 kWindow);
487 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
488 kWindow);
489 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(),
490 kWindow);
492 // Supply headers to both streams so that they are happy to receive data.
493 string headers =
494 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
495 stream_->OnStreamHeaders(headers);
496 stream_->OnStreamHeadersComplete(false, headers.size());
497 stream_->MarkHeadersConsumed(headers.length());
498 stream2_->OnStreamHeaders(headers);
499 stream2_->OnStreamHeadersComplete(false, headers.size());
500 stream2_->MarkHeadersConsumed(headers.length());
502 // Each stream gets a quarter window of data. This should not trigger a
503 // WINDOW_UPDATE for either stream, nor for the connection.
504 string body;
505 GenerateBody(&body, kWindow / 4);
506 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, StringPiece(body));
507 stream_->OnStreamFrame(frame1);
508 QuicStreamFrame frame2(kClientDataStreamId2, false, 0, StringPiece(body));
509 stream2_->OnStreamFrame(frame2);
511 // Now receive a further single byte on one stream - again this does not
512 // trigger a stream WINDOW_UPDATE, but now the connection flow control window
513 // is over half full and thus a connection WINDOW_UPDATE is sent.
514 EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId1, _)).Times(0);
515 EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId2, _)).Times(0);
516 EXPECT_CALL(*connection_,
517 SendWindowUpdate(0, QuicFlowControllerPeer::ReceiveWindowOffset(
518 session_->flow_controller()) +
519 1 + kWindow / 2));
520 QuicStreamFrame frame3(kClientDataStreamId1, false, (kWindow / 4),
521 StringPiece("a"));
522 stream_->OnStreamFrame(frame3);
525 TEST_P(QuicDataStreamTest, StreamFlowControlViolation) {
526 // Tests that on if the peer sends too much data (i.e. violates the flow
527 // control protocol), then we terminate the connection.
529 // Stream should not process data, so that data gets buffered in the
530 // sequencer, triggering flow control limits.
531 Initialize(!kShouldProcessData);
533 // Set a small flow control limit.
534 const uint64 kWindow = 50;
535 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
536 kWindow);
538 string headers =
539 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
540 stream_->OnStreamHeaders(headers);
541 stream_->OnStreamHeadersComplete(false, headers.size());
543 // Receive data to overflow the window, violating flow control.
544 string body;
545 GenerateBody(&body, kWindow + 1);
546 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
547 EXPECT_CALL(*connection_,
548 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA));
549 stream_->OnStreamFrame(frame);
552 TEST_P(QuicDataStreamTest, ConnectionFlowControlViolation) {
553 // Tests that on if the peer sends too much data (i.e. violates the flow
554 // control protocol), at the connection level (rather than the stream level)
555 // then we terminate the connection.
557 // Stream should not process data, so that data gets buffered in the
558 // sequencer, triggering flow control limits.
559 Initialize(!kShouldProcessData);
561 // Set a small flow control window on streams, and connection.
562 const uint64 kStreamWindow = 50;
563 const uint64 kConnectionWindow = 10;
564 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(),
565 kStreamWindow);
566 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(),
567 kConnectionWindow);
569 string headers =
570 SpdyUtils::SerializeUncompressedHeaders(headers_, GetParam());
571 stream_->OnStreamHeaders(headers);
572 stream_->OnStreamHeadersComplete(false, headers.size());
574 // Send enough data to overflow the connection level flow control window.
575 string body;
576 GenerateBody(&body, kConnectionWindow + 1);
577 EXPECT_LT(body.size(), kStreamWindow);
578 QuicStreamFrame frame(kClientDataStreamId1, false, 0, StringPiece(body));
580 EXPECT_CALL(*connection_,
581 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA));
582 stream_->OnStreamFrame(frame);
585 TEST_P(QuicDataStreamTest, StreamFlowControlFinNotBlocked) {
586 // An attempt to write a FIN with no data should not be flow control blocked,
587 // even if the send window is 0.
589 Initialize(kShouldProcessData);
591 // Set a flow control limit of zero.
592 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), 0);
593 EXPECT_EQ(0u, QuicFlowControllerPeer::ReceiveWindowOffset(
594 stream_->flow_controller()));
596 // Send a frame with a FIN but no data. This should not be blocked.
597 string body = "";
598 bool fin = true;
600 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0);
601 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _))
602 .WillOnce(Return(QuicConsumedData(0, fin)));
604 stream_->WriteOrBufferData(body, fin, nullptr);
607 } // namespace
608 } // namespace test
609 } // namespace net