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(),
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       kPrivacyModeDisabled);
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,
115558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
116558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch                    kProtoHTTP2Draft04));
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()));
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1",
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            delegate.TakeReceivedData());
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, PushedStream) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddReadEOF();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  OrderedSocketData data(GetReads(), GetNumReads(),
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         GetWrites(), GetNumWrites());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> spdy_session(CreateDefaultSpdySession());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Conjure up a stream.
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdyStream stream(SPDY_PUSH_STREAM,
195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    spdy_session,
196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    GURL(),
197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                    DEFAULT_PRIORITY,
198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                    kSpdyStreamInitialWindowSize,
199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                    kSpdyStreamInitialWindowSize,
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    BoundNetLog());
201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  stream.set_stream_id(2);
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream.HasUrlFromHeaders());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set a couple of headers.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyHeaderBlock response;
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  spdy_util_.AddUrlToHeaderBlock(kStreamUrl, &response);
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream.OnInitialResponseHeadersReceived(
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      response, base::Time::Now(), base::TimeTicks::Now());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send some basic headers.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpdyHeaderBlock headers;
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  headers[spdy_util_.GetStatusKey()] = "200";
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  headers[spdy_util_.GetVersionKey()] = "OK";
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream.OnAdditionalResponseHeadersReceived(headers);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream.HasUrlFromHeaders());
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream.GetUrlFromHeaders().spec());
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamDelegateDoNothing delegate(stream.GetWeakPtr());
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream.SetDelegate(&delegate);
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->RunUntilIdle();
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(spdy_session == NULL);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, StreamError) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> req(
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*resp);
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*msg);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*echo);
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingBoundNetLog log;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OrderedSocketData data(GetReads(), GetNumReads(),
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         GetWrites(), GetNumWrites());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.set_connect_data(connect_data);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const SpdyStreamId stream_id = delegate.stream_id();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1",
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            delegate.TakeReceivedData());
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the NetLog was filled reasonably.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CapturingNetLog::CapturedEntryList entries;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log.GetEntries(&entries);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(0u, entries.size());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that we logged SPDY_STREAM_ERROR correctly.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos = net::ExpectLogContainsSomewhere(
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      entries, 0,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::TYPE_SPDY_STREAM_ERROR,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::NetLog::PHASE_NONE);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int stream_id2;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(stream_id), stream_id2);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Make sure that large blocks of data are properly split up into
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// frame-sized chunks for a request/response (i.e., an HTTP-like)
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// stream.
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) {
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url(kStreamUrl);
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> chunk(
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          1, chunk_data.data(), chunk_data.length(), false));
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*chunk);
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*chunk);
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> last_chunk(
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          1, chunk_data.data(), chunk_data.length(), true));
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*last_chunk);
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*resp);
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OrderedSocketData data(GetReads(), GetNumReads(),
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         GetWrites(), GetNumWrites());
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.set_connect_data(connect_data);
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StreamDelegateWithBody delegate(stream, body_data);
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->SetDelegate(&delegate);
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1",
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Make sure that large blocks of data are properly split up into
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// frame-sized chunks for a bidirectional (i.e., non-HTTP-like)
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// stream.
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) {
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url(kStreamUrl);
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*resp);
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> chunk(
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          1, chunk_data.data(), chunk_data.length(), false));
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*chunk);
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*chunk);
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*chunk);
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OrderedSocketData data(GetReads(), GetNumReads(),
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         GetWrites(), GetNumWrites());
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.set_connect_data(connect_data);
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  session_deps_.socket_factory->AddSocketDataProvider(&data);
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string body_data(3 * kMaxSpdyFrameChunkSize, 'x');
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StreamDelegateSendImmediate delegate(stream, body_data);
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->SetDelegate(&delegate);
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ("HTTP/1.1",
434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            delegate.GetResponseHeaderValue(spdy_util_.GetVersionKey()));
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII should result in a protocol
440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// error.
441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeaders) {
442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_ =
445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> syn(
448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*syn);
450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      reply(spdy_util_.ConstructSpdyGetSynReply(kExtraHeaders, 1, 1));
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*reply);
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*rst);
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddReadEOF();
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(GetReads(), GetNumReads(),
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               GetWrites(), GetNumWrites());
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
466eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
467eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream =
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream.get() != NULL);
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
476eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamDelegateDoNothing delegate(stream);
477eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream->SetDelegate(&delegate);
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
480eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
481eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII should result in a protocol
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// error even for a push stream.
495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeadersOnPush) {
496eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_ =
499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> syn(
502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*syn);
504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*reply);
508eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
509eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* const extra_headers[] = {"X-UpperCase", "yes"};
510eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
511eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      push(spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kStreamUrl));
512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*push);
513eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*rst);
517eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddReadEOF();
519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(GetReads(), GetNumReads(),
521eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               GetWrites(), GetNumWrites());
522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream =
530eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(
531eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
532eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream.get() != NULL);
533eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
534eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamDelegateDoNothing delegate(stream);
535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream->SetDelegate(&delegate);
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
538eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
540eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
541eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
545eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
546eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(4);
547eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
548eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> push_stream;
549eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
550eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(push_stream);
551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a header with uppercase ASCII in a HEADERS frame should
558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// result in a protocol error.
559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_ =
563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
565eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> syn(
566eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
567eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*syn);
568eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
569eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
570eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
571eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*reply);
572eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
573eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
574eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
575eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*push);
576eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
577eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
578eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)["X-UpperCase"] = "yes";
579eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> headers_frame(
580eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
581eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
582eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
583eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
584eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
585eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
586eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
587eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*headers_frame);
588eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
589eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
591eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*rst);
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
593eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddReadEOF();
594eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
595eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(GetReads(), GetNumReads(),
596eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               GetWrites(), GetNumWrites());
597eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
598eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
599eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
600eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
603eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
604eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream =
605eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(
606eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream.get() != NULL);
608eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamDelegateDoNothing delegate(stream);
610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream->SetDelegate(&delegate);
611eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
614eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
615eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
616eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
617eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
620eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> push_stream;
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(push_stream);
626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
628eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
629eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(push_stream);
631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Receiving a duplicate header in a HEADERS frame should result in a
638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// protocol error.
639eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(SpdyStreamTest, DuplicateHeaders) {
640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  GURL url(kStreamUrl);
641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_ =
643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
645eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> syn(
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*syn);
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
649eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
651eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*reply);
652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
653eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame>
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      push(spdy_util_.ConstructSpdyPush(NULL, 0, 2, 1, kStreamUrl));
655eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*push);
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
657eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> late_headers(new SpdyHeaderBlock());
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  (*late_headers)[spdy_util_.GetStatusKey()] = "500 Server Error";
659eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> headers_frame(
660eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyControlFrame(late_headers.Pass(),
661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           false,
662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           2,
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           LOWEST,
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           HEADERS,
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           CONTROL_FLAG_NONE,
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                           0));
667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddRead(*headers_frame);
668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyFrame> rst(
670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddWrite(*rst);
672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  AddReadEOF();
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DeterministicSocketData data(GetReads(), GetNumReads(),
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               GetWrites(), GetNumWrites());
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  MockConnect connect_data(SYNCHRONOUS, OK);
678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.set_connect_data(connect_data);
679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> stream =
685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateStreamSynchronously(
686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(stream.get() != NULL);
688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  StreamDelegateDoNothing delegate(stream);
690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  stream->SetDelegate(&delegate);
691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
693eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
694eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> headers(
695eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
696eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_IO_PENDING,
697eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
700eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
701eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(3);
702eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
703eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::WeakPtr<SpdyStream> push_stream;
704eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_TRUE(push_stream);
706eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
707eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(1);
708eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
709eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(OK, session->GetPushStream(url, &push_stream, BoundNetLog()));
710eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_FALSE(push_stream);
711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  data.RunFor(2);
713eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
714eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
715eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
716eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The tests below are only for SPDY/3 and above.
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Call IncreaseSendWindowSize on a stream with a large enough delta
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to overflow an int32. The SpdyStream should handle that case
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// gracefully.
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, IncreaseSendWindowSizeOverflow) {
723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (spdy_util_.protocol() < kProtoSPDY3)
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
726a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  session_ =
727a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
729a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Triggered by the overflowing call to IncreaseSendWindowSize
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // below.
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> rst(
73790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_FLOW_CONTROL_ERROR));
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*rst);
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CapturingBoundNetLog log;
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeterministicSocketData data(GetReads(), GetNumReads(),
745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               GetWrites(), GetNumWrites());
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
749a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
754a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
75590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
75690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, log.bound());
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
75890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
762a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
76390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
76490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
767a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
768a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.RunFor(1);
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 old_send_window_size = stream->send_window_size();
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_GT(old_send_window_size, 0);
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32 delta_window_size = kint32max - old_send_window_size + 1;
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->IncreaseSendWindowSize(delta_window_size);
774a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(NULL, stream.get());
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
776a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  data.RunFor(2);
777a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
778a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose());
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Functions used with
78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// RunResumeAfterUnstall{RequestResponse,Bidirectional}Test().
78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
78490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void StallStream(const base::WeakPtr<SpdyStream>& stream) {
78590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reduce the send window size to 0 to stall.
78690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (stream->send_window_size() > 0) {
78790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    stream->DecreaseSendWindowSize(
78890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::min(kMaxSpdyFrameChunkSize, stream->send_window_size()));
78990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
79090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
79190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  int32 delta_window_size) {
79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->IncreaseSendWindowSize(delta_window_size);
79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream,
80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                int32 delta_window_size) {
80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Make sure that negative adjustments are handled properly.
80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->AdjustSendWindowSize(-delta_window_size);
80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->AdjustSendWindowSize(+delta_window_size);
80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  stream->AdjustSendWindowSize(+delta_window_size);
80890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
81090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Given an unstall function, runs a test to make sure that a
81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// request/response (i.e., an HTTP-like) stream resumes after a stall
81390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and unstall.
814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest(
81590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UnstallFunction& unstall_function) {
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_ =
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
82690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyFrame> body(
827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, true));
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*body);
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
831868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*resp);
832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeterministicSocketData data(GetReads(), GetNumReads(),
836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               GetWrites(), GetNumWrites());
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
844a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
84590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
84690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
849a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  StreamDelegateWithBody delegate(stream, kPostBodyStringPiece);
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
85390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
856b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
85790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
85890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StallStream(stream);
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  unstall_function.Run(stream, kPostBodyLength);
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(std::string(), delegate.TakeReceivedData());
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
883868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseRequestResponse) {
884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spdy_util_.protocol() < kProtoSPDY3)
885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunResumeAfterUnstallRequestResponseTest(
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&IncreaseStreamSendWindowSize));
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
891868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustRequestResponse) {
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spdy_util_.protocol() < kProtoSPDY3)
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
894eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
89590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunResumeAfterUnstallRequestResponseTest(
89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&AdjustStreamSendWindowSize));
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Given an unstall function, runs a test to make sure that a
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// bidirectional (i.e., non-HTTP-like) stream resumes after a stall
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and unstall.
902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest(
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const UnstallFunction& unstall_function) {
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url(kStreamUrl);
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_ =
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> req(
910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyPost(
911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0));
912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*req);
913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*resp);
916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> msg(
918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddWrite(*msg);
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<SpdyFrame> echo(
922868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
923868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddRead(*echo);
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
925868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddReadEOF();
926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DeterministicSocketData data(GetReads(), GetNumReads(),
928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                               GetWrites(), GetNumWrites());
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockConnect connect_data(SYNCHRONOUS, OK);
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.set_connect_data(connect_data);
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
934ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
936a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SpdyStream> stream =
93790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CreateStreamSynchronously(
93890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SPDY_BIDIRECTIONAL_STREAM, session, url, LOWEST, BoundNetLog());
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(stream.get() != NULL);
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StreamDelegateSendImmediate delegate(stream, kPostBodyStringPiece);
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stream->SetDelegate(&delegate);
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_FALSE(stream->HasUrlFromHeaders());
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<SpdyHeaderBlock> headers(
947b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      spdy_util_.ConstructPostHeaderBlock(kStreamUrl, kPostBodyLength));
94890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
94990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            stream->SendRequestHeaders(headers.Pass(), MORE_DATA_TO_SEND));
950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_TRUE(stream->HasUrlFromHeaders());
951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StallStream(stream);
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  data.RunFor(1);
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(stream->send_stalled_by_flow_control());
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
96390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  unstall_function.Run(stream, kPostBodyLength);
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(stream->send_stalled_by_flow_control());
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.RunFor(3);
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(delegate.send_headers_completed());
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status"));
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version"));
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            delegate.TakeReceivedData());
97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(data.at_write_eof());
97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
979868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeIncreaseBidirectional) {
980eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spdy_util_.protocol() < kProtoSPDY3)
981eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
982eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunResumeAfterUnstallBidirectionalTest(
98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&IncreaseStreamSendWindowSize));
98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
988eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (spdy_util_.protocol() < kProtoSPDY3)
989eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
990eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunResumeAfterUnstallBidirectionalTest(
99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&AdjustStreamSendWindowSize));
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace test
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1000