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