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