| OLD | NEW |
| (Empty) |
| 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_headers_stream.h" | |
| 6 | |
| 7 #include "net/quic/quic_utils.h" | |
| 8 #include "net/quic/spdy_utils.h" | |
| 9 #include "net/quic/test_tools/quic_connection_peer.h" | |
| 10 #include "net/quic/test_tools/quic_session_peer.h" | |
| 11 #include "net/quic/test_tools/quic_test_utils.h" | |
| 12 #include "net/quic/test_tools/reliable_quic_stream_peer.h" | |
| 13 #include "net/spdy/spdy_protocol.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 | |
| 16 using base::StringPiece; | |
| 17 using std::ostream; | |
| 18 using std::string; | |
| 19 using std::vector; | |
| 20 using testing::Invoke; | |
| 21 using testing::StrictMock; | |
| 22 using testing::WithArgs; | |
| 23 using testing::_; | |
| 24 | |
| 25 namespace net { | |
| 26 namespace test { | |
| 27 namespace { | |
| 28 | |
| 29 class MockVisitor : public SpdyFramerVisitorInterface { | |
| 30 public: | |
| 31 MOCK_METHOD1(OnError, void(SpdyFramer* framer)); | |
| 32 MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId stream_id, | |
| 33 size_t length, | |
| 34 bool fin)); | |
| 35 MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId stream_id, | |
| 36 const char* data, | |
| 37 size_t len, | |
| 38 bool fin)); | |
| 39 MOCK_METHOD3(OnControlFrameHeaderData, bool(SpdyStreamId stream_id, | |
| 40 const char* header_data, | |
| 41 size_t len)); | |
| 42 MOCK_METHOD5(OnSynStream, void(SpdyStreamId stream_id, | |
| 43 SpdyStreamId associated_stream_id, | |
| 44 SpdyPriority priority, | |
| 45 bool fin, | |
| 46 bool unidirectional)); | |
| 47 MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin)); | |
| 48 MOCK_METHOD2(OnRstStream, void(SpdyStreamId stream_id, | |
| 49 SpdyRstStreamStatus status)); | |
| 50 MOCK_METHOD1(OnSettings, void(bool clear_persisted)); | |
| 51 MOCK_METHOD3(OnSetting, void(SpdySettingsIds id, uint8 flags, uint32 value)); | |
| 52 MOCK_METHOD0(OnSettingsAck, void()); | |
| 53 MOCK_METHOD0(OnSettingsEnd, void()); | |
| 54 MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack)); | |
| 55 MOCK_METHOD2(OnGoAway, void(SpdyStreamId last_accepted_stream_id, | |
| 56 SpdyGoAwayStatus status)); | |
| 57 MOCK_METHOD5(OnHeaders, void(SpdyStreamId stream_id, bool has_priority, | |
| 58 SpdyPriority priority, bool fin, bool end)); | |
| 59 MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId stream_id, | |
| 60 uint32 delta_window_size)); | |
| 61 MOCK_METHOD2(OnCredentialFrameData, bool(const char* credential_data, | |
| 62 size_t len)); | |
| 63 MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id)); | |
| 64 MOCK_METHOD3(OnPushPromise, void(SpdyStreamId stream_id, | |
| 65 SpdyStreamId promised_stream_id, | |
| 66 bool end)); | |
| 67 MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end)); | |
| 68 MOCK_METHOD6(OnAltSvc, void(SpdyStreamId stream_id, | |
| 69 uint32 max_age, | |
| 70 uint16 port, | |
| 71 StringPiece protocol_id, | |
| 72 StringPiece host, | |
| 73 StringPiece origin)); | |
| 74 MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type)); | |
| 75 }; | |
| 76 | |
| 77 // Run all tests with each version, and client or server | |
| 78 struct TestParams { | |
| 79 TestParams(QuicVersion version, bool is_server) | |
| 80 : version(version), is_server(is_server) {} | |
| 81 | |
| 82 friend ostream& operator<<(ostream& os, const TestParams& p) { | |
| 83 os << "{ version: " << QuicVersionToString(p.version); | |
| 84 os << ", is_server: " << p.is_server << " }"; | |
| 85 return os; | |
| 86 } | |
| 87 | |
| 88 QuicVersion version; | |
| 89 bool is_server; | |
| 90 }; | |
| 91 | |
| 92 // Constructs various test permutations. | |
| 93 vector<TestParams> GetTestParams() { | |
| 94 vector<TestParams> params; | |
| 95 QuicVersionVector all_supported_versions = QuicSupportedVersions(); | |
| 96 for (const QuicVersion version : all_supported_versions) { | |
| 97 params.push_back(TestParams(version, false)); | |
| 98 params.push_back(TestParams(version, true)); | |
| 99 } | |
| 100 return params; | |
| 101 } | |
| 102 | |
| 103 class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParams> { | |
| 104 public: | |
| 105 QuicHeadersStreamTest() | |
| 106 : connection_(new StrictMock<MockConnection>(is_server(), GetVersion())), | |
| 107 session_(connection_), | |
| 108 headers_stream_(QuicSessionPeer::GetHeadersStream(&session_)), | |
| 109 body_("hello world"), | |
| 110 framer_(version() > QUIC_VERSION_23 ? SPDY4 : SPDY3) { | |
| 111 headers_[":version"] = "HTTP/1.1"; | |
| 112 headers_[":status"] = "200 Ok"; | |
| 113 headers_["content-length"] = "11"; | |
| 114 framer_.set_visitor(&visitor_); | |
| 115 EXPECT_EQ(version(), session_.connection()->version()); | |
| 116 EXPECT_TRUE(headers_stream_ != nullptr); | |
| 117 VLOG(1) << GetParam(); | |
| 118 } | |
| 119 | |
| 120 QuicConsumedData SaveIov(const IOVector& data) { | |
| 121 const iovec* iov = data.iovec(); | |
| 122 int count = data.Capacity(); | |
| 123 for (int i = 0 ; i < count; ++i) { | |
| 124 saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len); | |
| 125 } | |
| 126 return QuicConsumedData(saved_data_.length(), false); | |
| 127 } | |
| 128 | |
| 129 bool SaveHeaderData(const char* data, int len) { | |
| 130 saved_header_data_.append(data, len); | |
| 131 return true; | |
| 132 } | |
| 133 | |
| 134 void SaveHeaderDataStringPiece(StringPiece data) { | |
| 135 saved_header_data_.append(data.data(), data.length()); | |
| 136 } | |
| 137 | |
| 138 void WriteHeadersAndExpectSynStream(QuicStreamId stream_id, | |
| 139 bool fin, | |
| 140 QuicPriority priority) { | |
| 141 WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM); | |
| 142 } | |
| 143 | |
| 144 void WriteHeadersAndExpectSynReply(QuicStreamId stream_id, | |
| 145 bool fin) { | |
| 146 WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY); | |
| 147 } | |
| 148 | |
| 149 void WriteHeadersAndCheckData(QuicStreamId stream_id, | |
| 150 bool fin, | |
| 151 QuicPriority priority, | |
| 152 SpdyFrameType type) { | |
| 153 // Write the headers and capture the outgoing data | |
| 154 EXPECT_CALL(session_, WritevData(kHeadersStreamId, _, _, false, _, nullptr)) | |
| 155 .WillOnce(WithArgs<1>(Invoke(this, &QuicHeadersStreamTest::SaveIov))); | |
| 156 headers_stream_->WriteHeaders(stream_id, headers_, fin, priority, nullptr); | |
| 157 | |
| 158 // Parse the outgoing data and check that it matches was was written. | |
| 159 if (type == SYN_STREAM) { | |
| 160 if (version() > QUIC_VERSION_23) { | |
| 161 EXPECT_CALL(visitor_, OnHeaders(stream_id, kHasPriority, priority, fin, | |
| 162 kFrameComplete)); | |
| 163 } else { | |
| 164 EXPECT_CALL(visitor_, | |
| 165 OnSynStream(stream_id, kNoAssociatedStream, | |
| 166 /*priority=*/0, fin, kNotUnidirectional)); | |
| 167 } | |
| 168 } else { | |
| 169 if (version() > QUIC_VERSION_23) { | |
| 170 EXPECT_CALL(visitor_, OnHeaders(stream_id, !kHasPriority, | |
| 171 /*priority=*/0, fin, kFrameComplete)); | |
| 172 } else { | |
| 173 EXPECT_CALL(visitor_, OnSynReply(stream_id, fin)); | |
| 174 } | |
| 175 } | |
| 176 EXPECT_CALL(visitor_, OnControlFrameHeaderData(stream_id, _, _)) | |
| 177 .WillRepeatedly(WithArgs<1, 2>( | |
| 178 Invoke(this, &QuicHeadersStreamTest::SaveHeaderData))); | |
| 179 if (fin) { | |
| 180 EXPECT_CALL(visitor_, OnStreamFrameData(stream_id, nullptr, 0, true)); | |
| 181 } | |
| 182 framer_.ProcessInput(saved_data_.data(), saved_data_.length()); | |
| 183 EXPECT_FALSE(framer_.HasError()) | |
| 184 << SpdyFramer::ErrorCodeToString(framer_.error_code()); | |
| 185 | |
| 186 CheckHeaders(); | |
| 187 saved_data_.clear(); | |
| 188 } | |
| 189 | |
| 190 void CheckHeaders() { | |
| 191 SpdyHeaderBlock headers; | |
| 192 EXPECT_EQ(saved_header_data_.length(), | |
| 193 framer_.ParseHeaderBlockInBuffer(saved_header_data_.data(), | |
| 194 saved_header_data_.length(), | |
| 195 &headers)); | |
| 196 EXPECT_EQ(headers_, headers); | |
| 197 saved_header_data_.clear(); | |
| 198 } | |
| 199 | |
| 200 bool is_server() { return GetParam().is_server; } | |
| 201 | |
| 202 QuicVersion version() { return GetParam().version; } | |
| 203 | |
| 204 QuicVersionVector GetVersion() { | |
| 205 QuicVersionVector versions; | |
| 206 versions.push_back(version()); | |
| 207 return versions; | |
| 208 } | |
| 209 | |
| 210 void CloseConnection() { | |
| 211 QuicConnectionPeer::CloseConnection(connection_); | |
| 212 } | |
| 213 | |
| 214 static const bool kFrameComplete = true; | |
| 215 static const bool kHasPriority = true; | |
| 216 static const bool kNotUnidirectional = false; | |
| 217 static const bool kNoAssociatedStream = false; | |
| 218 | |
| 219 StrictMock<MockConnection>* connection_; | |
| 220 StrictMock<MockSession> session_; | |
| 221 QuicHeadersStream* headers_stream_; | |
| 222 SpdyHeaderBlock headers_; | |
| 223 string body_; | |
| 224 string saved_data_; | |
| 225 string saved_header_data_; | |
| 226 SpdyFramer framer_; | |
| 227 StrictMock<MockVisitor> visitor_; | |
| 228 }; | |
| 229 | |
| 230 INSTANTIATE_TEST_CASE_P(Tests, | |
| 231 QuicHeadersStreamTest, | |
| 232 ::testing::ValuesIn(GetTestParams())); | |
| 233 | |
| 234 TEST_P(QuicHeadersStreamTest, StreamId) { | |
| 235 EXPECT_EQ(3u, headers_stream_->id()); | |
| 236 } | |
| 237 | |
| 238 TEST_P(QuicHeadersStreamTest, EffectivePriority) { | |
| 239 EXPECT_EQ(0u, headers_stream_->EffectivePriority()); | |
| 240 } | |
| 241 | |
| 242 TEST_P(QuicHeadersStreamTest, WriteHeaders) { | |
| 243 for (QuicStreamId stream_id = kClientDataStreamId1; | |
| 244 stream_id < kClientDataStreamId3; stream_id += 2) { | |
| 245 for (int count = 0; count < 2; ++count) { | |
| 246 bool fin = (count == 0); | |
| 247 if (is_server()) { | |
| 248 WriteHeadersAndExpectSynReply(stream_id, fin); | |
| 249 } else { | |
| 250 for (QuicPriority priority = 0; priority < 7; ++priority) { | |
| 251 // TODO(rch): implement priorities correctly. | |
| 252 WriteHeadersAndExpectSynStream(stream_id, fin, 0); | |
| 253 } | |
| 254 } | |
| 255 } | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 TEST_P(QuicHeadersStreamTest, ProcessRawData) { | |
| 260 for (QuicStreamId stream_id = kClientDataStreamId1; | |
| 261 stream_id < kClientDataStreamId3; stream_id += 2) { | |
| 262 for (int count = 0; count < 2; ++count) { | |
| 263 bool fin = (count == 0); | |
| 264 for (QuicPriority priority = 0; priority < 7; ++priority) { | |
| 265 // Replace with "WriteHeadersAndSaveData" | |
| 266 scoped_ptr<SpdySerializedFrame> frame; | |
| 267 if (is_server()) { | |
| 268 if (version() > QUIC_VERSION_23) { | |
| 269 SpdyHeadersIR headers_frame(stream_id); | |
| 270 headers_frame.set_name_value_block(headers_); | |
| 271 headers_frame.set_fin(fin); | |
| 272 headers_frame.set_has_priority(true); | |
| 273 frame.reset(framer_.SerializeFrame(headers_frame)); | |
| 274 } else { | |
| 275 SpdySynStreamIR syn_stream(stream_id); | |
| 276 syn_stream.set_name_value_block(headers_); | |
| 277 syn_stream.set_fin(fin); | |
| 278 frame.reset(framer_.SerializeSynStream(syn_stream)); | |
| 279 } | |
| 280 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); | |
| 281 } else { | |
| 282 if (version() > QUIC_VERSION_23) { | |
| 283 SpdyHeadersIR headers_frame(stream_id); | |
| 284 headers_frame.set_name_value_block(headers_); | |
| 285 headers_frame.set_fin(fin); | |
| 286 frame.reset(framer_.SerializeFrame(headers_frame)); | |
| 287 } else { | |
| 288 SpdySynReplyIR syn_reply(stream_id); | |
| 289 syn_reply.set_name_value_block(headers_); | |
| 290 syn_reply.set_fin(fin); | |
| 291 frame.reset(framer_.SerializeSynReply(syn_reply)); | |
| 292 } | |
| 293 } | |
| 294 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)) | |
| 295 .WillRepeatedly(WithArgs<1>( | |
| 296 Invoke(this, | |
| 297 &QuicHeadersStreamTest::SaveHeaderDataStringPiece))); | |
| 298 EXPECT_CALL(session_, | |
| 299 OnStreamHeadersComplete(stream_id, fin, frame->size())); | |
| 300 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 301 CheckHeaders(); | |
| 302 } | |
| 303 } | |
| 304 } | |
| 305 } | |
| 306 | |
| 307 TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { | |
| 308 // We want to create a frame that is more than the SPDY Framer's max control | |
| 309 // frame size, which is 16K, but less than the HPACK decoders max decode | |
| 310 // buffer size, which is 32K. | |
| 311 headers_["key0"] = string(1 << 13, '.'); | |
| 312 headers_["key1"] = string(1 << 13, '.'); | |
| 313 headers_["key2"] = string(1 << 13, '.'); | |
| 314 for (QuicStreamId stream_id = kClientDataStreamId1; | |
| 315 stream_id < kClientDataStreamId3; stream_id += 2) { | |
| 316 for (int count = 0; count < 2; ++count) { | |
| 317 bool fin = (count == 0); | |
| 318 for (QuicPriority priority = 0; priority < 7; ++priority) { | |
| 319 // Replace with "WriteHeadersAndSaveData" | |
| 320 scoped_ptr<SpdySerializedFrame> frame; | |
| 321 if (is_server()) { | |
| 322 if (version() > QUIC_VERSION_23) { | |
| 323 SpdyHeadersIR headers_frame(stream_id); | |
| 324 headers_frame.set_name_value_block(headers_); | |
| 325 headers_frame.set_fin(fin); | |
| 326 headers_frame.set_has_priority(true); | |
| 327 frame.reset(framer_.SerializeFrame(headers_frame)); | |
| 328 } else { | |
| 329 SpdySynStreamIR syn_stream(stream_id); | |
| 330 syn_stream.set_name_value_block(headers_); | |
| 331 syn_stream.set_fin(fin); | |
| 332 frame.reset(framer_.SerializeSynStream(syn_stream)); | |
| 333 } | |
| 334 EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)); | |
| 335 } else { | |
| 336 if (version() > QUIC_VERSION_23) { | |
| 337 SpdyHeadersIR headers_frame(stream_id); | |
| 338 headers_frame.set_name_value_block(headers_); | |
| 339 headers_frame.set_fin(fin); | |
| 340 frame.reset(framer_.SerializeFrame(headers_frame)); | |
| 341 } else { | |
| 342 SpdySynReplyIR syn_reply(stream_id); | |
| 343 syn_reply.set_name_value_block(headers_); | |
| 344 syn_reply.set_fin(fin); | |
| 345 frame.reset(framer_.SerializeSynReply(syn_reply)); | |
| 346 } | |
| 347 } | |
| 348 EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)) | |
| 349 .WillRepeatedly(WithArgs<1>(Invoke( | |
| 350 this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece))); | |
| 351 EXPECT_CALL(session_, | |
| 352 OnStreamHeadersComplete(stream_id, fin, frame->size())); | |
| 353 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 354 CheckHeaders(); | |
| 355 } | |
| 356 } | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 TEST_P(QuicHeadersStreamTest, ProcessBadData) { | |
| 361 const char kBadData[] = "blah blah blah"; | |
| 362 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( | |
| 363 QUIC_INVALID_HEADERS_STREAM_DATA, _)) | |
| 364 .Times(::testing::AnyNumber()); | |
| 365 headers_stream_->ProcessRawData(kBadData, strlen(kBadData)); | |
| 366 } | |
| 367 | |
| 368 TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { | |
| 369 SpdyDataIR data(2, ""); | |
| 370 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 371 EXPECT_CALL(*connection_, | |
| 372 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 373 "SPDY DATA frame received.")) | |
| 374 .WillOnce(InvokeWithoutArgs(this, | |
| 375 &QuicHeadersStreamTest::CloseConnection)); | |
| 376 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 377 } | |
| 378 | |
| 379 TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { | |
| 380 SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR, ""); | |
| 381 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 382 EXPECT_CALL(*connection_, | |
| 383 SendConnectionCloseWithDetails( | |
| 384 QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 385 "SPDY RST_STREAM frame received.")) | |
| 386 .WillOnce(InvokeWithoutArgs(this, | |
| 387 &QuicHeadersStreamTest::CloseConnection)); | |
| 388 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 389 } | |
| 390 | |
| 391 TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) { | |
| 392 SpdySettingsIR data; | |
| 393 if (version() > QUIC_VERSION_23) { | |
| 394 data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0); | |
| 395 } else { | |
| 396 data.AddSetting(SETTINGS_UPLOAD_BANDWIDTH, true, true, 0); | |
| 397 } | |
| 398 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 399 EXPECT_CALL(*connection_, | |
| 400 SendConnectionCloseWithDetails( | |
| 401 QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 402 "SPDY SETTINGS frame received.")) | |
| 403 .WillOnce(InvokeWithoutArgs(this, | |
| 404 &QuicHeadersStreamTest::CloseConnection)); | |
| 405 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 406 } | |
| 407 | |
| 408 TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) { | |
| 409 SpdyPingIR data(1); | |
| 410 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 411 EXPECT_CALL(*connection_, | |
| 412 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 413 "SPDY PING frame received.")) | |
| 414 .WillOnce(InvokeWithoutArgs(this, | |
| 415 &QuicHeadersStreamTest::CloseConnection)); | |
| 416 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 417 } | |
| 418 | |
| 419 TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) { | |
| 420 SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away"); | |
| 421 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 422 EXPECT_CALL(*connection_, | |
| 423 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 424 "SPDY GOAWAY frame received.")) | |
| 425 .WillOnce(InvokeWithoutArgs(this, | |
| 426 &QuicHeadersStreamTest::CloseConnection)); | |
| 427 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 428 } | |
| 429 | |
| 430 TEST_P(QuicHeadersStreamTest, ProcessSpdyHeadersFrame) { | |
| 431 if (version() > QUIC_VERSION_23) { | |
| 432 // HEADERS frames are an error when using SPDY/3, but | |
| 433 // when using SPDY/4 they're the "normal" way of sending headers | |
| 434 // so we test their handling in the ProcessRawData test. | |
| 435 return; | |
| 436 } | |
| 437 SpdyHeadersIR data(1); | |
| 438 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 439 EXPECT_CALL(*connection_, | |
| 440 SendConnectionCloseWithDetails(QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 441 "SPDY HEADERS frame received.")) | |
| 442 .WillOnce(InvokeWithoutArgs(this, | |
| 443 &QuicHeadersStreamTest::CloseConnection)); | |
| 444 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 445 } | |
| 446 | |
| 447 TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) { | |
| 448 SpdyWindowUpdateIR data(1, 1); | |
| 449 scoped_ptr<SpdySerializedFrame> frame(framer_.SerializeFrame(data)); | |
| 450 EXPECT_CALL(*connection_, | |
| 451 SendConnectionCloseWithDetails( | |
| 452 QUIC_INVALID_HEADERS_STREAM_DATA, | |
| 453 "SPDY WINDOW_UPDATE frame received.")) | |
| 454 .WillOnce(InvokeWithoutArgs(this, | |
| 455 &QuicHeadersStreamTest::CloseConnection)); | |
| 456 headers_stream_->ProcessRawData(frame->data(), frame->size()); | |
| 457 } | |
| 458 | |
| 459 TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) { | |
| 460 EXPECT_TRUE(headers_stream_->flow_controller()->IsEnabled()); | |
| 461 EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl( | |
| 462 headers_stream_)); | |
| 463 } | |
| 464 | |
| 465 } // namespace | |
| 466 } // namespace test | |
| 467 } // namespace net | |
| OLD | NEW |