1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <cstddef> 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <string> 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <vector> 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/stl_util.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/request_priority.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h" 177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "net/socket/socket_test_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/buffered_spdy_framer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_utils.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_protocol.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_stream.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_stream_test_util.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/spdy/spdy_test_util_common.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kStreamUrl[] = "http://www.google.com/"; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kPostBody[] = "\0hello!\xff"; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kPostBodyLength = arraysize(kPostBody); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class SpdyStreamTest : public ::testing::Test, 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public ::testing::WithParamInterface<NextProto> { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // A function that takes a SpdyStream and the number of bytes which 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // will unstall the next frame completely. 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32)> 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UnstallFunction; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyStreamTest() 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : spdy_util_(GetParam()), 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) session_deps_(GetParam()), 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) offset_(0) {} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> CreateDefaultSpdySession() { 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdySessionKey key(HostPortPair("www.google.com", 80), 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProxyServer::Direct(), 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch PRIVACY_MODE_DISABLED); 577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return CreateInsecureSpdySession(session_, key, BoundNetLog()); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void TearDown() { 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void RunResumeAfterUnstallRequestResponseTest( 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const UnstallFunction& unstall_function); 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void RunResumeAfterUnstallBidirectionalTest( 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const UnstallFunction& unstall_function); 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Add{Read,Write}() populates lists that are eventually passed to a 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // SocketData class. |frame| must live for the whole test. 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void AddRead(const SpdyFrame& frame) { 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reads_.push_back(CreateMockRead(frame, offset_++)); 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void AddWrite(const SpdyFrame& frame) { 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) writes_.push_back(CreateMockWrite(frame, offset_++)); 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) void AddReadEOF() { 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reads_.push_back(MockRead(ASYNC, 0, offset_++)); 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MockRead* GetReads() { 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return vector_as_array(&reads_); 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t GetNumReads() const { 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return reads_.size(); 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MockWrite* GetWrites() { 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return vector_as_array(&writes_); 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int GetNumWrites() const { 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return writes_.size(); 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) SpdyTestUtil spdy_util_; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies session_deps_; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<HttpNetworkSession> session_; 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Used by Add{Read,Write}() above. 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<MockWrite> writes_; 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<MockRead> reads_; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int offset_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NextProto, 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyStreamTest, 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) testing::Values(kProtoDeprecatedSPDY2, 116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kProtoSPDY3, kProtoSPDY31, kProtoSPDY4)); 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, SendDataAfterOpen) { 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> req( 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp( 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> msg( 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*msg); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> echo( 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*echo); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OrderedSocketData data(GetReads(), GetNumReads(), 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog()); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 162b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(std::string(kPostBody, kPostBodyLength), 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delegate.TakeReceivedData()); 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, PushedStream) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddReadEOF(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OrderedSocketData data(GetReads(), GetNumReads(), 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWrites(), GetNumWrites()); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Conjure up a stream. 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SpdyStream stream(SPDY_PUSH_STREAM, 193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch spdy_session, 194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GURL(), 195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DEFAULT_PRIORITY, 196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) kSpdyStreamInitialWindowSize, 197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) kSpdyStreamInitialWindowSize, 1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BoundNetLog()); 199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) stream.set_stream_id(2); 200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream.HasUrlFromHeaders()); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Set required request headers. 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SpdyHeaderBlock request_headers; 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &request_headers); 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stream.OnPushPromiseHeadersReceived(request_headers); 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Send some basic response headers. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock response; 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) response[spdy_util_.GetStatusKey()] = "200"; 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) response[spdy_util_.GetVersionKey()] = "OK"; 211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream.OnInitialResponseHeadersReceived( 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch response, base::Time::Now(), base::TimeTicks::Now()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // And some more headers. 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(baranovich): not valid for HTTP 2. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock headers; 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) headers["alpha"] = "beta"; 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream.OnAdditionalResponseHeadersReceived(headers); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream.HasUrlFromHeaders()); 221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec()); 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamDelegateDoNothing delegate(stream.GetWeakPtr()); 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream.SetDelegate(&delegate); 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) EXPECT_EQ("beta", delegate.GetResponseHeaderValue("alpha")); 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(spdy_session == NULL); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, StreamError) { 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> req( 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp( 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> msg( 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*msg); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<SpdyFrame> echo( 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*echo); 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CapturingBoundNetLog log; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OrderedSocketData data(GetReads(), GetNumReads(), 261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.set_connect_data(connect_data); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 269a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound()); 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const SpdyStreamId stream_id = delegate.stream_id(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(std::string(kPostBody, kPostBodyLength), 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delegate.TakeReceivedData()); 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the NetLog was filled reasonably. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::CapturingNetLog::CapturedEntryList entries; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log.GetEntries(&entries); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(0u, entries.size()); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that we logged SPDY_STREAM_ERROR correctly. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos = net::ExpectLogContainsSomewhere( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries, 0, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetLog::TYPE_SPDY_STREAM_ERROR, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::NetLog::PHASE_NONE); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int stream_id2; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2)); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(static_cast<int>(stream_id), stream_id2); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Make sure that large blocks of data are properly split up into 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// frame-sized chunks for a request/response (i.e., an HTTP-like) 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// stream. 315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) { 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GURL url(kStreamUrl); 31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> chunk( 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1, chunk_data.data(), chunk_data.length(), false)); 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*chunk); 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*chunk); 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> last_chunk( 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1, chunk_data.data(), chunk_data.length(), true)); 335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*last_chunk); 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OrderedSocketData data(GetReads(), GetNumReads(), 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.set_connect_data(connect_data); 34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x'); 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateWithBody delegate(stream, body_data); 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SetDelegate(&delegate); 35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Make sure that large blocks of data are properly split up into 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// frame-sized chunks for a bidirectional (i.e., non-HTTP-like) 37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// stream. 380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) { 38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) GURL url(kStreamUrl); 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); 38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); 39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> chunk( 395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame( 39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1, chunk_data.data(), chunk_data.length(), false)); 397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*chunk); 398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*chunk); 399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*chunk); 40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) OrderedSocketData data(GetReads(), GetNumReads(), 404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.set_connect_data(connect_data); 40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_deps_.socket_factory->AddSocketDataProvider(&data); 40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog()); 41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x'); 41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateSendImmediate delegate(stream, body_data); 41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SetDelegate(&delegate); 42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey())); 43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII should result in a protocol 439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// error. 440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeaders) { 441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GURL url(kStreamUrl); 442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_ = 444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> syn( 447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*syn); 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; 451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1)); 453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*reply); 454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> rst( 456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR)); 457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*rst); 458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddReadEOF(); 460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(GetReads(), GetNumReads(), 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWrites(), GetNumWrites()); 463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream = 471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously( 472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream.get() != NULL); 474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamDelegateDoNothing delegate(stream); 476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SetDelegate(&delegate); 477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 479eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(kStreamUrl)); 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND)); 484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(4); 488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose()); 490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII should result in a protocol 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// error even for a push stream. 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) { 495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GURL url(kStreamUrl); 496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_ = 498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> syn( 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*syn); 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*reply); 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const char* const extra_headers[] = {"X-UpperCase", "yes"}; 509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl)); 511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*push); 512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> rst( 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*rst); 516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddReadEOF(); 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(GetReads(), GetNumReads(), 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWrites(), GetNumWrites()); 521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream = 529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously( 530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream.get() != NULL); 532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamDelegateDoNothing delegate(stream); 534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SetDelegate(&delegate); 535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(kStreamUrl)); 540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND)); 542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 544eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(4); 546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> push_stream; 548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog())); 549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(push_stream); 550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII in a HEADERS frame should 557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// result in a protocol error. 558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) { 559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GURL url(kStreamUrl); 560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_ = 562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> syn( 565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*syn); 567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*reply); 571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl)); 574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*push); 575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*late_headers)["X-UpperCase"] = "yes"; 578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> headers_frame( 579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false, 581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2, 582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOWEST, 583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HEADERS, 584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CONTROL_FLAG_NONE, 585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0)); 586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*headers_frame); 587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> rst( 589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*rst); 591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddReadEOF(); 593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(GetReads(), GetNumReads(), 595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWrites(), GetNumWrites()); 596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 602eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream = 604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously( 605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream.get() != NULL); 607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamDelegateDoNothing delegate(stream); 609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SetDelegate(&delegate); 610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 612eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(kStreamUrl)); 615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND)); 617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 619eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(3); 621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> push_stream; 623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog())); 624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(push_stream); 625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog())); 629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(push_stream); 630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a duplicate header in a HEADERS frame should result in a 637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// protocol error. 638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, DuplicateHeaders) { 639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GURL url(kStreamUrl); 640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_ = 642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> syn( 645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*syn); 647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*reply); 651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> 653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl)); 654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*push); 655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock()); 657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error"; 658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> headers_frame( 659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(), 660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false, 661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2, 662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOWEST, 663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HEADERS, 664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CONTROL_FLAG_NONE, 665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0)); 666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddRead(*headers_frame); 667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyFrame> rst( 669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR)); 670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddWrite(*rst); 671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddReadEOF(); 673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeterministicSocketData data(GetReads(), GetNumReads(), 675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GetWrites(), GetNumWrites()); 676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch MockConnect connect_data(SYNCHRONOUS, OK); 677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.set_connect_data(connect_data); 678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> stream = 684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CreateStreamSynchronously( 685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ASSERT_TRUE(stream.get() != NULL); 687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch StreamDelegateDoNothing delegate(stream); 689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SetDelegate(&delegate); 690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 692eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdyHeaderBlock> headers( 694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch spdy_util_.ConstructGetHeaderBlock(kStreamUrl)); 695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_IO_PENDING, 696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND)); 697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 699eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(3); 701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WeakPtr<SpdyStream> push_stream; 703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog())); 704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(push_stream); 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(1); 707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog())); 709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_FALSE(push_stream); 710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch data.RunFor(2); 712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The tests below are only for SPDY/3 and above. 717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Call IncreaseSendWindowSize on a stream with a large enough delta 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to overflow an int32. The SpdyStream should handle that case 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// gracefully. 721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) { 722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (spdy_util_.protocol() < kProtoSPDY3) 723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 725a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) session_ = 726a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 728a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Triggered by the overflowing call to IncreaseSendWindowSize 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // below. 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> rst( 73690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR)); 737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*rst); 738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CapturingBoundNetLog log; 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DeterministicSocketData data(GetReads(), GetNumReads(), 744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 748a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 753a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 75490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 75590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound()); 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 75790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 76090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 761a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 76290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 76390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 766a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 767a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) data.RunFor(1); 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 old_send_window_size = stream->send_window_size(); 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_GT(old_send_window_size, 0); 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 delta_window_size = kint32max - old_send_window_size + 1; 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->IncreaseSendWindowSize(delta_window_size); 773a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(NULL, stream.get()); 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 775a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) data.RunFor(2); 776a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 777a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose()); 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 78090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Functions used with 78190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// RunResumeAfterUnstall{RequestResponse,Bidirectional}Test(). 78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void StallStream(const base::WeakPtr<SpdyStream>& stream) { 78490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Reduce the send window size to 0 to stall. 78590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) while (stream->send_window_size() > 0) { 78690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->DecreaseSendWindowSize( 78790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); 78890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 78990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 79090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 79190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream, 79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int32 delta_window_size) { 79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->IncreaseSendWindowSize(delta_window_size); 79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream, 79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int32 delta_window_size) { 80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Make sure that negative adjustments are handled properly. 80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->AdjustSendWindowSize(-delta_window_size); 80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->AdjustSendWindowSize(+delta_window_size); 80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->AdjustSendWindowSize(+delta_window_size); 80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 80890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 81090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Given an unstall function, runs a test to make sure that a 81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// request/response (i.e., an HTTP-like) stream resumes after a stall 81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and unstall. 813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest( 81490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const UnstallFunction& unstall_function) { 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 82590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyFrame> body( 826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true)); 827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*body); 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DeterministicSocketData data(GetReads(), GetNumReads(), 835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 843a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 84490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 84590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 848a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) StreamDelegateWithBody delegate(stream, kPostBodyStringPiece); 8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 85290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 85790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StallStream(stream); 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unstall_function.Run(stream, kPostBodyLength); 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(3); 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); 87790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(std::string(), delegate.TakeReceivedData()); 87890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 881868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) { 882eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (spdy_util_.protocol() < kProtoSPDY3) 883eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 88590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RunResumeAfterUnstallRequestResponseTest( 88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&IncreaseStreamSendWindowSize)); 88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) { 890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (spdy_util_.protocol() < kProtoSPDY3) 891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RunResumeAfterUnstallRequestResponseTest( 89490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&AdjustStreamSendWindowSize)); 89590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Given an unstall function, runs a test to make sure that a 89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// bidirectional (i.e., non-HTTP-like) stream resumes after a stall 89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and unstall. 900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest( 90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const UnstallFunction& unstall_function) { 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL url(kStreamUrl); 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_ = 9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> req( 908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyPost( 909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); 910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*req); 911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*resp); 914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> msg( 916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddWrite(*msg); 9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> echo( 920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddRead(*echo); 9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddReadEOF(); 924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DeterministicSocketData data(GetReads(), GetNumReads(), 926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetWrites(), GetNumWrites()); 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.set_connect_data(connect_data); 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 934a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SpdyStream> stream = 93590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) CreateStreamSynchronously( 93690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog()); 9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 93990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece); 9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream->SetDelegate(&delegate); 9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(stream->HasUrlFromHeaders()); 9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 945b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength)); 94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 94790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND)); 948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(stream->HasUrlFromHeaders()); 949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) StallStream(stream); 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) data.RunFor(1); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(stream->send_stalled_by_flow_control()); 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 96190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) unstall_function.Run(stream, kPostBodyLength); 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(stream->send_stalled_by_flow_control()); 9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) data.RunFor(3); 9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(delegate.send_headers_completed()); 9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); 971c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(std::string(kPostBody, kPostBodyLength), 972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delegate.TakeReceivedData()); 97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(data.at_write_eof()); 97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 976868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) { 977eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (spdy_util_.protocol() < kProtoSPDY3) 978eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 979eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RunResumeAfterUnstallBidirectionalTest( 98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&IncreaseStreamSendWindowSize)); 98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 984868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) { 985eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (spdy_util_.protocol() < kProtoSPDY3) 986eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 987eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 98890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RunResumeAfterUnstallBidirectionalTest( 98990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&AdjustStreamSendWindowSize)); 9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Test calculation of amount of bytes received from network. 993a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST_P(SpdyStreamTest, ReceivedBytes) { 994a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GURL url(kStreamUrl); 995a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 996a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) session_ = 997a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); 998a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<SpdyFrame> syn( 1000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); 1001a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddWrite(*syn); 1002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<SpdyFrame> 1004a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); 1005a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddRead(*reply); 1006a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1007a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<SpdyFrame> msg( 1008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); 1009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddRead(*msg); 1010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) AddReadEOF(); 1012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeterministicSocketData data(GetReads(), GetNumReads(), 1014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GetWrites(), GetNumWrites()); 1015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) MockConnect connect_data(SYNCHRONOUS, OK); 1016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.set_connect_data(connect_data); 1017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 1019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::WeakPtr<SpdySession> session(CreateDefaultSpdySession()); 1021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::WeakPtr<SpdyStream> stream = 1023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateStreamSynchronously( 1024a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); 1025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ASSERT_TRUE(stream.get() != NULL); 1026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) StreamDelegateDoNothing delegate(stream); 1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream->SetDelegate(&delegate); 1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_FALSE(stream->HasUrlFromHeaders()); 1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<SpdyHeaderBlock> headers( 1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) spdy_util_.ConstructGetHeaderBlock(kStreamUrl)); 1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(ERR_IO_PENDING, 1035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND)); 1036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_TRUE(stream->HasUrlFromHeaders()); 1037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec()); 1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 reply_frame_len = reply->size(); 1040c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int64 data_header_len = spdy_util_.CreateFramer(false) 1041c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ->GetDataFrameMinimumSize(); 1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 data_frame_len = data_header_len + kPostBodyLength; 1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 response_len = reply_frame_len + data_frame_len; 1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(0, stream->raw_received_bytes()); 1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.RunFor(1); // SYN 1047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(0, stream->raw_received_bytes()); 1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.RunFor(1); // REPLY 1049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(reply_frame_len, stream->raw_received_bytes()); 1050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.RunFor(1); // DATA 1051a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(response_len, stream->raw_received_bytes()); 1052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.RunFor(1); // FIN 1053a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1054a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose()); 1055a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1056a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 10582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace test 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1062