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