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