| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_data_stream.h" | 5 #include "net/quic/quic_data_stream.h" |
| 6 | 6 |
| 7 #include <string> |
| 8 |
| 7 #include "net/quic/quic_ack_notifier.h" | 9 #include "net/quic/quic_ack_notifier.h" |
| 8 #include "net/quic/quic_connection.h" | 10 #include "net/quic/quic_connection.h" |
| 9 #include "net/quic/quic_utils.h" | 11 #include "net/quic/quic_utils.h" |
| 10 #include "net/quic/quic_write_blocked_list.h" | 12 #include "net/quic/quic_write_blocked_list.h" |
| 11 #include "net/quic/spdy_utils.h" | 13 #include "net/quic/spdy_utils.h" |
| 12 #include "net/quic/test_tools/quic_flow_controller_peer.h" | 14 #include "net/quic/test_tools/quic_flow_controller_peer.h" |
| 13 #include "net/quic/test_tools/quic_session_peer.h" | 15 #include "net/quic/test_tools/quic_session_peer.h" |
| 14 #include "net/quic/test_tools/quic_test_utils.h" | 16 #include "net/quic/test_tools/quic_test_utils.h" |
| 15 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | 17 #include "net/quic/test_tools/reliable_quic_stream_peer.h" |
| 16 #include "net/test/gtest_util.h" | 18 #include "net/test/gtest_util.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 36 public: | 38 public: |
| 37 TestStream(QuicStreamId id, | 39 TestStream(QuicStreamId id, |
| 38 QuicSession* session, | 40 QuicSession* session, |
| 39 bool should_process_data) | 41 bool should_process_data) |
| 40 : QuicDataStream(id, session), | 42 : QuicDataStream(id, session), |
| 41 should_process_data_(should_process_data) {} | 43 should_process_data_(should_process_data) {} |
| 42 | 44 |
| 43 uint32 ProcessData(const char* data, uint32 data_len) override { | 45 uint32 ProcessData(const char* data, uint32 data_len) override { |
| 44 EXPECT_NE(0u, data_len); | 46 EXPECT_NE(0u, data_len); |
| 45 DVLOG(1) << "ProcessData data_len: " << data_len; | 47 DVLOG(1) << "ProcessData data_len: " << data_len; |
| 46 data_ += string(data, data_len); | 48 data_ += std::string(data, data_len); |
| 47 return should_process_data_ ? data_len : 0; | 49 return should_process_data_ ? data_len : 0; |
| 48 } | 50 } |
| 49 | 51 |
| 50 using ReliableQuicStream::WriteOrBufferData; | 52 using ReliableQuicStream::WriteOrBufferData; |
| 51 using ReliableQuicStream::CloseReadSide; | 53 using ReliableQuicStream::CloseReadSide; |
| 52 using ReliableQuicStream::CloseWriteSide; | 54 using ReliableQuicStream::CloseWriteSide; |
| 53 | 55 |
| 54 const string& data() const { return data_; } | 56 const std::string& data() const { return data_; } |
| 55 | 57 |
| 56 private: | 58 private: |
| 57 bool should_process_data_; | 59 bool should_process_data_; |
| 58 string data_; | 60 std::string data_; |
| 59 }; | 61 }; |
| 60 | 62 |
| 61 class QuicDataStreamTest : public ::testing::TestWithParam<QuicVersion> { | 63 class QuicDataStreamTest : public ::testing::TestWithParam<QuicVersion> { |
| 62 public: | 64 public: |
| 63 QuicDataStreamTest() { | 65 QuicDataStreamTest() { |
| 64 headers_[":host"] = "www.google.com"; | 66 headers_[":host"] = "www.google.com"; |
| 65 headers_[":path"] = "/index.hml"; | 67 headers_[":path"] = "/index.hml"; |
| 66 headers_[":scheme"] = "https"; | 68 headers_[":scheme"] = "https"; |
| 67 headers_["cookie"] = | 69 headers_["cookie"] = |
| 68 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " | 70 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 SpdyHeaderBlock headers_; | 112 SpdyHeaderBlock headers_; |
| 111 QuicWriteBlockedList* write_blocked_list_; | 113 QuicWriteBlockedList* write_blocked_list_; |
| 112 }; | 114 }; |
| 113 | 115 |
| 114 INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest, | 116 INSTANTIATE_TEST_CASE_P(Tests, QuicDataStreamTest, |
| 115 ::testing::ValuesIn(QuicSupportedVersions())); | 117 ::testing::ValuesIn(QuicSupportedVersions())); |
| 116 | 118 |
| 117 TEST_P(QuicDataStreamTest, ProcessHeaders) { | 119 TEST_P(QuicDataStreamTest, ProcessHeaders) { |
| 118 Initialize(kShouldProcessData); | 120 Initialize(kShouldProcessData); |
| 119 | 121 |
| 120 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 122 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 121 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); | 123 stream_->OnStreamHeadersPriority(QuicUtils::HighestPriority()); |
| 122 stream_->OnStreamHeaders(headers); | 124 stream_->OnStreamHeaders(headers); |
| 123 EXPECT_EQ(headers, stream_->data()); | 125 EXPECT_EQ(headers, stream_->data()); |
| 124 stream_->OnStreamHeadersComplete(false, headers.size()); | 126 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 125 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); | 127 EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority()); |
| 126 EXPECT_EQ(headers, stream_->data()); | 128 EXPECT_EQ(headers, stream_->data()); |
| 127 EXPECT_FALSE(stream_->IsDoneReading()); | 129 EXPECT_FALSE(stream_->IsDoneReading()); |
| 128 } | 130 } |
| 129 | 131 |
| 130 TEST_P(QuicDataStreamTest, ProcessHeadersAndBody) { | 132 TEST_P(QuicDataStreamTest, ProcessHeadersAndBody) { |
| 131 Initialize(kShouldProcessData); | 133 Initialize(kShouldProcessData); |
| 132 | 134 |
| 133 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 135 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 134 string body = "this is the body"; | 136 std::string body = "this is the body"; |
| 135 | 137 |
| 136 stream_->OnStreamHeaders(headers); | 138 stream_->OnStreamHeaders(headers); |
| 137 EXPECT_EQ(headers, stream_->data()); | 139 EXPECT_EQ(headers, stream_->data()); |
| 138 stream_->OnStreamHeadersComplete(false, headers.size()); | 140 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 139 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 141 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 140 stream_->OnStreamFrame(frame); | 142 stream_->OnStreamFrame(frame); |
| 141 | 143 |
| 142 EXPECT_EQ(headers + body, stream_->data()); | 144 EXPECT_EQ(headers + body, stream_->data()); |
| 143 } | 145 } |
| 144 | 146 |
| 145 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragments) { | 147 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragments) { |
| 146 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 148 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 147 string body = "this is the body"; | 149 std::string body = "this is the body"; |
| 148 | 150 |
| 149 for (size_t fragment_size = 1; fragment_size < body.size(); | 151 for (size_t fragment_size = 1; fragment_size < body.size(); |
| 150 ++fragment_size) { | 152 ++fragment_size) { |
| 151 Initialize(kShouldProcessData); | 153 Initialize(kShouldProcessData); |
| 152 for (size_t offset = 0; offset < headers.size(); | 154 for (size_t offset = 0; offset < headers.size(); |
| 153 offset += fragment_size) { | 155 offset += fragment_size) { |
| 154 size_t remaining_data = headers.size() - offset; | 156 size_t remaining_data = headers.size() - offset; |
| 155 StringPiece fragment(headers.data() + offset, | 157 StringPiece fragment(headers.data() + offset, |
| 156 min(fragment_size, remaining_data)); | 158 min(fragment_size, remaining_data)); |
| 157 stream_->OnStreamHeaders(fragment); | 159 stream_->OnStreamHeaders(fragment); |
| 158 } | 160 } |
| 159 stream_->OnStreamHeadersComplete(false, headers.size()); | 161 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 160 for (size_t offset = 0; offset < body.size(); offset += fragment_size) { | 162 for (size_t offset = 0; offset < body.size(); offset += fragment_size) { |
| 161 size_t remaining_data = body.size() - offset; | 163 size_t remaining_data = body.size() - offset; |
| 162 StringPiece fragment(body.data() + offset, | 164 StringPiece fragment(body.data() + offset, |
| 163 min(fragment_size, remaining_data)); | 165 min(fragment_size, remaining_data)); |
| 164 QuicStreamFrame frame(kClientDataStreamId1, false, offset, | 166 QuicStreamFrame frame(kClientDataStreamId1, false, offset, |
| 165 MakeIOVector(fragment)); | 167 MakeIOVector(fragment)); |
| 166 stream_->OnStreamFrame(frame); | 168 stream_->OnStreamFrame(frame); |
| 167 } | 169 } |
| 168 ASSERT_EQ(headers + body, | 170 ASSERT_EQ(headers + body, |
| 169 stream_->data()) << "fragment_size: " << fragment_size; | 171 stream_->data()) << "fragment_size: " << fragment_size; |
| 170 } | 172 } |
| 171 } | 173 } |
| 172 | 174 |
| 173 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragmentsSplit) { | 175 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyFragmentsSplit) { |
| 174 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 176 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 175 string body = "this is the body"; | 177 std::string body = "this is the body"; |
| 176 | 178 |
| 177 for (size_t split_point = 1; split_point < body.size() - 1; ++split_point) { | 179 for (size_t split_point = 1; split_point < body.size() - 1; ++split_point) { |
| 178 Initialize(kShouldProcessData); | 180 Initialize(kShouldProcessData); |
| 179 StringPiece headers1(headers.data(), split_point); | 181 StringPiece headers1(headers.data(), split_point); |
| 180 stream_->OnStreamHeaders(headers1); | 182 stream_->OnStreamHeaders(headers1); |
| 181 | 183 |
| 182 StringPiece headers2(headers.data() + split_point, | 184 StringPiece headers2(headers.data() + split_point, |
| 183 headers.size() - split_point); | 185 headers.size() - split_point); |
| 184 stream_->OnStreamHeaders(headers2); | 186 stream_->OnStreamHeaders(headers2); |
| 185 stream_->OnStreamHeadersComplete(false, headers.size()); | 187 stream_->OnStreamHeadersComplete(false, headers.size()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 196 stream_->OnStreamFrame(frame2); | 198 stream_->OnStreamFrame(frame2); |
| 197 | 199 |
| 198 ASSERT_EQ(headers + body, | 200 ASSERT_EQ(headers + body, |
| 199 stream_->data()) << "split_point: " << split_point; | 201 stream_->data()) << "split_point: " << split_point; |
| 200 } | 202 } |
| 201 } | 203 } |
| 202 | 204 |
| 203 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyReadv) { | 205 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyReadv) { |
| 204 Initialize(!kShouldProcessData); | 206 Initialize(!kShouldProcessData); |
| 205 | 207 |
| 206 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 208 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 207 string body = "this is the body"; | 209 std::string body = "this is the body"; |
| 208 | 210 |
| 209 stream_->OnStreamHeaders(headers); | 211 stream_->OnStreamHeaders(headers); |
| 210 EXPECT_EQ(headers, stream_->data()); | 212 EXPECT_EQ(headers, stream_->data()); |
| 211 stream_->OnStreamHeadersComplete(false, headers.size()); | 213 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 212 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 214 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 213 stream_->OnStreamFrame(frame); | 215 stream_->OnStreamFrame(frame); |
| 214 | 216 |
| 215 char buffer[2048]; | 217 char buffer[2048]; |
| 216 ASSERT_LT(headers.length() + body.length(), arraysize(buffer)); | 218 ASSERT_LT(headers.length() + body.length(), arraysize(buffer)); |
| 217 struct iovec vec; | 219 struct iovec vec; |
| 218 vec.iov_base = buffer; | 220 vec.iov_base = buffer; |
| 219 vec.iov_len = arraysize(buffer); | 221 vec.iov_len = arraysize(buffer); |
| 220 | 222 |
| 221 size_t bytes_read = stream_->Readv(&vec, 1); | 223 size_t bytes_read = stream_->Readv(&vec, 1); |
| 222 EXPECT_EQ(headers.length(), bytes_read); | 224 EXPECT_EQ(headers.length(), bytes_read); |
| 223 EXPECT_EQ(headers, string(buffer, bytes_read)); | 225 EXPECT_EQ(headers, std::string(buffer, bytes_read)); |
| 224 | 226 |
| 225 bytes_read = stream_->Readv(&vec, 1); | 227 bytes_read = stream_->Readv(&vec, 1); |
| 226 EXPECT_EQ(body.length(), bytes_read); | 228 EXPECT_EQ(body.length(), bytes_read); |
| 227 EXPECT_EQ(body, string(buffer, bytes_read)); | 229 EXPECT_EQ(body, std::string(buffer, bytes_read)); |
| 228 } | 230 } |
| 229 | 231 |
| 230 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) { | 232 TEST_P(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) { |
| 231 Initialize(!kShouldProcessData); | 233 Initialize(!kShouldProcessData); |
| 232 | 234 |
| 233 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 235 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 234 string body = "this is the body"; | 236 std::string body = "this is the body"; |
| 235 stream_->OnStreamHeaders(headers); | 237 stream_->OnStreamHeaders(headers); |
| 236 EXPECT_EQ(headers, stream_->data()); | 238 EXPECT_EQ(headers, stream_->data()); |
| 237 stream_->OnStreamHeadersComplete(false, headers.size()); | 239 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 238 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 240 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 239 stream_->OnStreamFrame(frame); | 241 stream_->OnStreamFrame(frame); |
| 240 | 242 |
| 241 char buffer[1]; | 243 char buffer[1]; |
| 242 struct iovec vec; | 244 struct iovec vec; |
| 243 vec.iov_base = buffer; | 245 vec.iov_base = buffer; |
| 244 vec.iov_len = arraysize(buffer); | 246 vec.iov_len = arraysize(buffer); |
| 245 | 247 |
| 246 string data = headers + body; | 248 std::string data = headers + body; |
| 247 for (size_t i = 0; i < data.length(); ++i) { | 249 for (size_t i = 0; i < data.length(); ++i) { |
| 248 size_t bytes_read = stream_->Readv(&vec, 1); | 250 size_t bytes_read = stream_->Readv(&vec, 1); |
| 249 ASSERT_EQ(1u, bytes_read); | 251 ASSERT_EQ(1u, bytes_read); |
| 250 EXPECT_EQ(data.data()[i], buffer[0]); | 252 EXPECT_EQ(data.data()[i], buffer[0]); |
| 251 } | 253 } |
| 252 } | 254 } |
| 253 | 255 |
| 254 TEST_P(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { | 256 TEST_P(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) { |
| 255 Initialize(!kShouldProcessData); | 257 Initialize(!kShouldProcessData); |
| 256 | 258 |
| 257 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 259 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 258 string body = "this is the body"; | 260 std::string body = "this is the body"; |
| 259 stream_->OnStreamHeaders(headers); | 261 stream_->OnStreamHeaders(headers); |
| 260 EXPECT_EQ(headers, stream_->data()); | 262 EXPECT_EQ(headers, stream_->data()); |
| 261 stream_->OnStreamHeadersComplete(false, headers.size()); | 263 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 262 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 264 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 263 stream_->OnStreamFrame(frame); | 265 stream_->OnStreamFrame(frame); |
| 264 | 266 |
| 265 char buffer1[1]; | 267 char buffer1[1]; |
| 266 char buffer2[1]; | 268 char buffer2[1]; |
| 267 struct iovec vec[2]; | 269 struct iovec vec[2]; |
| 268 vec[0].iov_base = buffer1; | 270 vec[0].iov_base = buffer1; |
| 269 vec[0].iov_len = arraysize(buffer1); | 271 vec[0].iov_len = arraysize(buffer1); |
| 270 vec[1].iov_base = buffer2; | 272 vec[1].iov_base = buffer2; |
| 271 vec[1].iov_len = arraysize(buffer2); | 273 vec[1].iov_len = arraysize(buffer2); |
| 272 string data = headers + body; | 274 std::string data = headers + body; |
| 273 for (size_t i = 0; i < data.length(); i += 2) { | 275 for (size_t i = 0; i < data.length(); i += 2) { |
| 274 size_t bytes_read = stream_->Readv(vec, 2); | 276 size_t bytes_read = stream_->Readv(vec, 2); |
| 275 ASSERT_EQ(2u, bytes_read) << i; | 277 ASSERT_EQ(2u, bytes_read) << i; |
| 276 ASSERT_EQ(data.data()[i], buffer1[0]) << i; | 278 ASSERT_EQ(data.data()[i], buffer1[0]) << i; |
| 277 ASSERT_EQ(data.data()[i + 1], buffer2[0]) << i; | 279 ASSERT_EQ(data.data()[i + 1], buffer2[0]) << i; |
| 278 } | 280 } |
| 279 } | 281 } |
| 280 | 282 |
| 281 TEST_P(QuicDataStreamTest, StreamFlowControlBlocked) { | 283 TEST_P(QuicDataStreamTest, StreamFlowControlBlocked) { |
| 282 // Tests that we send a BLOCKED frame to the peer when we attempt to write, | 284 // Tests that we send a BLOCKED frame to the peer when we attempt to write, |
| 283 // but are flow control blocked. | 285 // but are flow control blocked. |
| 284 Initialize(kShouldProcessData); | 286 Initialize(kShouldProcessData); |
| 285 | 287 |
| 286 // Set a small flow control limit. | 288 // Set a small flow control limit. |
| 287 const uint64 kWindow = 36; | 289 const uint64 kWindow = 36; |
| 288 QuicFlowControllerPeer::SetSendWindowOffset(stream_->flow_controller(), | 290 QuicFlowControllerPeer::SetSendWindowOffset(stream_->flow_controller(), |
| 289 kWindow); | 291 kWindow); |
| 290 EXPECT_EQ(kWindow, QuicFlowControllerPeer::SendWindowOffset( | 292 EXPECT_EQ(kWindow, QuicFlowControllerPeer::SendWindowOffset( |
| 291 stream_->flow_controller())); | 293 stream_->flow_controller())); |
| 292 | 294 |
| 293 // Try to send more data than the flow control limit allows. | 295 // Try to send more data than the flow control limit allows. |
| 294 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 296 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 295 string body; | 297 std::string body; |
| 296 const uint64 kOverflow = 15; | 298 const uint64 kOverflow = 15; |
| 297 GenerateBody(&body, kWindow + kOverflow); | 299 GenerateBody(&body, kWindow + kOverflow); |
| 298 | 300 |
| 299 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)); | 301 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)); |
| 300 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) | 302 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) |
| 301 .WillOnce(Return(QuicConsumedData(kWindow, true))); | 303 .WillOnce(Return(QuicConsumedData(kWindow, true))); |
| 302 stream_->WriteOrBufferData(body, false, nullptr); | 304 stream_->WriteOrBufferData(body, false, nullptr); |
| 303 | 305 |
| 304 // Should have sent as much as possible, resulting in no send window left. | 306 // Should have sent as much as possible, resulting in no send window left. |
| 305 EXPECT_EQ(0u, | 307 EXPECT_EQ(0u, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 325 // Set a small flow control receive window. | 327 // Set a small flow control receive window. |
| 326 const uint64 kWindow = 36; | 328 const uint64 kWindow = 36; |
| 327 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), | 329 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), |
| 328 kWindow); | 330 kWindow); |
| 329 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(), | 331 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(), |
| 330 kWindow); | 332 kWindow); |
| 331 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset( | 333 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset( |
| 332 stream_->flow_controller())); | 334 stream_->flow_controller())); |
| 333 | 335 |
| 334 // Stream receives enough data to fill a fraction of the receive window. | 336 // Stream receives enough data to fill a fraction of the receive window. |
| 335 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 337 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 336 string body; | 338 std::string body; |
| 337 GenerateBody(&body, kWindow / 3); | 339 GenerateBody(&body, kWindow / 3); |
| 338 stream_->OnStreamHeaders(headers); | 340 stream_->OnStreamHeaders(headers); |
| 339 EXPECT_EQ(headers, stream_->data()); | 341 EXPECT_EQ(headers, stream_->data()); |
| 340 stream_->OnStreamHeadersComplete(false, headers.size()); | 342 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 341 | 343 |
| 342 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 344 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 343 stream_->OnStreamFrame(frame1); | 345 stream_->OnStreamFrame(frame1); |
| 344 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( | 346 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( |
| 345 stream_->flow_controller())); | 347 stream_->flow_controller())); |
| 346 | 348 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 364 // Set a small flow control limit. | 366 // Set a small flow control limit. |
| 365 const uint64 kWindow = 36; | 367 const uint64 kWindow = 36; |
| 366 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), | 368 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), |
| 367 kWindow); | 369 kWindow); |
| 368 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(), | 370 QuicFlowControllerPeer::SetMaxReceiveWindow(stream_->flow_controller(), |
| 369 kWindow); | 371 kWindow); |
| 370 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset( | 372 EXPECT_EQ(kWindow, QuicFlowControllerPeer::ReceiveWindowOffset( |
| 371 stream_->flow_controller())); | 373 stream_->flow_controller())); |
| 372 | 374 |
| 373 // Stream receives enough data to fill a fraction of the receive window. | 375 // Stream receives enough data to fill a fraction of the receive window. |
| 374 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 376 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 375 string body; | 377 std::string body; |
| 376 GenerateBody(&body, kWindow / 3); | 378 GenerateBody(&body, kWindow / 3); |
| 377 stream_->OnStreamHeaders(headers); | 379 stream_->OnStreamHeaders(headers); |
| 378 EXPECT_EQ(headers, stream_->data()); | 380 EXPECT_EQ(headers, stream_->data()); |
| 379 stream_->OnStreamHeadersComplete(false, headers.size()); | 381 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 380 | 382 |
| 381 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 383 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 382 stream_->OnStreamFrame(frame1); | 384 stream_->OnStreamFrame(frame1); |
| 383 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( | 385 EXPECT_EQ(kWindow - (kWindow / 3), QuicFlowControllerPeer::ReceiveWindowSize( |
| 384 stream_->flow_controller())); | 386 stream_->flow_controller())); |
| 385 | 387 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 414 QuicFlowControllerPeer::SetReceiveWindowOffset(stream2_->flow_controller(), | 416 QuicFlowControllerPeer::SetReceiveWindowOffset(stream2_->flow_controller(), |
| 415 kWindow); | 417 kWindow); |
| 416 QuicFlowControllerPeer::SetMaxReceiveWindow(stream2_->flow_controller(), | 418 QuicFlowControllerPeer::SetMaxReceiveWindow(stream2_->flow_controller(), |
| 417 kWindow); | 419 kWindow); |
| 418 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), | 420 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), |
| 419 kWindow); | 421 kWindow); |
| 420 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(), | 422 QuicFlowControllerPeer::SetMaxReceiveWindow(session_->flow_controller(), |
| 421 kWindow); | 423 kWindow); |
| 422 | 424 |
| 423 // Supply headers to both streams so that they are happy to receive data. | 425 // Supply headers to both streams so that they are happy to receive data. |
| 424 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 426 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 425 stream_->OnStreamHeaders(headers); | 427 stream_->OnStreamHeaders(headers); |
| 426 stream_->OnStreamHeadersComplete(false, headers.size()); | 428 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 427 stream2_->OnStreamHeaders(headers); | 429 stream2_->OnStreamHeaders(headers); |
| 428 stream2_->OnStreamHeadersComplete(false, headers.size()); | 430 stream2_->OnStreamHeadersComplete(false, headers.size()); |
| 429 | 431 |
| 430 // Each stream gets a quarter window of data. This should not trigger a | 432 // Each stream gets a quarter window of data. This should not trigger a |
| 431 // WINDOW_UPDATE for either stream, nor for the connection. | 433 // WINDOW_UPDATE for either stream, nor for the connection. |
| 432 string body; | 434 std::string body; |
| 433 GenerateBody(&body, kWindow / 4); | 435 GenerateBody(&body, kWindow / 4); |
| 434 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 436 QuicStreamFrame frame1(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 435 stream_->OnStreamFrame(frame1); | 437 stream_->OnStreamFrame(frame1); |
| 436 QuicStreamFrame frame2(kClientDataStreamId2, false, 0, MakeIOVector(body)); | 438 QuicStreamFrame frame2(kClientDataStreamId2, false, 0, MakeIOVector(body)); |
| 437 stream2_->OnStreamFrame(frame2); | 439 stream2_->OnStreamFrame(frame2); |
| 438 | 440 |
| 439 // Now receive a further single byte on one stream - again this does not | 441 // Now receive a further single byte on one stream - again this does not |
| 440 // trigger a stream WINDOW_UPDATE, but now the connection flow control window | 442 // trigger a stream WINDOW_UPDATE, but now the connection flow control window |
| 441 // is over half full and thus a connection WINDOW_UPDATE is sent. | 443 // is over half full and thus a connection WINDOW_UPDATE is sent. |
| 442 EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId1, _)).Times(0); | 444 EXPECT_CALL(*connection_, SendWindowUpdate(kClientDataStreamId1, _)).Times(0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 456 | 458 |
| 457 // Stream should not process data, so that data gets buffered in the | 459 // Stream should not process data, so that data gets buffered in the |
| 458 // sequencer, triggering flow control limits. | 460 // sequencer, triggering flow control limits. |
| 459 Initialize(!kShouldProcessData); | 461 Initialize(!kShouldProcessData); |
| 460 | 462 |
| 461 // Set a small flow control limit. | 463 // Set a small flow control limit. |
| 462 const uint64 kWindow = 50; | 464 const uint64 kWindow = 50; |
| 463 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), | 465 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), |
| 464 kWindow); | 466 kWindow); |
| 465 | 467 |
| 466 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 468 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 467 stream_->OnStreamHeaders(headers); | 469 stream_->OnStreamHeaders(headers); |
| 468 EXPECT_EQ(headers, stream_->data()); | 470 EXPECT_EQ(headers, stream_->data()); |
| 469 stream_->OnStreamHeadersComplete(false, headers.size()); | 471 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 470 | 472 |
| 471 // Receive data to overflow the window, violating flow control. | 473 // Receive data to overflow the window, violating flow control. |
| 472 string body; | 474 std::string body; |
| 473 GenerateBody(&body, kWindow + 1); | 475 GenerateBody(&body, kWindow + 1); |
| 474 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 476 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 475 EXPECT_CALL(*connection_, | 477 EXPECT_CALL(*connection_, |
| 476 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)); | 478 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)); |
| 477 stream_->OnStreamFrame(frame); | 479 stream_->OnStreamFrame(frame); |
| 478 } | 480 } |
| 479 | 481 |
| 480 TEST_P(QuicDataStreamTest, ConnectionFlowControlViolation) { | 482 TEST_P(QuicDataStreamTest, ConnectionFlowControlViolation) { |
| 481 // Tests that on if the peer sends too much data (i.e. violates the flow | 483 // Tests that on if the peer sends too much data (i.e. violates the flow |
| 482 // control protocol), at the connection level (rather than the stream level) | 484 // control protocol), at the connection level (rather than the stream level) |
| 483 // then we terminate the connection. | 485 // then we terminate the connection. |
| 484 | 486 |
| 485 // Stream should not process data, so that data gets buffered in the | 487 // Stream should not process data, so that data gets buffered in the |
| 486 // sequencer, triggering flow control limits. | 488 // sequencer, triggering flow control limits. |
| 487 Initialize(!kShouldProcessData); | 489 Initialize(!kShouldProcessData); |
| 488 | 490 |
| 489 // Set a small flow control window on streams, and connection. | 491 // Set a small flow control window on streams, and connection. |
| 490 const uint64 kStreamWindow = 50; | 492 const uint64 kStreamWindow = 50; |
| 491 const uint64 kConnectionWindow = 10; | 493 const uint64 kConnectionWindow = 10; |
| 492 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), | 494 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), |
| 493 kStreamWindow); | 495 kStreamWindow); |
| 494 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), | 496 QuicFlowControllerPeer::SetReceiveWindowOffset(session_->flow_controller(), |
| 495 kConnectionWindow); | 497 kConnectionWindow); |
| 496 | 498 |
| 497 string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); | 499 std::string headers = SpdyUtils::SerializeUncompressedHeaders(headers_); |
| 498 stream_->OnStreamHeaders(headers); | 500 stream_->OnStreamHeaders(headers); |
| 499 EXPECT_EQ(headers, stream_->data()); | 501 EXPECT_EQ(headers, stream_->data()); |
| 500 stream_->OnStreamHeadersComplete(false, headers.size()); | 502 stream_->OnStreamHeadersComplete(false, headers.size()); |
| 501 | 503 |
| 502 // Send enough data to overflow the connection level flow control window. | 504 // Send enough data to overflow the connection level flow control window. |
| 503 string body; | 505 std::string body; |
| 504 GenerateBody(&body, kConnectionWindow + 1); | 506 GenerateBody(&body, kConnectionWindow + 1); |
| 505 EXPECT_LT(body.size(), kStreamWindow); | 507 EXPECT_LT(body.size(), kStreamWindow); |
| 506 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); | 508 QuicStreamFrame frame(kClientDataStreamId1, false, 0, MakeIOVector(body)); |
| 507 | 509 |
| 508 EXPECT_CALL(*connection_, | 510 EXPECT_CALL(*connection_, |
| 509 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)); | 511 SendConnectionClose(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA)); |
| 510 stream_->OnStreamFrame(frame); | 512 stream_->OnStreamFrame(frame); |
| 511 } | 513 } |
| 512 | 514 |
| 513 TEST_P(QuicDataStreamTest, StreamFlowControlFinNotBlocked) { | 515 TEST_P(QuicDataStreamTest, StreamFlowControlFinNotBlocked) { |
| 514 // An attempt to write a FIN with no data should not be flow control blocked, | 516 // An attempt to write a FIN with no data should not be flow control blocked, |
| 515 // even if the send window is 0. | 517 // even if the send window is 0. |
| 516 | 518 |
| 517 Initialize(kShouldProcessData); | 519 Initialize(kShouldProcessData); |
| 518 | 520 |
| 519 // Set a flow control limit of zero. | 521 // Set a flow control limit of zero. |
| 520 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), 0); | 522 QuicFlowControllerPeer::SetReceiveWindowOffset(stream_->flow_controller(), 0); |
| 521 EXPECT_EQ(0u, QuicFlowControllerPeer::ReceiveWindowOffset( | 523 EXPECT_EQ(0u, QuicFlowControllerPeer::ReceiveWindowOffset( |
| 522 stream_->flow_controller())); | 524 stream_->flow_controller())); |
| 523 | 525 |
| 524 // Send a frame with a FIN but no data. This should not be blocked. | 526 // Send a frame with a FIN but no data. This should not be blocked. |
| 525 string body = ""; | 527 std::string body = ""; |
| 526 bool fin = true; | 528 bool fin = true; |
| 527 | 529 |
| 528 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); | 530 EXPECT_CALL(*connection_, SendBlocked(kClientDataStreamId1)).Times(0); |
| 529 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) | 531 EXPECT_CALL(*session_, WritevData(kClientDataStreamId1, _, _, _, _, _)) |
| 530 .WillOnce(Return(QuicConsumedData(0, fin))); | 532 .WillOnce(Return(QuicConsumedData(0, fin))); |
| 531 | 533 |
| 532 stream_->WriteOrBufferData(body, fin, nullptr); | 534 stream_->WriteOrBufferData(body, fin, nullptr); |
| 533 } | 535 } |
| 534 | 536 |
| 535 } // namespace | 537 } // namespace |
| 536 } // namespace test | 538 } // namespace test |
| 537 } // namespace net | 539 } // namespace net |
| OLD | NEW |