1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_stream.h"
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/spdy/spdy_http_utils.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_session.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_test_util.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(ukai): factor out common part with spdy_http_stream_unittest.cc
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdySessionPoolPeer {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  explicit SpdySessionPoolPeer(SpdySessionPool* pool)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : pool_(pool) {}
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RemoveSpdySession(const scoped_refptr<SpdySession>& session) {
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    pool_->Remove(session);
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SpdySessionPool* const pool_;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SpdySessionPoolPeer);
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass TestSpdyStreamDelegate : public SpdyStream::Delegate {
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestSpdyStreamDelegate(SpdyStream* stream,
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         IOBufferWithSize* buf,
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         CompletionCallback* callback)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : stream_(stream),
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        buf_(buf),
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        callback_(callback),
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        send_headers_completed_(false),
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        response_(new spdy::SpdyHeaderBlock),
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        data_sent_(0),
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        closed_(false) {}
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~TestSpdyStreamDelegate() {}
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool OnSendHeadersComplete(int status) {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    send_headers_completed_ = true;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int OnSendBody() {
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ADD_FAILURE() << "OnSendBody should not be called";
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_UNEXPECTED;
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual int OnSendBodyComplete(int /*status*/, bool* /*eof*/) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ADD_FAILURE() << "OnSendBodyComplete should not be called";
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_UNEXPECTED;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int OnResponseReceived(const spdy::SpdyHeaderBlock& response,
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 base::Time response_time,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 int status) {
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(send_headers_completed_);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *response_ = response;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (buf_) {
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      EXPECT_EQ(ERR_IO_PENDING,
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                stream_->WriteStreamData(buf_.get(), buf_->size(),
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         spdy::DATA_FLAG_NONE));
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return status;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnDataReceived(const char* buffer, int bytes) {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    received_data_ += std::string(buffer, bytes);
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnDataSent(int length) {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    data_sent_ += length;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnClose(int status) {
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    closed_ = true;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CompletionCallback* callback = callback_;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    callback_ = NULL;
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    callback->Run(OK);
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void set_chunk_callback(net::ChunkCallback *) {}
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool send_headers_completed() const { return send_headers_completed_; }
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const linked_ptr<spdy::SpdyHeaderBlock>& response() const {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return response_;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& received_data() const { return received_data_; }
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int data_sent() const { return data_sent_; }
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool closed() const {  return closed_; }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdyStream* stream_;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<IOBufferWithSize> buf_;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CompletionCallback* callback_;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool send_headers_completed_;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  linked_ptr<spdy::SpdyHeaderBlock> response_;
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string received_data_;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int data_sent_;
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool closed_;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyBodyFrame(const char* data, int length) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return framer.CreateDataFrame(1, data, length, spdy::DATA_FLAG_NONE);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // anonymous namespace
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdyStreamTest : public testing::Test {
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdyStreamTest() {
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<SpdySession> CreateSpdySession() {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SpdyFramer::set_enable_compression_default(false);
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HostPortPair host_port_pair("www.google.com", 80);
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    scoped_refptr<SpdySession> session(
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        session_->spdy_session_pool()->Get(pair, BoundNetLog()));
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return session;
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->RunAllPending();
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<HttpNetworkSession> session_;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(SpdyStreamTest, SendDataAfterOpen) {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySessionDependencies session_deps;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SpdyHeaderInfo kSynStartHeader = {
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_STREAM,
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    1,
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,
1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(LOWEST),
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_NONE,
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    false,
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* const kGetHeaders[] = {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "method",
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "GET",
153201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "scheme",
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "http",
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "host",
156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "www.google.com",
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "path",
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "/",
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "HTTP/1.1",
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> req(
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyPacket(
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          kSynStartHeader, NULL, 0, kGetHeaders, arraysize(kGetHeaders) / 2));
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> msg(
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyBodyFrame("\0hello!\xff", 8));
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite writes[] = {
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*req),
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockWrite(*msg),
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  writes[0].sequence_number = 0;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  writes[1].sequence_number = 2;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<spdy::SpdyFrame> echo(
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConstructSpdyBodyFrame("\0hello!\xff", 8));
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead reads[] = {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*resp),
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CreateMockRead(*echo),
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MockRead(true, 0, 0), // EOF
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  reads[0].sequence_number = 1;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  reads[1].sequence_number = 3;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  reads[2].sequence_number = 4;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<OrderedSocketData> data(
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new OrderedSocketData(reads, arraysize(reads),
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            writes, arraysize(writes)));
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockConnect connect_data(false, OK);
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  data->set_connect_data(connect_data);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  session_deps.socket_factory->AddSocketDataProvider(data.get());
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySession::SetSSLMode(false);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<SpdySession> session(CreateSpdySession());
196201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const char* kStreamUrl = "http://www.google.com/";
197201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  GURL url(kStreamUrl);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HostPortPair host_port_pair("www.google.com", 80);
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<TransportSocketParams> transport_params(
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new TransportSocketParams(host_port_pair, LOWEST, GURL(), false, false));
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(OK,
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            connection->Init(host_port_pair.ToString(),
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             transport_params,
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             LOWEST,
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             NULL,
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             session_->transport_socket_pool(),
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             BoundNetLog()));
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  session->InitializeWithSocket(connection.release(), false, OK);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<SpdyStream> stream;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ASSERT_EQ(
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OK,
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      session->CreateStream(url, LOWEST, &stream, BoundNetLog(), NULL));
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(8));
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  memcpy(buf->data(), "\0hello!\xff", 8);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TestCompletionCallback callback;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<TestSpdyStreamDelegate> delegate(
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new TestSpdyStreamDelegate(stream.get(), buf.get(), &callback));
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  stream->SetDelegate(delegate.get());
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_FALSE(stream->HasUrl());
226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  linked_ptr<spdy::SpdyHeaderBlock> headers(new spdy::SpdyHeaderBlock);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  (*headers)["method"] = "GET";
229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  (*headers)["scheme"] = url.scheme();
230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  (*headers)["host"] = url.host();
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  (*headers)["path"] = url.path();
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  (*headers)["version"] = "HTTP/1.1";
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  stream->set_spdy_headers(headers);
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(stream->HasUrl());
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true));
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(OK, callback.WaitForResult());
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(delegate->send_headers_completed());
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("200", (*delegate->response())["status"]);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("HTTP/1.1", (*delegate->response())["version"]);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(std::string("\0hello!\xff", 8), delegate->received_data());
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(8, delegate->data_sent());
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(delegate->closed());
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochTEST_F(SpdyStreamTest, PushedStream) {
250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const char kStreamUrl[] = "http://www.google.com/";
251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SpdySessionDependencies session_deps;
253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps);
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SpdySessionPoolPeer pool_peer_(session_->spdy_session_pool());
255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<SpdySession> spdy_session(CreateSpdySession());
256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  BoundNetLog net_log;
257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Conjure up a stream.
259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  scoped_refptr<SpdyStream> stream = new SpdyStream(spdy_session,
260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                    2,
261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                    true,
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                                    net_log);
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_FALSE(stream->response_received());
264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_FALSE(stream->HasUrl());
265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Set a couple of headers.
267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  spdy::SpdyHeaderBlock response;
268201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response["url"] = kStreamUrl;
269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  stream->OnResponseReceived(response);
270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Send some basic headers.
272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  spdy::SpdyHeaderBlock headers;
273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response["status"] = "200";
274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  response["version"] = "OK";
275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  stream->OnHeaders(headers);
276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  stream->set_response_received();
278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(stream->response_received());
279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_TRUE(stream->HasUrl());
280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  EXPECT_EQ(kStreamUrl, stream->GetUrl().spec());
281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
282201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
285